From ebe1127e34731c708c703e95d9777ba68e3151ab Mon Sep 17 00:00:00 2001 From: callumalpass Date: Sun, 13 Sep 2026 22:07:40 +1000 Subject: [PATCH] Add the TaskNotes collection connection walkthrough --- .generated/content.json | 2 +- app/globals.css | 29 +++ content/app/collections.md | 5 +- content/app/connect-mdbase.md | 150 ++++++++++++++ content/app/getting-started.md | 15 +- content/app/index.md | 3 +- content/app/mdbase.md | 3 +- navigation.yml | 2 + .../assets/app/connect-mdbase/captions.en.vtt | 79 ++++++++ public/assets/app/connect-mdbase/poster.png | Bin 0 -> 40247 bytes .../assets/app/connect-mdbase/walkthrough.mp4 | Bin 0 -> 3106383 bytes public/llms-full.txt | 188 ++++++++++++++++-- public/llms.txt | 1 + public/search-index.json | 2 +- public/sitemap.xml | 4 + scripts/generate-content.mjs | 2 + tests/connect-walkthrough.test.mjs | 66 ++++++ tests/link-integrity.test.mjs | 11 +- tests/rendered-html.test.mjs | 23 +++ 19 files changed, 557 insertions(+), 28 deletions(-) create mode 100644 content/app/connect-mdbase.md create mode 100644 public/assets/app/connect-mdbase/captions.en.vtt create mode 100644 public/assets/app/connect-mdbase/poster.png create mode 100644 public/assets/app/connect-mdbase/walkthrough.mp4 create mode 100644 tests/connect-walkthrough.test.mjs diff --git a/.generated/content.json b/.generated/content.json index 3a25de7..dbd75a2 100644 --- a/.generated/content.json +++ b/.generated/content.json @@ -1 +1 @@ -{"generatedAt":"2026-08-10T11:59:24.540Z","versions":{"app":"0.1.0","obsidian":"4.12.3"},"navigation":[{"label":"Start here","items":[{"title":"TaskNotes documentation","route":"/"},{"title":"TaskNotes app","route":"/app/"},{"title":"Obsidian plugin","route":"/obsidian/"},{"title":"Shared concepts","route":"/concepts/task-records/"}]},{"label":"TaskNotes app","items":[{"title":"Get started","route":"/app/getting-started/"},{"title":"Interactive demo","route":"/app/demo/"},{"title":"Choose a collection","route":"/app/collections/"},{"title":"What is mdbase?","route":"/app/mdbase/"},{"title":"Tasks","route":"/app/tasks/"},{"title":"Views and navigation","route":"/app/views/"},{"title":"Connection and availability","route":"/app/connection/"},{"title":"Reminders","route":"/app/reminders/"},{"title":"Troubleshooting","route":"/app/troubleshooting/"}]},{"label":"Obsidian plugin","items":[{"title":"Get started","route":"/obsidian/"},{"title":"Core concepts","route":"/obsidian/core-concepts/"},{"title":"Task management","route":"/obsidian/features/task-management/"},{"title":"Recurring tasks","route":"/obsidian/features/recurring-tasks/"},{"title":"Views","route":"/obsidian/views/"},{"title":"Settings","route":"/obsidian/settings/"},{"title":"APIs and automation","route":"/obsidian/HTTP_API/"},{"title":"Companion plugins","route":"/obsidian/companion-plugins/"},{"title":"Release notes","route":"/obsidian/releases/"},{"title":"Troubleshooting","route":"/obsidian/troubleshooting/"}]},{"label":"Developers","items":[{"title":"TaskNotes specification","route":"/developers/specification/"},{"title":"App integration manifest","route":"/app/reference/manifest/"},{"title":"Command reference","route":"/obsidian/reference/commands/"},{"title":"Settings source","route":"/obsidian/reference/settings-source/"},{"title":"HTTP route index","route":"/obsidian/reference/http-routes/"}]},{"label":"Policies","items":[{"title":"Privacy","route":"/privacy/"}]}],"redirects":{"/app/sync-and-conflicts/":"/app/connection/","/core-concepts/":"/obsidian/core-concepts/","/getting-started/existing-vault/":"/obsidian/getting-started/existing-vault/","/getting-started/mobile/":"/obsidian/getting-started/mobile/","/migration-v3-to-v4/":"/obsidian/migration-v3-to-v4/","/features/":"/obsidian/features/","/views/":"/obsidian/views/","/settings/":"/obsidian/settings/","/calendar-setup/":"/obsidian/calendar-setup/","/troubleshooting/":"/obsidian/troubleshooting/","/HTTP_API/":"/obsidian/HTTP_API/","/javascript-api/":"/obsidian/javascript-api/","/nlp-api/":"/obsidian/nlp-api/","/obsidian-cli/":"/obsidian/obsidian-cli/","/mdbase-tasknotes-cli/":"/obsidian/mdbase-tasknotes-cli/","/webhooks/":"/obsidian/webhooks/","/workflows/":"/obsidian/workflows/","/companion-plugins/":"/obsidian/companion-plugins/","/releases/":"/obsidian/releases/","/spec/":"/developers/specification/","/views/default-base-templates/":"/obsidian/reference/default-base-templates/","/settings/defaults/":"/obsidian/settings/task-properties/","/settings/task-defaults/":"/obsidian/settings/task-properties/","/settings/inline-task-settings/":"/obsidian/settings/features/","/settings/calendar-settings/":"/obsidian/settings/appearance/","/settings/misc-settings/":"/obsidian/settings/features/","/settings/advanced-settings/":"/obsidian/settings/features/","/companion-plugins/canvas-bases/":"/obsidian/companion-plugins/canvas-bases/","/companion-plugins/tasknotes-workflows/":"/obsidian/companion-plugins/tasknotes-workflows/","/features/calendar-integration/":"/obsidian/features/calendar-integration/","/features/ics-integration/":"/obsidian/features/ics-integration/","/features/inline-tasks/":"/obsidian/features/inline-tasks/","/features/integrations/":"/obsidian/features/integrations/","/features/recurring-tasks/":"/obsidian/features/recurring-tasks/","/features/reminders/":"/obsidian/features/reminders/","/features/task-management/":"/obsidian/features/task-management/","/features/template-variables/":"/obsidian/features/template-variables/","/features/time-management/":"/obsidian/features/time-management/","/features/user-fields/":"/obsidian/features/user-fields/","/guides/backup-recovery/":"/obsidian/guides/backup-recovery/","/guides/custom-bases/":"/obsidian/guides/custom-bases/","/settings/appearance/":"/obsidian/settings/appearance/","/settings/features/":"/obsidian/settings/features/","/settings/general/":"/obsidian/settings/general/","/settings/integrations/":"/obsidian/settings/integrations/","/settings/modal-fields/":"/obsidian/settings/modal-fields/","/settings/property-identification/":"/obsidian/settings/property-identification/","/settings/property-types-reference/":"/obsidian/settings/property-types-reference/","/settings/task-properties/":"/obsidian/settings/task-properties/","/views/agenda-view/":"/obsidian/views/agenda-view/","/views/calendar-views/":"/obsidian/views/calendar-views/","/views/kanban-view/":"/obsidian/views/kanban-view/","/views/pomodoro-view/":"/obsidian/views/pomodoro-view/","/views/task-list/":"/obsidian/views/task-list/","/releases/0.2.2/":"/obsidian/releases/0.2.2/","/releases/0.2.3/":"/obsidian/releases/0.2.3/","/releases/0.2.4/":"/obsidian/releases/0.2.4/","/releases/0.3.0/":"/obsidian/releases/0.3.0/","/releases/0.4.0/":"/obsidian/releases/0.4.0/","/releases/0.4.1/":"/obsidian/releases/0.4.1/","/releases/0.4.2/":"/obsidian/releases/0.4.2/","/releases/0.6.0/":"/obsidian/releases/0.6.0/","/releases/0.6.1/":"/obsidian/releases/0.6.1/","/releases/0.6.2/":"/obsidian/releases/0.6.2/","/releases/0.6.3/":"/obsidian/releases/0.6.3/","/releases/0.7.0/":"/obsidian/releases/0.7.0/","/releases/0.8.0/":"/obsidian/releases/0.8.0/","/releases/1.0.0/":"/obsidian/releases/1.0.0/","/releases/1.1.0/":"/obsidian/releases/1.1.0/","/releases/1.2.0/":"/obsidian/releases/1.2.0/","/releases/2.0.0/":"/obsidian/releases/2.0.0/","/releases/2.0.1/":"/obsidian/releases/2.0.1/","/releases/2.0.2/":"/obsidian/releases/2.0.2/","/releases/2.0.3/":"/obsidian/releases/2.0.3/","/releases/2.0.4/":"/obsidian/releases/2.0.4/","/releases/2.1.0/":"/obsidian/releases/2.1.0/","/releases/2.2.0/":"/obsidian/releases/2.2.0/","/releases/2.2.1/":"/obsidian/releases/2.2.1/","/releases/2.2.2/":"/obsidian/releases/2.2.2/","/releases/2.2.3/":"/obsidian/releases/2.2.3/","/releases/3.0.0/":"/obsidian/releases/3.0.0/","/releases/3.0.1/":"/obsidian/releases/3.0.1/","/releases/3.1.0/":"/obsidian/releases/3.1.0/","/releases/3.1.1/":"/obsidian/releases/3.1.1/","/releases/3.10.0/":"/obsidian/releases/3.10.0/","/releases/3.11.0/":"/obsidian/releases/3.11.0/","/releases/3.11.1/":"/obsidian/releases/3.11.1/","/releases/3.11.2/":"/obsidian/releases/3.11.2/","/releases/3.12.0/":"/obsidian/releases/3.12.0/","/releases/3.12.1/":"/obsidian/releases/3.12.1/","/releases/3.12.2/":"/obsidian/releases/3.12.2/","/releases/3.13.0/":"/obsidian/releases/3.13.0/","/releases/3.13.1/":"/obsidian/releases/3.13.1/","/releases/3.13.2/":"/obsidian/releases/3.13.2/","/releases/3.13.3/":"/obsidian/releases/3.13.3/","/releases/3.13.4/":"/obsidian/releases/3.13.4/","/releases/3.14.0/":"/obsidian/releases/3.14.0/","/releases/3.15.0/":"/obsidian/releases/3.15.0/","/releases/3.15.1/":"/obsidian/releases/3.15.1/","/releases/3.16.0/":"/obsidian/releases/3.16.0/","/releases/3.16.1/":"/obsidian/releases/3.16.1/","/releases/3.16.2/":"/obsidian/releases/3.16.2/","/releases/3.16.3/":"/obsidian/releases/3.16.3/","/releases/3.16.4/":"/obsidian/releases/3.16.4/","/releases/3.17.0/":"/obsidian/releases/3.17.0/","/releases/3.17.1/":"/obsidian/releases/3.17.1/","/releases/3.18.0/":"/obsidian/releases/3.18.0/","/releases/3.18.1/":"/obsidian/releases/3.18.1/","/releases/3.18.2/":"/obsidian/releases/3.18.2/","/releases/3.19.0/":"/obsidian/releases/3.19.0/","/releases/3.19.1/":"/obsidian/releases/3.19.1/","/releases/3.20.0/":"/obsidian/releases/3.20.0/","/releases/3.20.1/":"/obsidian/releases/3.20.1/","/releases/3.21.0/":"/obsidian/releases/3.21.0/","/releases/3.22.0/":"/obsidian/releases/3.22.0/","/releases/3.22.1/":"/obsidian/releases/3.22.1/","/releases/3.23.0/":"/obsidian/releases/3.23.0/","/releases/3.23.1/":"/obsidian/releases/3.23.1/","/releases/3.23.2/":"/obsidian/releases/3.23.2/","/releases/3.23.3/":"/obsidian/releases/3.23.3/","/releases/3.23.4/":"/obsidian/releases/3.23.4/","/releases/3.24.0/":"/obsidian/releases/3.24.0/","/releases/3.24.1/":"/obsidian/releases/3.24.1/","/releases/3.24.2/":"/obsidian/releases/3.24.2/","/releases/3.24.3/":"/obsidian/releases/3.24.3/","/releases/3.24.4/":"/obsidian/releases/3.24.4/","/releases/3.24.5/":"/obsidian/releases/3.24.5/","/releases/3.24.6/":"/obsidian/releases/3.24.6/","/releases/3.25.0/":"/obsidian/releases/3.25.0/","/releases/3.25.1/":"/obsidian/releases/3.25.1/","/releases/3.25.2/":"/obsidian/releases/3.25.2/","/releases/3.25.3/":"/obsidian/releases/3.25.3/","/releases/3.25.4/":"/obsidian/releases/3.25.4/","/releases/3.25.6/":"/obsidian/releases/3.25.6/","/releases/3.3.0/":"/obsidian/releases/3.3.0/","/releases/3.4.0/":"/obsidian/releases/3.4.0/","/releases/3.4.1/":"/obsidian/releases/3.4.1/","/releases/3.4.2/":"/obsidian/releases/3.4.2/","/releases/3.5.1/":"/obsidian/releases/3.5.1/","/releases/3.6.0/":"/obsidian/releases/3.6.0/","/releases/3.7.0/":"/obsidian/releases/3.7.0/","/releases/3.7.1/":"/obsidian/releases/3.7.1/","/releases/3.8.1/":"/obsidian/releases/3.8.1/","/releases/3.8.5/":"/obsidian/releases/3.8.5/","/releases/3.8.6/":"/obsidian/releases/3.8.6/","/releases/3.8.7/":"/obsidian/releases/3.8.7/","/releases/3.9.0/":"/obsidian/releases/3.9.0/","/releases/3.9.1/":"/obsidian/releases/3.9.1/","/releases/4.0.0-beta.0/":"/obsidian/releases/4.0.0-beta.0/","/releases/4.0.0-beta.1/":"/obsidian/releases/4.0.0-beta.1/","/releases/4.0.0-beta.2/":"/obsidian/releases/4.0.0-beta.2/","/releases/4.0.0-beta.3/":"/obsidian/releases/4.0.0-beta.3/","/releases/4.0.1/":"/obsidian/releases/4.0.1/","/releases/4.0.2/":"/obsidian/releases/4.0.2/","/releases/4.0.3/":"/obsidian/releases/4.0.3/","/releases/4.0.4/":"/obsidian/releases/4.0.4/","/releases/4.0.5/":"/obsidian/releases/4.0.5/","/releases/4.1.0/":"/obsidian/releases/4.1.0/","/releases/4.1.1/":"/obsidian/releases/4.1.1/","/releases/4.1.2/":"/obsidian/releases/4.1.2/","/releases/4.1.3/":"/obsidian/releases/4.1.3/","/releases/4.10.0/":"/obsidian/releases/4.10.0/","/releases/4.10.1/":"/obsidian/releases/4.10.1/","/releases/4.10.2/":"/obsidian/releases/4.10.2/","/releases/4.11.0/":"/obsidian/releases/4.11.0/","/releases/4.11.1/":"/obsidian/releases/4.11.1/","/releases/4.12.0/":"/obsidian/releases/4.12.0/","/releases/4.12.1/":"/obsidian/releases/4.12.1/","/releases/4.12.2/":"/obsidian/releases/4.12.2/","/releases/4.12.3/":"/obsidian/releases/4.12.3/","/releases/4.2.0/":"/obsidian/releases/4.2.0/","/releases/4.2.1/":"/obsidian/releases/4.2.1/","/releases/4.3.0/":"/obsidian/releases/4.3.0/","/releases/4.3.1/":"/obsidian/releases/4.3.1/","/releases/4.3.2/":"/obsidian/releases/4.3.2/","/releases/4.3.3/":"/obsidian/releases/4.3.3/","/releases/4.4.0/":"/obsidian/releases/4.4.0/","/releases/4.5.0/":"/obsidian/releases/4.5.0/","/releases/4.5.1/":"/obsidian/releases/4.5.1/","/releases/4.5.2/":"/obsidian/releases/4.5.2/","/releases/4.5.3/":"/obsidian/releases/4.5.3/","/releases/4.6.0/":"/obsidian/releases/4.6.0/","/releases/4.7.0/":"/obsidian/releases/4.7.0/","/releases/4.7.1/":"/obsidian/releases/4.7.1/","/releases/4.7.2/":"/obsidian/releases/4.7.2/","/releases/4.8.0/":"/obsidian/releases/4.8.0/","/releases/4.8.1/":"/obsidian/releases/4.8.1/","/releases/4.9.0/":"/obsidian/releases/4.9.0/","/releases/4.9.1/":"/obsidian/releases/4.9.1/","/releases/4.9.2/":"/obsidian/releases/4.9.2/","/releases/unreleased/":"/obsidian/releases/unreleased/","/reference/commands/":"/obsidian/reference/commands/","/reference/compatibility/":"/obsidian/reference/compatibility/","/reference/settings-source/":"/obsidian/reference/settings-source/","/reference/http-routes/":"/obsidian/reference/http-routes/","/reference/default-base-templates/":"/obsidian/reference/default-base-templates/","/spec/00-overview/":"/developers/specification/","/spec/01-terminology/":"/developers/specification/01-terminology/","/spec/02-model-and-mapping/":"/developers/specification/02-model-and-mapping/","/spec/03-temporal-semantics/":"/developers/specification/03-temporal-semantics/","/spec/04-recurrence/":"/developers/specification/04-recurrence/","/spec/05-operations/":"/developers/specification/05-operations/","/spec/06-validation/":"/developers/specification/06-validation/","/spec/07-conformance/":"/developers/specification/07-conformance/","/spec/08-compatibility-and-migrations/":"/developers/specification/08-compatibility-and-migrations/","/spec/09-configuration/":"/developers/specification/09-configuration/","/spec/10-dependencies-and-reminders/":"/developers/specification/10-dependencies-and-reminders/","/spec/11-links/":"/developers/specification/11-links/","/spec/12-mdbase-v0.3-binding/":"/developers/specification/12-mdbase-v0.3-binding/","/spec/CHANGELOG/":"/developers/specification/CHANGELOG/"},"pages":[{"route":"/","title":"TaskNotes documentation","description":"Guides and reference material for the TaskNotes app, the Obsidian plugin, and the portable task format they share.","product":"shared","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":true,"source":"tasknotes.dev:content/index.md","namespace":"index.md","relativePath":"","raw":"---\ntitle: TaskNotes documentation\ndescription: Guides and reference material for the TaskNotes app, the Obsidian plugin, and the portable task format they share.\nroute: /\nproduct: shared\nhide_toc: true\n---\n\n# TaskNotes documentation\n\nTaskNotes keeps structured task information in portable Markdown records. Use\nthe dedicated app on the web, Android, or iOS, or work inside Obsidian with the\nTaskNotes plugin.\n\n
\n \n Beta · Web · Android · iOS\n TaskNotes app\n Manage portable TaskNotes v5 collections on the web, Android, and iOS through mdbase.\n Open the app guide →\n \n \n Obsidian\n TaskNotes plugin\n Task and note management inside an Obsidian vault using Bases and Markdown.\n Open the plugin guide →\n \n
\n\n## One portable task model\n\nBoth clients understand the same TaskNotes concepts: status, priority, dates,\nprojects, contexts, recurrence, reminders, relationships, and custom fields.\nThe interface and available integrations differ, but your task records are not\nlocked to one screen or application.\n\n- Start with [portable task records](/concepts/task-records/) if you want to\n understand what the products share.\n- Read the [formal specification](/developers/specification/) when implementing\n or integrating with TaskNotes.\n- Review the [privacy overview](/privacy/) before choosing a hosted or\n computer-connected collection.\n","aliases":[],"toc":[{"level":2,"id":"one-portable-task-model","text":"One portable task model"}],"html":"

TaskNotes keeps structured task information in portable Markdown records. Use\nthe dedicated app on the web, Android, or iOS, or work inside Obsidian with the\nTaskNotes plugin.

\n
\n \n Beta · Web · Android · iOS\n TaskNotes app\n Manage portable TaskNotes v5 collections on the web, Android, and iOS through mdbase.\n Open the app guide →\n \n \n Obsidian\n TaskNotes plugin\n Task and note management inside an Obsidian vault using Bases and Markdown.\n Open the plugin guide →\n \n
\n\n

One portable task model#

\n

Both clients understand the same TaskNotes concepts: status, priority, dates,\nprojects, contexts, recurrence, reminders, relationships, and custom fields.\nThe interface and available integrations differ, but your task records are not\nlocked to one screen or application.

\n\n","text":"TaskNotes keeps structured task information in portable Markdown records. Use the dedicated app on the web, Android, or iOS, or work inside Obsidian with the TaskNotes plugin. Beta · Web · Android · iOS TaskNotes app Manage portable TaskNotes v5 collections on the web, Android, and iOS through mdbase. Open the app guide → Obsidian TaskNotes plugin Task and note management inside an Obsidian vault using Bases and Markdown. Open the plugin guide → One portable task model# Both clients understand the same TaskNotes concepts: status, priority, dates, projects, contexts, recurrence, reminders, relationships, and custom fields. The interface and available integrations differ, but your task records are not locked to one screen or application. Start with portable task records if you want to understand what the products share. Read the formal specification when implementing or integrating with TaskNotes. Review the privacy overview before choosing a hosted or computer-connected collection."},{"route":"/app/","title":"TaskNotes app","description":"Use TaskNotes on the web, Android, and iOS with portable Markdown through mdbase.","product":"app","platforms":["web","android","ios"],"version":"0.1.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/app/index.md","namespace":"app","relativePath":"index.md","raw":"---\ntitle: TaskNotes app\ndescription: Use TaskNotes on the web, Android, and iOS with portable Markdown through mdbase.\nroute: /app/\nproduct: app\nplatforms: [web, android, ios]\n---\n\n# TaskNotes app\n\nThe TaskNotes app is currently in beta. It is a web-first client packaged for\nAndroid and iOS, designed for quick capture, daily review, editing, and\ncompletion while keeping task records portable.\n\nThe app is compatible with **TaskNotes v5 collections**, which use the\n**mdbase 0.3.0 specification**. The same collection can be used by other\ncompatible TaskNotes and mdbase tools.\n\nEvery TaskNotes session opens an mdbase collection. You can use a collection\nhosted online or connect to a Markdown collection on your computer through the\nencrypted mdbase relay. TaskNotes reads and writes that collection directly, so\nchanges require a connection.\n\n
\n \"TaskNotes\n
The Today workspace in the desktop layout.
\n
\n\n
\n Disposable sample collection\n Try TaskNotes before connecting your own collection.\n Explore Today, Scratchpad, search, and saved views with sample tasks. Your changes disappear when the demo resets.\n Open the interactive demo →\n
\n\n## Begin here\n\n1. [Try TaskNotes with sample tasks](/app/demo/) or [open or install TaskNotes](/app/getting-started/).\n2. [Learn how mdbase supports TaskNotes](/app/mdbase/).\n3. [Choose where your collection lives](/app/collections/).\n4. Create a task and open **Today**.\n5. Turn on reminders only if the collection and platform support delivery.\n\n## What the app includes\n\n- Today, Upcoming, Projects, lists, boards, and calendars\n- Capture, editing, completion, archive, and search\n- Projects, contexts, tags, priorities, relationships, and custom fields\n- Recurrence, materialized occurrence notes, reminders, and time tracking\n- Hosted mdbase and end-to-end encrypted relay connections\n- Browser, Android, and iOS packaging from the same application\n\nPlugin-only functionality such as inline Obsidian widgets, the command palette,\nexternal calendar integrations, HTTP APIs, and companion plugins is documented\nunder the [Obsidian plugin](/obsidian/).\n","aliases":[],"toc":[{"level":2,"id":"begin-here","text":"Begin here"},{"level":2,"id":"what-the-app-includes","text":"What the app includes"}],"html":"

The TaskNotes app is currently in beta. It is a web-first client packaged for\nAndroid and iOS, designed for quick capture, daily review, editing, and\ncompletion while keeping task records portable.

\n

The app is compatible with TaskNotes v5 collections, which use the\nmdbase 0.3.0 specification. The same collection can be used by other\ncompatible TaskNotes and mdbase tools.

\n

Every TaskNotes session opens an mdbase collection. You can use a collection\nhosted online or connect to a Markdown collection on your computer through the\nencrypted mdbase relay. TaskNotes reads and writes that collection directly, so\nchanges require a connection.

\n
\n \"TaskNotes\n
The Today workspace in the desktop layout.
\n
\n\n
\n Disposable sample collection\n Try TaskNotes before connecting your own collection.\n Explore Today, Scratchpad, search, and saved views with sample tasks. Your changes disappear when the demo resets.\n Open the interactive demo →\n
\n\n

Begin here#

\n
    \n
  1. Try TaskNotes with sample tasks or open or install TaskNotes.
  2. \n
  3. Learn how mdbase supports TaskNotes.
  4. \n
  5. Choose where your collection lives.
  6. \n
  7. Create a task and open Today.
  8. \n
  9. Turn on reminders only if the collection and platform support delivery.
  10. \n
\n

What the app includes#

\n\n

Plugin-only functionality such as inline Obsidian widgets, the command palette,\nexternal calendar integrations, HTTP APIs, and companion plugins is documented\nunder the Obsidian plugin.

\n","text":"The TaskNotes app is currently in beta. It is a web-first client packaged for Android and iOS, designed for quick capture, daily review, editing, and completion while keeping task records portable. The app is compatible with TaskNotes v5 collections, which use the mdbase 0.3.0 specification. The same collection can be used by other compatible TaskNotes and mdbase tools. Every TaskNotes session opens an mdbase collection. You can use a collection hosted online or connect to a Markdown collection on your computer through the encrypted mdbase relay. TaskNotes reads and writes that collection directly, so changes require a connection. The Today workspace in the desktop layout. Disposable sample collection Try TaskNotes before connecting your own collection. Explore Today, Scratchpad, search, and saved views with sample tasks. Your changes disappear when the demo resets. Open the interactive demo → Begin here# Try TaskNotes with sample tasks or open or install TaskNotes. Learn how mdbase supports TaskNotes. Choose where your collection lives. Create a task and open Today. Turn on reminders only if the collection and platform support delivery. What the app includes# Today, Upcoming, Projects, lists, boards, and calendars Capture, editing, completion, archive, and search Projects, contexts, tags, priorities, relationships, and custom fields Recurrence, materialized occurrence notes, reminders, and time tracking Hosted mdbase and end-to-end encrypted relay connections Browser, Android, and iOS packaging from the same application Plugin-only functionality such as inline Obsidian widgets, the command palette, external calendar integrations, HTTP APIs, and companion plugins is documented under the Obsidian plugin."},{"route":"/app/collections/","title":"Choose a collection","description":"Compare hosted mdbase with a collection connected from your own computer.","product":"app","platforms":["web","android","ios"],"version":"0.1.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/app/collections.md","namespace":"app","relativePath":"collections.md","raw":"---\ntitle: Choose a collection\ndescription: Compare hosted mdbase with a collection connected from your own computer.\nroute: /app/collections/\nproduct: app\nplatforms: [web, android, ios]\n---\n\n# Choose a collection\n\nTaskNotes opens every collection through mdbase. The choice is where the main\ncopy of your Markdown lives: hosted online or on your own computer.\n\nIf mdbase is new to you, start with [mdbase and TaskNotes](/app/mdbase/) for a\nplain-language explanation of the format, Connect desktop app, and hosting\nchoices.\n\n## Hosted mdbase\n\nHosted mdbase is the recommended choice for convenient access across the web,\nAndroid, and iOS. The provider keeps the main collection online, so it is\navailable from any TaskNotes device with a network connection and can deliver\nreminders while TaskNotes is closed.\n\nTaskNotes reads and writes the hosted collection directly. It does not keep a\nseparate offline copy, so you need a network connection to open the collection\nor make changes.\n\n## Connect to a computer\n\nmdbase Connect can make a Markdown collection on your computer available to\nTaskNotes. Requests and responses travel through an end-to-end encrypted relay;\nthe relay cannot read your task contents and you do not need to open a port on\nyour router.\n\nThe computer holds the main copy, so it must be awake, online, and running the\nmdbase Connect background service whenever you use TaskNotes. See how to\n[install mdbase Connect and use a computer collection](/app/mdbase/#use-a-collection-on-your-computer).\n\n## Change collections later\n\nOpen **More** and choose **Change collection**. Opening another collection does\nnot copy or move records from the collection you were using.\n","aliases":[],"toc":[{"level":2,"id":"hosted-mdbase","text":"Hosted mdbase"},{"level":2,"id":"connect-to-a-computer","text":"Connect to a computer"},{"level":2,"id":"change-collections-later","text":"Change collections later"}],"html":"

TaskNotes opens every collection through mdbase. The choice is where the main\ncopy of your Markdown lives: hosted online or on your own computer.

\n

If mdbase is new to you, start with mdbase and TaskNotes for a\nplain-language explanation of the format, Connect desktop app, and hosting\nchoices.

\n

Hosted mdbase#

\n

Hosted mdbase is the recommended choice for convenient access across the web,\nAndroid, and iOS. The provider keeps the main collection online, so it is\navailable from any TaskNotes device with a network connection and can deliver\nreminders while TaskNotes is closed.

\n

TaskNotes reads and writes the hosted collection directly. It does not keep a\nseparate offline copy, so you need a network connection to open the collection\nor make changes.

\n

Connect to a computer#

\n

mdbase Connect can make a Markdown collection on your computer available to\nTaskNotes. Requests and responses travel through an end-to-end encrypted relay;\nthe relay cannot read your task contents and you do not need to open a port on\nyour router.

\n

The computer holds the main copy, so it must be awake, online, and running the\nmdbase Connect background service whenever you use TaskNotes. See how to\ninstall mdbase Connect and use a computer collection.

\n

Change collections later#

\n

Open More and choose Change collection. Opening another collection does\nnot copy or move records from the collection you were using.

\n","text":"TaskNotes opens every collection through mdbase. The choice is where the main copy of your Markdown lives: hosted online or on your own computer. If mdbase is new to you, start with mdbase and TaskNotes for a plain-language explanation of the format, Connect desktop app, and hosting choices. Hosted mdbase# Hosted mdbase is the recommended choice for convenient access across the web, Android, and iOS. The provider keeps the main collection online, so it is available from any TaskNotes device with a network connection and can deliver reminders while TaskNotes is closed. TaskNotes reads and writes the hosted collection directly. It does not keep a separate offline copy, so you need a network connection to open the collection or make changes. Connect to a computer# mdbase Connect can make a Markdown collection on your computer available to TaskNotes. Requests and responses travel through an end-to-end encrypted relay; the relay cannot read your task contents and you do not need to open a port on your router. The computer holds the main copy, so it must be awake, online, and running the mdbase Connect background service whenever you use TaskNotes. See how to install mdbase Connect and use a computer collection. Change collections later# Open More and choose Change collection. Opening another collection does not copy or move records from the collection you were using."},{"route":"/app/connection/","title":"Connection and availability","description":"Understand when TaskNotes can reach hosted and computer-connected mdbase collections.","product":"app","platforms":["web","android","ios"],"version":"0.1.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/app/connection.md","namespace":"app","relativePath":"connection.md","raw":"---\ntitle: Connection and availability\ndescription: Understand when TaskNotes can reach hosted and computer-connected mdbase collections.\nroute: /app/connection/\nproduct: app\nplatforms: [web, android, ios]\n---\n\n# Connection and availability\n\nTaskNotes reads and writes the selected mdbase collection directly. It does not\nkeep a separate offline collection or a queue of changes waiting to sync.\n\n## What each status means\n\n| Status | Meaning |\n| --- | --- |\n| Connected | TaskNotes can read and change the selected collection |\n| Connecting | TaskNotes is checking the collection connection |\n| Collection unavailable | The hosted service or connected computer cannot be reached |\n\nOpen **More** to see the current status and use **Refresh now** to read the\nlatest collection state.\n\n## Hosted collections\n\nA hosted collection needs a network connection and an available hosted mdbase\nservice. If either is unavailable, TaskNotes cannot open the collection or save\nchanges. Reconnect the collection if its authorization has expired.\n\n## Collections on your computer\n\nA computer collection also needs the computer holding the Markdown to be\nawake, online, and running the mdbase Connect background service. TaskNotes\nreaches it through the end-to-end encrypted relay. If the computer becomes\nunavailable, access returns when the computer and connector return.\n\n## During a connection problem\n\nTasks already visible in the current session may remain on screen during a\nshort interruption, but TaskNotes cannot safely save new changes until mdbase\nis reachable. A failed action is not silently queued for later.\n\nIf the problem continues, open **More** and choose **Change collection** to use\nanother mdbase collection.\n","aliases":[],"toc":[{"level":2,"id":"what-each-status-means","text":"What each status means"},{"level":2,"id":"hosted-collections","text":"Hosted collections"},{"level":2,"id":"collections-on-your-computer","text":"Collections on your computer"},{"level":2,"id":"during-a-connection-problem","text":"During a connection problem"}],"html":"

TaskNotes reads and writes the selected mdbase collection directly. It does not\nkeep a separate offline collection or a queue of changes waiting to sync.

\n

What each status means#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusMeaning
ConnectedTaskNotes can read and change the selected collection
ConnectingTaskNotes is checking the collection connection
Collection unavailableThe hosted service or connected computer cannot be reached
\n

Open More to see the current status and use Refresh now to read the\nlatest collection state.

\n

Hosted collections#

\n

A hosted collection needs a network connection and an available hosted mdbase\nservice. If either is unavailable, TaskNotes cannot open the collection or save\nchanges. Reconnect the collection if its authorization has expired.

\n

Collections on your computer#

\n

A computer collection also needs the computer holding the Markdown to be\nawake, online, and running the mdbase Connect background service. TaskNotes\nreaches it through the end-to-end encrypted relay. If the computer becomes\nunavailable, access returns when the computer and connector return.

\n

During a connection problem#

\n

Tasks already visible in the current session may remain on screen during a\nshort interruption, but TaskNotes cannot safely save new changes until mdbase\nis reachable. A failed action is not silently queued for later.

\n

If the problem continues, open More and choose Change collection to use\nanother mdbase collection.

\n","text":"TaskNotes reads and writes the selected mdbase collection directly. It does not keep a separate offline collection or a queue of changes waiting to sync. What each status means# Status Meaning Connected TaskNotes can read and change the selected collection Connecting TaskNotes is checking the collection connection Collection unavailable The hosted service or connected computer cannot be reached Open More to see the current status and use Refresh now to read the latest collection state. Hosted collections# A hosted collection needs a network connection and an available hosted mdbase service. If either is unavailable, TaskNotes cannot open the collection or save changes. Reconnect the collection if its authorization has expired. Collections on your computer# A computer collection also needs the computer holding the Markdown to be awake, online, and running the mdbase Connect background service. TaskNotes reaches it through the end-to-end encrypted relay. If the computer becomes unavailable, access returns when the computer and connector return. During a connection problem# Tasks already visible in the current session may remain on screen during a short interruption, but TaskNotes cannot safely save new changes until mdbase is reachable. A failed action is not silently queued for later. If the problem continues, open More and choose Change collection to use another mdbase collection."},{"route":"/app/demo/","title":"Interactive demo","description":"Explore the TaskNotes app with disposable sample tasks before connecting a collection.","product":"app","platforms":["web"],"version":"0.1.0","generated":false,"noIndex":false,"hideToc":true,"source":"tasknotes.dev:content/app/demo.md","namespace":"app","relativePath":"demo.md","raw":"---\ntitle: Interactive demo\ndescription: Explore the TaskNotes app with disposable sample tasks before connecting a collection.\nroute: /app/demo/\nproduct: app\nplatforms: [web]\nhide_toc: true\n---\n\n# Interactive demo\n\nExplore the TaskNotes app using a disposable collection of sample tasks. You\ncan complete and edit tasks, use Scratchpad, search, and move between views\nwithout signing in or connecting a collection.\n\nThe demo keeps changes only for the current session. Reloading or resetting it\nstarts again with the original sample data.\n","aliases":[],"toc":[],"html":"

Explore the TaskNotes app using a disposable collection of sample tasks. You\ncan complete and edit tasks, use Scratchpad, search, and move between views\nwithout signing in or connecting a collection.

\n

The demo keeps changes only for the current session. Reloading or resetting it\nstarts again with the original sample data.

\n","text":"Explore the TaskNotes app using a disposable collection of sample tasks. You can complete and edit tasks, use Scratchpad, search, and move between views without signing in or connecting a collection. The demo keeps changes only for the current session. Reloading or resetting it starts again with the original sample data."},{"route":"/app/getting-started/","title":"Get started with the TaskNotes app","description":"Open TaskNotes, connect an mdbase collection, create a task, and find your way around the app.","product":"app","platforms":["web","android","ios"],"version":"0.1.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/app/getting-started.md","namespace":"app","relativePath":"getting-started.md","raw":"---\ntitle: Get started with the TaskNotes app\ndescription: Open TaskNotes, connect an mdbase collection, create a task, and find your way around the app.\nroute: /app/getting-started/\nproduct: app\nplatforms: [web, android, ios]\n---\n\n# Get started with the TaskNotes app\n\nTaskNotes app is currently in beta. Features, availability, and setup steps may\nchange before the stable release.\n\nThe app supports TaskNotes v5 collections based on the mdbase 0.3.0\nspecification.\n\n## 1. Open TaskNotes\n\nUse [app.tasknotes.dev](https://app.tasknotes.dev/) in a supported browser or\ninstall the Android or iOS application when it is available through its store.\nThe web and native applications use the same task interface.\n\n## 2. Choose a collection\n\nTaskNotes opens every collection through mdbase. Choose **Hosted mdbase** for a\ncollection available anywhere with a network connection, or **Connect to a\ncomputer** to use a Markdown collection kept on your own computer through the\nencrypted relay. Read [What is mdbase?](/app/mdbase/) if this is new to you,\nthen [Choose a collection](/app/collections/) to compare the two options.\n\n## 3. Create a task\n\nUse **Add task**, enter a title, and save. Capture understands the collection's\nconfigured status, priority, project, context, and tag values.\n\n## 4. Review the starter views\n\nOpen **Today** for current work, **Upcoming** for scheduled tasks, and **Views**\nfor the complete collection of lists, boards, calendars, and project views.\nNavigation belongs to the current collection and can be reordered from Views.\n\n## 5. Check collection status\n\nOpen **More** to see the collection location, connection state, last refresh,\nnotification access, task model settings, and appearance preference.\n","aliases":[],"toc":[{"level":2,"id":"1-open-tasknotes","text":"1. Open TaskNotes"},{"level":2,"id":"2-choose-a-collection","text":"2. Choose a collection"},{"level":2,"id":"3-create-a-task","text":"3. Create a task"},{"level":2,"id":"4-review-the-starter-views","text":"4. Review the starter views"},{"level":2,"id":"5-check-collection-status","text":"5. Check collection status"}],"html":"

TaskNotes app is currently in beta. Features, availability, and setup steps may\nchange before the stable release.

\n

The app supports TaskNotes v5 collections based on the mdbase 0.3.0\nspecification.

\n

1. Open TaskNotes#

\n

Use app.tasknotes.dev in a supported browser or\ninstall the Android or iOS application when it is available through its store.\nThe web and native applications use the same task interface.

\n

2. Choose a collection#

\n

TaskNotes opens every collection through mdbase. Choose Hosted mdbase for a\ncollection available anywhere with a network connection, or Connect to a\ncomputer to use a Markdown collection kept on your own computer through the\nencrypted relay. Read What is mdbase? if this is new to you,\nthen Choose a collection to compare the two options.

\n

3. Create a task#

\n

Use Add task, enter a title, and save. Capture understands the collection's\nconfigured status, priority, project, context, and tag values.

\n

4. Review the starter views#

\n

Open Today for current work, Upcoming for scheduled tasks, and Views\nfor the complete collection of lists, boards, calendars, and project views.\nNavigation belongs to the current collection and can be reordered from Views.

\n

5. Check collection status#

\n

Open More to see the collection location, connection state, last refresh,\nnotification access, task model settings, and appearance preference.

\n","text":"TaskNotes app is currently in beta. Features, availability, and setup steps may change before the stable release. The app supports TaskNotes v5 collections based on the mdbase 0.3.0 specification. 1. Open TaskNotes# Use app.tasknotes.dev in a supported browser or install the Android or iOS application when it is available through its store. The web and native applications use the same task interface. 2. Choose a collection# TaskNotes opens every collection through mdbase. Choose Hosted mdbase for a collection available anywhere with a network connection, or Connect to a computer to use a Markdown collection kept on your own computer through the encrypted relay. Read What is mdbase? if this is new to you, then Choose a collection to compare the two options. 3. Create a task# Use Add task, enter a title, and save. Capture understands the collection's configured status, priority, project, context, and tag values. 4. Review the starter views# Open Today for current work, Upcoming for scheduled tasks, and Views for the complete collection of lists, boards, calendars, and project views. Navigation belongs to the current collection and can be reordered from Views. 5. Check collection status# Open More to see the collection location, connection state, last refresh, notification access, task model settings, and appearance preference."},{"route":"/app/mdbase/","title":"mdbase and TaskNotes","description":"Understand how TaskNotes uses hosted mdbase or the encrypted relay to reach a collection on your computer.","product":"app","platforms":["web","android","ios"],"version":"0.1.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/app/mdbase.md","namespace":"app","relativePath":"mdbase.md","raw":"---\ntitle: mdbase and TaskNotes\ndescription: Understand how TaskNotes uses hosted mdbase or the encrypted relay to reach a collection on your computer.\nroute: /app/mdbase/\nproduct: app\nplatforms: [web, android, ios]\n---\n\n# mdbase and TaskNotes\n\nmdbase lets TaskNotes work with a portable Markdown collection instead of\nhiding your tasks in a TaskNotes-only database. Every TaskNotes session opens\none mdbase collection: either a collection hosted online or one kept on your\ncomputer and reached through the encrypted relay.\n\n## What is mdbase?\n\nTwo related names appear in TaskNotes:\n\n- **mdbase** is the open collection format and specification. A collection is\n a folder of Markdown files plus a small description of what those files mean.\n- **mdbase Connect** is the access service TaskNotes uses to ask for permission\n and connect to a hosted collection or a collection on your computer.\n\nRead the [mdbase introduction](https://mdbase.dev/) for a visual explanation of\nthe wider ecosystem.\n\n## What it gives TaskNotes\n\nTaskNotes understands what a task looks like inside an mdbase collection. That\ncompatibility is defined by the TaskNotes v5 collection format and its mdbase\n0.3.0 binding. That means TaskNotes can:\n\n- use the same task fields, projects, tags, saved views, and settings on the\n web, Android, and iOS;\n- ask for access to one collection without seeing your other folders; and\n- keep reminders running while TaskNotes is closed when your collection\n supports them.\n\nBehind the scenes, mdbase checks that each change is valid and writes it to the\nmain collection. You still own readable Markdown files rather than a database\nthat only TaskNotes can open.\n\n## How the connection works\n\nThe mdbase collection is the source of truth. TaskNotes reads and writes it\ndirectly and does not keep a separate offline collection, so opening tasks and\nsaving changes require a connection.\n\n| Choice | Where the Markdown lives | What must be available |\n| --- | --- | --- |\n| Hosted mdbase | With the hosted provider | Your device must have a network connection |\n| Connect to your computer | In a folder on your computer | Both devices must be online, and your computer must be running mdbase Connect |\n\n[Choose a collection](/app/collections/) compares the TaskNotes behavior of\nthese options in more detail.\n\n## Use a collection on your computer\n\nInstall the Electron-based mdbase Connect desktop app to make a folder on your\ncomputer available to TaskNotes. It runs a small background service that keeps\nTaskNotes connected to the Markdown folder. The download also includes command\nline tools. The mdbase editor is online and is not part of the desktop app.\n\n1. Open the [mdbase Connect download page](https://mdbase.dev/downloads/) and\n choose the package for macOS, Windows, or Linux.\n2. Install and open mdbase Connect. Follow any platform-specific beta\n installation notes shown on the download page.\n3. Add an existing mdbase folder on the computer, or create a collection.\n4. In TaskNotes, choose **Connect to a computer** and select that collection.\n5. Review the requested actions and approve the connection.\n\nTaskNotes requests and responses travel through an end-to-end encrypted relay.\nThe relay passes the encrypted data along but cannot read your task contents.\nYou do not need to open an inbound port on your router.\n\nThe background service on your computer checks that TaskNotes has permission,\nthen reads or changes the Markdown files. It does not create another hosted or\noffline copy of the collection.\n\n## Do I need to leave my computer on?\n\nYes. Your computer holds the main copy, so it is part of the connection:\n\n- It must be awake, connected to the internet, and running the mdbase Connect\n background service whenever TaskNotes needs remote access.\n- Sleep, shutdown, a network outage, or a stopped connector makes the\n collection unavailable until the computer returns.\n- Reminder delivery also depends on the computer remaining available.\n- You are responsible for the computer's security, disk health, and backups.\n\nThis works well for an always-on desktop or home server. It is less convenient\nfor a laptop that sleeps or travels regularly. Hosted mdbase removes the\nalways-on-computer requirement, but it moves the main copy to a provider you\nmust trust. Both choices require a network connection while you use TaskNotes.\n\nFor more detail about how Connect protects and routes your data, read\n[How mdbase Connect works](https://mdbase.dev/connect/).\n\n## A practical recommendation\n\nChoose **Hosted mdbase** if dependable access across several devices and\nreminder delivery matter most. Choose **Connect to a computer** if keeping the\nmain Markdown folder on your own machine matters more and that machine can\nremain available.\n","aliases":[],"toc":[{"level":2,"id":"what-is-mdbase","text":"What is mdbase?"},{"level":2,"id":"what-it-gives-tasknotes","text":"What it gives TaskNotes"},{"level":2,"id":"how-the-connection-works","text":"How the connection works"},{"level":2,"id":"use-a-collection-on-your-computer","text":"Use a collection on your computer"},{"level":2,"id":"do-i-need-to-leave-my-computer-on","text":"Do I need to leave my computer on?"},{"level":2,"id":"a-practical-recommendation","text":"A practical recommendation"}],"html":"

mdbase lets TaskNotes work with a portable Markdown collection instead of\nhiding your tasks in a TaskNotes-only database. Every TaskNotes session opens\none mdbase collection: either a collection hosted online or one kept on your\ncomputer and reached through the encrypted relay.

\n

What is mdbase?#

\n

Two related names appear in TaskNotes:

\n\n

Read the mdbase introduction for a visual explanation of\nthe wider ecosystem.

\n

What it gives TaskNotes#

\n

TaskNotes understands what a task looks like inside an mdbase collection. That\ncompatibility is defined by the TaskNotes v5 collection format and its mdbase\n0.3.0 binding. That means TaskNotes can:

\n\n

Behind the scenes, mdbase checks that each change is valid and writes it to the\nmain collection. You still own readable Markdown files rather than a database\nthat only TaskNotes can open.

\n

How the connection works#

\n

The mdbase collection is the source of truth. TaskNotes reads and writes it\ndirectly and does not keep a separate offline collection, so opening tasks and\nsaving changes require a connection.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
ChoiceWhere the Markdown livesWhat must be available
Hosted mdbaseWith the hosted providerYour device must have a network connection
Connect to your computerIn a folder on your computerBoth devices must be online, and your computer must be running mdbase Connect
\n

Choose a collection compares the TaskNotes behavior of\nthese options in more detail.

\n

Use a collection on your computer#

\n

Install the Electron-based mdbase Connect desktop app to make a folder on your\ncomputer available to TaskNotes. It runs a small background service that keeps\nTaskNotes connected to the Markdown folder. The download also includes command\nline tools. The mdbase editor is online and is not part of the desktop app.

\n
    \n
  1. Open the mdbase Connect download page and\nchoose the package for macOS, Windows, or Linux.
  2. \n
  3. Install and open mdbase Connect. Follow any platform-specific beta\ninstallation notes shown on the download page.
  4. \n
  5. Add an existing mdbase folder on the computer, or create a collection.
  6. \n
  7. In TaskNotes, choose Connect to a computer and select that collection.
  8. \n
  9. Review the requested actions and approve the connection.
  10. \n
\n

TaskNotes requests and responses travel through an end-to-end encrypted relay.\nThe relay passes the encrypted data along but cannot read your task contents.\nYou do not need to open an inbound port on your router.

\n

The background service on your computer checks that TaskNotes has permission,\nthen reads or changes the Markdown files. It does not create another hosted or\noffline copy of the collection.

\n

Do I need to leave my computer on?#

\n

Yes. Your computer holds the main copy, so it is part of the connection:

\n\n

This works well for an always-on desktop or home server. It is less convenient\nfor a laptop that sleeps or travels regularly. Hosted mdbase removes the\nalways-on-computer requirement, but it moves the main copy to a provider you\nmust trust. Both choices require a network connection while you use TaskNotes.

\n

For more detail about how Connect protects and routes your data, read\nHow mdbase Connect works.

\n

A practical recommendation#

\n

Choose Hosted mdbase if dependable access across several devices and\nreminder delivery matter most. Choose Connect to a computer if keeping the\nmain Markdown folder on your own machine matters more and that machine can\nremain available.

\n","text":"mdbase lets TaskNotes work with a portable Markdown collection instead of hiding your tasks in a TaskNotes-only database. Every TaskNotes session opens one mdbase collection: either a collection hosted online or one kept on your computer and reached through the encrypted relay. What is mdbase?# Two related names appear in TaskNotes: mdbase is the open collection format and specification. A collection is a folder of Markdown files plus a small description of what those files mean. mdbase Connect is the access service TaskNotes uses to ask for permission and connect to a hosted collection or a collection on your computer. Read the mdbase introduction for a visual explanation of the wider ecosystem. What it gives TaskNotes# TaskNotes understands what a task looks like inside an mdbase collection. That compatibility is defined by the TaskNotes v5 collection format and its mdbase 0.3.0 binding. That means TaskNotes can: use the same task fields, projects, tags, saved views, and settings on the web, Android, and iOS; ask for access to one collection without seeing your other folders; and keep reminders running while TaskNotes is closed when your collection supports them. Behind the scenes, mdbase checks that each change is valid and writes it to the main collection. You still own readable Markdown files rather than a database that only TaskNotes can open. How the connection works# The mdbase collection is the source of truth. TaskNotes reads and writes it directly and does not keep a separate offline collection, so opening tasks and saving changes require a connection. Choice Where the Markdown lives What must be available Hosted mdbase With the hosted provider Your device must have a network connection Connect to your computer In a folder on your computer Both devices must be online, and your computer must be running mdbase Connect Choose a collection compares the TaskNotes behavior of these options in more detail. Use a collection on your computer# Install the Electron-based mdbase Connect desktop app to make a folder on your computer available to TaskNotes. It runs a small background service that keeps TaskNotes connected to the Markdown folder. The download also includes command line tools. The mdbase editor is online and is not part of the desktop app. Open the mdbase Connect download page and choose the package for macOS, Windows, or Linux. Install and open mdbase Connect. Follow any platform-specific beta installation notes shown on the download page. Add an existing mdbase folder on the computer, or create a collection. In TaskNotes, choose Connect to a computer and select that collection. Review the requested actions and approve the connection. TaskNotes requests and responses travel through an end-to-end encrypted relay. The relay passes the encrypted data along but cannot read your task contents. You do not need to open an inbound port on your router. The background service on your computer checks that TaskNotes has permission, then reads or changes the Markdown files. It does not create another hosted or offline copy of the collection. Do I need to leave my computer on?# Yes. Your computer holds the main copy, so it is part of the connection: It must be awake, connected to the internet, and running the mdbase Connect background service whenever TaskNotes needs remote access. Sleep, shutdown, a network outage, or a stopped connector makes the collection unavailable until the computer returns. Reminder delivery also depends on the computer remaining available. You are responsible for the computer's security, disk health, and backups. This works well for an always-on desktop or home server. It is less convenient for a laptop that sleeps or travels regularly. Hosted mdbase removes the always-on-computer requirement, but it moves the main copy to a provider you must trust. Both choices require a network connection while you use TaskNotes. For more detail about how Connect protects and routes your data, read How mdbase Connect works. A practical recommendation# Choose Hosted mdbase if dependable access across several devices and reminder delivery matter most. Choose Connect to a computer if keeping the main Markdown folder on your own machine matters more and that machine can remain available."},{"route":"/app/reference/manifest/","title":"App integration manifest","description":"Generated reference for the TaskNotes app's mdbase integration requirements and capabilities.","product":"app","platforms":[],"version":"0.1.0","generated":true,"noIndex":false,"hideToc":false,"source":"tasknotes-app:src/generated/mdbase-app.json","namespace":"app","relativePath":"reference/manifest.md","raw":"---\ntitle: App integration manifest\ndescription: Generated reference for the TaskNotes app's mdbase integration requirements and capabilities.\n---\n\n# App integration manifest\n\nThis page is generated from the integration manifest shipped by TaskNotes app 0.1.0.\n\n| Field | Value |\n| --- | --- |\n| Application ID | `dev.tasknotes.app` |\n| Manifest version | `1` |\n| Homepage | [https://app.tasknotes.dev/](https://app.tasknotes.dev/) |\n| Collection access | `full_collection` |\n\n## Required contracts\n\n- `tasknotes.task` version `0.3.0-rc.3`\n\n## File capabilities\n\n- `list`\n- `read`\n- `add`\n- `replace`\n- `move`\n- `delete`\n\n## Notification criteria\n\n- `task.reminder` listens for `mdbase.runtime.timer.fired` version `1.0.0`.\n","aliases":[],"toc":[{"level":2,"id":"required-contracts","text":"Required contracts"},{"level":2,"id":"file-capabilities","text":"File capabilities"},{"level":2,"id":"notification-criteria","text":"Notification criteria"}],"html":"

This page is generated from the integration manifest shipped by TaskNotes app 0.1.0.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
FieldValue
Application IDdev.tasknotes.app
Manifest version1
Homepagehttps://app.tasknotes.dev/
Collection accessfull_collection
\n

Required contracts#

\n\n

File capabilities#

\n\n

Notification criteria#

\n\n","text":"This page is generated from the integration manifest shipped by TaskNotes app 0.1.0. Field Value Application ID dev.tasknotes.app Manifest version 1 Homepage https://app.tasknotes.dev/ Collection access full_collection Required contracts# tasknotes.task version 0.3.0-rc.3 File capabilities# list read add replace move delete Notification criteria# task.reminder listens for mdbase.runtime.timer.fired version 1.0.0."},{"route":"/app/reminders/","title":"Reminders in the TaskNotes app","description":"Understand reminder data, notification delivery, permissions, and collection requirements.","product":"app","platforms":["web","android","ios"],"version":"0.1.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/app/reminders.md","namespace":"app","relativePath":"reminders.md","raw":"---\ntitle: Reminders in the TaskNotes app\ndescription: Understand reminder data, notification delivery, permissions, and collection requirements.\nroute: /app/reminders/\nproduct: app\nplatforms: [web, android, ios]\n---\n\n# Reminders in the TaskNotes app\n\nTask records can contain relative reminders anchored to scheduled or due dates,\nor absolute reminders fixed to a particular time. Saving reminder data does not\nby itself guarantee notification delivery.\n\n## Delivery by collection\n\n| Collection | Reminder data | Notification delivery |\n| --- | --- | --- |\n| Hosted mdbase | Saved in the collection | Available after opt-in |\n| Computer through the relay | Saved in the collection | Available while the computer and connector remain available |\n\nFor mdbase collections, the authority schedules reminder events so delivery\ndoes not depend on one TaskNotes screen remaining open. Notification payloads\nare content-free; selecting one refreshes authorized collection state in the\napp.\n\n## Turn on reminders\n\nOpen **More**, select **Turn on reminders**, and approve the browser or operating\nsystem permission. Some existing mdbase grants require **Review notification\naccess** before the channel can be enabled.\n\nAn unsupported or insecure browser reports that notification delivery is not\navailable. The reminder definitions remain in the task record.\n","aliases":[],"toc":[{"level":2,"id":"delivery-by-collection","text":"Delivery by collection"},{"level":2,"id":"turn-on-reminders","text":"Turn on reminders"}],"html":"

Task records can contain relative reminders anchored to scheduled or due dates,\nor absolute reminders fixed to a particular time. Saving reminder data does not\nby itself guarantee notification delivery.

\n

Delivery by collection#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
CollectionReminder dataNotification delivery
Hosted mdbaseSaved in the collectionAvailable after opt-in
Computer through the relaySaved in the collectionAvailable while the computer and connector remain available
\n

For mdbase collections, the authority schedules reminder events so delivery\ndoes not depend on one TaskNotes screen remaining open. Notification payloads\nare content-free; selecting one refreshes authorized collection state in the\napp.

\n

Turn on reminders#

\n

Open More, select Turn on reminders, and approve the browser or operating\nsystem permission. Some existing mdbase grants require Review notification\naccess before the channel can be enabled.

\n

An unsupported or insecure browser reports that notification delivery is not\navailable. The reminder definitions remain in the task record.

\n","text":"Task records can contain relative reminders anchored to scheduled or due dates, or absolute reminders fixed to a particular time. Saving reminder data does not by itself guarantee notification delivery. Delivery by collection# Collection Reminder data Notification delivery Hosted mdbase Saved in the collection Available after opt-in Computer through the relay Saved in the collection Available while the computer and connector remain available For mdbase collections, the authority schedules reminder events so delivery does not depend on one TaskNotes screen remaining open. Notification payloads are content-free; selecting one refreshes authorized collection state in the app. Turn on reminders# Open More, select Turn on reminders, and approve the browser or operating system permission. Some existing mdbase grants require Review notification access before the channel can be enabled. An unsupported or insecure browser reports that notification delivery is not available. The reminder definitions remain in the task record."},{"route":"/app/tasks/","title":"Work with tasks","description":"Capture, edit, organize, complete, archive, and search tasks in the TaskNotes app.","product":"app","platforms":["web","android","ios"],"version":"0.1.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/app/tasks.md","namespace":"app","relativePath":"tasks.md","raw":"---\ntitle: Work with tasks\ndescription: Capture, edit, organize, complete, archive, and search tasks in the TaskNotes app.\nroute: /app/tasks/\nproduct: app\nplatforms: [web, android, ios]\n---\n\n# Work with tasks\n\n
\n \"TaskNotes\n
A task opens beside its source view on wider screens.
\n
\n\n## Capture\n\nUse **Add task** from navigation or from a saved view. When a view has safe\ncreation defaults, TaskNotes applies them automatically so the new task remains\nin that view.\n\n## Edit\n\nA task can contain:\n\n- Status and priority\n- Scheduled and due dates\n- Markdown notes\n- Projects, contexts, and tags\n- Dependencies and subtasks\n- Collection-defined custom properties\n- Time estimates and tracked sessions\n- Recurrence and occurrence-note policies\n- Relative and absolute reminder definitions\n\nBackground saves remain ordered if you navigate away while a write is still in\nprogress.\n\n## Complete, archive, and delete\n\nComplete a task from its row or detail screen. Archive retains the record and\nmay move its Markdown file according to collection settings. Delete offers a\nshort undo period before committing the removal.\n\n## Search\n\nSearch runs across the current collection and matches titles, notes, projects,\ncontexts, and tags. Use **Refresh now** under **More** if a change made by\nanother tool does not appear yet.\n","aliases":[],"toc":[{"level":2,"id":"capture","text":"Capture"},{"level":2,"id":"edit","text":"Edit"},{"level":2,"id":"complete-archive-and-delete","text":"Complete, archive, and delete"},{"level":2,"id":"search","text":"Search"}],"html":"
\n \"TaskNotes\n
A task opens beside its source view on wider screens.
\n
\n\n

Capture#

\n

Use Add task from navigation or from a saved view. When a view has safe\ncreation defaults, TaskNotes applies them automatically so the new task remains\nin that view.

\n

Edit#

\n

A task can contain:

\n\n

Background saves remain ordered if you navigate away while a write is still in\nprogress.

\n

Complete, archive, and delete#

\n

Complete a task from its row or detail screen. Archive retains the record and\nmay move its Markdown file according to collection settings. Delete offers a\nshort undo period before committing the removal.

\n

Search#

\n

Search runs across the current collection and matches titles, notes, projects,\ncontexts, and tags. Use Refresh now under More if a change made by\nanother tool does not appear yet.

\n","text":"A task opens beside its source view on wider screens. Capture# Use Add task from navigation or from a saved view. When a view has safe creation defaults, TaskNotes applies them automatically so the new task remains in that view. Edit# A task can contain: Status and priority Scheduled and due dates Markdown notes Projects, contexts, and tags Dependencies and subtasks Collection-defined custom properties Time estimates and tracked sessions Recurrence and occurrence-note policies Relative and absolute reminder definitions Background saves remain ordered if you navigate away while a write is still in progress. Complete, archive, and delete# Complete a task from its row or detail screen. Archive retains the record and may move its Markdown file according to collection settings. Delete offers a short undo period before committing the removal. Search# Search runs across the current collection and matches titles, notes, projects, contexts, and tags. Use Refresh now under More if a change made by another tool does not appear yet."},{"route":"/app/troubleshooting/","title":"Troubleshoot the TaskNotes app","description":"Diagnose mdbase connection, authorization, refresh, and notification problems in the app.","product":"app","platforms":["web","android","ios"],"version":"0.1.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/app/troubleshooting.md","namespace":"app","relativePath":"troubleshooting.md","raw":"---\ntitle: Troubleshoot the TaskNotes app\ndescription: Diagnose mdbase connection, authorization, refresh, and notification problems in the app.\nroute: /app/troubleshooting/\nproduct: app\nplatforms: [web, android, ios]\n---\n\n# Troubleshoot the TaskNotes app\n\nStart by recording the app version, platform, collection type, collection\nstatus shown under **More**, and the smallest sequence that reproduces the\nproblem.\n\n## The collection is unavailable\n\nFor a hosted collection, confirm that the device is online and try **Reconnect\nthis collection**. For a computer collection, also confirm that the computer\nholding the Markdown is awake, online, and running mdbase Connect.\n\n## An authorization error appears\n\nUse the reconnect action for the current collection and review the access that\nmdbase requests. If you no longer want to use that collection, open **More** and\nchoose **Change collection**.\n\n## A change did not save\n\nTaskNotes writes directly to mdbase and does not queue failed changes for later.\nRestore the connection, then retry the action. Capture and editing screens keep\nrecoverable input visible when they can do so safely.\n\n## A change from another tool is missing\n\nOpen **More** and choose **Refresh now**. If the record still does not appear,\nconfirm that the other tool wrote to the same mdbase collection and that the\nrecord uses a compatible TaskNotes task definition.\n\n## Notifications do not arrive\n\nConfirm that the current collection is an mdbase collection, reminders are\nenabled in **More**, the browser or operating system permission is granted, and\nthe task contains a valid future reminder. For a computer collection, the\ncomputer and mdbase Connect must remain available.\n","aliases":[],"toc":[{"level":2,"id":"the-collection-is-unavailable","text":"The collection is unavailable"},{"level":2,"id":"an-authorization-error-appears","text":"An authorization error appears"},{"level":2,"id":"a-change-did-not-save","text":"A change did not save"},{"level":2,"id":"a-change-from-another-tool-is-missing","text":"A change from another tool is missing"},{"level":2,"id":"notifications-do-not-arrive","text":"Notifications do not arrive"}],"html":"

Start by recording the app version, platform, collection type, collection\nstatus shown under More, and the smallest sequence that reproduces the\nproblem.

\n

The collection is unavailable#

\n

For a hosted collection, confirm that the device is online and try Reconnect\nthis collection. For a computer collection, also confirm that the computer\nholding the Markdown is awake, online, and running mdbase Connect.

\n

An authorization error appears#

\n

Use the reconnect action for the current collection and review the access that\nmdbase requests. If you no longer want to use that collection, open More and\nchoose Change collection.

\n

A change did not save#

\n

TaskNotes writes directly to mdbase and does not queue failed changes for later.\nRestore the connection, then retry the action. Capture and editing screens keep\nrecoverable input visible when they can do so safely.

\n

A change from another tool is missing#

\n

Open More and choose Refresh now. If the record still does not appear,\nconfirm that the other tool wrote to the same mdbase collection and that the\nrecord uses a compatible TaskNotes task definition.

\n

Notifications do not arrive#

\n

Confirm that the current collection is an mdbase collection, reminders are\nenabled in More, the browser or operating system permission is granted, and\nthe task contains a valid future reminder. For a computer collection, the\ncomputer and mdbase Connect must remain available.

\n","text":"Start by recording the app version, platform, collection type, collection status shown under More, and the smallest sequence that reproduces the problem. The collection is unavailable# For a hosted collection, confirm that the device is online and try Reconnect this collection. For a computer collection, also confirm that the computer holding the Markdown is awake, online, and running mdbase Connect. An authorization error appears# Use the reconnect action for the current collection and review the access that mdbase requests. If you no longer want to use that collection, open More and choose Change collection. A change did not save# TaskNotes writes directly to mdbase and does not queue failed changes for later. Restore the connection, then retry the action. Capture and editing screens keep recoverable input visible when they can do so safely. A change from another tool is missing# Open More and choose Refresh now. If the record still does not appear, confirm that the other tool wrote to the same mdbase collection and that the record uses a compatible TaskNotes task definition. Notifications do not arrive# Confirm that the current collection is an mdbase collection, reminders are enabled in More, the browser or operating system permission is granted, and the task contains a valid future reminder. For a computer collection, the computer and mdbase Connect must remain available."},{"route":"/app/views/","title":"Views and navigation","description":"Use and arrange lists, boards, calendars, projects, and saved views in the TaskNotes app.","product":"app","platforms":["web","android","ios"],"version":"0.1.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/app/views.md","namespace":"app","relativePath":"views.md","raw":"---\ntitle: Views and navigation\ndescription: Use and arrange lists, boards, calendars, projects, and saved views in the TaskNotes app.\nroute: /app/views/\nproduct: app\nplatforms: [web, android, ios]\n---\n\n# Views and navigation\n\nViews are saved ways of selecting, sorting, grouping, and presenting records in\na collection. They travel with the collection; the set pinned to navigation is\na preference on each device.\n\n
\n \"TaskNotes\n
The Views manager controls navigation order and saved view definitions.
\n
\n\n## Starter views\n\nTaskNotes creates managed starter views such as Today, Upcoming, Calendar, and\nProjects. They use the same saved-view catalog as user-created views while\nproviding focused presentations for common work.\n\n## Presentations\n\n- **Task list** supports grouping, visible properties, section moves, and manual ordering.\n- **Kanban** groups tasks into columns and can update the grouped property when a task moves.\n- **Calendar** shows task dates in month, week, day, and list layouts.\n- **Mini calendar** combines a month picker with tasks for the selected day.\n- **Projects** finds project records referenced by active tasks.\n\n## Navigation\n\nOpen **Views** to add or remove a view from navigation and to change its order.\nThe first navigation item is the collection's home. Mobile displays the first\nthree views directly and keeps the rest in the Views destination.\n\n## Create and edit views\n\nThe view editor controls the name, presentation, query, grouping, sort order,\nvisible properties, and safe defaults for tasks created from the view. View\ndocuments remain ordinary collection resources rather than being stored only\ninside the TaskNotes app.\n","aliases":[],"toc":[{"level":2,"id":"starter-views","text":"Starter views"},{"level":2,"id":"presentations","text":"Presentations"},{"level":2,"id":"navigation","text":"Navigation"},{"level":2,"id":"create-and-edit-views","text":"Create and edit views"}],"html":"

Views are saved ways of selecting, sorting, grouping, and presenting records in\na collection. They travel with the collection; the set pinned to navigation is\na preference on each device.

\n
\n \"TaskNotes\n
The Views manager controls navigation order and saved view definitions.
\n
\n\n

Starter views#

\n

TaskNotes creates managed starter views such as Today, Upcoming, Calendar, and\nProjects. They use the same saved-view catalog as user-created views while\nproviding focused presentations for common work.

\n

Presentations#

\n\n

Navigation#

\n

Open Views to add or remove a view from navigation and to change its order.\nThe first navigation item is the collection's home. Mobile displays the first\nthree views directly and keeps the rest in the Views destination.

\n

Create and edit views#

\n

The view editor controls the name, presentation, query, grouping, sort order,\nvisible properties, and safe defaults for tasks created from the view. View\ndocuments remain ordinary collection resources rather than being stored only\ninside the TaskNotes app.

\n","text":"Views are saved ways of selecting, sorting, grouping, and presenting records in a collection. They travel with the collection; the set pinned to navigation is a preference on each device. The Views manager controls navigation order and saved view definitions. Starter views# TaskNotes creates managed starter views such as Today, Upcoming, Calendar, and Projects. They use the same saved-view catalog as user-created views while providing focused presentations for common work. Presentations# Task list supports grouping, visible properties, section moves, and manual ordering. Kanban groups tasks into columns and can update the grouped property when a task moves. Calendar shows task dates in month, week, day, and list layouts. Mini calendar combines a month picker with tasks for the selected day. Projects finds project records referenced by active tasks. Navigation# Open Views to add or remove a view from navigation and to change its order. The first navigation item is the collection's home. Mobile displays the first three views directly and keeps the rest in the Views destination. Create and edit views# The view editor controls the name, presentation, query, grouping, sort order, visible properties, and safe defaults for tasks created from the view. View documents remain ordinary collection resources rather than being stored only inside the TaskNotes app."},{"route":"/concepts/task-records/","title":"Portable task records","description":"The Markdown records, collection configuration, and task concepts shared by TaskNotes clients.","product":"shared","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/shared/task-records.md","namespace":"shared","relativePath":"task-records.md","raw":"---\ntitle: Portable task records\ndescription: The Markdown records, collection configuration, and task concepts shared by TaskNotes clients.\nroute: /concepts/task-records/\nproduct: shared\n---\n\n# Portable task records\n\nA TaskNotes task is an ordinary Markdown record with structured properties.\nThose properties describe the task; the Markdown body remains available for\nnotes, checklists, links, and supporting detail.\n\n## Collections\n\nA collection is a group of records plus the configuration that explains how to\ninterpret them. The configuration defines field names, statuses, priorities,\ncustom properties, record locations, and saved views.\n\nThe TaskNotes app uses **collection** throughout. The Obsidian plugin usually\ndescribes the containing folder as a **vault** and presents saved views through\nObsidian Bases.\n\n## Source of truth\n\nWhere the authoritative copy lives depends on the client and connection:\n\n| Client and collection | Source of truth | Availability |\n| --- | --- | --- |\n| TaskNotes app · hosted mdbase | Hosted collection | Requires a network connection |\n| TaskNotes app · computer through relay | Collection on that computer | Requires the network, computer, and connector |\n| Obsidian vault | Markdown files in the vault | Controlled by Obsidian and your sync choice |\n\n## Portability and compatibility\n\nPortable does not mean every client exposes every feature. Inline task widgets,\nObsidian commands, external calendar integrations, and companion plugins belong\nto the Obsidian client. mdbase collection access and background reminder\ndelivery belong to the TaskNotes app.\n\nUse the client-specific guide for interface instructions and the\n[specification](/developers/specification/) for normative data semantics.\n","aliases":[],"toc":[{"level":2,"id":"collections","text":"Collections"},{"level":2,"id":"source-of-truth","text":"Source of truth"},{"level":2,"id":"portability-and-compatibility","text":"Portability and compatibility"}],"html":"

A TaskNotes task is an ordinary Markdown record with structured properties.\nThose properties describe the task; the Markdown body remains available for\nnotes, checklists, links, and supporting detail.

\n

Collections#

\n

A collection is a group of records plus the configuration that explains how to\ninterpret them. The configuration defines field names, statuses, priorities,\ncustom properties, record locations, and saved views.

\n

The TaskNotes app uses collection throughout. The Obsidian plugin usually\ndescribes the containing folder as a vault and presents saved views through\nObsidian Bases.

\n

Source of truth#

\n

Where the authoritative copy lives depends on the client and connection:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Client and collectionSource of truthAvailability
TaskNotes app · hosted mdbaseHosted collectionRequires a network connection
TaskNotes app · computer through relayCollection on that computerRequires the network, computer, and connector
Obsidian vaultMarkdown files in the vaultControlled by Obsidian and your sync choice
\n

Portability and compatibility#

\n

Portable does not mean every client exposes every feature. Inline task widgets,\nObsidian commands, external calendar integrations, and companion plugins belong\nto the Obsidian client. mdbase collection access and background reminder\ndelivery belong to the TaskNotes app.

\n

Use the client-specific guide for interface instructions and the\nspecification for normative data semantics.

\n","text":"A TaskNotes task is an ordinary Markdown record with structured properties. Those properties describe the task; the Markdown body remains available for notes, checklists, links, and supporting detail. Collections# A collection is a group of records plus the configuration that explains how to interpret them. The configuration defines field names, statuses, priorities, custom properties, record locations, and saved views. The TaskNotes app uses collection throughout. The Obsidian plugin usually describes the containing folder as a vault and presents saved views through Obsidian Bases. Source of truth# Where the authoritative copy lives depends on the client and connection: Client and collection Source of truth Availability TaskNotes app · hosted mdbase Hosted collection Requires a network connection TaskNotes app · computer through relay Collection on that computer Requires the network, computer, and connector Obsidian vault Markdown files in the vault Controlled by Obsidian and your sync choice Portability and compatibility# Portable does not mean every client exposes every feature. Inline task widgets, Obsidian commands, external calendar integrations, and companion plugins belong to the Obsidian client. mdbase collection access and background reminder delivery belong to the TaskNotes app. Use the client-specific guide for interface instructions and the specification for normative data semantics."},{"route":"/developers/specification/","title":"0. Overview","description":"TaskNotes is an Obsidian plugin that stores tasks as individual markdown files with YAML frontmatter in a user's vault. Each task is a first-class file: readable and editabl...","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:00-overview.md","namespace":"specification","relativePath":"00-overview.md","raw":"# 0. Overview\n\n## 0.0 About tasknotes\n\n**TaskNotes** is an [Obsidian](https://obsidian.md) plugin that stores tasks as individual markdown files with YAML frontmatter in a user's vault. Each task is a first-class file: readable and editable with any text editor, version-controllable, and searchable without special tooling.\n\nA minimal task file looks like this:\n\n```markdown\n---\ntitle: Buy groceries\nstatus: open\npriority: normal\ndue: 2026-02-21\ntags: [task]\ndateCreated: 2026-02-20T11:15:00Z\ndateModified: 2026-02-20T11:15:00Z\n---\n\nBuy fruit and cleaning supplies.\n```\n\nTasks are identified within the vault by a configurable detection method — by default, by the presence of a specific tag (e.g. `#task` in body or frontmatter). The plugin stores its configuration in `.obsidian/plugins/tasknotes/data.json` within the vault root.\n\n**This specification** was derived from the behavior of the tasknotes plugin and is intended to serve as a stable, testable contract for:\n\n- CLI tools and scripts that process task files outside Obsidian,\n- any application that wants to interoperate with a tasknotes vault.\n\nThe spec is deliberately language-agnostic. It does not require any particular runtime, and the executable conformance suite (in `conformance/`) can be driven by an adapter written in any language.\n\nThe tasknotes plugin is the primary reference for how this spec was derived, but **the specification is normative** — where the spec and the plugin behavior differ, the spec defines the intended behavior. Known deviations are disclosed via conformance claims (§7.5).\n\n## 0.1 Status and authority\n\nThis document is part of `tasknotes-spec` version `0.3.0-rc.3`.\n\nThis specification is normative for implementations that claim conformance.\nNo single implementation is normative; implementations are expected to conform to the specification.\n\n## 0.2 Motivation\n\nTaskNotes-style systems store tasks as markdown files with YAML frontmatter. This model has practical advantages:\n\n- Task records are plain files that can be inspected and edited without proprietary tooling.\n- Data remains portable across environments.\n- Files are suitable for version control and collaboration workflows.\n\nAs soon as more than one tool reads and writes the same task files, implicit assumptions become an interoperability risk. In practice, these risks appear in three areas:\n\n1. Field semantics and naming drift.\n2. Date and timezone interpretation differences.\n3. Recurring-task state transitions that are handled differently by different clients.\n\nWhen these rules are not explicit, users can get inconsistent results from equivalent operations. A shared specification reduces that risk by making behavior testable and versioned.\n\n## 0.3 Objectives\n\nThis specification defines a stable contract for:\n\n- Representing task records in markdown frontmatter.\n- Mapping storage keys to canonical semantic roles.\n- Defining effective collection configuration via provider model (for example `tasknotes.yaml` and/or TaskNotes `data.json`).\n- Interpreting date and datetime values consistently.\n- Applying recurrence, per-instance completion/skip behavior, and optional materialized occurrence notes.\n- Managing time tracking sessions and `time_entries` lifecycle behavior.\n- Parsing and resolving links consistently across task fields.\n- Defining dependency and reminder behavior.\n- Optionally applying deterministic create-time templating behavior.\n- Executing write operations with predictable side-effects.\n- Validating task records and reporting issues.\n\n## 0.4 Non-objectives\n\nThis specification does not standardize:\n\n- UI layout, styling, command palettes, or interaction design.\n- Internal caching architecture or rendering pipelines.\n- Transport protocols (HTTP, IPC, etc.) except where they affect persisted task semantics.\n- Rich template-language features beyond the portable create-time templating contract in §5/§7/§9.\n\n## 0.5 Scope\n\nThis specification is standalone. It does not require conformance to any other specification.\n\nImplementations MAY internally reuse other libraries or specifications, but conformance claims under `tasknotes-spec` are evaluated only against this document.\nTemplating is optional and profile-gated; implementations that do not claim the templating profile remain conformant without template support.\nReferences to TaskNotes plugin behavior, Obsidian behavior, or external specifications are informative context only unless this specification explicitly marks a requirement as normative.\n\n## 0.6 Design principles\n\n### 0.6.1 File-first persistence\n\nTask state is represented in user-visible files. Derived indexes and caches are non-canonical.\n\n### 0.6.2 Deterministic semantics\n\nEquivalent inputs MUST produce equivalent persisted outputs under the same configuration and active runtime timezone.\n\n### 0.6.3 Explicit mapping\n\nSemantic roles are canonical. Storage key names are configurable and therefore must be mapped explicitly.\n\n### 0.6.4 Backward evolution\n\nThe specification supports migration from legacy keys and historical behaviors through explicit compatibility rules.\n\n## 0.7 Conformance\n\nConformance is profile-based (see §7). A minimal implementation can conform to a narrow profile while remaining interoperable for core operations.\n\n## 0.8 Normative language\n\nThe key words **MUST**, **MUST NOT**, **SHOULD**, **SHOULD NOT**, and **MAY** are to be interpreted as described in RFC 2119.\n\n## 0.9 Example collection\n\nA default tasknotes vault looks like this:\n\n```text\nMyVault/\n├── TaskNotes/\n│ ├── Tasks/\n│ │ ├── buy-groceries.md ← task file (title-derived filename by default)\n│ │ └── weekly-review.md\n│ └── Archive/ ← archive folder (if moveArchivedTasks=true)\n├── .obsidian/\n│ └── plugins/\n│ └── tasknotes/\n│ └── data.json ← plugin settings (primary config provider)\n└── tasknotes.yaml ← optional spec-level config (secondary provider)\n```\n\nTask files are identified by the `#task` tag by default (configurable). The full default collection state is described in §9.21.\n\nConfiguration provider semantics and effective configuration rules are defined in §9. An implementation MAY use either provider, both, or additional providers, based on its documented precedence policy.\n\nA task file example (using default field mapping):\n\n```markdown\n---\ntitle: Buy groceries\nstatus: open\npriority: normal\ndue: 2026-02-21\ntags: [task, errands]\ncontexts: [\"town\"]\ndateCreated: 2026-02-20T11:15:00Z\ndateModified: 2026-02-20T11:15:00Z\n---\n\nBuy fruit and cleaning supplies.\n```\n\n## 0.10 Versioning policy\n\nThis specification uses semantic versioning.\n\n- A **major** version introduces breaking semantic changes.\n- A **minor** version introduces additive behavior or optional features.\n- A **patch** version clarifies wording or fixes non-breaking defects.\n\nImplementations MUST reject unsupported major versions when strict mode is enabled.\n\n## 0.11 Change governance\n\nSpecification changes SHOULD be accompanied by:\n\n- a motivation statement,\n- precise normative edits,\n- migration notes when behavior changes,\n- updated examples.\n","aliases":["/spec/00-overview/"],"toc":[{"level":2,"id":"00-about-tasknotes","text":"0.0 About tasknotes"},{"level":2,"id":"01-status-and-authority","text":"0.1 Status and authority"},{"level":2,"id":"02-motivation","text":"0.2 Motivation"},{"level":2,"id":"03-objectives","text":"0.3 Objectives"},{"level":2,"id":"04-non-objectives","text":"0.4 Non-objectives"},{"level":2,"id":"05-scope","text":"0.5 Scope"},{"level":2,"id":"06-design-principles","text":"0.6 Design principles"},{"level":3,"id":"061-file-first-persistence","text":"0.6.1 File-first persistence"},{"level":3,"id":"062-deterministic-semantics","text":"0.6.2 Deterministic semantics"},{"level":3,"id":"063-explicit-mapping","text":"0.6.3 Explicit mapping"},{"level":3,"id":"064-backward-evolution","text":"0.6.4 Backward evolution"},{"level":2,"id":"07-conformance","text":"0.7 Conformance"},{"level":2,"id":"08-normative-language","text":"0.8 Normative language"},{"level":2,"id":"09-example-collection","text":"0.9 Example collection"},{"level":2,"id":"010-versioning-policy","text":"0.10 Versioning policy"},{"level":2,"id":"011-change-governance","text":"0.11 Change governance"}],"html":"

0.0 About tasknotes#

\n

TaskNotes is an Obsidian plugin that stores tasks as individual markdown files with YAML frontmatter in a user's vault. Each task is a first-class file: readable and editable with any text editor, version-controllable, and searchable without special tooling.

\n

A minimal task file looks like this:

\n
---\ntitle: Buy groceries\nstatus: open\npriority: normal\ndue: 2026-02-21\ntags: [task]\ndateCreated: 2026-02-20T11:15:00Z\ndateModified: 2026-02-20T11:15:00Z\n---\n\nBuy fruit and cleaning supplies.\n

Tasks are identified within the vault by a configurable detection method — by default, by the presence of a specific tag (e.g. #task in body or frontmatter). The plugin stores its configuration in .obsidian/plugins/tasknotes/data.json within the vault root.

\n

This specification was derived from the behavior of the tasknotes plugin and is intended to serve as a stable, testable contract for:

\n\n

The spec is deliberately language-agnostic. It does not require any particular runtime, and the executable conformance suite (in conformance/) can be driven by an adapter written in any language.

\n

The tasknotes plugin is the primary reference for how this spec was derived, but the specification is normative — where the spec and the plugin behavior differ, the spec defines the intended behavior. Known deviations are disclosed via conformance claims (§7.5).

\n

0.1 Status and authority#

\n

This document is part of tasknotes-spec version 0.3.0-rc.3.

\n

This specification is normative for implementations that claim conformance.\nNo single implementation is normative; implementations are expected to conform to the specification.

\n

0.2 Motivation#

\n

TaskNotes-style systems store tasks as markdown files with YAML frontmatter. This model has practical advantages:

\n\n

As soon as more than one tool reads and writes the same task files, implicit assumptions become an interoperability risk. In practice, these risks appear in three areas:

\n
    \n
  1. Field semantics and naming drift.
  2. \n
  3. Date and timezone interpretation differences.
  4. \n
  5. Recurring-task state transitions that are handled differently by different clients.
  6. \n
\n

When these rules are not explicit, users can get inconsistent results from equivalent operations. A shared specification reduces that risk by making behavior testable and versioned.

\n

0.3 Objectives#

\n

This specification defines a stable contract for:

\n\n

0.4 Non-objectives#

\n

This specification does not standardize:

\n\n

0.5 Scope#

\n

This specification is standalone. It does not require conformance to any other specification.

\n

Implementations MAY internally reuse other libraries or specifications, but conformance claims under tasknotes-spec are evaluated only against this document.\nTemplating is optional and profile-gated; implementations that do not claim the templating profile remain conformant without template support.\nReferences to TaskNotes plugin behavior, Obsidian behavior, or external specifications are informative context only unless this specification explicitly marks a requirement as normative.

\n

0.6 Design principles#

\n

0.6.1 File-first persistence#

\n

Task state is represented in user-visible files. Derived indexes and caches are non-canonical.

\n

0.6.2 Deterministic semantics#

\n

Equivalent inputs MUST produce equivalent persisted outputs under the same configuration and active runtime timezone.

\n

0.6.3 Explicit mapping#

\n

Semantic roles are canonical. Storage key names are configurable and therefore must be mapped explicitly.

\n

0.6.4 Backward evolution#

\n

The specification supports migration from legacy keys and historical behaviors through explicit compatibility rules.

\n

0.7 Conformance#

\n

Conformance is profile-based (see §7). A minimal implementation can conform to a narrow profile while remaining interoperable for core operations.

\n

0.8 Normative language#

\n

The key words MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY are to be interpreted as described in RFC 2119.

\n

0.9 Example collection#

\n

A default tasknotes vault looks like this:

\n
MyVault/\n├── TaskNotes/\n│   ├── Tasks/\n│   │   ├── buy-groceries.md    ← task file (title-derived filename by default)\n│   │   └── weekly-review.md\n│   └── Archive/                ← archive folder (if moveArchivedTasks=true)\n├── .obsidian/\n│   └── plugins/\n│       └── tasknotes/\n│           └── data.json       ← plugin settings (primary config provider)\n└── tasknotes.yaml              ← optional spec-level config (secondary provider)\n

Task files are identified by the #task tag by default (configurable). The full default collection state is described in §9.21.

\n

Configuration provider semantics and effective configuration rules are defined in §9. An implementation MAY use either provider, both, or additional providers, based on its documented precedence policy.

\n

A task file example (using default field mapping):

\n
---\ntitle: Buy groceries\nstatus: open\npriority: normal\ndue: 2026-02-21\ntags: [task, errands]\ncontexts: ["town"]\ndateCreated: 2026-02-20T11:15:00Z\ndateModified: 2026-02-20T11:15:00Z\n---\n\nBuy fruit and cleaning supplies.\n

0.10 Versioning policy#

\n

This specification uses semantic versioning.

\n\n

Implementations MUST reject unsupported major versions when strict mode is enabled.

\n

0.11 Change governance#

\n

Specification changes SHOULD be accompanied by:

\n\n","text":"0.0 About tasknotes# TaskNotes is an Obsidian plugin that stores tasks as individual markdown files with YAML frontmatter in a user's vault. Each task is a first-class file: readable and editable with any text editor, version-controllable, and searchable without special tooling. A minimal task file looks like this: --- title: Buy groceries status: open priority: normal due: 2026-02-21 tags: [task] dateCreated: 2026-02-20T11:15:00Z dateModified: 2026-02-20T11:15:00Z --- Buy fruit and cleaning supplies. Tasks are identified within the vault by a configurable detection method — by default, by the presence of a specific tag (e.g. #task in body or frontmatter). The plugin stores its configuration in .obsidian/plugins/tasknotes/data.json within the vault root. This specification was derived from the behavior of the tasknotes plugin and is intended to serve as a stable, testable contract for: CLI tools and scripts that process task files outside Obsidian, any application that wants to interoperate with a tasknotes vault. The spec is deliberately language-agnostic. It does not require any particular runtime, and the executable conformance suite (in conformance/) can be driven by an adapter written in any language. The tasknotes plugin is the primary reference for how this spec was derived, but the specification is normative — where the spec and the plugin behavior differ, the spec defines the intended behavior. Known deviations are disclosed via conformance claims (§7.5). 0.1 Status and authority# This document is part of tasknotes-spec version 0.3.0-rc.3. This specification is normative for implementations that claim conformance. No single implementation is normative; implementations are expected to conform to the specification. 0.2 Motivation# TaskNotes-style systems store tasks as markdown files with YAML frontmatter. This model has practical advantages: Task records are plain files that can be inspected and edited without proprietary tooling. Data remains portable across environments. Files are suitable for version control and collaboration workflows. As soon as more than one tool reads and writes the same task files, implicit assumptions become an interoperability risk. In practice, these risks appear in three areas: Field semantics and naming drift. Date and timezone interpretation differences. Recurring-task state transitions that are handled differently by different clients. When these rules are not explicit, users can get inconsistent results from equivalent operations. A shared specification reduces that risk by making behavior testable and versioned. 0.3 Objectives# This specification defines a stable contract for: Representing task records in markdown frontmatter. Mapping storage keys to canonical semantic roles. Defining effective collection configuration via provider model (for example tasknotes.yaml and/or TaskNotes data.json). Interpreting date and datetime values consistently. Applying recurrence, per-instance completion/skip behavior, and optional materialized occurrence notes. Managing time tracking sessions and time_entries lifecycle behavior. Parsing and resolving links consistently across task fields. Defining dependency and reminder behavior. Optionally applying deterministic create-time templating behavior. Executing write operations with predictable side-effects. Validating task records and reporting issues. 0.4 Non-objectives# This specification does not standardize: UI layout, styling, command palettes, or interaction design. Internal caching architecture or rendering pipelines. Transport protocols (HTTP, IPC, etc.) except where they affect persisted task semantics. Rich template-language features beyond the portable create-time templating contract in §5/§7/§9. 0.5 Scope# This specification is standalone. It does not require conformance to any other specification. Implementations MAY internally reuse other libraries or specifications, but conformance claims under tasknotes-spec are evaluated only against this document. Templating is optional and profile-gated; implementations that do not claim the templating profile remain conformant without template support. References to TaskNotes plugin behavior, Obsidian behavior, or external specifications are informative context only unless this specification explicitly marks a requirement as normative. 0.6 Design principles# 0.6.1 File-first persistence# Task state is represented in user-visible files. Derived indexes and caches are non-canonical. 0.6.2 Deterministic semantics# Equivalent inputs MUST produce equivalent persisted outputs under the same configuration and active runtime timezone. 0.6.3 Explicit mapping# Semantic roles are canonical. Storage key names are configurable and therefore must be mapped explicitly. 0.6.4 Backward evolution# The specification supports migration from legacy keys and historical behaviors through explicit compatibility rules. 0.7 Conformance# Conformance is profile-based (see §7). A minimal implementation can conform to a narrow profile while remaining interoperable for core operations. 0.8 Normative language# The key words MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY are to be interpreted as described in RFC 2119. 0.9 Example collection# A default tasknotes vault looks like this: MyVault/ ├── TaskNotes/ │ ├── Tasks/ │ │ ├── buy-groceries.md ← task file (title-derived filename by default) │ │ └── weekly-review.md │ └── Archive/ ← archive folder (if moveArchivedTasks=true) ├── .obsidian/ │ └── plugins/ │ └── tasknotes/ │ └── data.json ← plugin settings (primary config provider) └── tasknotes.yaml ← optional spec-level config (secondary provider) Task files are identified by the #task tag by default (configurable). The full default collection state is described in §9.21. Configuration provider semantics and effective configuration rules are defined in §9. An implementation MAY use either provider, both, or additional providers, based on its documented precedence policy. A task file example (using default field mapping): --- title: Buy groceries status: open priority: normal due: 2026-02-21 tags: [task, errands] contexts: [\"town\"] dateCreated: 2026-02-20T11:15:00Z dateModified: 2026-02-20T11:15:00Z --- Buy fruit and cleaning supplies. 0.10 Versioning policy# This specification uses semantic versioning. A major version introduces breaking semantic changes. A minor version introduces additive behavior or optional features. A patch version clarifies wording or fixes non-breaking defects. Implementations MUST reject unsupported major versions when strict mode is enabled. 0.11 Change governance# Specification changes SHOULD be accompanied by: a motivation statement, precise normative edits, migration notes when behavior changes, updated examples."},{"route":"/developers/specification/01-terminology/","title":"1. Terminology","description":"This section defines terms used normatively in this specification.","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:01-terminology.md","namespace":"specification","relativePath":"01-terminology.md","raw":"# 1. Terminology\n\nThis section defines terms used normatively in this specification.\n\n## 1.1 Collection\n\nA **collection** is a filesystem scope within which task files are discovered and managed under a single TaskNotes configuration.\n\n## 1.2 Task file\n\nA **task file** is a markdown file identified as a task record by collection rules.\n\n## 1.3 Frontmatter\n\n**Frontmatter** is the YAML block at the start of a markdown file delimited by `---` markers.\n\n## 1.4 Task record\n\nA **task record** is the semantic task object obtained from parsing a task file frontmatter (plus optional derived metadata).\n\n## 1.5 Semantic role\n\nA **semantic role** is a canonical meaning defined by this specification, independent of storage key names.\n\nExamples: `title`, `status`, `date_created`, `complete_instances`.\n\n## 1.6 Storage key\n\nA **storage key** is the YAML property name used in frontmatter.\n\nExamples: `dateCreated`, `date_created`, `completedDate`.\n\n## 1.7 Field mapping\n\n**Field mapping** is the configuration that maps semantic roles to storage keys for reads and writes.\n\n## 1.8 Alias\n\nAn **alias** is a non-canonical storage key accepted for compatibility during reads.\n\n## 1.9 Canonical write key\n\nThe **canonical write key** is the configured storage key that conforming writers use for persisted output.\n\n## 1.10 Date value\n\nA **date value** represents a calendar day with no time-of-day and no timezone.\n\nCanonical form: `YYYY-MM-DD`.\n\n## 1.11 Datetime value\n\nA **datetime value** represents an instant in time.\n\nCanonical form: ISO 8601 UTC with trailing `Z`.\n\n## 1.12 Target date\n\nA **target date** is the calendar date to which a recurrence instance operation applies (for example complete instance on 2026-02-20).\n\n## 1.13 Recurrence rule\n\nA **recurrence rule** is a tasknotes recurrence string stored in the recurrence semantic role.\nIt uses RFC 5545 RRULE-style parameters inside a single semicolon-delimited field value and MAY include an explicit inline `DTSTART` prefix segment as defined in §4.3.\n\n## 1.14 Recurrence anchor\n\n**Recurrence anchor** defines how next-instance progression is computed. Allowed values:\n\n- `scheduled`\n- `completion`\n\n## 1.15 Complete instances\n\n**Complete instances** is the set/list of target dates marked completed for a recurring task.\n\n## 1.16 Skipped instances\n\n**Skipped instances** is the set/list of target dates marked skipped for a recurring task.\n\n## 1.17 Materialized occurrence note\n\nA **materialized occurrence note** is a task file created for one target date of a recurring parent task.\nIt stores user-authored per-occurrence content and, when supported by the implementation, owns the authoritative task state for that occurrence date.\n\n## 1.18 Recurrence parent\n\nA **recurrence parent** is the recurring task record referenced by a materialized occurrence note.\nThe reference is stored in semantic role `recurrence_parent` and resolved as a link according to §11.\n\n## 1.19 Occurrence materialization\n\n**Occurrence materialization** is the creation and reconciliation of materialized occurrence notes from a recurring parent task according to §4.18 and §5.20.\n\n## 1.20 Effective status\n\n**Effective status** is the status presented for a given date context after applying recurrence instance state.\n\n## 1.21 Completed-status list\n\nThe **completed-status list** is the configured ordered list of status values treated as completed for non-recurring completion semantics.\nWhen a single value must be chosen deterministically, the first list entry is used unless explicit operation input overrides it.\n\n## 1.22 Idempotent operation\n\nAn operation is **idempotent** if applying it multiple times with the same input produces the same persisted state as applying it once.\n\n## 1.23 Unknown field\n\nAn **unknown field** is a frontmatter property not mapped to a semantic role in current configuration.\n\n## 1.24 Validation issue\n\nA **validation issue** is a structured report containing at least:\n\n- machine-readable code,\n- severity,\n- optional path/field context,\n- human-readable message.\n\n## 1.25 Strict validation mode\n\n**Strict validation mode** is a mode where invalid required semantics are treated as hard errors and write operations fail.\n\n## 1.26 Legacy compatibility mode\n\n**Legacy compatibility mode** is a mode where specific historical behaviors or aliases are accepted for migration but are not canonical for new writes.\n\n## 1.27 Configuration provider\n\nA **configuration provider** is an adapter that loads configuration from a source (for example `tasknotes.yaml` or `.obsidian/plugins/tasknotes/data.json`) and normalizes it to the schema in §9.\n\n## 1.28 Effective configuration\n\nThe **effective configuration** is the final resolved configuration after applying provider precedence and fallback rules.\n\n## 1.29 Template file\n\nA **template file** is a markdown document used at create time to generate frontmatter and/or body content through variable expansion.\nWhen templating is enabled, template behavior is defined by §5.3.5 and §9.14.\n\n## 1.30 Template expansion\n\n**Template expansion** is deterministic replacement of template variables with create-time task data and runtime date/time values, followed by template merge rules.\n\n## 1.31 Time entry\n\nA **time entry** is a structured record in `time_entries` containing `startTime`, optional `endTime`, and optional `description`.\n\n## 1.32 Active time entry\n\nAn **active time entry** is a time entry with `startTime` present and `endTime` absent.\n\n## 1.33 Time tracking management\n\n**Time tracking management** is the set of operations that start, stop, edit, and remove `time_entries`, including completion-triggered auto-stop behavior when configured.\n","aliases":["/spec/01-terminology/"],"toc":[{"level":2,"id":"11-collection","text":"1.1 Collection"},{"level":2,"id":"12-task-file","text":"1.2 Task file"},{"level":2,"id":"13-frontmatter","text":"1.3 Frontmatter"},{"level":2,"id":"14-task-record","text":"1.4 Task record"},{"level":2,"id":"15-semantic-role","text":"1.5 Semantic role"},{"level":2,"id":"16-storage-key","text":"1.6 Storage key"},{"level":2,"id":"17-field-mapping","text":"1.7 Field mapping"},{"level":2,"id":"18-alias","text":"1.8 Alias"},{"level":2,"id":"19-canonical-write-key","text":"1.9 Canonical write key"},{"level":2,"id":"110-date-value","text":"1.10 Date value"},{"level":2,"id":"111-datetime-value","text":"1.11 Datetime value"},{"level":2,"id":"112-target-date","text":"1.12 Target date"},{"level":2,"id":"113-recurrence-rule","text":"1.13 Recurrence rule"},{"level":2,"id":"114-recurrence-anchor","text":"1.14 Recurrence anchor"},{"level":2,"id":"115-complete-instances","text":"1.15 Complete instances"},{"level":2,"id":"116-skipped-instances","text":"1.16 Skipped instances"},{"level":2,"id":"117-materialized-occurrence-note","text":"1.17 Materialized occurrence note"},{"level":2,"id":"118-recurrence-parent","text":"1.18 Recurrence parent"},{"level":2,"id":"119-occurrence-materialization","text":"1.19 Occurrence materialization"},{"level":2,"id":"120-effective-status","text":"1.20 Effective status"},{"level":2,"id":"121-completed-status-list","text":"1.21 Completed-status list"},{"level":2,"id":"122-idempotent-operation","text":"1.22 Idempotent operation"},{"level":2,"id":"123-unknown-field","text":"1.23 Unknown field"},{"level":2,"id":"124-validation-issue","text":"1.24 Validation issue"},{"level":2,"id":"125-strict-validation-mode","text":"1.25 Strict validation mode"},{"level":2,"id":"126-legacy-compatibility-mode","text":"1.26 Legacy compatibility mode"},{"level":2,"id":"127-configuration-provider","text":"1.27 Configuration provider"},{"level":2,"id":"128-effective-configuration","text":"1.28 Effective configuration"},{"level":2,"id":"129-template-file","text":"1.29 Template file"},{"level":2,"id":"130-template-expansion","text":"1.30 Template expansion"},{"level":2,"id":"131-time-entry","text":"1.31 Time entry"},{"level":2,"id":"132-active-time-entry","text":"1.32 Active time entry"},{"level":2,"id":"133-time-tracking-management","text":"1.33 Time tracking management"}],"html":"

This section defines terms used normatively in this specification.

\n

1.1 Collection#

\n

A collection is a filesystem scope within which task files are discovered and managed under a single TaskNotes configuration.

\n

1.2 Task file#

\n

A task file is a markdown file identified as a task record by collection rules.

\n

1.3 Frontmatter#

\n

Frontmatter is the YAML block at the start of a markdown file delimited by --- markers.

\n

1.4 Task record#

\n

A task record is the semantic task object obtained from parsing a task file frontmatter (plus optional derived metadata).

\n

1.5 Semantic role#

\n

A semantic role is a canonical meaning defined by this specification, independent of storage key names.

\n

Examples: title, status, date_created, complete_instances.

\n

1.6 Storage key#

\n

A storage key is the YAML property name used in frontmatter.

\n

Examples: dateCreated, date_created, completedDate.

\n

1.7 Field mapping#

\n

Field mapping is the configuration that maps semantic roles to storage keys for reads and writes.

\n

1.8 Alias#

\n

An alias is a non-canonical storage key accepted for compatibility during reads.

\n

1.9 Canonical write key#

\n

The canonical write key is the configured storage key that conforming writers use for persisted output.

\n

1.10 Date value#

\n

A date value represents a calendar day with no time-of-day and no timezone.

\n

Canonical form: YYYY-MM-DD.

\n

1.11 Datetime value#

\n

A datetime value represents an instant in time.

\n

Canonical form: ISO 8601 UTC with trailing Z.

\n

1.12 Target date#

\n

A target date is the calendar date to which a recurrence instance operation applies (for example complete instance on 2026-02-20).

\n

1.13 Recurrence rule#

\n

A recurrence rule is a tasknotes recurrence string stored in the recurrence semantic role.\nIt uses RFC 5545 RRULE-style parameters inside a single semicolon-delimited field value and MAY include an explicit inline DTSTART prefix segment as defined in §4.3.

\n

1.14 Recurrence anchor#

\n

Recurrence anchor defines how next-instance progression is computed. Allowed values:

\n\n

1.15 Complete instances#

\n

Complete instances is the set/list of target dates marked completed for a recurring task.

\n

1.16 Skipped instances#

\n

Skipped instances is the set/list of target dates marked skipped for a recurring task.

\n

1.17 Materialized occurrence note#

\n

A materialized occurrence note is a task file created for one target date of a recurring parent task.\nIt stores user-authored per-occurrence content and, when supported by the implementation, owns the authoritative task state for that occurrence date.

\n

1.18 Recurrence parent#

\n

A recurrence parent is the recurring task record referenced by a materialized occurrence note.\nThe reference is stored in semantic role recurrence_parent and resolved as a link according to §11.

\n

1.19 Occurrence materialization#

\n

Occurrence materialization is the creation and reconciliation of materialized occurrence notes from a recurring parent task according to §4.18 and §5.20.

\n

1.20 Effective status#

\n

Effective status is the status presented for a given date context after applying recurrence instance state.

\n

1.21 Completed-status list#

\n

The completed-status list is the configured ordered list of status values treated as completed for non-recurring completion semantics.\nWhen a single value must be chosen deterministically, the first list entry is used unless explicit operation input overrides it.

\n

1.22 Idempotent operation#

\n

An operation is idempotent if applying it multiple times with the same input produces the same persisted state as applying it once.

\n

1.23 Unknown field#

\n

An unknown field is a frontmatter property not mapped to a semantic role in current configuration.

\n

1.24 Validation issue#

\n

A validation issue is a structured report containing at least:

\n\n

1.25 Strict validation mode#

\n

Strict validation mode is a mode where invalid required semantics are treated as hard errors and write operations fail.

\n

1.26 Legacy compatibility mode#

\n

Legacy compatibility mode is a mode where specific historical behaviors or aliases are accepted for migration but are not canonical for new writes.

\n

1.27 Configuration provider#

\n

A configuration provider is an adapter that loads configuration from a source (for example tasknotes.yaml or .obsidian/plugins/tasknotes/data.json) and normalizes it to the schema in §9.

\n

1.28 Effective configuration#

\n

The effective configuration is the final resolved configuration after applying provider precedence and fallback rules.

\n

1.29 Template file#

\n

A template file is a markdown document used at create time to generate frontmatter and/or body content through variable expansion.\nWhen templating is enabled, template behavior is defined by §5.3.5 and §9.14.

\n

1.30 Template expansion#

\n

Template expansion is deterministic replacement of template variables with create-time task data and runtime date/time values, followed by template merge rules.

\n

1.31 Time entry#

\n

A time entry is a structured record in time_entries containing startTime, optional endTime, and optional description.

\n

1.32 Active time entry#

\n

An active time entry is a time entry with startTime present and endTime absent.

\n

1.33 Time tracking management#

\n

Time tracking management is the set of operations that start, stop, edit, and remove time_entries, including completion-triggered auto-stop behavior when configured.

\n","text":"This section defines terms used normatively in this specification. 1.1 Collection# A collection is a filesystem scope within which task files are discovered and managed under a single TaskNotes configuration. 1.2 Task file# A task file is a markdown file identified as a task record by collection rules. 1.3 Frontmatter# Frontmatter is the YAML block at the start of a markdown file delimited by --- markers. 1.4 Task record# A task record is the semantic task object obtained from parsing a task file frontmatter (plus optional derived metadata). 1.5 Semantic role# A semantic role is a canonical meaning defined by this specification, independent of storage key names. Examples: title, status, date_created, complete_instances. 1.6 Storage key# A storage key is the YAML property name used in frontmatter. Examples: dateCreated, date_created, completedDate. 1.7 Field mapping# Field mapping is the configuration that maps semantic roles to storage keys for reads and writes. 1.8 Alias# An alias is a non-canonical storage key accepted for compatibility during reads. 1.9 Canonical write key# The canonical write key is the configured storage key that conforming writers use for persisted output. 1.10 Date value# A date value represents a calendar day with no time-of-day and no timezone. Canonical form: YYYY-MM-DD. 1.11 Datetime value# A datetime value represents an instant in time. Canonical form: ISO 8601 UTC with trailing Z. 1.12 Target date# A target date is the calendar date to which a recurrence instance operation applies (for example complete instance on 2026-02-20). 1.13 Recurrence rule# A recurrence rule is a tasknotes recurrence string stored in the recurrence semantic role. It uses RFC 5545 RRULE-style parameters inside a single semicolon-delimited field value and MAY include an explicit inline DTSTART prefix segment as defined in §4.3. 1.14 Recurrence anchor# Recurrence anchor defines how next-instance progression is computed. Allowed values: scheduled completion 1.15 Complete instances# Complete instances is the set/list of target dates marked completed for a recurring task. 1.16 Skipped instances# Skipped instances is the set/list of target dates marked skipped for a recurring task. 1.17 Materialized occurrence note# A materialized occurrence note is a task file created for one target date of a recurring parent task. It stores user-authored per-occurrence content and, when supported by the implementation, owns the authoritative task state for that occurrence date. 1.18 Recurrence parent# A recurrence parent is the recurring task record referenced by a materialized occurrence note. The reference is stored in semantic role recurrence_parent and resolved as a link according to §11. 1.19 Occurrence materialization# Occurrence materialization is the creation and reconciliation of materialized occurrence notes from a recurring parent task according to §4.18 and §5.20. 1.20 Effective status# Effective status is the status presented for a given date context after applying recurrence instance state. 1.21 Completed-status list# The completed-status list is the configured ordered list of status values treated as completed for non-recurring completion semantics. When a single value must be chosen deterministically, the first list entry is used unless explicit operation input overrides it. 1.22 Idempotent operation# An operation is idempotent if applying it multiple times with the same input produces the same persisted state as applying it once. 1.23 Unknown field# An unknown field is a frontmatter property not mapped to a semantic role in current configuration. 1.24 Validation issue# A validation issue is a structured report containing at least: machine-readable code, severity, optional path/field context, human-readable message. 1.25 Strict validation mode# Strict validation mode is a mode where invalid required semantics are treated as hard errors and write operations fail. 1.26 Legacy compatibility mode# Legacy compatibility mode is a mode where specific historical behaviors or aliases are accepted for migration but are not canonical for new writes. 1.27 Configuration provider# A configuration provider is an adapter that loads configuration from a source (for example tasknotes.yaml or .obsidian/plugins/tasknotes/data.json) and normalizes it to the schema in §9. 1.28 Effective configuration# The effective configuration is the final resolved configuration after applying provider precedence and fallback rules. 1.29 Template file# A template file is a markdown document used at create time to generate frontmatter and/or body content through variable expansion. When templating is enabled, template behavior is defined by §5.3.5 and §9.14. 1.30 Template expansion# Template expansion is deterministic replacement of template variables with create-time task data and runtime date/time values, followed by template merge rules. 1.31 Time entry# A time entry is a structured record in time_entries containing startTime, optional endTime, and optional description. 1.32 Active time entry# An active time entry is a time entry with startTime present and endTime absent. 1.33 Time tracking management# Time tracking management is the set of operations that start, stop, edit, and remove time_entries, including completion-triggered auto-stop behavior when configured."},{"route":"/developers/specification/02-model-and-mapping/","title":"2. Model and Field Mapping","description":"A task record consists of:","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:02-model-and-mapping.md","namespace":"specification","relativePath":"02-model-and-mapping.md","raw":"# 2. Model and Field Mapping\n\n## 2.1 Task record model\n\nA task record consists of:\n\n- frontmatter object (structured fields),\n- markdown body (freeform text),\n- file metadata (path, created/modified time) where available.\n\nFrontmatter is normative for task semantics. Body content is non-normative except where an implementation exposes body search or body-derived features.\n\n## 2.2 Required semantic roles\n\nConforming implementations MUST support these semantic roles:\n\n| Semantic role | Type | Required |\n|---|---|---|\n| `title` | string | support required (value required via configured title source, see §2.2.2) |\n| `status` | string/enum | yes |\n| `completed_date` | date | support required (conditionally required, see §2.2.1) |\n| `date_created` | datetime | yes |\n| `date_modified` | datetime | yes |\n\nIf storage omits a role marked `yes`, validation MUST report an error (see §6).\nFor operation-required roles, validation and operation rules in §5 and §6 apply.\n\n### 2.2.1 Conditional requiredness (`completed_date`)\n\n`completed_date` support is mandatory, but presence is conditional:\n\n- For non-recurring tasks with `status` in configured `status.completed_values`, `completed_date` MUST be present.\n- For non-recurring tasks with non-completed status, `completed_date` MAY be absent.\n- For recurring tasks, `completed_date` is not required by recurrence completion semantics and MAY be absent.\n\nValidators MUST apply this conditional rule and MUST NOT treat `completed_date` as unconditionally required.\n\n### 2.2.2 Conditional requiredness (`title`)\n\nSemantic `title` is always required, with deterministic read resolution and storage-mode-dependent read/write behavior:\n\n- Readers MUST resolve semantic title using storage-mode-aware precedence (§9.13):\n 1. when `title.storage=frontmatter`: mapped `title` key when present and non-empty, then file basename fallback;\n 2. when `title.storage=filename`: file basename first, then mapped `title` fallback when basename is unavailable.\n- If mapped title and filename-derived title both exist and differ, the source authoritative for active `title.storage` MUST win and implementations SHOULD emit `title_source_conflict`.\n- When `title.storage=filename`, implementations MAY keep mapped `title` as a synchronized compatibility mirror, but filename-derived title remains authoritative.\n- Title storage mode controls canonical writes (§9.13): `frontmatter` favors mapped-key writes; `filename` favors filename-derived title with rename-on-title-change behavior.\n\nValidators MUST enforce semantic title presence using the active title-resolution policy (§9.13), not frontmatter key presence alone.\n\n## 2.3 Common semantic roles\n\nImplementations conforming beyond minimal scope SHOULD support:\n\n| Semantic role | Type | Notes |\n|---|---|---|\n| `id` | string | stable task identity token; see §2.6.5 |\n| `priority` | string/enum | configurable values |\n| `due` | date or datetime | see §3 |\n| `scheduled` | date or datetime | see §3 |\n| `tags` | list | free tags |\n| `contexts` | list | commonly prefixed with `@` |\n| `projects` | list | project references, see §11 |\n| `attachments` | list | ordered file references owned by the task, see §2.6.7 and §11.8.3 |\n| `time_estimate` | integer >= 0 | minutes |\n| `time_entries` | list | see §2.6 |\n| `recurrence` | string | tasknotes recurrence string; see §4 |\n| `recurrence_anchor` | enum | `scheduled` or `completion` |\n| `complete_instances` | list | recurring completion state |\n| `skipped_instances` | list | recurring skip state |\n| `recurrence_parent` | link-or-string | parent recurring task reference for materialized occurrence notes; see §4.18 |\n| `occurrence_date` | date | target date represented by a materialized occurrence note |\n| `occurrence_materialization` | enum | parent task materialization mode: `manual`, `on_completion`, or `rolling` |\n| `occurrence_next_trigger` | enum | parent task next-note trigger: `completion` or `completion_or_skip` |\n| `occurrence_template` | link-or-string | optional template used when creating materialized occurrence notes |\n| `occurrence_past_horizon` | duration | optional rolling materialization lookbehind bound |\n| `occurrence_future_horizon` | duration | optional rolling materialization lookahead bound |\n| `blocked_by` | list | dependency records, see §10 and §11 |\n| `reminders` | list | reminder records, see §10 |\n\nOptional extended roles are defined in §7 profiles.\n\n## 2.4 Field mapping requirements\n\n### 2.4.1 Mapping presence\n\nAn implementation MUST have an effective mapping from each supported semantic role to a canonical write key.\nMapping configuration is defined in §9.\nIf semantic role `id` is supported, it MUST also have a canonical write key.\n\n### 2.4.2 Read behavior\n\nReaders MUST:\n\n1. Read the canonical mapped key if present.\n2. Support configured aliases where enabled.\n3. Resolve conflicts deterministically when canonical and alias keys coexist.\n4. When canonical and alias keys both exist for the same semantic role, canonical key value MUST win.\n5. When canonical key wins over alias, validator/loader SHOULD emit warning `alias_conflict_ignored`.\n\n### 2.4.3 Write behavior\n\nWriters MUST:\n\n- write only canonical keys,\n- avoid introducing alias keys in new writes,\n- preserve unknown fields unless the operation explicitly opts into normalization.\n\n## 2.5 Legacy alias compatibility\n\nImplementations SHOULD accept these aliases on read for interoperability:\n\n| Semantic role | Canonical example | Alias examples |\n|---|---|---|\n| `recurrence_anchor` | `recurrence_anchor` | `recurrenceAnchor` |\n| `complete_instances` | `complete_instances` | `completeInstances` |\n| `skipped_instances` | `skipped_instances` | `skippedInstances` |\n| `recurrence_parent` | `recurrence_parent` | `recurrenceParent` |\n| `occurrence_date` | `occurrence_date` | `occurrenceDate` |\n| `occurrence_materialization` | `occurrence_materialization` | `occurrenceMaterialization` |\n| `occurrence_next_trigger` | `occurrence_next_trigger` | `occurrenceNextTrigger` |\n| `occurrence_template` | `occurrence_template` | `occurrenceTemplate` |\n| `occurrence_past_horizon` | `occurrence_past_horizon` | `occurrencePastHorizon` |\n| `occurrence_future_horizon` | `occurrence_future_horizon` | `occurrenceFutureHorizon` |\n| `date_created` | `dateCreated` | `date_created` |\n| `date_modified` | `dateModified` | `date_modified` |\n| `completed_date` | `completedDate` | `completed_date` |\n| `time_entries` | `timeEntries` | `time_entries` |\n| `time_estimate` | `timeEstimate` | `time_estimate` |\n| `blocked_by` | `blockedBy` | `blocked_by` |\n| `attachments` | `attachments` | — |\n\nThis table is compatibility guidance, not a requirement to choose camelCase or snake_case as canonical.\n\n## 2.6 Structured role schemas\n\n### 2.6.1 time_entries\n\n`time_entries` items MUST be objects with:\n\n- `startTime` datetime (required)\n- `endTime` datetime (optional)\n- `description` string (optional)\n\nAdditional constraints:\n\n- a task MUST NOT contain more than one active time entry (entry with `startTime` and no `endTime`) at commit time.\n- an entry with missing `endTime` is interpreted as an active/running session.\n- an implementation MAY accept `duration` on read for backward compatibility, but canonical duration is derived from start/end and SHOULD NOT be persisted on canonical writes.\n\nNested key names in `time_entries` are fixed by this specification and are not independently configurable in `mapping`.\n\n### 2.6.2 projects\n\n`projects` SHOULD be represented as links when link semantics are supported, but plain strings MAY be accepted.\nWhen interpreted as links, parsing and resolution MUST follow §11.\n\n### 2.6.3 blocked_by\n\n`blocked_by` items MUST be objects with:\n\n- `uid` link-or-string task reference (required)\n- `reltype` enum (required; default allowed by §10 when omitted)\n- `gap` ISO 8601 duration string (optional)\n\nDetailed semantics are defined in §10. `uid` parsing and resolution MUST follow §11.\n\n### 2.6.4 reminders\n\n`reminders` items MUST be objects with:\n\n- `id` string (required)\n- `type` enum `absolute|relative` (required)\n- relative-only fields: `relatedTo`, `offset`\n- absolute-only fields: `absoluteTime`\n- `description` string (optional)\n\nDetailed semantics are defined in §10.\n\n### 2.6.5 id (stable task identity)\n\nWhen semantic role `id` is present:\n\n- value MUST be a non-empty string.\n- value MUST be treated as stable identity metadata and MUST NOT be rewritten by rename, move, or title-change operations.\n- readers and link resolution MAY use it as an identity lookup key (see §11.4 Step 3).\n- implementations SHOULD keep `id` unique within a collection; duplicate IDs SHOULD produce a validation issue.\n\n### 2.6.6 Materialized occurrence roles\n\nThe roles in this subsection are required only for implementations claiming profile `materialized-occurrences` (§7.3.4).\n\nParent recurring task roles:\n\n- `occurrence_materialization`: enum `manual|on_completion|rolling`; controls when occurrence notes are created (§4.18.5).\n- `occurrence_next_trigger`: enum `completion|completion_or_skip`; controls whether skip/cancel transitions advance creation of the next occurrence note (§4.18.6).\n- `occurrence_template`: link-or-string reference to a template file used when creating occurrence notes. Link parsing/resolution follows §11 when supported.\n- `occurrence_past_horizon` and `occurrence_future_horizon`: ISO 8601 durations used by rolling materialization (§4.18.7).\n\nMaterialized occurrence note roles:\n\n- `recurrence_parent`: link-or-string reference to the parent recurring task. Wikilinks are the default interoperable representation in Obsidian-oriented collections.\n- `occurrence_date`: date value identifying the target date this occurrence note represents.\n\nImplementations claiming `materialized-occurrences` MUST treat `recurrence_parent` and `occurrence_date` together as the occurrence identity key.\nWithin a resolved parent task, at most one materialized occurrence note SHOULD exist for each `occurrence_date`; duplicate notes MUST be reported when detected (§6.4).\n\nMaterialized occurrence notes MAY also use normal task roles such as `status`, `completed_date`, `scheduled`, `due`, `time_entries`, `reminders`, `contexts`, `projects`, and body content.\nFor dates where a materialized occurrence note exists, its own task state is authoritative as defined in §4.18.3.\n\n### 2.6.7 attachments\n\n`attachments` is the authoritative task-membership list for files associated\nwith a task. It MUST be represented as an ordered list of non-empty\nlink-or-string values. Each value MUST identify one collection file and MUST\nfollow the parsing, resolution, and canonical-write rules in §11.8.3.\n\nThe list itself intentionally contains references only. MIME type, byte size,\ncontent digest, storage revision, timestamps, and other binary metadata belong\nto the collection's file descriptor or filesystem metadata and MUST NOT be\nduplicated into canonical task frontmatter.\n\nThe Markdown body MAY embed or link an attached file for inline presentation,\nbut body links and embeds do not add or remove task membership. A file is a task\nattachment if and only if it appears in the mapped `attachments` list.\n\nReaders MAY accept a single scalar reference as compatibility input and\nnormalize it to a one-item list. Canonical writes MUST use a list, preserve its\norder, and MUST NOT contain empty or duplicate normalized targets.\n\n## 2.7 Unknown fields\n\nUnknown frontmatter keys MUST be preserved by default during updates, complete/uncomplete, skip/unskip, dependency mutations, reminder mutations, and archive operations.\n\nUnknown fields MAY be removed only when:\n\n- explicit normalization/migration is requested, or\n- strict schema replacement is explicitly requested.\n\n## 2.8 Example mapping\n\nExample effective mapping:\n\n```yaml\nmapping:\n id: id\n title: title\n status: status\n date_created: dateCreated\n date_modified: dateModified\n completed_date: completedDate\n recurrence: recurrence\n recurrence_anchor: recurrence_anchor\n complete_instances: complete_instances\n skipped_instances: skipped_instances\n recurrence_parent: recurrence_parent\n occurrence_date: occurrence_date\n occurrence_materialization: occurrence_materialization\n occurrence_next_trigger: occurrence_next_trigger\n occurrence_template: occurrence_template\n occurrence_past_horizon: occurrence_past_horizon\n occurrence_future_horizon: occurrence_future_horizon\n time_estimate: timeEstimate\n time_entries: timeEntries\n blocked_by: blockedBy\n reminders: reminders\n```\n\n## 2.9 Example task record\n\n```markdown\n---\nid: task-2026-01-10-weekly-review\ntitle: Weekly review\nstatus: open\npriority: high\nscheduled: 2026-02-20\nrecurrence: FREQ=WEEKLY;BYDAY=FR\nrecurrence_anchor: scheduled\ncomplete_instances: [2026-02-13]\nskipped_instances: []\nblockedBy:\n - uid: \"[[prepare-metrics]]\"\n reltype: FINISHTOSTART\n gap: P1D\nreminders:\n - id: rem_day_before\n type: relative\n relatedTo: due\n offset: -P1D\n - id: rem_start\n type: absolute\n absoluteTime: 2026-02-20T09:00:00Z\ndateCreated: 2026-01-10T09:30:00Z\ndateModified: 2026-02-20T08:02:11Z\n---\n\nReview completed work and plan next week.\n```\n\n## 2.10 Deterministic load example\n\nGiven frontmatter:\n\n```yaml\nrecurrence_anchor: scheduled\nrecurrenceAnchor: completion\n```\n\nIf canonical key is `recurrence_anchor`, a conforming loader using canonical-precedence policy MUST resolve semantic `recurrence_anchor` as `scheduled` and SHOULD emit a compatibility warning.\n","aliases":["/spec/02-model-and-mapping/"],"toc":[{"level":2,"id":"21-task-record-model","text":"2.1 Task record model"},{"level":2,"id":"22-required-semantic-roles","text":"2.2 Required semantic roles"},{"level":3,"id":"221-conditional-requiredness-completeddate","text":"2.2.1 Conditional requiredness (completed_date)"},{"level":3,"id":"222-conditional-requiredness-title","text":"2.2.2 Conditional requiredness (title)"},{"level":2,"id":"23-common-semantic-roles","text":"2.3 Common semantic roles"},{"level":2,"id":"24-field-mapping-requirements","text":"2.4 Field mapping requirements"},{"level":3,"id":"241-mapping-presence","text":"2.4.1 Mapping presence"},{"level":3,"id":"242-read-behavior","text":"2.4.2 Read behavior"},{"level":3,"id":"243-write-behavior","text":"2.4.3 Write behavior"},{"level":2,"id":"25-legacy-alias-compatibility","text":"2.5 Legacy alias compatibility"},{"level":2,"id":"26-structured-role-schemas","text":"2.6 Structured role schemas"},{"level":3,"id":"261-timeentries","text":"2.6.1 time_entries"},{"level":3,"id":"262-projects","text":"2.6.2 projects"},{"level":3,"id":"263-blockedby","text":"2.6.3 blocked_by"},{"level":3,"id":"264-reminders","text":"2.6.4 reminders"},{"level":3,"id":"265-id-stable-task-identity","text":"2.6.5 id (stable task identity)"},{"level":3,"id":"266-materialized-occurrence-roles","text":"2.6.6 Materialized occurrence roles"},{"level":3,"id":"267-attachments","text":"2.6.7 attachments"},{"level":2,"id":"27-unknown-fields","text":"2.7 Unknown fields"},{"level":2,"id":"28-example-mapping","text":"2.8 Example mapping"},{"level":2,"id":"29-example-task-record","text":"2.9 Example task record"},{"level":2,"id":"210-deterministic-load-example","text":"2.10 Deterministic load example"}],"html":"

2.1 Task record model#

\n

A task record consists of:

\n
    \n
  • frontmatter object (structured fields),
  • \n
  • markdown body (freeform text),
  • \n
  • file metadata (path, created/modified time) where available.
  • \n
\n

Frontmatter is normative for task semantics. Body content is non-normative except where an implementation exposes body search or body-derived features.

\n

2.2 Required semantic roles#

\n

Conforming implementations MUST support these semantic roles:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Semantic roleTypeRequired
titlestringsupport required (value required via configured title source, see §2.2.2)
statusstring/enumyes
completed_datedatesupport required (conditionally required, see §2.2.1)
date_createddatetimeyes
date_modifieddatetimeyes
\n

If storage omits a role marked yes, validation MUST report an error (see §6).\nFor operation-required roles, validation and operation rules in §5 and §6 apply.

\n

2.2.1 Conditional requiredness (completed_date)#

\n

completed_date support is mandatory, but presence is conditional:

\n
    \n
  • For non-recurring tasks with status in configured status.completed_values, completed_date MUST be present.
  • \n
  • For non-recurring tasks with non-completed status, completed_date MAY be absent.
  • \n
  • For recurring tasks, completed_date is not required by recurrence completion semantics and MAY be absent.
  • \n
\n

Validators MUST apply this conditional rule and MUST NOT treat completed_date as unconditionally required.

\n

2.2.2 Conditional requiredness (title)#

\n

Semantic title is always required, with deterministic read resolution and storage-mode-dependent read/write behavior:

\n
    \n
  • Readers MUST resolve semantic title using storage-mode-aware precedence (§9.13):
      \n
    1. when title.storage=frontmatter: mapped title key when present and non-empty, then file basename fallback;
    2. \n
    3. when title.storage=filename: file basename first, then mapped title fallback when basename is unavailable.
    4. \n
    \n
  • \n
  • If mapped title and filename-derived title both exist and differ, the source authoritative for active title.storage MUST win and implementations SHOULD emit title_source_conflict.
  • \n
  • When title.storage=filename, implementations MAY keep mapped title as a synchronized compatibility mirror, but filename-derived title remains authoritative.
  • \n
  • Title storage mode controls canonical writes (§9.13): frontmatter favors mapped-key writes; filename favors filename-derived title with rename-on-title-change behavior.
  • \n
\n

Validators MUST enforce semantic title presence using the active title-resolution policy (§9.13), not frontmatter key presence alone.

\n

2.3 Common semantic roles#

\n

Implementations conforming beyond minimal scope SHOULD support:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Semantic roleTypeNotes
idstringstable task identity token; see §2.6.5
prioritystring/enumconfigurable values
duedate or datetimesee §3
scheduleddate or datetimesee §3
tagslistfree tags
contextslistcommonly prefixed with @
projectslistproject references, see §11
attachmentslistordered file references owned by the task, see §2.6.7 and §11.8.3
time_estimateinteger >= 0minutes
time_entrieslistsee §2.6
recurrencestringtasknotes recurrence string; see §4
recurrence_anchorenumscheduled or completion
complete_instanceslistrecurring completion state
skipped_instanceslistrecurring skip state
recurrence_parentlink-or-stringparent recurring task reference for materialized occurrence notes; see §4.18
occurrence_datedatetarget date represented by a materialized occurrence note
occurrence_materializationenumparent task materialization mode: manual, on_completion, or rolling
occurrence_next_triggerenumparent task next-note trigger: completion or completion_or_skip
occurrence_templatelink-or-stringoptional template used when creating materialized occurrence notes
occurrence_past_horizondurationoptional rolling materialization lookbehind bound
occurrence_future_horizondurationoptional rolling materialization lookahead bound
blocked_bylistdependency records, see §10 and §11
reminderslistreminder records, see §10
\n

Optional extended roles are defined in §7 profiles.

\n

2.4 Field mapping requirements#

\n

2.4.1 Mapping presence#

\n

An implementation MUST have an effective mapping from each supported semantic role to a canonical write key.\nMapping configuration is defined in §9.\nIf semantic role id is supported, it MUST also have a canonical write key.

\n

2.4.2 Read behavior#

\n

Readers MUST:

\n
    \n
  1. Read the canonical mapped key if present.
  2. \n
  3. Support configured aliases where enabled.
  4. \n
  5. Resolve conflicts deterministically when canonical and alias keys coexist.
  6. \n
  7. When canonical and alias keys both exist for the same semantic role, canonical key value MUST win.
  8. \n
  9. When canonical key wins over alias, validator/loader SHOULD emit warning alias_conflict_ignored.
  10. \n
\n

2.4.3 Write behavior#

\n

Writers MUST:

\n
    \n
  • write only canonical keys,
  • \n
  • avoid introducing alias keys in new writes,
  • \n
  • preserve unknown fields unless the operation explicitly opts into normalization.
  • \n
\n

2.5 Legacy alias compatibility#

\n

Implementations SHOULD accept these aliases on read for interoperability:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Semantic roleCanonical exampleAlias examples
recurrence_anchorrecurrence_anchorrecurrenceAnchor
complete_instancescomplete_instancescompleteInstances
skipped_instancesskipped_instancesskippedInstances
recurrence_parentrecurrence_parentrecurrenceParent
occurrence_dateoccurrence_dateoccurrenceDate
occurrence_materializationoccurrence_materializationoccurrenceMaterialization
occurrence_next_triggeroccurrence_next_triggeroccurrenceNextTrigger
occurrence_templateoccurrence_templateoccurrenceTemplate
occurrence_past_horizonoccurrence_past_horizonoccurrencePastHorizon
occurrence_future_horizonoccurrence_future_horizonoccurrenceFutureHorizon
date_createddateCreateddate_created
date_modifieddateModifieddate_modified
completed_datecompletedDatecompleted_date
time_entriestimeEntriestime_entries
time_estimatetimeEstimatetime_estimate
blocked_byblockedByblocked_by
attachmentsattachments—
\n

This table is compatibility guidance, not a requirement to choose camelCase or snake_case as canonical.

\n

2.6 Structured role schemas#

\n

2.6.1 time_entries#

\n

time_entries items MUST be objects with:

\n
    \n
  • startTime datetime (required)
  • \n
  • endTime datetime (optional)
  • \n
  • description string (optional)
  • \n
\n

Additional constraints:

\n
    \n
  • a task MUST NOT contain more than one active time entry (entry with startTime and no endTime) at commit time.
  • \n
  • an entry with missing endTime is interpreted as an active/running session.
  • \n
  • an implementation MAY accept duration on read for backward compatibility, but canonical duration is derived from start/end and SHOULD NOT be persisted on canonical writes.
  • \n
\n

Nested key names in time_entries are fixed by this specification and are not independently configurable in mapping.

\n

2.6.2 projects#

\n

projects SHOULD be represented as links when link semantics are supported, but plain strings MAY be accepted.\nWhen interpreted as links, parsing and resolution MUST follow §11.

\n

2.6.3 blocked_by#

\n

blocked_by items MUST be objects with:

\n
    \n
  • uid link-or-string task reference (required)
  • \n
  • reltype enum (required; default allowed by §10 when omitted)
  • \n
  • gap ISO 8601 duration string (optional)
  • \n
\n

Detailed semantics are defined in §10. uid parsing and resolution MUST follow §11.

\n

2.6.4 reminders#

\n

reminders items MUST be objects with:

\n
    \n
  • id string (required)
  • \n
  • type enum absolute|relative (required)
  • \n
  • relative-only fields: relatedTo, offset
  • \n
  • absolute-only fields: absoluteTime
  • \n
  • description string (optional)
  • \n
\n

Detailed semantics are defined in §10.

\n

2.6.5 id (stable task identity)#

\n

When semantic role id is present:

\n
    \n
  • value MUST be a non-empty string.
  • \n
  • value MUST be treated as stable identity metadata and MUST NOT be rewritten by rename, move, or title-change operations.
  • \n
  • readers and link resolution MAY use it as an identity lookup key (see §11.4 Step 3).
  • \n
  • implementations SHOULD keep id unique within a collection; duplicate IDs SHOULD produce a validation issue.
  • \n
\n

2.6.6 Materialized occurrence roles#

\n

The roles in this subsection are required only for implementations claiming profile materialized-occurrences (§7.3.4).

\n

Parent recurring task roles:

\n
    \n
  • occurrence_materialization: enum manual|on_completion|rolling; controls when occurrence notes are created (§4.18.5).
  • \n
  • occurrence_next_trigger: enum completion|completion_or_skip; controls whether skip/cancel transitions advance creation of the next occurrence note (§4.18.6).
  • \n
  • occurrence_template: link-or-string reference to a template file used when creating occurrence notes. Link parsing/resolution follows §11 when supported.
  • \n
  • occurrence_past_horizon and occurrence_future_horizon: ISO 8601 durations used by rolling materialization (§4.18.7).
  • \n
\n

Materialized occurrence note roles:

\n
    \n
  • recurrence_parent: link-or-string reference to the parent recurring task. Wikilinks are the default interoperable representation in Obsidian-oriented collections.
  • \n
  • occurrence_date: date value identifying the target date this occurrence note represents.
  • \n
\n

Implementations claiming materialized-occurrences MUST treat recurrence_parent and occurrence_date together as the occurrence identity key.\nWithin a resolved parent task, at most one materialized occurrence note SHOULD exist for each occurrence_date; duplicate notes MUST be reported when detected (§6.4).

\n

Materialized occurrence notes MAY also use normal task roles such as status, completed_date, scheduled, due, time_entries, reminders, contexts, projects, and body content.\nFor dates where a materialized occurrence note exists, its own task state is authoritative as defined in §4.18.3.

\n

2.6.7 attachments#

\n

attachments is the authoritative task-membership list for files associated\nwith a task. It MUST be represented as an ordered list of non-empty\nlink-or-string values. Each value MUST identify one collection file and MUST\nfollow the parsing, resolution, and canonical-write rules in §11.8.3.

\n

The list itself intentionally contains references only. MIME type, byte size,\ncontent digest, storage revision, timestamps, and other binary metadata belong\nto the collection's file descriptor or filesystem metadata and MUST NOT be\nduplicated into canonical task frontmatter.

\n

The Markdown body MAY embed or link an attached file for inline presentation,\nbut body links and embeds do not add or remove task membership. A file is a task\nattachment if and only if it appears in the mapped attachments list.

\n

Readers MAY accept a single scalar reference as compatibility input and\nnormalize it to a one-item list. Canonical writes MUST use a list, preserve its\norder, and MUST NOT contain empty or duplicate normalized targets.

\n

2.7 Unknown fields#

\n

Unknown frontmatter keys MUST be preserved by default during updates, complete/uncomplete, skip/unskip, dependency mutations, reminder mutations, and archive operations.

\n

Unknown fields MAY be removed only when:

\n
    \n
  • explicit normalization/migration is requested, or
  • \n
  • strict schema replacement is explicitly requested.
  • \n
\n

2.8 Example mapping#

\n

Example effective mapping:

\n
mapping:\n  id: id\n  title: title\n  status: status\n  date_created: dateCreated\n  date_modified: dateModified\n  completed_date: completedDate\n  recurrence: recurrence\n  recurrence_anchor: recurrence_anchor\n  complete_instances: complete_instances\n  skipped_instances: skipped_instances\n  recurrence_parent: recurrence_parent\n  occurrence_date: occurrence_date\n  occurrence_materialization: occurrence_materialization\n  occurrence_next_trigger: occurrence_next_trigger\n  occurrence_template: occurrence_template\n  occurrence_past_horizon: occurrence_past_horizon\n  occurrence_future_horizon: occurrence_future_horizon\n  time_estimate: timeEstimate\n  time_entries: timeEntries\n  blocked_by: blockedBy\n  reminders: reminders\n

2.9 Example task record#

\n
---\nid: task-2026-01-10-weekly-review\ntitle: Weekly review\nstatus: open\npriority: high\nscheduled: 2026-02-20\nrecurrence: FREQ=WEEKLY;BYDAY=FR\nrecurrence_anchor: scheduled\ncomplete_instances: [2026-02-13]\nskipped_instances: []\nblockedBy:\n  - uid: "[[prepare-metrics]]"\n    reltype: FINISHTOSTART\n    gap: P1D\nreminders:\n  - id: rem_day_before\n    type: relative\n    relatedTo: due\n    offset: -P1D\n  - id: rem_start\n    type: absolute\n    absoluteTime: 2026-02-20T09:00:00Z\ndateCreated: 2026-01-10T09:30:00Z\ndateModified: 2026-02-20T08:02:11Z\n---\n\nReview completed work and plan next week.\n

2.10 Deterministic load example#

\n

Given frontmatter:

\n
recurrence_anchor: scheduled\nrecurrenceAnchor: completion\n

If canonical key is recurrence_anchor, a conforming loader using canonical-precedence policy MUST resolve semantic recurrence_anchor as scheduled and SHOULD emit a compatibility warning.

\n","text":"2.1 Task record model# A task record consists of: frontmatter object (structured fields), markdown body (freeform text), file metadata (path, created/modified time) where available. Frontmatter is normative for task semantics. Body content is non-normative except where an implementation exposes body search or body-derived features. 2.2 Required semantic roles# Conforming implementations MUST support these semantic roles: Semantic role Type Required title string support required (value required via configured title source, see §2.2.2) status string/enum yes completed_date date support required (conditionally required, see §2.2.1) date_created datetime yes date_modified datetime yes If storage omits a role marked yes, validation MUST report an error (see §6). For operation-required roles, validation and operation rules in §5 and §6 apply. 2.2.1 Conditional requiredness (completed_date)# completed_date support is mandatory, but presence is conditional: For non-recurring tasks with status in configured status.completed_values, completed_date MUST be present. For non-recurring tasks with non-completed status, completed_date MAY be absent. For recurring tasks, completed_date is not required by recurrence completion semantics and MAY be absent. Validators MUST apply this conditional rule and MUST NOT treat completed_date as unconditionally required. 2.2.2 Conditional requiredness (title)# Semantic title is always required, with deterministic read resolution and storage-mode-dependent read/write behavior: Readers MUST resolve semantic title using storage-mode-aware precedence (§9.13): when title.storage=frontmatter: mapped title key when present and non-empty, then file basename fallback; when title.storage=filename: file basename first, then mapped title fallback when basename is unavailable. If mapped title and filename-derived title both exist and differ, the source authoritative for active title.storage MUST win and implementations SHOULD emit title_source_conflict. When title.storage=filename, implementations MAY keep mapped title as a synchronized compatibility mirror, but filename-derived title remains authoritative. Title storage mode controls canonical writes (§9.13): frontmatter favors mapped-key writes; filename favors filename-derived title with rename-on-title-change behavior. Validators MUST enforce semantic title presence using the active title-resolution policy (§9.13), not frontmatter key presence alone. 2.3 Common semantic roles# Implementations conforming beyond minimal scope SHOULD support: Semantic role Type Notes id string stable task identity token; see §2.6.5 priority string/enum configurable values due date or datetime see §3 scheduled date or datetime see §3 tags list free tags contexts list commonly prefixed with @ projects list project references, see §11 attachments list ordered file references owned by the task, see §2.6.7 and §11.8.3 time_estimate integer >= 0 minutes time_entries list see §2.6 recurrence string tasknotes recurrence string; see §4 recurrence_anchor enum scheduled or completion complete_instances list recurring completion state skipped_instances list recurring skip state recurrence_parent link-or-string parent recurring task reference for materialized occurrence notes; see §4.18 occurrence_date date target date represented by a materialized occurrence note occurrence_materialization enum parent task materialization mode: manual, on_completion, or rolling occurrence_next_trigger enum parent task next-note trigger: completion or completion_or_skip occurrence_template link-or-string optional template used when creating materialized occurrence notes occurrence_past_horizon duration optional rolling materialization lookbehind bound occurrence_future_horizon duration optional rolling materialization lookahead bound blocked_by list dependency records, see §10 and §11 reminders list reminder records, see §10 Optional extended roles are defined in §7 profiles. 2.4 Field mapping requirements# 2.4.1 Mapping presence# An implementation MUST have an effective mapping from each supported semantic role to a canonical write key. Mapping configuration is defined in §9. If semantic role id is supported, it MUST also have a canonical write key. 2.4.2 Read behavior# Readers MUST: Read the canonical mapped key if present. Support configured aliases where enabled. Resolve conflicts deterministically when canonical and alias keys coexist. When canonical and alias keys both exist for the same semantic role, canonical key value MUST win. When canonical key wins over alias, validator/loader SHOULD emit warning alias_conflict_ignored. 2.4.3 Write behavior# Writers MUST: write only canonical keys, avoid introducing alias keys in new writes, preserve unknown fields unless the operation explicitly opts into normalization. 2.5 Legacy alias compatibility# Implementations SHOULD accept these aliases on read for interoperability: Semantic role Canonical example Alias examples recurrence_anchor recurrence_anchor recurrenceAnchor complete_instances complete_instances completeInstances skipped_instances skipped_instances skippedInstances recurrence_parent recurrence_parent recurrenceParent occurrence_date occurrence_date occurrenceDate occurrence_materialization occurrence_materialization occurrenceMaterialization occurrence_next_trigger occurrence_next_trigger occurrenceNextTrigger occurrence_template occurrence_template occurrenceTemplate occurrence_past_horizon occurrence_past_horizon occurrencePastHorizon occurrence_future_horizon occurrence_future_horizon occurrenceFutureHorizon date_created dateCreated date_created date_modified dateModified date_modified completed_date completedDate completed_date time_entries timeEntries time_entries time_estimate timeEstimate time_estimate blocked_by blockedBy blocked_by attachments attachments — This table is compatibility guidance, not a requirement to choose camelCase or snake_case as canonical. 2.6 Structured role schemas# 2.6.1 time_entries# time_entries items MUST be objects with: startTime datetime (required) endTime datetime (optional) description string (optional) Additional constraints: a task MUST NOT contain more than one active time entry (entry with startTime and no endTime) at commit time. an entry with missing endTime is interpreted as an active/running session. an implementation MAY accept duration on read for backward compatibility, but canonical duration is derived from start/end and SHOULD NOT be persisted on canonical writes. Nested key names in time_entries are fixed by this specification and are not independently configurable in mapping. 2.6.2 projects# projects SHOULD be represented as links when link semantics are supported, but plain strings MAY be accepted. When interpreted as links, parsing and resolution MUST follow §11. 2.6.3 blocked_by# blocked_by items MUST be objects with: uid link-or-string task reference (required) reltype enum (required; default allowed by §10 when omitted) gap ISO 8601 duration string (optional) Detailed semantics are defined in §10. uid parsing and resolution MUST follow §11. 2.6.4 reminders# reminders items MUST be objects with: id string (required) type enum absolute|relative (required) relative-only fields: relatedTo, offset absolute-only fields: absoluteTime description string (optional) Detailed semantics are defined in §10. 2.6.5 id (stable task identity)# When semantic role id is present: value MUST be a non-empty string. value MUST be treated as stable identity metadata and MUST NOT be rewritten by rename, move, or title-change operations. readers and link resolution MAY use it as an identity lookup key (see §11.4 Step 3). implementations SHOULD keep id unique within a collection; duplicate IDs SHOULD produce a validation issue. 2.6.6 Materialized occurrence roles# The roles in this subsection are required only for implementations claiming profile materialized-occurrences (§7.3.4). Parent recurring task roles: occurrence_materialization: enum manual|on_completion|rolling; controls when occurrence notes are created (§4.18.5). occurrence_next_trigger: enum completion|completion_or_skip; controls whether skip/cancel transitions advance creation of the next occurrence note (§4.18.6). occurrence_template: link-or-string reference to a template file used when creating occurrence notes. Link parsing/resolution follows §11 when supported. occurrence_past_horizon and occurrence_future_horizon: ISO 8601 durations used by rolling materialization (§4.18.7). Materialized occurrence note roles: recurrence_parent: link-or-string reference to the parent recurring task. Wikilinks are the default interoperable representation in Obsidian-oriented collections. occurrence_date: date value identifying the target date this occurrence note represents. Implementations claiming materialized-occurrences MUST treat recurrence_parent and occurrence_date together as the occurrence identity key. Within a resolved parent task, at most one materialized occurrence note SHOULD exist for each occurrence_date; duplicate notes MUST be reported when detected (§6.4). Materialized occurrence notes MAY also use normal task roles such as status, completed_date, scheduled, due, time_entries, reminders, contexts, projects, and body content. For dates where a materialized occurrence note exists, its own task state is authoritative as defined in §4.18.3. 2.6.7 attachments# attachments is the authoritative task-membership list for files associated with a task. It MUST be represented as an ordered list of non-empty link-or-string values. Each value MUST identify one collection file and MUST follow the parsing, resolution, and canonical-write rules in §11.8.3. The list itself intentionally contains references only. MIME type, byte size, content digest, storage revision, timestamps, and other binary metadata belong to the collection's file descriptor or filesystem metadata and MUST NOT be duplicated into canonical task frontmatter. The Markdown body MAY embed or link an attached file for inline presentation, but body links and embeds do not add or remove task membership. A file is a task attachment if and only if it appears in the mapped attachments list. Readers MAY accept a single scalar reference as compatibility input and normalize it to a one-item list. Canonical writes MUST use a list, preserve its order, and MUST NOT contain empty or duplicate normalized targets. 2.7 Unknown fields# Unknown frontmatter keys MUST be preserved by default during updates, complete/uncomplete, skip/unskip, dependency mutations, reminder mutations, and archive operations. Unknown fields MAY be removed only when: explicit normalization/migration is requested, or strict schema replacement is explicitly requested. 2.8 Example mapping# Example effective mapping: mapping: id: id title: title status: status date_created: dateCreated date_modified: dateModified completed_date: completedDate recurrence: recurrence recurrence_anchor: recurrence_anchor complete_instances: complete_instances skipped_instances: skipped_instances recurrence_parent: recurrence_parent occurrence_date: occurrence_date occurrence_materialization: occurrence_materialization occurrence_next_trigger: occurrence_next_trigger occurrence_template: occurrence_template occurrence_past_horizon: occurrence_past_horizon occurrence_future_horizon: occurrence_future_horizon time_estimate: timeEstimate time_entries: timeEntries blocked_by: blockedBy reminders: reminders 2.9 Example task record# --- id: task-2026-01-10-weekly-review title: Weekly review status: open priority: high scheduled: 2026-02-20 recurrence: FREQ=WEEKLY;BYDAY=FR recurrence_anchor: scheduled complete_instances: [2026-02-13] skipped_instances: [] blockedBy: - uid: \"[[prepare-metrics]]\" reltype: FINISHTOSTART gap: P1D reminders: - id: rem_day_before type: relative relatedTo: due offset: -P1D - id: rem_start type: absolute absoluteTime: 2026-02-20T09:00:00Z dateCreated: 2026-01-10T09:30:00Z dateModified: 2026-02-20T08:02:11Z --- Review completed work and plan next week. 2.10 Deterministic load example# Given frontmatter: recurrence_anchor: scheduled recurrenceAnchor: completion If canonical key is recurrence_anchor, a conforming loader using canonical-precedence policy MUST resolve semantic recurrence_anchor as scheduled and SHOULD emit a compatibility warning."},{"route":"/developers/specification/03-temporal-semantics/","title":"3. Temporal Semantics","description":"This section defines how implementations MUST interpret, compare, and serialize task-related date and datetime values.","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:03-temporal-semantics.md","namespace":"specification","relativePath":"03-temporal-semantics.md","raw":"# 3. Temporal Semantics\n\n## 3.1 Purpose\n\nThis section defines how implementations MUST interpret, compare, and serialize task-related date and datetime values.\n\n## 3.2 Supported temporal value classes\n\nImplementations MUST support:\n\n1. **Date values**: calendar day without time or timezone.\n2. **Datetime values**: instant in time.\n\n## 3.3 Canonical serialization\n\n### 3.3.1 Date\n\nCanonical date serialization is:\n\n```text\nYYYY-MM-DD\n```\n\n### 3.3.2 Datetime\n\nCanonical datetime serialization is UTC ISO 8601 with `Z`, for example:\n\n```text\n2026-02-20T13:45:00Z\n```\n\nCanonical datetime writes MUST use second precision (`YYYY-MM-DDTHH:MM:SSZ`) and MUST NOT include fractional seconds.\nImplementations MAY accept alternative inbound datetime forms but MUST normalize outbound canonical writes.\nIf an accepted inbound datetime includes fractional seconds, writers MUST normalize deterministically by truncating fractional precision to whole seconds.\n\n## 3.4 Parsing requirements\n\n### 3.4.1 Date parsing\n\nDate parsing MUST reject invalid calendar dates.\n\n- valid: `2026-02-28`\n- invalid: `2026-02-30`\n\n### 3.4.2 Datetime parsing\n\nDatetime parsing MUST reject malformed values.\nIn strict mode, datetime parsing MUST reject ambiguous local datetimes without offset (for example `2026-02-20T09:00:00` with no timezone offset).\nIn permissive mode, implementations MAY accept such values only under an explicitly documented compatibility policy and SHOULD emit a warning.\n\n### 3.4.3 Mixed input tolerance\n\nImplementations MAY accept both date and datetime values for roles like `due` and `scheduled` if configured to do so. The accepted form MUST be documented.\n\n### 3.4.4 Inbound acceptance matrix\n\nTo avoid ambiguity, conforming parsers MUST follow this matrix.\n\nDate forms:\n\n| Form | Example | Strict | Permissive |\n|---|---|---|---|\n| Canonical date | `2026-02-20` | accept | accept |\n| Basic date (no separators) | `20260220` | reject (`invalid_date_value`) | MAY accept only under documented compatibility policy; SHOULD emit warning |\n\nDatetime forms:\n\n| Form | Example | Strict | Permissive |\n|---|---|---|---|\n| Canonical UTC | `2026-02-20T09:00:00Z` | accept | accept |\n| ISO with explicit offset | `2026-02-20T09:00:00+10:00` | accept | accept |\n| ISO with fractional seconds | `2026-02-20T09:00:00.250Z` | accept (normalize to second precision on write) | accept (normalize to second precision on write) |\n| Offset-less local datetime | `2026-02-20T09:00:00` | reject (`invalid_datetime_value`) | MAY accept only under documented compatibility policy; SHOULD emit warning |\n| Space-separated datetime | `2026-02-20 09:00:00` | reject (`invalid_datetime_value`) | MAY accept only under documented compatibility policy; SHOULD emit warning |\n| Basic datetime (no separators) | `20260220T090000Z` | reject (`invalid_datetime_value`) | MAY accept only under documented compatibility policy; SHOULD emit warning |\n\nWhen permissive-mode compatibility accepts a non-canonical form, canonical writes MUST still follow §3.3.\n\n## 3.5 Day semantics vs instant semantics\n\n### 3.5.1 Date roles\n\nDate roles represent days, not instants, and MUST NOT be timezone-shifted.\n\n### 3.5.2 Datetime roles\n\nDatetime roles represent instants and MUST preserve instant equality through normalization.\n\nExample:\n\n- input `2026-02-20T08:00:00-05:00`\n- canonical write `2026-02-20T13:00:00Z`\n\n### 3.5.3 Implementation guidance: UTC-anchor strategy (non-normative)\n\nBecause date-only fields are human-readable (`YYYY-MM-DD`) while implementations often compute using datetime objects, a common strategy is to use a UTC-midnight anchor for date-only internals.\n\nRecommended approach:\n\n1. Parse date-only values to a UTC-midnight anchor instant for internal computations.\n2. Format date-only values from UTC calendar components when writing `YYYY-MM-DD`.\n3. Keep date-only roles as date-only on write unless an explicit conversion operation is requested.\n4. Evaluate user-facing day semantics (today, overdue, day grouping) using local calendar-day boundaries per §3.6.\n\nImplementations MAY use different internal representations as long as all normative requirements in this section are preserved.\n\n## 3.6 Local calendar-day evaluation\n\n### 3.6.1 Active runtime timezone\n\nFor day-level semantics, the active runtime timezone is:\n\n1. the caller-provided temporal execution context, when present\n2. the collection authority's configured timezone\n3. the process/system local timezone.\n\nThe timezone is runtime context, not TaskNotes type-binding configuration. A\nremote caller SHOULD send its current IANA timezone for interactive operations;\na headless authority SHOULD use its durable collection timezone. Every\noperation MUST resolve this precedence once and use one effective timezone for\nall day-level semantics in that operation.\n\nImplementations MUST make the effective timezone discoverable.\n\n### 3.6.2 Local calendar-day rules\n\nWhen calculating day-level concepts (for example overdue/day grouping/calendar day cells), implementations MUST evaluate against local calendar-day boundaries of the active runtime timezone.\n\nThis requirement prevents off-by-one day drift in positive and negative UTC offsets.\n\n## 3.7 Comparison rules\n\n### 3.7.1 Date-to-date\n\nCompare by calendar day ordering.\n\n### 3.7.2 Datetime-to-datetime\n\nCompare by instant ordering.\n\n### 3.7.3 Date-to-datetime\n\nIf compared, implementations MUST document coercion policy. Recommended policy:\n\n- convert date to local start-of-day for day-level comparisons,\n- avoid implicit coercion for instant-level comparisons.\n\n## 3.8 due and scheduled semantics\n\n`due` and `scheduled` MAY be either date or datetime by configuration.\n\nImplementations MUST:\n\n- preserve stored granularity unless explicit conversion is requested,\n- avoid silently converting date to datetime during unrelated writes,\n- require documented explicit policy for date-to-datetime conversion operations,\n- apply consistent coercion policy in filters and status calculations.\n\n## 3.9 Completion date semantics\n\n`completed_date` is a date role.\n\nFor non-recurring completion, writers MUST set `completed_date` using §5 semantics:\n\n- explicit completion-day input when provided,\n- otherwise current local day in active runtime timezone.\n\n## 3.10 Created/modified timestamps\n\n`date_created` and `date_modified` are datetime roles.\n\nWriters MUST:\n\n- set both on create,\n- update `date_modified` on successful mutating operations that change persisted state,\n- preserve `date_created` unless explicit migration/edit operation changes it.\n\n## 3.11 time_entries semantics\n\n### 3.11.1 Timestamp format\n\n`time_entries.startTime` and `time_entries.endTime` MUST be datetime instants in canonical form on write.\n\n### 3.11.2 Range validity\n\nIf both times exist, `endTime` MUST be greater than or equal to `startTime`.\n\n### 3.11.3 Duration handling\n\nIf duration is present, implementations SHOULD treat it as derived and MAY rewrite or remove stale duration values during normalization.\n\n### 3.11.4 Active session semantics\n\nAn entry with `startTime` and no `endTime` represents an active/running session.\n\nImplementations that support time-tracking management operations (§5.19) MUST enforce at most one active session per task at commit time.\n\n### 3.11.5 Derived time calculations\n\nFor interoperability, implementations SHOULD expose both derived views when reporting tracked time:\n\n- `closed_minutes`: sum of entries where both `startTime` and `endTime` exist.\n- `live_minutes`: `closed_minutes` plus elapsed minutes of active entries (if any).\n\nImplementations MUST document which derived view is used by each reporting surface (for example task cards, stats, APIs).\n\n## 3.12 reminder temporal semantics\n\nReminder time fields are governed by §10.3 and MUST follow canonical datetime and duration formats from this section.\n\nRules:\n\n- `reminders[].absoluteTime` MUST be a canonical datetime on write.\n- `reminders[].offset` MUST be a valid ISO 8601 duration string.\n- relative reminder base conversion for date-only values MUST use `reminders.date_only_anchor_time` from §9, or `00:00` local time if unset.\n\n## 3.13 Example: local-day overdue evaluation\n\nAssume local timezone `America/Los_Angeles` and local date `2026-02-20`.\n\nTask A:\n\n```yaml\ndue: 2026-02-19\nstatus: open\n```\n\nTask A is overdue.\n\nTask B:\n\n```yaml\ndue: 2026-02-20\nstatus: open\n```\n\nTask B is not overdue at start of day; it becomes overdue on `2026-02-21` local day.\n\n## 3.14 Example: preserving granularity\n\nBefore update:\n\n```yaml\ndue: 2026-02-20\npriority: normal\n```\n\nOperation: update priority only.\n\nAfter update (conforming):\n\n```yaml\ndue: 2026-02-20\npriority: high\n```\n\nNon-conforming behavior would silently rewrite `due` to a datetime.\n\n## 3.15 Example: canonical datetime write\n\nInput:\n\n```yaml\ntimeEntries:\n - startTime: 2026-02-20T09:30:00+01:00\n endTime: 2026-02-20T10:00:00+01:00\n```\n\nCanonical write:\n\n```yaml\ntimeEntries:\n - startTime: 2026-02-20T08:30:00Z\n endTime: 2026-02-20T09:00:00Z\n```\n\n## 3.16 Example: UTC-anchor roundtrip for date-only field\n\nInput:\n\n```yaml\ndue: 2026-02-20\n```\n\nInternal computation anchor:\n\n```text\n2026-02-20T00:00:00Z\n```\n\nAfter unrelated update, conforming write:\n\n```yaml\ndue: 2026-02-20\n```\n\nNon-conforming behavior would rewrite `due` as a datetime or shift it to another day based on local offset.\n","aliases":["/spec/03-temporal-semantics/"],"toc":[{"level":2,"id":"31-purpose","text":"3.1 Purpose"},{"level":2,"id":"32-supported-temporal-value-classes","text":"3.2 Supported temporal value classes"},{"level":2,"id":"33-canonical-serialization","text":"3.3 Canonical serialization"},{"level":3,"id":"331-date","text":"3.3.1 Date"},{"level":3,"id":"332-datetime","text":"3.3.2 Datetime"},{"level":2,"id":"34-parsing-requirements","text":"3.4 Parsing requirements"},{"level":3,"id":"341-date-parsing","text":"3.4.1 Date parsing"},{"level":3,"id":"342-datetime-parsing","text":"3.4.2 Datetime parsing"},{"level":3,"id":"343-mixed-input-tolerance","text":"3.4.3 Mixed input tolerance"},{"level":3,"id":"344-inbound-acceptance-matrix","text":"3.4.4 Inbound acceptance matrix"},{"level":2,"id":"35-day-semantics-vs-instant-semantics","text":"3.5 Day semantics vs instant semantics"},{"level":3,"id":"351-date-roles","text":"3.5.1 Date roles"},{"level":3,"id":"352-datetime-roles","text":"3.5.2 Datetime roles"},{"level":3,"id":"353-implementation-guidance-utc-anchor-strategy-non-normative","text":"3.5.3 Implementation guidance: UTC-anchor strategy (non-normative)"},{"level":2,"id":"36-local-calendar-day-evaluation","text":"3.6 Local calendar-day evaluation"},{"level":3,"id":"361-active-runtime-timezone","text":"3.6.1 Active runtime timezone"},{"level":3,"id":"362-local-calendar-day-rules","text":"3.6.2 Local calendar-day rules"},{"level":2,"id":"37-comparison-rules","text":"3.7 Comparison rules"},{"level":3,"id":"371-date-to-date","text":"3.7.1 Date-to-date"},{"level":3,"id":"372-datetime-to-datetime","text":"3.7.2 Datetime-to-datetime"},{"level":3,"id":"373-date-to-datetime","text":"3.7.3 Date-to-datetime"},{"level":2,"id":"38-due-and-scheduled-semantics","text":"3.8 due and scheduled semantics"},{"level":2,"id":"39-completion-date-semantics","text":"3.9 Completion date semantics"},{"level":2,"id":"310-createdmodified-timestamps","text":"3.10 Created/modified timestamps"},{"level":2,"id":"311-timeentries-semantics","text":"3.11 time_entries semantics"},{"level":3,"id":"3111-timestamp-format","text":"3.11.1 Timestamp format"},{"level":3,"id":"3112-range-validity","text":"3.11.2 Range validity"},{"level":3,"id":"3113-duration-handling","text":"3.11.3 Duration handling"},{"level":3,"id":"3114-active-session-semantics","text":"3.11.4 Active session semantics"},{"level":3,"id":"3115-derived-time-calculations","text":"3.11.5 Derived time calculations"},{"level":2,"id":"312-reminder-temporal-semantics","text":"3.12 reminder temporal semantics"},{"level":2,"id":"313-example-local-day-overdue-evaluation","text":"3.13 Example: local-day overdue evaluation"},{"level":2,"id":"314-example-preserving-granularity","text":"3.14 Example: preserving granularity"},{"level":2,"id":"315-example-canonical-datetime-write","text":"3.15 Example: canonical datetime write"},{"level":2,"id":"316-example-utc-anchor-roundtrip-for-date-only-field","text":"3.16 Example: UTC-anchor roundtrip for date-only field"}],"html":"

3.1 Purpose#

\n

This section defines how implementations MUST interpret, compare, and serialize task-related date and datetime values.

\n

3.2 Supported temporal value classes#

\n

Implementations MUST support:

\n
    \n
  1. Date values: calendar day without time or timezone.
  2. \n
  3. Datetime values: instant in time.
  4. \n
\n

3.3 Canonical serialization#

\n

3.3.1 Date#

\n

Canonical date serialization is:

\n
YYYY-MM-DD\n

3.3.2 Datetime#

\n

Canonical datetime serialization is UTC ISO 8601 with Z, for example:

\n
2026-02-20T13:45:00Z\n

Canonical datetime writes MUST use second precision (YYYY-MM-DDTHH:MM:SSZ) and MUST NOT include fractional seconds.\nImplementations MAY accept alternative inbound datetime forms but MUST normalize outbound canonical writes.\nIf an accepted inbound datetime includes fractional seconds, writers MUST normalize deterministically by truncating fractional precision to whole seconds.

\n

3.4 Parsing requirements#

\n

3.4.1 Date parsing#

\n

Date parsing MUST reject invalid calendar dates.

\n
    \n
  • valid: 2026-02-28
  • \n
  • invalid: 2026-02-30
  • \n
\n

3.4.2 Datetime parsing#

\n

Datetime parsing MUST reject malformed values.\nIn strict mode, datetime parsing MUST reject ambiguous local datetimes without offset (for example 2026-02-20T09:00:00 with no timezone offset).\nIn permissive mode, implementations MAY accept such values only under an explicitly documented compatibility policy and SHOULD emit a warning.

\n

3.4.3 Mixed input tolerance#

\n

Implementations MAY accept both date and datetime values for roles like due and scheduled if configured to do so. The accepted form MUST be documented.

\n

3.4.4 Inbound acceptance matrix#

\n

To avoid ambiguity, conforming parsers MUST follow this matrix.

\n

Date forms:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
FormExampleStrictPermissive
Canonical date2026-02-20acceptaccept
Basic date (no separators)20260220reject (invalid_date_value)MAY accept only under documented compatibility policy; SHOULD emit warning
\n

Datetime forms:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
FormExampleStrictPermissive
Canonical UTC2026-02-20T09:00:00Zacceptaccept
ISO with explicit offset2026-02-20T09:00:00+10:00acceptaccept
ISO with fractional seconds2026-02-20T09:00:00.250Zaccept (normalize to second precision on write)accept (normalize to second precision on write)
Offset-less local datetime2026-02-20T09:00:00reject (invalid_datetime_value)MAY accept only under documented compatibility policy; SHOULD emit warning
Space-separated datetime2026-02-20 09:00:00reject (invalid_datetime_value)MAY accept only under documented compatibility policy; SHOULD emit warning
Basic datetime (no separators)20260220T090000Zreject (invalid_datetime_value)MAY accept only under documented compatibility policy; SHOULD emit warning
\n

When permissive-mode compatibility accepts a non-canonical form, canonical writes MUST still follow §3.3.

\n

3.5 Day semantics vs instant semantics#

\n

3.5.1 Date roles#

\n

Date roles represent days, not instants, and MUST NOT be timezone-shifted.

\n

3.5.2 Datetime roles#

\n

Datetime roles represent instants and MUST preserve instant equality through normalization.

\n

Example:

\n
    \n
  • input 2026-02-20T08:00:00-05:00
  • \n
  • canonical write 2026-02-20T13:00:00Z
  • \n
\n

3.5.3 Implementation guidance: UTC-anchor strategy (non-normative)#

\n

Because date-only fields are human-readable (YYYY-MM-DD) while implementations often compute using datetime objects, a common strategy is to use a UTC-midnight anchor for date-only internals.

\n

Recommended approach:

\n
    \n
  1. Parse date-only values to a UTC-midnight anchor instant for internal computations.
  2. \n
  3. Format date-only values from UTC calendar components when writing YYYY-MM-DD.
  4. \n
  5. Keep date-only roles as date-only on write unless an explicit conversion operation is requested.
  6. \n
  7. Evaluate user-facing day semantics (today, overdue, day grouping) using local calendar-day boundaries per §3.6.
  8. \n
\n

Implementations MAY use different internal representations as long as all normative requirements in this section are preserved.

\n

3.6 Local calendar-day evaluation#

\n

3.6.1 Active runtime timezone#

\n

For day-level semantics, the active runtime timezone is:

\n
    \n
  1. the caller-provided temporal execution context, when present
  2. \n
  3. the collection authority's configured timezone
  4. \n
  5. the process/system local timezone.
  6. \n
\n

The timezone is runtime context, not TaskNotes type-binding configuration. A\nremote caller SHOULD send its current IANA timezone for interactive operations;\na headless authority SHOULD use its durable collection timezone. Every\noperation MUST resolve this precedence once and use one effective timezone for\nall day-level semantics in that operation.

\n

Implementations MUST make the effective timezone discoverable.

\n

3.6.2 Local calendar-day rules#

\n

When calculating day-level concepts (for example overdue/day grouping/calendar day cells), implementations MUST evaluate against local calendar-day boundaries of the active runtime timezone.

\n

This requirement prevents off-by-one day drift in positive and negative UTC offsets.

\n

3.7 Comparison rules#

\n

3.7.1 Date-to-date#

\n

Compare by calendar day ordering.

\n

3.7.2 Datetime-to-datetime#

\n

Compare by instant ordering.

\n

3.7.3 Date-to-datetime#

\n

If compared, implementations MUST document coercion policy. Recommended policy:

\n
    \n
  • convert date to local start-of-day for day-level comparisons,
  • \n
  • avoid implicit coercion for instant-level comparisons.
  • \n
\n

3.8 due and scheduled semantics#

\n

due and scheduled MAY be either date or datetime by configuration.

\n

Implementations MUST:

\n
    \n
  • preserve stored granularity unless explicit conversion is requested,
  • \n
  • avoid silently converting date to datetime during unrelated writes,
  • \n
  • require documented explicit policy for date-to-datetime conversion operations,
  • \n
  • apply consistent coercion policy in filters and status calculations.
  • \n
\n

3.9 Completion date semantics#

\n

completed_date is a date role.

\n

For non-recurring completion, writers MUST set completed_date using §5 semantics:

\n
    \n
  • explicit completion-day input when provided,
  • \n
  • otherwise current local day in active runtime timezone.
  • \n
\n

3.10 Created/modified timestamps#

\n

date_created and date_modified are datetime roles.

\n

Writers MUST:

\n
    \n
  • set both on create,
  • \n
  • update date_modified on successful mutating operations that change persisted state,
  • \n
  • preserve date_created unless explicit migration/edit operation changes it.
  • \n
\n

3.11 time_entries semantics#

\n

3.11.1 Timestamp format#

\n

time_entries.startTime and time_entries.endTime MUST be datetime instants in canonical form on write.

\n

3.11.2 Range validity#

\n

If both times exist, endTime MUST be greater than or equal to startTime.

\n

3.11.3 Duration handling#

\n

If duration is present, implementations SHOULD treat it as derived and MAY rewrite or remove stale duration values during normalization.

\n

3.11.4 Active session semantics#

\n

An entry with startTime and no endTime represents an active/running session.

\n

Implementations that support time-tracking management operations (§5.19) MUST enforce at most one active session per task at commit time.

\n

3.11.5 Derived time calculations#

\n

For interoperability, implementations SHOULD expose both derived views when reporting tracked time:

\n
    \n
  • closed_minutes: sum of entries where both startTime and endTime exist.
  • \n
  • live_minutes: closed_minutes plus elapsed minutes of active entries (if any).
  • \n
\n

Implementations MUST document which derived view is used by each reporting surface (for example task cards, stats, APIs).

\n

3.12 reminder temporal semantics#

\n

Reminder time fields are governed by §10.3 and MUST follow canonical datetime and duration formats from this section.

\n

Rules:

\n
    \n
  • reminders[].absoluteTime MUST be a canonical datetime on write.
  • \n
  • reminders[].offset MUST be a valid ISO 8601 duration string.
  • \n
  • relative reminder base conversion for date-only values MUST use reminders.date_only_anchor_time from §9, or 00:00 local time if unset.
  • \n
\n

3.13 Example: local-day overdue evaluation#

\n

Assume local timezone America/Los_Angeles and local date 2026-02-20.

\n

Task A:

\n
due: 2026-02-19\nstatus: open\n

Task A is overdue.

\n

Task B:

\n
due: 2026-02-20\nstatus: open\n

Task B is not overdue at start of day; it becomes overdue on 2026-02-21 local day.

\n

3.14 Example: preserving granularity#

\n

Before update:

\n
due: 2026-02-20\npriority: normal\n

Operation: update priority only.

\n

After update (conforming):

\n
due: 2026-02-20\npriority: high\n

Non-conforming behavior would silently rewrite due to a datetime.

\n

3.15 Example: canonical datetime write#

\n

Input:

\n
timeEntries:\n  - startTime: 2026-02-20T09:30:00+01:00\n    endTime: 2026-02-20T10:00:00+01:00\n

Canonical write:

\n
timeEntries:\n  - startTime: 2026-02-20T08:30:00Z\n    endTime: 2026-02-20T09:00:00Z\n

3.16 Example: UTC-anchor roundtrip for date-only field#

\n

Input:

\n
due: 2026-02-20\n

Internal computation anchor:

\n
2026-02-20T00:00:00Z\n

After unrelated update, conforming write:

\n
due: 2026-02-20\n

Non-conforming behavior would rewrite due as a datetime or shift it to another day based on local offset.

\n","text":"3.1 Purpose# This section defines how implementations MUST interpret, compare, and serialize task-related date and datetime values. 3.2 Supported temporal value classes# Implementations MUST support: Date values: calendar day without time or timezone. Datetime values: instant in time. 3.3 Canonical serialization# 3.3.1 Date# Canonical date serialization is: YYYY-MM-DD 3.3.2 Datetime# Canonical datetime serialization is UTC ISO 8601 with Z, for example: 2026-02-20T13:45:00Z Canonical datetime writes MUST use second precision (YYYY-MM-DDTHH:MM:SSZ) and MUST NOT include fractional seconds. Implementations MAY accept alternative inbound datetime forms but MUST normalize outbound canonical writes. If an accepted inbound datetime includes fractional seconds, writers MUST normalize deterministically by truncating fractional precision to whole seconds. 3.4 Parsing requirements# 3.4.1 Date parsing# Date parsing MUST reject invalid calendar dates. valid: 2026-02-28 invalid: 2026-02-30 3.4.2 Datetime parsing# Datetime parsing MUST reject malformed values. In strict mode, datetime parsing MUST reject ambiguous local datetimes without offset (for example 2026-02-20T09:00:00 with no timezone offset). In permissive mode, implementations MAY accept such values only under an explicitly documented compatibility policy and SHOULD emit a warning. 3.4.3 Mixed input tolerance# Implementations MAY accept both date and datetime values for roles like due and scheduled if configured to do so. The accepted form MUST be documented. 3.4.4 Inbound acceptance matrix# To avoid ambiguity, conforming parsers MUST follow this matrix. Date forms: Form Example Strict Permissive Canonical date 2026-02-20 accept accept Basic date (no separators) 20260220 reject (invalid_date_value) MAY accept only under documented compatibility policy; SHOULD emit warning Datetime forms: Form Example Strict Permissive Canonical UTC 2026-02-20T09:00:00Z accept accept ISO with explicit offset 2026-02-20T09:00:00+10:00 accept accept ISO with fractional seconds 2026-02-20T09:00:00.250Z accept (normalize to second precision on write) accept (normalize to second precision on write) Offset-less local datetime 2026-02-20T09:00:00 reject (invalid_datetime_value) MAY accept only under documented compatibility policy; SHOULD emit warning Space-separated datetime 2026-02-20 09:00:00 reject (invalid_datetime_value) MAY accept only under documented compatibility policy; SHOULD emit warning Basic datetime (no separators) 20260220T090000Z reject (invalid_datetime_value) MAY accept only under documented compatibility policy; SHOULD emit warning When permissive-mode compatibility accepts a non-canonical form, canonical writes MUST still follow §3.3. 3.5 Day semantics vs instant semantics# 3.5.1 Date roles# Date roles represent days, not instants, and MUST NOT be timezone-shifted. 3.5.2 Datetime roles# Datetime roles represent instants and MUST preserve instant equality through normalization. Example: input 2026-02-20T08:00:00-05:00 canonical write 2026-02-20T13:00:00Z 3.5.3 Implementation guidance: UTC-anchor strategy (non-normative)# Because date-only fields are human-readable (YYYY-MM-DD) while implementations often compute using datetime objects, a common strategy is to use a UTC-midnight anchor for date-only internals. Recommended approach: Parse date-only values to a UTC-midnight anchor instant for internal computations. Format date-only values from UTC calendar components when writing YYYY-MM-DD. Keep date-only roles as date-only on write unless an explicit conversion operation is requested. Evaluate user-facing day semantics (today, overdue, day grouping) using local calendar-day boundaries per §3.6. Implementations MAY use different internal representations as long as all normative requirements in this section are preserved. 3.6 Local calendar-day evaluation# 3.6.1 Active runtime timezone# For day-level semantics, the active runtime timezone is: the caller-provided temporal execution context, when present the collection authority's configured timezone the process/system local timezone. The timezone is runtime context, not TaskNotes type-binding configuration. A remote caller SHOULD send its current IANA timezone for interactive operations; a headless authority SHOULD use its durable collection timezone. Every operation MUST resolve this precedence once and use one effective timezone for all day-level semantics in that operation. Implementations MUST make the effective timezone discoverable. 3.6.2 Local calendar-day rules# When calculating day-level concepts (for example overdue/day grouping/calendar day cells), implementations MUST evaluate against local calendar-day boundaries of the active runtime timezone. This requirement prevents off-by-one day drift in positive and negative UTC offsets. 3.7 Comparison rules# 3.7.1 Date-to-date# Compare by calendar day ordering. 3.7.2 Datetime-to-datetime# Compare by instant ordering. 3.7.3 Date-to-datetime# If compared, implementations MUST document coercion policy. Recommended policy: convert date to local start-of-day for day-level comparisons, avoid implicit coercion for instant-level comparisons. 3.8 due and scheduled semantics# due and scheduled MAY be either date or datetime by configuration. Implementations MUST: preserve stored granularity unless explicit conversion is requested, avoid silently converting date to datetime during unrelated writes, require documented explicit policy for date-to-datetime conversion operations, apply consistent coercion policy in filters and status calculations. 3.9 Completion date semantics# completed_date is a date role. For non-recurring completion, writers MUST set completed_date using §5 semantics: explicit completion-day input when provided, otherwise current local day in active runtime timezone. 3.10 Created/modified timestamps# date_created and date_modified are datetime roles. Writers MUST: set both on create, update date_modified on successful mutating operations that change persisted state, preserve date_created unless explicit migration/edit operation changes it. 3.11 time_entries semantics# 3.11.1 Timestamp format# time_entries.startTime and time_entries.endTime MUST be datetime instants in canonical form on write. 3.11.2 Range validity# If both times exist, endTime MUST be greater than or equal to startTime. 3.11.3 Duration handling# If duration is present, implementations SHOULD treat it as derived and MAY rewrite or remove stale duration values during normalization. 3.11.4 Active session semantics# An entry with startTime and no endTime represents an active/running session. Implementations that support time-tracking management operations (§5.19) MUST enforce at most one active session per task at commit time. 3.11.5 Derived time calculations# For interoperability, implementations SHOULD expose both derived views when reporting tracked time: closed_minutes: sum of entries where both startTime and endTime exist. live_minutes: closed_minutes plus elapsed minutes of active entries (if any). Implementations MUST document which derived view is used by each reporting surface (for example task cards, stats, APIs). 3.12 reminder temporal semantics# Reminder time fields are governed by §10.3 and MUST follow canonical datetime and duration formats from this section. Rules: reminders[].absoluteTime MUST be a canonical datetime on write. reminders[].offset MUST be a valid ISO 8601 duration string. relative reminder base conversion for date-only values MUST use reminders.date_only_anchor_time from §9, or 00:00 local time if unset. 3.13 Example: local-day overdue evaluation# Assume local timezone America/Los_Angeles and local date 2026-02-20. Task A: due: 2026-02-19 status: open Task A is overdue. Task B: due: 2026-02-20 status: open Task B is not overdue at start of day; it becomes overdue on 2026-02-21 local day. 3.14 Example: preserving granularity# Before update: due: 2026-02-20 priority: normal Operation: update priority only. After update (conforming): due: 2026-02-20 priority: high Non-conforming behavior would silently rewrite due to a datetime. 3.15 Example: canonical datetime write# Input: timeEntries: - startTime: 2026-02-20T09:30:00+01:00 endTime: 2026-02-20T10:00:00+01:00 Canonical write: timeEntries: - startTime: 2026-02-20T08:30:00Z endTime: 2026-02-20T09:00:00Z 3.16 Example: UTC-anchor roundtrip for date-only field# Input: due: 2026-02-20 Internal computation anchor: 2026-02-20T00:00:00Z After unrelated update, conforming write: due: 2026-02-20 Non-conforming behavior would rewrite due as a datetime or shift it to another day based on local offset."},{"route":"/developers/specification/04-recurrence/","title":"4. Recurrence","description":"This section defines recurrence semantics, including rule representation, anchor behavior, and per-instance completion/skip state.","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:04-recurrence.md","namespace":"specification","relativePath":"04-recurrence.md","raw":"# 4. Recurrence\n\n## 4.1 Purpose\n\nThis section defines recurrence semantics, including rule representation, anchor behavior, and per-instance completion/skip state.\n\n## 4.2 Recurrence applicability\n\nA task is recurring when semantic role `recurrence` contains a valid tasknotes recurrence string.\n\nIf `recurrence` is absent or empty, the task is non-recurring.\n\n## 4.3 Rule format\n\n### 4.3.1 Required format\n\n`recurrence` MUST be a tasknotes recurrence string.\nThis syntax is RRULE-derived but is not a full RFC 5545 content line or multi-line iCalendar fragment.\nThe RRULE parameter portion MUST use RFC 5545 RRULE property syntax.\nIt MAY include a leading inline `DTSTART` segment.\n\nIf `DTSTART` is present, it MUST use one of:\n\n- `DTSTART:YYYYMMDD` (date-only)\n- `DTSTART:YYYYMMDDTHHMMSSZ` (UTC datetime)\n\nCanonical combined form is:\n\n- `DTSTART:...;FREQ=...`\n\nImplementations MAY accept inbound `RRULE:` prefixes or multi-line iCalendar-like inputs for compatibility, but canonical writes SHOULD use the combined single-field form above.\n\nExamples:\n\n- `FREQ=DAILY`\n- `FREQ=WEEKLY;BYDAY=MO,WE,FR`\n- `FREQ=MONTHLY;BYMONTHDAY=1`\n- `DTSTART:20260220;FREQ=WEEKLY;BYDAY=FR`\n\n### 4.3.2 Invalid rule handling\n\nInvalid recurrence rules MUST produce a validation error in strict mode and SHOULD produce at least a warning in permissive mode.\n\n## 4.4 Recurrence anchor\n\n`recurrence_anchor` controls progression semantics and MUST be one of:\n\n- `scheduled`\n- `completion`\n\nIf missing, implementations SHOULD default to `scheduled` unless collection configuration defines another default.\n\n### 4.4.1 Recurrence seed precedence\n\nWhen recurrence generation requires a seed/start date, implementations MUST resolve it in this order:\n\n1. `DTSTART` embedded in `recurrence`,\n2. semantic `scheduled`,\n3. semantic `date_created`.\n\nIf no seed can be resolved, recurrence materialization MUST fail deterministically and validation MUST report an error.\n\n### 4.4.2 Anchor progression behavior\n\nFor `recurrence_anchor=scheduled`, progression is based on the scheduled chain and `DTSTART` MUST remain fixed after it is set.\n\nFor `recurrence_anchor=completion`, complete-instance operations MUST advance progression by updating `DTSTART` to the completion target (date or datetime per §4.4.3).\n\n### 4.4.3 `DTSTART` update semantics\n\nWhen `recurrence_anchor=completion` and instance completion succeeds for resolved target day `D`:\n\n1. Instance-list state (`complete_instances`, `skipped_instances`) MUST always use day `D`.\n2. If the caller provided an explicit datetime target, `DTSTART` MUST be rewritten as `DTSTART:YYYYMMDDTHHMMSSZ` using that target instant normalized to UTC.\n3. Otherwise, `DTSTART` MUST be rewritten as `DTSTART:YYYYMMDD` for day `D`.\n4. RRULE components other than `DTSTART` MUST be preserved unless an explicit recurrence-edit operation changes them.\n5. If `DTSTART` is absent, completion-anchor progression MUST insert it before RRULE parameters.\n\n### 4.4.4 Recalculation semantics for `recurrence_anchor=completion`\n\nWhen calculating the next candidate occurrence for `recurrence_anchor=completion`:\n\n1. Implementations MUST treat `DTSTART` progression as the consumed-history mechanism.\n2. `complete_instances` MUST NOT be used as an exclusion set for future occurrence selection in this mode.\n3. `skipped_instances` MUST still exclude matching candidate dates.\n4. Candidate selection MUST choose the first RRULE occurrence strictly after the current `DTSTART` anchor (or resolved seed if `DTSTART` is absent).\n\nThis matches the completion-anchor progression model where each completion advances the chain by rewriting `DTSTART`.\nThis model is intentionally not fully reversible via ordinary `uncomplete instance`; progression history lives in `DTSTART`, not only in `complete_instances`.\n\n### 4.4.5 `DTSTART` canonicalization on recurring writes\n\nTo ensure stable recurrence materialization across implementations, writers that persist recurring tasks MUST ensure `DTSTART` is present after create or successful recurring-instance completion.\n\nRules:\n\n1. If persisted `recurrence` already contains `DTSTART`, keep it unless an explicit operation updates it per §4.4.3.\n2. If persisted `recurrence` omits `DTSTART`, writers MUST resolve a seed using §4.4.1 and insert `DTSTART` before RRULE parameters.\n3. For `recurrence_anchor=scheduled`, inserted `DTSTART` becomes the fixed progression baseline and MUST NOT be rewritten by later scheduled-anchor completions.\n4. If seed resolution fails, operation MUST fail deterministically and emit `missing_recurrence_seed`.\n\n## 4.5 Instance state fields\n\nPer-instance state is represented by:\n\n- `complete_instances`: list of date values\n- `skipped_instances`: list of date values\n\nThese lists represent day-level instance outcomes.\n\n## 4.6 Invariants\n\nImplementations MUST enforce:\n\n1. Items in instance lists are valid date values.\n2. No date appears in both lists simultaneously.\n3. Duplicate dates are normalized (set semantics) or rejected deterministically.\n4. Validators MUST NOT reject an instance date solely because it is not an RRULE-generated occurrence.\n\n## 4.7 Instance completion semantics\n\nOperation: `complete instance` for target date `D`.\n\nConforming behavior:\n\n1. Add `D` to `complete_instances`.\n2. Remove `D` from `skipped_instances` if present.\n3. Leave base task status unchanged unless explicit policy states otherwise.\n4. Update `date_modified` when state changes.\n\nOperation MUST be idempotent.\n\n## 4.8 Instance uncompletion semantics\n\nOperation: `uncomplete instance` for target date `D`.\n\nConforming behavior:\n\n1. Remove `D` from `complete_instances` if present.\n2. Do not add `D` to `skipped_instances` implicitly.\n3. For `recurrence_anchor=completion`, uncomplete MUST NOT rewrite or roll back `DTSTART`; restoring prior progression requires an explicit recurrence edit or implementation-specific rewind operation.\n4. Update `date_modified` when state changes.\n\nOperation MUST be idempotent.\n\n## 4.9 Instance skip semantics\n\nOperation: `skip instance` for target date `D`.\n\nConforming behavior:\n\n1. Add `D` to `skipped_instances`.\n2. Remove `D` from `complete_instances` if present.\n3. Update `date_modified` when state changes.\n\nOperation MUST be idempotent.\n\n## 4.10 Instance unskip semantics\n\nOperation: `unskip instance` for target date `D`.\n\nConforming behavior:\n\n1. Remove `D` from `skipped_instances` if present.\n2. Do not add to `complete_instances` implicitly.\n3. Update `date_modified` when state changes.\n\nOperation MUST be idempotent.\n\n## 4.11 Effective instance state\n\nFor target date `D`, effective state MUST be resolved in this order:\n\n1. If `D` in `complete_instances`: state is `completed`.\n2. Else if `D` in `skipped_instances`: state is `skipped`.\n3. Else: state is unresolved/default for that instance.\n\nBecause overlap is invalid, this ordering is deterministic.\n\n## 4.12 Interaction with base status\n\nFor recurring tasks:\n\n- Base `status` is task-level metadata and MUST NOT be forcibly rewritten to a completed status on instance completion unless explicitly configured.\n- Instance state determines completion for recurrence-aware views and operations.\n- Dependency blocked/unblocked evaluation for v0.1 follows §10.2.5 and is not recurrence-instance-aware unless explicitly extended by implementation policy.\n\nFor non-recurring tasks, completion uses base status semantics (§5).\n\n## 4.13 Completed-status configuration\n\nImplementations MUST define which status values are treated as complete for non-recurring tasks.\n\nThe completed-status list MUST be configurable or schema-driven and MUST NOT rely on a hardcoded single literal.\n\n## 4.14 Example: complete then skip same day\n\nInitial:\n\n```yaml\nrecurrence: FREQ=DAILY\ncompleteInstances: [2026-02-20]\nskippedInstances: []\n```\n\nSkip target date `2026-02-20`:\n\n```yaml\nrecurrence: FREQ=DAILY\ncompleteInstances: []\nskippedInstances: [2026-02-20]\n```\n\n## 4.15 Example: idempotent complete\n\nInitial:\n\n```yaml\ncompleteInstances: [2026-02-20]\nskippedInstances: []\n```\n\nComplete `2026-02-20` again:\n\n- persisted instance lists remain unchanged,\n- operation succeeds without duplicate entries.\n\n## 4.16 Example: anchor semantics\n\nTask:\n\n```yaml\nrecurrence: FREQ=WEEKLY;BYDAY=FR\nrecurrenceAnchor: completion\n```\n\nIf implementation supports next-occurrence materialization, it MUST compute next occurrence relative to completion progression when anchor is `completion`, not solely by scheduled chain.\nImplementations using `DTSTART` progression MUST update `DTSTART` to the completion date for this mode.\n\nWorked example (`recurrence_anchor=completion`):\n\n```yaml\nrecurrence: DTSTART:20260220;FREQ=DAILY\nrecurrence_anchor: completion\ncomplete_instances: [2026-02-20, 2026-02-21]\nskipped_instances: [2026-02-23]\n```\n\nConforming recalculation:\n\n- does **not** exclude `2026-02-22` because it is absent from `skipped_instances`,\n- does exclude `2026-02-23` because it is skipped,\n- ignores `complete_instances` for future exclusion in this mode (§4.4.4).\n\n## 4.17 Validation examples\n\nInvalid overlap:\n\n```yaml\ncompleteInstances: [2026-02-20]\nskippedInstances: [2026-02-20]\n```\n\nResult: validation error `instance_state_overlap`.\n\nInvalid date in list:\n\n```yaml\ncompleteInstances: [2026-02-30]\n```\n\nResult: validation error `invalid_date_value`.\n\n## 4.18 Recurrence materialization\n\nThis subsection is required only for implementations claiming profile `materialized-occurrences` (§7.3.4).\n\nRecurrence materialization creates ordinary task files for specific target dates of a recurring parent task.\nIt is additive behavior: implementations that do not claim `materialized-occurrences` continue to use the instance-list model in §4.5-§4.12.\nMaterialized occurrence notes MUST be task files according to the collection's task-detection rules (§9.7).\n\n### 4.18.1 Parent and occurrence ownership\n\nThe parent recurring task owns series-level semantics:\n\n- `recurrence`\n- `recurrence_anchor`\n- recurrence generation and `DTSTART` progression\n- parent instance-list compatibility state (`complete_instances`, `skipped_instances`)\n- materialization policy fields (`occurrence_materialization`, `occurrence_next_trigger`, `occurrence_template`, `occurrence_past_horizon`, `occurrence_future_horizon`)\n\nA materialized occurrence note owns per-date task semantics for its `occurrence_date`, including:\n\n- `status`\n- `completed_date`\n- body content and checklists\n- `time_entries`\n- per-occurrence `due`, `scheduled`, `reminders`, `contexts`, `projects`, and unknown fields\n\n### 4.18.2 Occurrence identity and parent reference\n\nA materialized occurrence note MUST store:\n\n- `recurrence_parent`: a link-or-string reference to the parent recurring task\n- `occurrence_date`: the target date represented by the occurrence note\n\nThe preferred Obsidian-compatible representation for `recurrence_parent` is a wikilink, for example:\n\n```yaml\nrecurrence_parent: \"[[Weekly Review]]\"\noccurrence_date: 2026-02-27\n```\n\nImplementations claiming `materialized-occurrences` MUST resolve `recurrence_parent` using §11 link semantics for this role, even if they do not claim full `extended`.\nIf the parent cannot be resolved, validation SHOULD report `invalid_recurrence_parent`.\n\nFor one resolved parent, there SHOULD be at most one materialized occurrence note per `occurrence_date`.\nDuplicate detected occurrence notes SHOULD report `duplicate_occurrence_note` and MUST NOT be chosen nondeterministically for writes.\n\n### 4.18.3 Effective state precedence\n\nFor target date `D`, recurrence-aware effective state MUST be resolved in this order:\n\n1. If a materialized occurrence note exists for `(parent, D)`, derive state from that note's own task state:\n - `completed` when its `status` is in `status.completed_values`;\n - `skipped` when its `status` is in `status.skipped_values`;\n - otherwise unresolved/default for that instance.\n2. Else if `D` is in parent `complete_instances`: state is `completed`.\n3. Else if `D` is in parent `skipped_instances`: state is `skipped`.\n4. Else: state is unresolved/default for that instance.\n\nIf a materialized occurrence note disagrees with the parent instance lists, the materialized occurrence note wins for `D`.\nValidators SHOULD report `occurrence_state_conflict`, and repair/normalization operations MAY update parent lists to match occurrence notes.\n\n### 4.18.4 Parent instance lists as compatibility state\n\nWhen materialized occurrence notes are supported, parent `complete_instances` and `skipped_instances` remain part of canonical persisted state.\nThey serve as interoperability state for unmaterialized occurrences and as a compatibility index for clients that do not read occurrence notes.\n\nConforming writers SHOULD reconcile parent lists after materialized occurrence completion, skip, uncompletion, or unskip:\n\n- completed child state: add `D` to `complete_instances`, remove `D` from `skipped_instances`;\n- skipped child state: add `D` to `skipped_instances`, remove `D` from `complete_instances`;\n- active/unresolved child state after uncompletion/unskip: remove `D` from the relevant parent list.\n\nReconciliation failure MUST NOT silently change the occurrence note state.\nImplementations SHOULD surface a recoverable error or warning.\n\n### 4.18.5 Materialization modes\n\n`occurrence_materialization` controls when materialized occurrence notes are created.\nAllowed values:\n\n- `manual`: occurrence notes are created only by explicit user or API action.\n- `on_completion`: completing a materialized occurrence note creates the next occurrence note.\n- `rolling`: the implementation maintains a bounded materialized window, such as today through the next 14 days.\n\nIf absent, `occurrence_materialization` MUST default to `manual`.\n\n`on_completion` does not by itself create the first occurrence note in a series.\nThe first materialized occurrence MUST be created by explicit materialization, rolling materialization, or a documented create-time option.\n\nConforming implementations MUST NOT create occurrence notes merely as a side effect of read-only browsing.\n\n### 4.18.6 Next-occurrence trigger\n\n`occurrence_next_trigger` controls whether skip/cancel transitions also create the next occurrence note when `occurrence_materialization=on_completion`.\nAllowed values:\n\n- `completion`: only completion creates the next occurrence note.\n- `completion_or_skip`: completion and skip/cancel create the next occurrence note.\n\nIf absent, `occurrence_next_trigger` MUST default to `completion`.\n\nThe next occurrence MUST be computed from the parent recurring task after applying the triggering state transition and §4.4 anchor semantics.\nMaterializing the next occurrence MUST be idempotent: if the next occurrence note already exists, the operation MUST return or reuse it rather than creating a duplicate.\n\n### 4.18.7 Rolling materialization bounds\n\nFor `occurrence_materialization=rolling`, implementations MUST enforce finite bounds.\nUnbounded future materialization is non-conformant.\n\nBounds SHOULD be expressed with ISO 8601 durations such as:\n\n```yaml\noccurrence_past_horizon: P0D\noccurrence_future_horizon: P14D\n```\n\nIf bounds are absent and rolling mode is enabled, implementations MUST use documented finite defaults.\n\n### 4.18.8 Recurrence edits and historical notes\n\nMaterialized occurrence notes are durable task files.\nEditing the parent recurrence rule MUST NOT silently delete, rewrite, or move existing materialized occurrence notes.\n\nIf an existing occurrence note's `occurrence_date` is no longer generated by the current parent recurrence rule, validators MAY report `materialization_target_not_generated` as a warning.\nThis condition MUST NOT be treated as an error by default because recurrence edits can make historical notes intentionally non-generated.\n","aliases":["/spec/04-recurrence/"],"toc":[{"level":2,"id":"41-purpose","text":"4.1 Purpose"},{"level":2,"id":"42-recurrence-applicability","text":"4.2 Recurrence applicability"},{"level":2,"id":"43-rule-format","text":"4.3 Rule format"},{"level":3,"id":"431-required-format","text":"4.3.1 Required format"},{"level":3,"id":"432-invalid-rule-handling","text":"4.3.2 Invalid rule handling"},{"level":2,"id":"44-recurrence-anchor","text":"4.4 Recurrence anchor"},{"level":3,"id":"441-recurrence-seed-precedence","text":"4.4.1 Recurrence seed precedence"},{"level":3,"id":"442-anchor-progression-behavior","text":"4.4.2 Anchor progression behavior"},{"level":3,"id":"443-dtstart-update-semantics","text":"4.4.3 DTSTART update semantics"},{"level":3,"id":"444-recalculation-semantics-for-recurrenceanchorcompletion","text":"4.4.4 Recalculation semantics for recurrence_anchor=completion"},{"level":3,"id":"445-dtstart-canonicalization-on-recurring-writes","text":"4.4.5 DTSTART canonicalization on recurring writes"},{"level":2,"id":"45-instance-state-fields","text":"4.5 Instance state fields"},{"level":2,"id":"46-invariants","text":"4.6 Invariants"},{"level":2,"id":"47-instance-completion-semantics","text":"4.7 Instance completion semantics"},{"level":2,"id":"48-instance-uncompletion-semantics","text":"4.8 Instance uncompletion semantics"},{"level":2,"id":"49-instance-skip-semantics","text":"4.9 Instance skip semantics"},{"level":2,"id":"410-instance-unskip-semantics","text":"4.10 Instance unskip semantics"},{"level":2,"id":"411-effective-instance-state","text":"4.11 Effective instance state"},{"level":2,"id":"412-interaction-with-base-status","text":"4.12 Interaction with base status"},{"level":2,"id":"413-completed-status-configuration","text":"4.13 Completed-status configuration"},{"level":2,"id":"414-example-complete-then-skip-same-day","text":"4.14 Example: complete then skip same day"},{"level":2,"id":"415-example-idempotent-complete","text":"4.15 Example: idempotent complete"},{"level":2,"id":"416-example-anchor-semantics","text":"4.16 Example: anchor semantics"},{"level":2,"id":"417-validation-examples","text":"4.17 Validation examples"},{"level":2,"id":"418-recurrence-materialization","text":"4.18 Recurrence materialization"},{"level":3,"id":"4181-parent-and-occurrence-ownership","text":"4.18.1 Parent and occurrence ownership"},{"level":3,"id":"4182-occurrence-identity-and-parent-reference","text":"4.18.2 Occurrence identity and parent reference"},{"level":3,"id":"4183-effective-state-precedence","text":"4.18.3 Effective state precedence"},{"level":3,"id":"4184-parent-instance-lists-as-compatibility-state","text":"4.18.4 Parent instance lists as compatibility state"},{"level":3,"id":"4185-materialization-modes","text":"4.18.5 Materialization modes"},{"level":3,"id":"4186-next-occurrence-trigger","text":"4.18.6 Next-occurrence trigger"},{"level":3,"id":"4187-rolling-materialization-bounds","text":"4.18.7 Rolling materialization bounds"},{"level":3,"id":"4188-recurrence-edits-and-historical-notes","text":"4.18.8 Recurrence edits and historical notes"}],"html":"

4.1 Purpose#

\n

This section defines recurrence semantics, including rule representation, anchor behavior, and per-instance completion/skip state.

\n

4.2 Recurrence applicability#

\n

A task is recurring when semantic role recurrence contains a valid tasknotes recurrence string.

\n

If recurrence is absent or empty, the task is non-recurring.

\n

4.3 Rule format#

\n

4.3.1 Required format#

\n

recurrence MUST be a tasknotes recurrence string.\nThis syntax is RRULE-derived but is not a full RFC 5545 content line or multi-line iCalendar fragment.\nThe RRULE parameter portion MUST use RFC 5545 RRULE property syntax.\nIt MAY include a leading inline DTSTART segment.

\n

If DTSTART is present, it MUST use one of:

\n
    \n
  • DTSTART:YYYYMMDD (date-only)
  • \n
  • DTSTART:YYYYMMDDTHHMMSSZ (UTC datetime)
  • \n
\n

Canonical combined form is:

\n
    \n
  • DTSTART:...;FREQ=...
  • \n
\n

Implementations MAY accept inbound RRULE: prefixes or multi-line iCalendar-like inputs for compatibility, but canonical writes SHOULD use the combined single-field form above.

\n

Examples:

\n
    \n
  • FREQ=DAILY
  • \n
  • FREQ=WEEKLY;BYDAY=MO,WE,FR
  • \n
  • FREQ=MONTHLY;BYMONTHDAY=1
  • \n
  • DTSTART:20260220;FREQ=WEEKLY;BYDAY=FR
  • \n
\n

4.3.2 Invalid rule handling#

\n

Invalid recurrence rules MUST produce a validation error in strict mode and SHOULD produce at least a warning in permissive mode.

\n

4.4 Recurrence anchor#

\n

recurrence_anchor controls progression semantics and MUST be one of:

\n
    \n
  • scheduled
  • \n
  • completion
  • \n
\n

If missing, implementations SHOULD default to scheduled unless collection configuration defines another default.

\n

4.4.1 Recurrence seed precedence#

\n

When recurrence generation requires a seed/start date, implementations MUST resolve it in this order:

\n
    \n
  1. DTSTART embedded in recurrence,
  2. \n
  3. semantic scheduled,
  4. \n
  5. semantic date_created.
  6. \n
\n

If no seed can be resolved, recurrence materialization MUST fail deterministically and validation MUST report an error.

\n

4.4.2 Anchor progression behavior#

\n

For recurrence_anchor=scheduled, progression is based on the scheduled chain and DTSTART MUST remain fixed after it is set.

\n

For recurrence_anchor=completion, complete-instance operations MUST advance progression by updating DTSTART to the completion target (date or datetime per §4.4.3).

\n

4.4.3 DTSTART update semantics#

\n

When recurrence_anchor=completion and instance completion succeeds for resolved target day D:

\n
    \n
  1. Instance-list state (complete_instances, skipped_instances) MUST always use day D.
  2. \n
  3. If the caller provided an explicit datetime target, DTSTART MUST be rewritten as DTSTART:YYYYMMDDTHHMMSSZ using that target instant normalized to UTC.
  4. \n
  5. Otherwise, DTSTART MUST be rewritten as DTSTART:YYYYMMDD for day D.
  6. \n
  7. RRULE components other than DTSTART MUST be preserved unless an explicit recurrence-edit operation changes them.
  8. \n
  9. If DTSTART is absent, completion-anchor progression MUST insert it before RRULE parameters.
  10. \n
\n

4.4.4 Recalculation semantics for recurrence_anchor=completion#

\n

When calculating the next candidate occurrence for recurrence_anchor=completion:

\n
    \n
  1. Implementations MUST treat DTSTART progression as the consumed-history mechanism.
  2. \n
  3. complete_instances MUST NOT be used as an exclusion set for future occurrence selection in this mode.
  4. \n
  5. skipped_instances MUST still exclude matching candidate dates.
  6. \n
  7. Candidate selection MUST choose the first RRULE occurrence strictly after the current DTSTART anchor (or resolved seed if DTSTART is absent).
  8. \n
\n

This matches the completion-anchor progression model where each completion advances the chain by rewriting DTSTART.\nThis model is intentionally not fully reversible via ordinary uncomplete instance; progression history lives in DTSTART, not only in complete_instances.

\n

4.4.5 DTSTART canonicalization on recurring writes#

\n

To ensure stable recurrence materialization across implementations, writers that persist recurring tasks MUST ensure DTSTART is present after create or successful recurring-instance completion.

\n

Rules:

\n
    \n
  1. If persisted recurrence already contains DTSTART, keep it unless an explicit operation updates it per §4.4.3.
  2. \n
  3. If persisted recurrence omits DTSTART, writers MUST resolve a seed using §4.4.1 and insert DTSTART before RRULE parameters.
  4. \n
  5. For recurrence_anchor=scheduled, inserted DTSTART becomes the fixed progression baseline and MUST NOT be rewritten by later scheduled-anchor completions.
  6. \n
  7. If seed resolution fails, operation MUST fail deterministically and emit missing_recurrence_seed.
  8. \n
\n

4.5 Instance state fields#

\n

Per-instance state is represented by:

\n
    \n
  • complete_instances: list of date values
  • \n
  • skipped_instances: list of date values
  • \n
\n

These lists represent day-level instance outcomes.

\n

4.6 Invariants#

\n

Implementations MUST enforce:

\n
    \n
  1. Items in instance lists are valid date values.
  2. \n
  3. No date appears in both lists simultaneously.
  4. \n
  5. Duplicate dates are normalized (set semantics) or rejected deterministically.
  6. \n
  7. Validators MUST NOT reject an instance date solely because it is not an RRULE-generated occurrence.
  8. \n
\n

4.7 Instance completion semantics#

\n

Operation: complete instance for target date D.

\n

Conforming behavior:

\n
    \n
  1. Add D to complete_instances.
  2. \n
  3. Remove D from skipped_instances if present.
  4. \n
  5. Leave base task status unchanged unless explicit policy states otherwise.
  6. \n
  7. Update date_modified when state changes.
  8. \n
\n

Operation MUST be idempotent.

\n

4.8 Instance uncompletion semantics#

\n

Operation: uncomplete instance for target date D.

\n

Conforming behavior:

\n
    \n
  1. Remove D from complete_instances if present.
  2. \n
  3. Do not add D to skipped_instances implicitly.
  4. \n
  5. For recurrence_anchor=completion, uncomplete MUST NOT rewrite or roll back DTSTART; restoring prior progression requires an explicit recurrence edit or implementation-specific rewind operation.
  6. \n
  7. Update date_modified when state changes.
  8. \n
\n

Operation MUST be idempotent.

\n

4.9 Instance skip semantics#

\n

Operation: skip instance for target date D.

\n

Conforming behavior:

\n
    \n
  1. Add D to skipped_instances.
  2. \n
  3. Remove D from complete_instances if present.
  4. \n
  5. Update date_modified when state changes.
  6. \n
\n

Operation MUST be idempotent.

\n

4.10 Instance unskip semantics#

\n

Operation: unskip instance for target date D.

\n

Conforming behavior:

\n
    \n
  1. Remove D from skipped_instances if present.
  2. \n
  3. Do not add to complete_instances implicitly.
  4. \n
  5. Update date_modified when state changes.
  6. \n
\n

Operation MUST be idempotent.

\n

4.11 Effective instance state#

\n

For target date D, effective state MUST be resolved in this order:

\n
    \n
  1. If D in complete_instances: state is completed.
  2. \n
  3. Else if D in skipped_instances: state is skipped.
  4. \n
  5. Else: state is unresolved/default for that instance.
  6. \n
\n

Because overlap is invalid, this ordering is deterministic.

\n

4.12 Interaction with base status#

\n

For recurring tasks:

\n
    \n
  • Base status is task-level metadata and MUST NOT be forcibly rewritten to a completed status on instance completion unless explicitly configured.
  • \n
  • Instance state determines completion for recurrence-aware views and operations.
  • \n
  • Dependency blocked/unblocked evaluation for v0.1 follows §10.2.5 and is not recurrence-instance-aware unless explicitly extended by implementation policy.
  • \n
\n

For non-recurring tasks, completion uses base status semantics (§5).

\n

4.13 Completed-status configuration#

\n

Implementations MUST define which status values are treated as complete for non-recurring tasks.

\n

The completed-status list MUST be configurable or schema-driven and MUST NOT rely on a hardcoded single literal.

\n

4.14 Example: complete then skip same day#

\n

Initial:

\n
recurrence: FREQ=DAILY\ncompleteInstances: [2026-02-20]\nskippedInstances: []\n

Skip target date 2026-02-20:

\n
recurrence: FREQ=DAILY\ncompleteInstances: []\nskippedInstances: [2026-02-20]\n

4.15 Example: idempotent complete#

\n

Initial:

\n
completeInstances: [2026-02-20]\nskippedInstances: []\n

Complete 2026-02-20 again:

\n
    \n
  • persisted instance lists remain unchanged,
  • \n
  • operation succeeds without duplicate entries.
  • \n
\n

4.16 Example: anchor semantics#

\n

Task:

\n
recurrence: FREQ=WEEKLY;BYDAY=FR\nrecurrenceAnchor: completion\n

If implementation supports next-occurrence materialization, it MUST compute next occurrence relative to completion progression when anchor is completion, not solely by scheduled chain.\nImplementations using DTSTART progression MUST update DTSTART to the completion date for this mode.

\n

Worked example (recurrence_anchor=completion):

\n
recurrence: DTSTART:20260220;FREQ=DAILY\nrecurrence_anchor: completion\ncomplete_instances: [2026-02-20, 2026-02-21]\nskipped_instances: [2026-02-23]\n

Conforming recalculation:

\n
    \n
  • does not exclude 2026-02-22 because it is absent from skipped_instances,
  • \n
  • does exclude 2026-02-23 because it is skipped,
  • \n
  • ignores complete_instances for future exclusion in this mode (§4.4.4).
  • \n
\n

4.17 Validation examples#

\n

Invalid overlap:

\n
completeInstances: [2026-02-20]\nskippedInstances: [2026-02-20]\n

Result: validation error instance_state_overlap.

\n

Invalid date in list:

\n
completeInstances: [2026-02-30]\n

Result: validation error invalid_date_value.

\n

4.18 Recurrence materialization#

\n

This subsection is required only for implementations claiming profile materialized-occurrences (§7.3.4).

\n

Recurrence materialization creates ordinary task files for specific target dates of a recurring parent task.\nIt is additive behavior: implementations that do not claim materialized-occurrences continue to use the instance-list model in §4.5-§4.12.\nMaterialized occurrence notes MUST be task files according to the collection's task-detection rules (§9.7).

\n

4.18.1 Parent and occurrence ownership#

\n

The parent recurring task owns series-level semantics:

\n
    \n
  • recurrence
  • \n
  • recurrence_anchor
  • \n
  • recurrence generation and DTSTART progression
  • \n
  • parent instance-list compatibility state (complete_instances, skipped_instances)
  • \n
  • materialization policy fields (occurrence_materialization, occurrence_next_trigger, occurrence_template, occurrence_past_horizon, occurrence_future_horizon)
  • \n
\n

A materialized occurrence note owns per-date task semantics for its occurrence_date, including:

\n
    \n
  • status
  • \n
  • completed_date
  • \n
  • body content and checklists
  • \n
  • time_entries
  • \n
  • per-occurrence due, scheduled, reminders, contexts, projects, and unknown fields
  • \n
\n

4.18.2 Occurrence identity and parent reference#

\n

A materialized occurrence note MUST store:

\n
    \n
  • recurrence_parent: a link-or-string reference to the parent recurring task
  • \n
  • occurrence_date: the target date represented by the occurrence note
  • \n
\n

The preferred Obsidian-compatible representation for recurrence_parent is a wikilink, for example:

\n
recurrence_parent: "[[Weekly Review]]"\noccurrence_date: 2026-02-27\n

Implementations claiming materialized-occurrences MUST resolve recurrence_parent using §11 link semantics for this role, even if they do not claim full extended.\nIf the parent cannot be resolved, validation SHOULD report invalid_recurrence_parent.

\n

For one resolved parent, there SHOULD be at most one materialized occurrence note per occurrence_date.\nDuplicate detected occurrence notes SHOULD report duplicate_occurrence_note and MUST NOT be chosen nondeterministically for writes.

\n

4.18.3 Effective state precedence#

\n

For target date D, recurrence-aware effective state MUST be resolved in this order:

\n
    \n
  1. If a materialized occurrence note exists for (parent, D), derive state from that note's own task state:
      \n
    • completed when its status is in status.completed_values;
    • \n
    • skipped when its status is in status.skipped_values;
    • \n
    • otherwise unresolved/default for that instance.
    • \n
    \n
  2. \n
  3. Else if D is in parent complete_instances: state is completed.
  4. \n
  5. Else if D is in parent skipped_instances: state is skipped.
  6. \n
  7. Else: state is unresolved/default for that instance.
  8. \n
\n

If a materialized occurrence note disagrees with the parent instance lists, the materialized occurrence note wins for D.\nValidators SHOULD report occurrence_state_conflict, and repair/normalization operations MAY update parent lists to match occurrence notes.

\n

4.18.4 Parent instance lists as compatibility state#

\n

When materialized occurrence notes are supported, parent complete_instances and skipped_instances remain part of canonical persisted state.\nThey serve as interoperability state for unmaterialized occurrences and as a compatibility index for clients that do not read occurrence notes.

\n

Conforming writers SHOULD reconcile parent lists after materialized occurrence completion, skip, uncompletion, or unskip:

\n
    \n
  • completed child state: add D to complete_instances, remove D from skipped_instances;
  • \n
  • skipped child state: add D to skipped_instances, remove D from complete_instances;
  • \n
  • active/unresolved child state after uncompletion/unskip: remove D from the relevant parent list.
  • \n
\n

Reconciliation failure MUST NOT silently change the occurrence note state.\nImplementations SHOULD surface a recoverable error or warning.

\n

4.18.5 Materialization modes#

\n

occurrence_materialization controls when materialized occurrence notes are created.\nAllowed values:

\n
    \n
  • manual: occurrence notes are created only by explicit user or API action.
  • \n
  • on_completion: completing a materialized occurrence note creates the next occurrence note.
  • \n
  • rolling: the implementation maintains a bounded materialized window, such as today through the next 14 days.
  • \n
\n

If absent, occurrence_materialization MUST default to manual.

\n

on_completion does not by itself create the first occurrence note in a series.\nThe first materialized occurrence MUST be created by explicit materialization, rolling materialization, or a documented create-time option.

\n

Conforming implementations MUST NOT create occurrence notes merely as a side effect of read-only browsing.

\n

4.18.6 Next-occurrence trigger#

\n

occurrence_next_trigger controls whether skip/cancel transitions also create the next occurrence note when occurrence_materialization=on_completion.\nAllowed values:

\n
    \n
  • completion: only completion creates the next occurrence note.
  • \n
  • completion_or_skip: completion and skip/cancel create the next occurrence note.
  • \n
\n

If absent, occurrence_next_trigger MUST default to completion.

\n

The next occurrence MUST be computed from the parent recurring task after applying the triggering state transition and §4.4 anchor semantics.\nMaterializing the next occurrence MUST be idempotent: if the next occurrence note already exists, the operation MUST return or reuse it rather than creating a duplicate.

\n

4.18.7 Rolling materialization bounds#

\n

For occurrence_materialization=rolling, implementations MUST enforce finite bounds.\nUnbounded future materialization is non-conformant.

\n

Bounds SHOULD be expressed with ISO 8601 durations such as:

\n
occurrence_past_horizon: P0D\noccurrence_future_horizon: P14D\n

If bounds are absent and rolling mode is enabled, implementations MUST use documented finite defaults.

\n

4.18.8 Recurrence edits and historical notes#

\n

Materialized occurrence notes are durable task files.\nEditing the parent recurrence rule MUST NOT silently delete, rewrite, or move existing materialized occurrence notes.

\n

If an existing occurrence note's occurrence_date is no longer generated by the current parent recurrence rule, validators MAY report materialization_target_not_generated as a warning.\nThis condition MUST NOT be treated as an error by default because recurrence edits can make historical notes intentionally non-generated.

\n","text":"4.1 Purpose# This section defines recurrence semantics, including rule representation, anchor behavior, and per-instance completion/skip state. 4.2 Recurrence applicability# A task is recurring when semantic role recurrence contains a valid tasknotes recurrence string. If recurrence is absent or empty, the task is non-recurring. 4.3 Rule format# 4.3.1 Required format# recurrence MUST be a tasknotes recurrence string. This syntax is RRULE-derived but is not a full RFC 5545 content line or multi-line iCalendar fragment. The RRULE parameter portion MUST use RFC 5545 RRULE property syntax. It MAY include a leading inline DTSTART segment. If DTSTART is present, it MUST use one of: DTSTART:YYYYMMDD (date-only) DTSTART:YYYYMMDDTHHMMSSZ (UTC datetime) Canonical combined form is: DTSTART:...;FREQ=... Implementations MAY accept inbound RRULE: prefixes or multi-line iCalendar-like inputs for compatibility, but canonical writes SHOULD use the combined single-field form above. Examples: FREQ=DAILY FREQ=WEEKLY;BYDAY=MO,WE,FR FREQ=MONTHLY;BYMONTHDAY=1 DTSTART:20260220;FREQ=WEEKLY;BYDAY=FR 4.3.2 Invalid rule handling# Invalid recurrence rules MUST produce a validation error in strict mode and SHOULD produce at least a warning in permissive mode. 4.4 Recurrence anchor# recurrence_anchor controls progression semantics and MUST be one of: scheduled completion If missing, implementations SHOULD default to scheduled unless collection configuration defines another default. 4.4.1 Recurrence seed precedence# When recurrence generation requires a seed/start date, implementations MUST resolve it in this order: DTSTART embedded in recurrence, semantic scheduled, semantic date_created. If no seed can be resolved, recurrence materialization MUST fail deterministically and validation MUST report an error. 4.4.2 Anchor progression behavior# For recurrence_anchor=scheduled, progression is based on the scheduled chain and DTSTART MUST remain fixed after it is set. For recurrence_anchor=completion, complete-instance operations MUST advance progression by updating DTSTART to the completion target (date or datetime per §4.4.3). 4.4.3 DTSTART update semantics# When recurrence_anchor=completion and instance completion succeeds for resolved target day D: Instance-list state (complete_instances, skipped_instances) MUST always use day D. If the caller provided an explicit datetime target, DTSTART MUST be rewritten as DTSTART:YYYYMMDDTHHMMSSZ using that target instant normalized to UTC. Otherwise, DTSTART MUST be rewritten as DTSTART:YYYYMMDD for day D. RRULE components other than DTSTART MUST be preserved unless an explicit recurrence-edit operation changes them. If DTSTART is absent, completion-anchor progression MUST insert it before RRULE parameters. 4.4.4 Recalculation semantics for recurrence_anchor=completion# When calculating the next candidate occurrence for recurrence_anchor=completion: Implementations MUST treat DTSTART progression as the consumed-history mechanism. complete_instances MUST NOT be used as an exclusion set for future occurrence selection in this mode. skipped_instances MUST still exclude matching candidate dates. Candidate selection MUST choose the first RRULE occurrence strictly after the current DTSTART anchor (or resolved seed if DTSTART is absent). This matches the completion-anchor progression model where each completion advances the chain by rewriting DTSTART. This model is intentionally not fully reversible via ordinary uncomplete instance; progression history lives in DTSTART, not only in complete_instances. 4.4.5 DTSTART canonicalization on recurring writes# To ensure stable recurrence materialization across implementations, writers that persist recurring tasks MUST ensure DTSTART is present after create or successful recurring-instance completion. Rules: If persisted recurrence already contains DTSTART, keep it unless an explicit operation updates it per §4.4.3. If persisted recurrence omits DTSTART, writers MUST resolve a seed using §4.4.1 and insert DTSTART before RRULE parameters. For recurrence_anchor=scheduled, inserted DTSTART becomes the fixed progression baseline and MUST NOT be rewritten by later scheduled-anchor completions. If seed resolution fails, operation MUST fail deterministically and emit missing_recurrence_seed. 4.5 Instance state fields# Per-instance state is represented by: complete_instances: list of date values skipped_instances: list of date values These lists represent day-level instance outcomes. 4.6 Invariants# Implementations MUST enforce: Items in instance lists are valid date values. No date appears in both lists simultaneously. Duplicate dates are normalized (set semantics) or rejected deterministically. Validators MUST NOT reject an instance date solely because it is not an RRULE-generated occurrence. 4.7 Instance completion semantics# Operation: complete instance for target date D. Conforming behavior: Add D to complete_instances. Remove D from skipped_instances if present. Leave base task status unchanged unless explicit policy states otherwise. Update date_modified when state changes. Operation MUST be idempotent. 4.8 Instance uncompletion semantics# Operation: uncomplete instance for target date D. Conforming behavior: Remove D from complete_instances if present. Do not add D to skipped_instances implicitly. For recurrence_anchor=completion, uncomplete MUST NOT rewrite or roll back DTSTART; restoring prior progression requires an explicit recurrence edit or implementation-specific rewind operation. Update date_modified when state changes. Operation MUST be idempotent. 4.9 Instance skip semantics# Operation: skip instance for target date D. Conforming behavior: Add D to skipped_instances. Remove D from complete_instances if present. Update date_modified when state changes. Operation MUST be idempotent. 4.10 Instance unskip semantics# Operation: unskip instance for target date D. Conforming behavior: Remove D from skipped_instances if present. Do not add to complete_instances implicitly. Update date_modified when state changes. Operation MUST be idempotent. 4.11 Effective instance state# For target date D, effective state MUST be resolved in this order: If D in complete_instances: state is completed. Else if D in skipped_instances: state is skipped. Else: state is unresolved/default for that instance. Because overlap is invalid, this ordering is deterministic. 4.12 Interaction with base status# For recurring tasks: Base status is task-level metadata and MUST NOT be forcibly rewritten to a completed status on instance completion unless explicitly configured. Instance state determines completion for recurrence-aware views and operations. Dependency blocked/unblocked evaluation for v0.1 follows §10.2.5 and is not recurrence-instance-aware unless explicitly extended by implementation policy. For non-recurring tasks, completion uses base status semantics (§5). 4.13 Completed-status configuration# Implementations MUST define which status values are treated as complete for non-recurring tasks. The completed-status list MUST be configurable or schema-driven and MUST NOT rely on a hardcoded single literal. 4.14 Example: complete then skip same day# Initial: recurrence: FREQ=DAILY completeInstances: [2026-02-20] skippedInstances: [] Skip target date 2026-02-20: recurrence: FREQ=DAILY completeInstances: [] skippedInstances: [2026-02-20] 4.15 Example: idempotent complete# Initial: completeInstances: [2026-02-20] skippedInstances: [] Complete 2026-02-20 again: persisted instance lists remain unchanged, operation succeeds without duplicate entries. 4.16 Example: anchor semantics# Task: recurrence: FREQ=WEEKLY;BYDAY=FR recurrenceAnchor: completion If implementation supports next-occurrence materialization, it MUST compute next occurrence relative to completion progression when anchor is completion, not solely by scheduled chain. Implementations using DTSTART progression MUST update DTSTART to the completion date for this mode. Worked example (recurrence_anchor=completion): recurrence: DTSTART:20260220;FREQ=DAILY recurrence_anchor: completion complete_instances: [2026-02-20, 2026-02-21] skipped_instances: [2026-02-23] Conforming recalculation: does not exclude 2026-02-22 because it is absent from skipped_instances, does exclude 2026-02-23 because it is skipped, ignores complete_instances for future exclusion in this mode (§4.4.4). 4.17 Validation examples# Invalid overlap: completeInstances: [2026-02-20] skippedInstances: [2026-02-20] Result: validation error instance_state_overlap. Invalid date in list: completeInstances: [2026-02-30] Result: validation error invalid_date_value. 4.18 Recurrence materialization# This subsection is required only for implementations claiming profile materialized-occurrences (§7.3.4). Recurrence materialization creates ordinary task files for specific target dates of a recurring parent task. It is additive behavior: implementations that do not claim materialized-occurrences continue to use the instance-list model in §4.5-§4.12. Materialized occurrence notes MUST be task files according to the collection's task-detection rules (§9.7). 4.18.1 Parent and occurrence ownership# The parent recurring task owns series-level semantics: recurrence recurrence_anchor recurrence generation and DTSTART progression parent instance-list compatibility state (complete_instances, skipped_instances) materialization policy fields (occurrence_materialization, occurrence_next_trigger, occurrence_template, occurrence_past_horizon, occurrence_future_horizon) A materialized occurrence note owns per-date task semantics for its occurrence_date, including: status completed_date body content and checklists time_entries per-occurrence due, scheduled, reminders, contexts, projects, and unknown fields 4.18.2 Occurrence identity and parent reference# A materialized occurrence note MUST store: recurrence_parent: a link-or-string reference to the parent recurring task occurrence_date: the target date represented by the occurrence note The preferred Obsidian-compatible representation for recurrence_parent is a wikilink, for example: recurrence_parent: \"[[Weekly Review]]\" occurrence_date: 2026-02-27 Implementations claiming materialized-occurrences MUST resolve recurrence_parent using §11 link semantics for this role, even if they do not claim full extended. If the parent cannot be resolved, validation SHOULD report invalid_recurrence_parent. For one resolved parent, there SHOULD be at most one materialized occurrence note per occurrence_date. Duplicate detected occurrence notes SHOULD report duplicate_occurrence_note and MUST NOT be chosen nondeterministically for writes. 4.18.3 Effective state precedence# For target date D, recurrence-aware effective state MUST be resolved in this order: If a materialized occurrence note exists for (parent, D), derive state from that note's own task state: completed when its status is in status.completed_values; skipped when its status is in status.skipped_values; otherwise unresolved/default for that instance. Else if D is in parent complete_instances: state is completed. Else if D is in parent skipped_instances: state is skipped. Else: state is unresolved/default for that instance. If a materialized occurrence note disagrees with the parent instance lists, the materialized occurrence note wins for D. Validators SHOULD report occurrence_state_conflict, and repair/normalization operations MAY update parent lists to match occurrence notes. 4.18.4 Parent instance lists as compatibility state# When materialized occurrence notes are supported, parent complete_instances and skipped_instances remain part of canonical persisted state. They serve as interoperability state for unmaterialized occurrences and as a compatibility index for clients that do not read occurrence notes. Conforming writers SHOULD reconcile parent lists after materialized occurrence completion, skip, uncompletion, or unskip: completed child state: add D to complete_instances, remove D from skipped_instances; skipped child state: add D to skipped_instances, remove D from complete_instances; active/unresolved child state after uncompletion/unskip: remove D from the relevant parent list. Reconciliation failure MUST NOT silently change the occurrence note state. Implementations SHOULD surface a recoverable error or warning. 4.18.5 Materialization modes# occurrence_materialization controls when materialized occurrence notes are created. Allowed values: manual: occurrence notes are created only by explicit user or API action. on_completion: completing a materialized occurrence note creates the next occurrence note. rolling: the implementation maintains a bounded materialized window, such as today through the next 14 days. If absent, occurrence_materialization MUST default to manual. on_completion does not by itself create the first occurrence note in a series. The first materialized occurrence MUST be created by explicit materialization, rolling materialization, or a documented create-time option. Conforming implementations MUST NOT create occurrence notes merely as a side effect of read-only browsing. 4.18.6 Next-occurrence trigger# occurrence_next_trigger controls whether skip/cancel transitions also create the next occurrence note when occurrence_materialization=on_completion. Allowed values: completion: only completion creates the next occurrence note. completion_or_skip: completion and skip/cancel create the next occurrence note. If absent, occurrence_next_trigger MUST default to completion. The next occurrence MUST be computed from the parent recurring task after applying the triggering state transition and §4.4 anchor semantics. Materializing the next occurrence MUST be idempotent: if the next occurrence note already exists, the operation MUST return or reuse it rather than creating a duplicate. 4.18.7 Rolling materialization bounds# For occurrence_materialization=rolling, implementations MUST enforce finite bounds. Unbounded future materialization is non-conformant. Bounds SHOULD be expressed with ISO 8601 durations such as: occurrence_past_horizon: P0D occurrence_future_horizon: P14D If bounds are absent and rolling mode is enabled, implementations MUST use documented finite defaults. 4.18.8 Recurrence edits and historical notes# Materialized occurrence notes are durable task files. Editing the parent recurrence rule MUST NOT silently delete, rewrite, or move existing materialized occurrence notes. If an existing occurrence note's occurrence_date is no longer generated by the current parent recurrence rule, validators MAY report materialization_target_not_generated as a warning. This condition MUST NOT be treated as an error by default because recurrence edits can make historical notes intentionally non-generated."},{"route":"/developers/specification/05-operations/","title":"5. Operations","description":"This section defines normative behavior for task mutations and read-facing resolution concerns that affect persisted state.","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:05-operations.md","namespace":"specification","relativePath":"05-operations.md","raw":"# 5. Operations\n\n## 5.1 Purpose\n\nThis section defines normative behavior for task mutations and read-facing resolution concerns that affect persisted state.\n\n## 5.2 General operation rules\n\nFor all mutating operations:\n\n1. Validation MUST run before commit in strict mode.\n2. Writes MUST be atomic at file level (all-or-nothing per file).\n3. `date_modified` MUST be updated on successful state change.\n4. Unknown fields MUST be preserved unless explicit normalization is requested. This applies to every operation in this section: create, update, complete, uncomplete, skip, unskip, dependency mutations, reminder mutations, archive, and time-tracking operations.\n5. Operations identified as idempotent MUST remain safe under repetition.\n\n### 5.2.1 Target day/date resolution\n\nRecurring instance operations act on a target day/date (`complete instance`, `uncomplete instance`, `skip`, `unskip`).\nNon-recurring `complete` uses completion-day semantics for `completed_date`.\n\nResolution MUST be deterministic:\n\n1. If caller provides an explicit target date/datetime, that value is authoritative.\n2. If caller omits target for recurring instance operations, implementations MUST resolve in this order:\n - task `scheduled`, if present and target-day-resolvable,\n - else task `due`, if present and target-day-resolvable,\n - else current local day in active runtime timezone (§3.6).\n3. Target-day resolution for fallback task fields (`scheduled` / `due`) MUST use this extraction policy:\n - if stored value is canonical date (`YYYY-MM-DD`), use it as-is;\n - if stored value is datetime, use the literal date token before `T` (`YYYY-MM-DD`) without timezone shifting;\n - if stored value is non-canonical but accepted by compatibility policy, implementations MAY normalize to a date token and SHOULD emit a warning;\n - if a candidate value is unusable, continue to the next fallback source.\n4. For non-recurring complete, if caller omits explicit completion-day input, implementations MUST use current local day in active runtime timezone.\n\nWhen an explicit target is datetime:\n\n- operations that require day semantics MUST use its calendar date part in active runtime timezone,\n- for recurring `complete instance` with `recurrence_anchor=completion`, the same explicit datetime target MUST also drive `DTSTART` rewrite semantics in §4.4.3.\n\nThis explicit-target datetime rule is intentionally distinct from persisted-field fallback extraction above.\n\n### 5.2.2 Idempotency and `date_modified`\n\nFor operations marked idempotent:\n\n- first application MAY change state and `date_modified`,\n- repeated application with semantically equivalent input MUST leave persisted state unchanged.\n\nWhen a repeated idempotent operation is a no-op, `date_modified` MUST remain unchanged.\n\n## 5.3 Create\n\n### 5.3.1 Input requirements\n\nCreate MUST provide at minimum semantic roles required by §2, directly or via defaults.\n\n### 5.3.2 Required behavior\n\nCreate MUST:\n\n- apply default values,\n- generate `date_created` and `date_modified` when absent,\n- resolve semantic `title` and filename/path behavior according to §9.13,\n- apply create-time templating when enabled and supported (§5.3.5, §9.14, §7),\n- serialize canonical keys and canonical temporal formats,\n- when `recurrence` is present, canonicalize `DTSTART` per §4.4.5,\n- preserve caller-provided semantic `id` when present,\n- fail with validation errors if required constraints are unmet,\n- apply default reminders according to §10.3.9 when configured.\n\n### 5.3.3 Title and filename resolution on create\n\nCreate MUST produce a deterministic initial filename/path.\n\nRules:\n\n- Generated filenames MUST use filename-safe sanitization and MUST avoid invalid/empty basenames.\n- If `title.storage=filename`:\n - basename MUST derive from semantic title,\n - title changes after create are handled by update semantics (§5.4.4),\n - implementations MAY also persist mapped `title` as a synchronized compatibility mirror,\n - `title.filename_format` and `title.custom_filename_template` MUST be ignored.\n- If `title.storage=frontmatter`, create-time basename MUST follow `title.filename_format`:\n - `title`: sanitized semantic title,\n - `zettel`: implementation-defined zettel pattern (MUST be documented),\n - `timestamp`: implementation-defined timestamp pattern (MUST be documented),\n - `custom`: `title.custom_filename_template` expansion.\n- If generated path already exists, implementation MUST resolve collision deterministically (for example numeric suffixing).\n\n### 5.3.4 Example\n\nInput intent:\n\n```yaml\ntitle: \"Pay electricity bill\"\n```\n\nAssume defaults:\n\n- status default `open`\n- priority default `normal`\n\nPersisted frontmatter (example):\n\n```yaml\ntitle: Pay electricity bill\nstatus: open\npriority: normal\ndateCreated: 2026-02-20T14:00:00Z\ndateModified: 2026-02-20T14:00:00Z\n```\n\n### 5.3.5 Optional create-time templating\n\nThis subsection is required only for implementations claiming profile `templating` (§7.3.3).\n\nCreate-time templating pipeline MUST be deterministic:\n\n1. Compute base create payload from explicit input, defaults (§9.8), and generated/system values (`date_created`, `date_modified`, resolved title policy).\n2. Expand template variables using that base payload and active runtime date/time context.\n3. Merge template frontmatter into base frontmatter with base payload precedence (base keys MUST win on conflict).\n4. Resolve body output:\n - if expanded template body is non-empty, use it;\n - otherwise use caller-provided body/details (if any).\n\nTemplate parse rules:\n\n- If template content begins with `---`, implementations MUST treat the first `--- ... ---` block as template frontmatter and the remainder as template body.\n- Frontmatter variable expansion MUST run before YAML parsing of template frontmatter.\n\nPortable variable support:\n\nImplementations claiming `templating` MUST support all variables in the **Required** column of the table below. Implementations MAY support any variable in the **Extended** column.\n\n**Required task-data variables:**\n\n| Variable | Value | Format / separator |\n|---|---|---|\n| `{{title}}` | Semantic title | string; YAML-quoted if needed |\n| `{{status}}` | Task status value | string |\n| `{{priority}}` | Task priority value | string |\n| `{{dueDate}}` | Due date if set | `YYYY-MM-DD` or empty |\n| `{{scheduledDate}}` | Scheduled date if set | `YYYY-MM-DD` or empty |\n| `{{details}}` | Caller-provided body/description | string |\n| `{{contexts}}` | Contexts list | comma-separated, e.g. `\"work, home\"` |\n| `{{tags}}` | Tags list | comma-separated, e.g. `\"task, errands\"` |\n| `{{hashtags}}` | Tags list as hashtags | space-separated, e.g. `\"#task #errands\"` |\n| `{{timeEstimate}}` | Time estimate in minutes | integer string or empty |\n| `{{parentNote}}` | Parent note name/path | string; YAML-quoted if needed |\n\n**Required date/time variables (expansion time):**\n\n| Variable | Value | Format |\n|---|---|---|\n| `{{date}}` | Current date | `yyyy-MM-dd` |\n| `{{time}}` | Current time (24h) | `HH:mm` |\n| `{{year}}` | Full year | `yyyy` |\n| `{{month}}` | Month number | `MM` |\n| `{{day}}` | Day of month | `dd` |\n\n**Extended variables (optional):**\n\n| Variable | Value | Format |\n|---|---|---|\n| `{{dateTime}}` | Date + time | `yyyy-MM-dd-HHmm` |\n| `{{timestamp}}` | Full timestamp | `yyyy-MM-dd-HHmmss` |\n| `{{shortDate}}` | Short date | `yyMMdd` |\n| `{{shortYear}}` | Two-digit year | `yy` |\n| `{{monthName}}` | Month full name | e.g. `February` |\n| `{{monthNameShort}}` | Month short name | e.g. `Feb` |\n| `{{dayName}}` | Weekday full name | e.g. `Monday` |\n| `{{dayNameShort}}` | Weekday short name | e.g. `Mon` |\n| `{{week}}` | ISO week number | `ww` |\n| `{{quarter}}` | Quarter number | `1`–`4` |\n| `{{hour}}` | Hour (24h) | `HH` |\n| `{{minute}}` | Minute | `mm` |\n| `{{second}}` | Second | `ss` |\n| `{{time12}}` | Time with AM/PM | `hh:mm a` |\n| `{{time24}}` | Time (24h) | `HH:mm` |\n| `{{timezone}}` | UTC offset long | e.g. `+05:30` |\n| `{{utcOffset}}` | UTC offset long | e.g. `+05:30` |\n| `{{unix}}` | Unix timestamp (seconds) | integer string |\n| `{{unixMs}}` | Unix timestamp (ms) | integer string |\n| `{{zettel}}` | Zettelkasten ID | date + seconds-since-midnight base-36 |\n| `{{titleLower}}` | Title lowercase | string |\n| `{{titleUpper}}` | Title uppercase | string |\n| `{{titleSnake}}` | Title snake_case | string |\n| `{{titleKebab}}` | Title kebab-case | string |\n| `{{titleCamel}}` | Title camelCase | string |\n| `{{titlePascal}}` | Title PascalCase | string |\n| `{{priorityShort}}` | First letter of priority | uppercase char |\n| `{{statusShort}}` | First letter of status | uppercase char |\n\nUnknown variables (not in the above lists) MUST be handled per `templating.unknown_variable_policy` (§9.14):\n- `preserve`: leave the `{{...}}` placeholder as-is.\n- `empty`: replace with an empty string.\n\nDeterministic expansion context:\n\n- date/time variable expansion MUST use the active runtime timezone from §3.6.\n- locale-sensitive variables (`monthName`, `monthNameShort`, `dayName`, `dayNameShort`, `time12`) MUST use English locale outputs for portability (`January`, `Jan`, `Monday`, `Mon`, `AM`/`PM`).\n- template-generated datetime-like outputs used in frontmatter MUST normalize to second precision when written as canonical datetime roles (§3.3.2).\n\nFailure behavior:\n\n- `templating.failure_mode=error`: template read/parse failures MUST abort create.\n- `templating.failure_mode=warning_fallback`: template read/parse failures MUST continue create using non-templated behavior (base frontmatter + caller body/details) and SHOULD emit warnings (`template_missing` or `template_parse_failed`).\n\n### 5.3.6 Identity handling on create\n\nIf semantic `id` is provided on create, writers MUST preserve it.\nIf implementation supports auto-generation of semantic `id`, generation policy MUST be documented and resulting `id` MUST remain stable after create.\n\n## 5.4 Update\n\n### 5.4.1 Patch semantics\n\nUpdate MUST be patch-by-default: only targeted semantic roles are changed.\n\n### 5.4.2 Preservation rules\n\nUpdate MUST preserve:\n\n- unrelated known roles,\n- unknown fields,\n- original date/datetime granularity for untouched fields.\n\n### 5.4.3 Example\n\nBefore:\n\n```yaml\ntitle: Weekly review\nscheduled: 2026-02-20\npriority: normal\ncustomClient: ACME\n```\n\nOperation: set priority to `high`.\n\nAfter:\n\n```yaml\ntitle: Weekly review\nscheduled: 2026-02-20\npriority: high\ncustomClient: ACME\n```\n\n### 5.4.4 Title updates and filename updates\n\nIf an update changes semantic `title`, behavior MUST follow `title.storage`:\n\n- `title.storage=filename`: implementation MUST rename file basename to match updated title (with sanitization and deterministic collision handling), preserving parent folder unless caller requested a move.\n- `title.storage=frontmatter`: implementation MUST update mapped title field and MUST NOT rename file unless an explicit rename operation is requested.\n\nIf implementation keeps frontmatter title for compatibility while `title.storage=filename`, it MUST keep stored title synchronized with effective filename-derived title.\n\n## 5.5 Complete (non-recurring)\n\nFor non-recurring tasks, complete MUST:\n\n1. Set `status` to a configured completed value, unless already completed.\n If multiple completed values are configured, implementation MUST choose deterministically (default: first entry in `status.completed_values`).\n2. Set `completed_date` to completion day:\n - explicit completion-day input when provided,\n - otherwise current local day in active runtime timezone (§5.2.1).\n3. Apply overwrite policy deterministically (`overwrite` or `preserve_if_present`).\n4. Update `date_modified` on state change.\n\nImplementations MUST document completion-day input handling and `completed_date` overwrite policy.\n\nOperation MUST be idempotent.\n\n## 5.6 Uncomplete (non-recurring)\n\nFor non-recurring tasks, uncomplete MUST:\n\n1. Set `status` to configured active/default status according to policy (default: `status.default`).\n2. Clear or retain `completed_date` according to policy.\n3. Update `date_modified` on state change.\n\nPolicy MUST be documented and deterministic.\n\nOperation MUST be idempotent.\n\n## 5.7 Complete instance (recurring)\n\nFor recurring tasks, complete with resolved target date `D` (§5.2.1) MUST follow §4.7.\n\nWriters MUST NOT convert recurring completion into a base status rewrite unless explicit configuration requires it.\nWhen `recurrence_anchor=completion` and caller supplies an explicit datetime target, implementations MUST apply §4.4.3 datetime `DTSTART` rewrite behavior.\nWhen `recurrence_anchor=scheduled` and `DTSTART` is absent, implementations MUST insert `DTSTART` deterministically per §4.4.5.\nNext-occurrence recalculation in this mode MUST follow §4.4.4.\n\n## 5.8 Uncomplete instance (recurring)\n\nFor recurring tasks, uncomplete with resolved target date `D` (§5.2.1) MUST follow §4.8.\nFor `recurrence_anchor=completion`, ordinary uncomplete is intentionally non-reversible and MUST NOT roll back `DTSTART`.\n\n## 5.9 Skip and unskip instance\n\nSkip/unskip for recurring tasks with resolved target date `D` (§5.2.1) MUST follow §4.9 and §4.10.\n\n## 5.10 Dependency operations\n\nDependency operations MUST follow §10.2.\n\n### 5.10.1 Add dependency\n\nAdd dependency MUST:\n\n- validate dependency entry schema,\n- parse and resolve `uid` per §11,\n- enforce duplicate and self-reference rules,\n- preserve existing non-target dependency entries,\n- update `date_modified` on change.\n\n### 5.10.2 Remove dependency\n\nRemove dependency by `uid` MUST be idempotent.\n\n### 5.10.3 Replace dependency list\n\nReplace dependency list MUST be explicit (not default patch behavior).\n\n## 5.11 Reminder operations\n\nReminder operations MUST follow §10.3.\n\n### 5.11.1 Add reminder\n\nAdd reminder MUST:\n\n- validate reminder schema,\n- enforce unique `id` within task,\n- update `date_modified` on change.\n\n### 5.11.2 Update reminder\n\nUpdate reminder MUST target a reminder by `id` and be patch-by-default.\n\n### 5.11.3 Remove reminder\n\nRemove reminder by `id` MUST be idempotent.\n\n## 5.12 Archive\n\nImplementations MAY support archive semantics through:\n\n- archive tag,\n- archive status,\n- dedicated boolean/archive field.\n\nArchive behavior MUST be documented.\n\nArchive MUST NOT implicitly delete the task.\n\n## 5.13 Delete\n\nDelete MUST remove the task file.\n\nDelete MUST NOT implicitly delete files referenced by `attachments`. An\nimplementation MAY offer a separate, explicit cleanup action subject to\n§5.21.4.\n\nOptional safety behavior:\n\n- Implementations MAY perform backlink/dependency checks.\n- If checks are enabled, implementation MUST provide a bypass option for explicit force delete.\n\n## 5.14 Rename\n\nRename operation changes file path/filename while preserving semantic record identity.\n\n### 5.14.1 Rename interaction with title storage mode\n\n- If `title.storage=filename`, basename changes from rename MUST update effective semantic title.\n- If `title.storage=frontmatter`, rename MUST NOT implicitly rewrite mapped `title` unless explicitly requested.\n- Implementations that persist frontmatter title in `title.storage=filename` mode MUST either update that field on rename or remove it to prevent divergence.\n- If semantic `id` is present, rename/move MUST preserve its value unchanged.\n\nIf implementation supports link/reference updating, it MUST:\n\n- update resolvable references deterministically,\n- report unresolved or ambiguous updates,\n- update dependency `uid` and `projects` references consistently with normal links.\n\nIf implementation does not support reference updates, this limitation MUST be disclosed in conformance claim.\n\n## 5.15 Batch operations\n\nBatch operations MAY be supported.\n\nIf supported, implementation MUST report per-item outcomes and summary counts:\n\n- total\n- succeeded\n- failed\n\nPartial success behavior MUST be documented.\n\n## 5.16 Concurrency\n\nImplementations SHOULD provide write-conflict detection (for example based on modified timestamp or file hash).\n\nWhen conflict is detected, operation MUST fail safely unless explicit overwrite is requested.\n\n## 5.17 Dry run\n\nIf dry run mode is supported, operation MUST:\n\n- execute validation and transformation logic,\n- report intended changes,\n- perform no file write.\n\n## 5.18 Error model\n\nImplementation-native operation failures MUST provide structured error information with:\n\n- operation name,\n- error code,\n- message,\n- optional field/path context.\n\nFor conformance adapter envelopes (§5.23), failures MAY be represented as a compact `error` string for transport compatibility, but implementations SHOULD also expose the structured fields (for example via `error_details`).\n\n## 5.19 Time tracking management\n\nThis subsection applies to implementations that support `time_entries`.\n\n### 5.19.1 Start time tracking\n\nStart on task `T` MUST:\n\n- fail when `T` already has an active time entry,\n- append a new entry with canonical `startTime` and no `endTime`,\n- MAY set a default `description`,\n- update `date_modified`,\n- persist canonical `time_entries` shape (including removal of legacy/stale `duration` fields when normalizing).\n\nRecommended error code when already active: `time_tracking_already_active`.\n\n### 5.19.2 Stop time tracking\n\nStop on task `T` MUST:\n\n- fail when `T` has no active time entry,\n- set `endTime` on the active entry to canonical current datetime,\n- update `date_modified`,\n- preserve non-target entries and unknown frontmatter fields.\n\nRecommended error code when no active session exists: `no_active_time_entry`.\n\n### 5.19.3 Edit or replace time entries\n\nWhen replacing/editing `time_entries` explicitly, implementations MUST:\n\n- validate each entry per §2.6.1 and §3.11,\n- persist canonical datetime formats,\n- treat `duration` as derived compatibility input and SHOULD remove it from canonical writes,\n- update `date_modified` when persisted state changes.\n\n### 5.19.4 Remove a time entry\n\nRemove MUST target one deterministic entry (for example by index or stable selector) and update `date_modified` on change.\nSelector semantics MUST be documented.\n\n### 5.19.5 Completion-triggered auto-stop\n\nIf `time_tracking.auto_stop_on_complete=true` (§9.16), completion transitions MUST trigger stop behavior for the same task only.\n\nRules:\n\n- non-recurring tasks: trigger when status transitions from non-completed to completed status.\n- recurring tasks: trigger when `complete_instances` grows.\n- materialized occurrence notes: trigger on the occurrence note's own status transition to completed; parent reconciliation SHOULD NOT trigger a second stop on the parent unless the parent itself has an active time entry and the implementation documents that policy.\n- implementations MUST NOT stop active sessions on unrelated tasks.\n- if `time_tracking.auto_stop_notification=true`, implementations MAY emit a user-visible notice.\n\n### 5.19.6 Reporting tracked time\n\nFor reporting surfaces (for example task summaries or stats), implementations MUST document whether totals use `closed_minutes` or `live_minutes` semantics from §3.11.5.\n\n## 5.20 Recurrence materialization operations\n\nThis subsection is required only for implementations claiming profile `materialized-occurrences` (§7.3.4).\n\n### 5.20.1 Materialize occurrence\n\nOperation: `materialize occurrence` for parent recurring task `P` and target date `D`.\n\nConforming behavior:\n\n1. Resolve `P` and confirm it is recurring.\n2. If an occurrence note for `(P, D)` already exists, return that note without creating a duplicate.\n3. Create a task note using `occurrence_template` when configured, otherwise using normal create behavior.\n4. Persist `recurrence_parent` as a link to `P` and `occurrence_date` as `D`.\n5. Set `scheduled` to `D` unless caller input or template output explicitly supplies another per-occurrence scheduled value.\n6. Set initial `status` using normal create defaults unless caller input or template output explicitly supplies a status.\n7. Preserve template/body output as occurrence-owned content after creation.\n8. Update `date_created` and `date_modified` according to create semantics.\n\nThe operation MUST be idempotent for `(P, D)`.\n\nIf `D` is not generated by the current recurrence rule, implementations MAY allow materialization as an explicit user action but SHOULD report `materialization_target_not_generated`.\n\n### 5.20.2 Complete materialized occurrence\n\nCompleting a materialized occurrence note MUST:\n\n1. Complete the occurrence note using normal non-recurring completion semantics (§5.5).\n2. Reconcile the parent by adding `D` to `complete_instances` and removing `D` from `skipped_instances`.\n3. If the parent has `recurrence_anchor=completion`, advance parent progression according to §4.4.3 and §4.4.4.\n4. If `occurrence_materialization=on_completion`, compute the next occurrence from the parent after the completion transition and materialize that next occurrence note idempotently.\n\nThe occurrence note's successful completion MUST NOT be rolled back solely because next-occurrence materialization fails.\nWhen the next note cannot be created, implementations SHOULD report `next_occurrence_materialization_failed`.\n\n### 5.20.3 Skip materialized occurrence\n\nSkipping a materialized occurrence note MUST preserve the note.\nSkip is a state transition, not deletion.\n\nConforming behavior:\n\n1. Set the occurrence note to the configured skipped status (`status.default_skipped`, or the first `status.skipped_values` entry when `default_skipped` is absent).\n2. Clear or retain `completed_date` according to the same documented policy used for uncompletion unless the implementation documents a skip-specific policy.\n3. Reconcile the parent by adding `D` to `skipped_instances` and removing `D` from `complete_instances`.\n4. If `occurrence_materialization=on_completion` and `occurrence_next_trigger=completion_or_skip`, compute and materialize the next occurrence note idempotently.\n\nIf no skipped status is configured, skip of a materialized occurrence MUST fail deterministically in strict mode and SHOULD report `missing_skipped_status`.\n\n### 5.20.4 Uncomplete and unskip materialized occurrence\n\nUncomplete of a materialized occurrence note MUST:\n\n1. Reopen the occurrence note using normal uncomplete semantics (§5.6).\n2. Remove `D` from parent `complete_instances`.\n3. For `recurrence_anchor=completion`, MUST NOT roll back parent `DTSTART`, matching §4.8.\n4. MUST NOT delete any later materialized occurrence note.\n\nUnskip of a materialized occurrence note MUST:\n\n1. Reopen the occurrence note to configured active/default status.\n2. Remove `D` from parent `skipped_instances`.\n3. MUST NOT add `D` to parent `complete_instances` implicitly.\n4. MUST NOT delete any later materialized occurrence note.\n\n### 5.20.5 Delete and unmaterialize occurrence\n\nDeleting a materialized occurrence note removes the task file and MUST NOT be interpreted as skip.\n\nImplementations MAY provide an explicit `unmaterialize occurrence` operation.\nIf supported, it MUST document whether parent state is preserved, cleared, or reconciled.\nIn all cases, deleting or unmaterializing an occurrence MUST NOT silently delete the parent recurring task.\n\nIf parent instance lists still refer to a deleted occurrence note's date, validators MAY report an orphan/cache warning such as `orphan_occurrence_note`.\n\n## 5.21 Attachment operations\n\nThese rules apply to implementations that support the `attachments`\ncapability.\n\n### 5.21.1 Attach a file\n\nAttach MUST:\n\n1. durably write the binary to a collection path before publishing its task\n reference;\n2. add one canonical reference to the mapped `attachments` list;\n3. preserve the existing list order and append new references by default;\n4. avoid duplicate normalized targets; and\n5. update `date_modified` only when membership changes.\n\nBinary write and task-frontmatter update are not assumed to be one atomic\nstorage transaction. Implementations MUST make interrupted operations\nrecoverable or idempotently retryable. If the binary write succeeds but the\ntask update does not, the implementation MUST retain enough durable intent to\nretry or identify the unreferenced file for explicit cleanup.\n\n### 5.21.2 Detach a file\n\nDetach removes the matching reference from `attachments` and is idempotent.\nDetach MUST NOT delete the underlying file. It MUST preserve the relative order\nof all other references.\n\n### 5.21.3 Insert an attached file inline\n\nAn implementation MAY offer an inline-insert operation. It MUST first satisfy\nattach semantics, then insert a Markdown link or embed into the task body.\nRemoving that body markup MUST NOT detach the file; detaching MUST NOT silently\nrewrite body content unless the user explicitly requests both changes.\n\n### 5.21.4 Delete an attachment file\n\nPhysical deletion MUST be a distinct, explicit action. Before deleting, an\nimplementation MUST check authoritative, current task `attachments` lists and\nSHOULD check body links/embeds and other collection backlinks. A stale or\noffline replica is not sufficient evidence that a file is unreferenced. If the\nbinary authority and record authority can change independently, the check and\ndelete MUST use an authority-provided transaction or equivalent precondition\nthat closes the race. An implementation MUST NOT offer physical deletion when\nit cannot establish that guarantee; detach remains available and leaves a safe\norphan. If another reference exists, deletion MUST be rejected unless the\ncaller explicitly chooses a force action whose affected references are\ndisclosed.\n\nAfter a successful non-forced deletion, implementations MUST remove the\ncurrent task's matching attachment reference. Failed deletion MUST leave\nfrontmatter unchanged. An accepted local outbox entry is not a successful\nphysical deletion until the binary authority acknowledges it.\n\n### 5.21.5 Materialized occurrences\n\nWhen an occurrence note is materialized, it SHOULD inherit the parent task's\nattachment references in the same order. This copies references, not file\nbytes. Subsequent edits to either task's membership list are independent, and\nphysical deletion remains governed by §5.21.4.\n\n## 5.22 Operation examples\n\n### 5.22.1 Non-recurring complete\n\nBefore:\n\n```yaml\ntitle: Buy groceries\nstatus: open\ncompletedDate:\ndateModified: 2026-02-20T09:00:00Z\n```\n\nAfter complete on `2026-02-20`:\n\n```yaml\ntitle: Buy groceries\nstatus: done\ncompletedDate: 2026-02-20\ndateModified: 2026-02-20T09:05:00Z\n```\n\n### 5.22.2 Recurring complete instance\n\nBefore:\n\n```yaml\ntitle: Weekly review\nstatus: open\nscheduled: 2026-02-20\nrecurrence: FREQ=WEEKLY;BYDAY=FR\ncompleteInstances: []\nskippedInstances: []\ndateModified: 2026-02-20T08:00:00Z\n```\n\nAfter complete instance on `2026-02-20`:\n\n```yaml\ntitle: Weekly review\nstatus: open\nscheduled: 2026-02-20\nrecurrence: DTSTART:20260220;FREQ=WEEKLY;BYDAY=FR\ncompleteInstances: [2026-02-20]\nskippedInstances: []\ndateModified: 2026-02-20T08:10:00Z\n```\n\n### 5.22.3 Recurring skip instance overriding completion\n\nBefore:\n\n```yaml\ncompleteInstances: [2026-02-20]\nskippedInstances: []\n```\n\nAfter skip `2026-02-20`:\n\n```yaml\ncompleteInstances: []\nskippedInstances: [2026-02-20]\n```\n\n### 5.22.4 Preserve unknown fields on update\n\nBefore:\n\n```yaml\ntitle: Plan Q2\nstatus: open\nvendorTicket: ZX-42\n```\n\nUpdate status to `in-progress`.\n\nAfter:\n\n```yaml\ntitle: Plan Q2\nstatus: in-progress\nvendorTicket: ZX-42\n```\n\n### 5.22.5 Add dependency\n\nBefore:\n\n```yaml\nblockedBy: []\n```\n\nAdd dependency:\n\n```yaml\nuid: \"[[prepare-metrics]]\"\nreltype: FINISHTOSTART\n```\n\nAfter:\n\n```yaml\nblockedBy:\n - uid: \"[[prepare-metrics]]\"\n reltype: FINISHTOSTART\n```\n\n### 5.22.6 Add reminder\n\nBefore:\n\n```yaml\nreminders: []\n```\n\nAdd reminder:\n\n```yaml\nid: due_minus_1h\ntype: relative\nrelatedTo: due\noffset: -PT1H\n```\n\nAfter:\n\n```yaml\nreminders:\n - id: due_minus_1h\n type: relative\n relatedTo: due\n offset: -PT1H\n```\n\n## 5.23 Conformance operation interface\n\nThe conformance suite exercises operations via the `execute(operation, input) → envelope` interface defined in the adapter contract. This section specifies the input/output contracts for each conformance-testable operation name.\n\nUnless otherwise noted, all operations return `{ ok: true, result: {...} }` on success and `{ ok: false, error: \"...\" }` on failure. Adapters MAY additionally return `error_details` with structured fields from §5.18.\n\n### General operations\n\n#### `op.mutate_with_validation`\n\nTests §5.2 rule 1: validation runs before commit.\n\nInput:\n```json\n{ \"strict\": true, \"frontmatter\": { ... } }\n```\n\nBehavior: validate `frontmatter` as a task record. In strict mode (`strict=true`), any validation error MUST produce `ok=false`.\n\nOutput on validation error:\n```json\n{ \"ok\": false, \"error\": \"validation|invalid_type|...\" }\n```\n\n---\n\n#### `op.atomic_write`\n\nTests §5.2 rule 2: writes are all-or-nothing.\n\nInput:\n```json\n{\n \"original\": { ... },\n \"patch\": { ... },\n \"simulateFailureAfterWrite\": true\n}\n```\n\nBehavior: apply `patch` to `original`, then simulate a post-write failure. The adapter MUST report whether the write was committed and what state the record is in after recovery.\n\nOutput:\n```json\n{\n \"ok\": true,\n \"result\": {\n \"committed\": false,\n \"persisted\": { ... }\n }\n}\n```\n\n`committed=false` means the write was rolled back. `persisted` reflects the actual frontmatter after recovery — it MUST match `original` (not the patched version) when `simulateFailureAfterWrite=true`.\n\n---\n\n#### `op.idempotency_check`\n\nTests §5.2 rule 5: operations are safe under repetition.\n\nInput:\n```json\n{\n \"operation\": \"complete_nonrecurring\",\n \"first\": { \"status\": \"open\", \"completedDate\": null },\n \"second\": { \"status\": \"done\", \"completedDate\": \"2026-02-20\" }\n}\n```\n\nBehavior: applying the named operation to `first` state and then again to `second` state MUST produce identical persisted results (including unchanged `dateModified` on the second no-op application). The adapter checks whether this holds.\n\nOutput:\n```json\n{ \"ok\": true, \"result\": { \"idempotent\": true } }\n```\n\n---\n\n#### `op.update_patch`\n\nTests §5.4 patch semantics and unknown-field preservation.\n\nInput:\n```json\n{\n \"original\": { \"title\": \"...\", \"vendorTicket\": \"ZX-42\", ... },\n \"patch\": { \"priority\": \"high\" },\n \"changed\": true\n}\n```\n\nBehavior: apply `patch` to `original`. Return the merged frontmatter.\n\nOutput:\n```json\n{\n \"ok\": true,\n \"result\": {\n \"changed\": true,\n \"frontmatter\": { \"title\": \"...\", \"priority\": \"high\", \"vendorTicket\": \"ZX-42\", ... }\n }\n}\n```\n\n- `changed` indicates whether any field actually changed value.\n- `frontmatter` MUST include all unknown fields from `original` unchanged.\n\n---\n\n#### `op.complete_nonrecurring`\n\nTests §5.5 non-recurring completion.\n\nInput:\n```json\n{\n \"frontmatter\": { \"title\": \"...\", \"status\": \"open\" },\n \"completedValues\": [\"done\", \"cancelled\"],\n \"explicitDate\": \"2026-02-20\"\n}\n```\n\nBehavior: apply a complete operation to `frontmatter` using `completedValues` (ordered list) and `explicitDate` as the completion day (omit to use current local day).\n\nOutput:\n```json\n{ \"ok\": true, \"result\": { \"status\": \"done\", \"completedDate\": \"2026-02-20\" } }\n```\n\n- `status` MUST be the first entry in `completedValues`.\n- `completedDate` MUST be `explicitDate` if provided; otherwise a valid `YYYY-MM-DD` date.\n- If `frontmatter.status` is already a completed value, the operation MUST still succeed (idempotent).\n\n---\n\n#### `op.uncomplete_nonrecurring`\n\nTests §5.6 non-recurring uncompletion.\n\nInput:\n```json\n{\n \"frontmatter\": { \"title\": \"...\", \"status\": \"done\", \"completedDate\": \"2026-02-20\" },\n \"defaultStatus\": \"open\",\n \"clearCompletedDate\": true\n}\n```\n\nOutput:\n```json\n{ \"ok\": true, \"result\": { \"status\": \"open\", \"completedDate\": null } }\n```\n\n- `status` MUST be `defaultStatus`.\n- If `clearCompletedDate=true`, `completedDate` MUST be `null` in the result.\n- If `clearCompletedDate=false`, `completedDate` MUST be preserved.\n\n---\n\n#### `op.error_shape`\n\nTests §5.18 error model.\n\nInput:\n```json\n{ \"operation\": \"update\", \"code\": \"invalid_type\", \"message\": \"bad value\", \"field\": \"status\" }\n```\n\nBehavior: construct and return a structured error object.\n\nOutput:\n```json\n{\n \"ok\": true,\n \"result\": {\n \"operation\": \"update\",\n \"code\": \"invalid_type\",\n \"message\": \"...\"\n }\n}\n```\n\nThe `message` field MUST be a non-empty string. The `operation` and `code` fields MUST match the input.\n\n---\n\n#### `op.detect_conflict`\n\nTests §5.16 write-conflict detection.\n\nInput:\n```json\n{ \"expectedVersion\": \"a\", \"actualVersion\": \"b\", \"overwrite\": false }\n```\n\nBehavior: when `expectedVersion != actualVersion` and `overwrite=false`, the operation MUST fail.\n\nOutput on conflict:\n```json\n{ \"ok\": false, \"error\": \"conflict|write_conflict|...\" }\n```\n\n---\n\n#### `op.dry_run`\n\nTests §5.17 dry-run mode.\n\nInput:\n```json\n{ \"operation\": \"update\", \"patch\": { \"status\": \"done\" } }\n```\n\nOutput:\n```json\n{\n \"ok\": true,\n \"result\": {\n \"wrote\": false,\n \"plannedChanges\": [\"status\", ...]\n }\n}\n```\n\n`wrote` MUST be `false`. `plannedChanges` MUST list the field names that would have changed.\n\n---\n\n### Recurrence operations\n\nFor `recurrence.complete`, `recurrence.uncomplete_instance`, `recurrence.skip_instance`, `recurrence.unskip_instance`, and `recurrence.effective_state`, the input and output contracts are defined by the respective sections of §4 and §5.7–5.9.\n\nCommon input fields for recurrence operations:\n- `targetDate` or `completionDate`: `YYYY-MM-DD` target day\n- `completeInstances`: current list of completed dates\n- `skippedInstances`: current list of skipped dates\n\n`recurrence.effective_state` output:\n```json\n{ \"ok\": true, \"result\": { \"value\": \"completed|skipped|open\" } }\n```\n\n---\n\n### Materialized occurrence operations\n\nFor `occurrence.materialize`, `occurrence.complete`, `occurrence.skip`, `occurrence.uncomplete`, `occurrence.unskip`, and `occurrence.unmaterialize`, input and output contracts are defined by §4.18 and §5.20.\n\nCommon input fields for materialized occurrence operations:\n- `parent`: frontmatter/path/link object for the recurring parent task\n- `occurrence`: frontmatter/path/link object for an existing occurrence note when applicable\n- `targetDate`: `YYYY-MM-DD` target day\n- `config`: effective occurrence/status configuration needed by the operation\n\n`occurrence.materialize` output:\n```json\n{ \"ok\": true, \"result\": { \"created\": true, \"occurrence\": { \"...\": \"...\" } } }\n```\n\n`created` MUST be `false` when the operation returns an already-existing occurrence note for the same parent/date.\n\n---\n\n### Time-tracking operations\n\nFor `time.start`, `time.stop`, `time.replace_entries`, `time.remove_entry`, `time.auto_stop_on_complete`, and `time.report_totals`, the contracts are defined by §5.19.\n\nCommon input patterns:\n- `entries`: current `time_entries` array\n- `now`: ISO 8601 datetime representing current instant\n- `dateModified`: current `date_modified` value\n\n`time.report_totals` output:\n```json\n{ \"ok\": true, \"result\": { \"closed_minutes\": N, \"live_minutes\": M } }\n```\n\n`live_minutes` is only present when an active (no `endTime`) entry exists.\n","aliases":["/spec/05-operations/"],"toc":[{"level":2,"id":"51-purpose","text":"5.1 Purpose"},{"level":2,"id":"52-general-operation-rules","text":"5.2 General operation rules"},{"level":3,"id":"521-target-daydate-resolution","text":"5.2.1 Target day/date resolution"},{"level":3,"id":"522-idempotency-and-datemodified","text":"5.2.2 Idempotency and date_modified"},{"level":2,"id":"53-create","text":"5.3 Create"},{"level":3,"id":"531-input-requirements","text":"5.3.1 Input requirements"},{"level":3,"id":"532-required-behavior","text":"5.3.2 Required behavior"},{"level":3,"id":"533-title-and-filename-resolution-on-create","text":"5.3.3 Title and filename resolution on create"},{"level":3,"id":"534-example","text":"5.3.4 Example"},{"level":3,"id":"535-optional-create-time-templating","text":"5.3.5 Optional create-time templating"},{"level":3,"id":"536-identity-handling-on-create","text":"5.3.6 Identity handling on create"},{"level":2,"id":"54-update","text":"5.4 Update"},{"level":3,"id":"541-patch-semantics","text":"5.4.1 Patch semantics"},{"level":3,"id":"542-preservation-rules","text":"5.4.2 Preservation rules"},{"level":3,"id":"543-example","text":"5.4.3 Example"},{"level":3,"id":"544-title-updates-and-filename-updates","text":"5.4.4 Title updates and filename updates"},{"level":2,"id":"55-complete-non-recurring","text":"5.5 Complete (non-recurring)"},{"level":2,"id":"56-uncomplete-non-recurring","text":"5.6 Uncomplete (non-recurring)"},{"level":2,"id":"57-complete-instance-recurring","text":"5.7 Complete instance (recurring)"},{"level":2,"id":"58-uncomplete-instance-recurring","text":"5.8 Uncomplete instance (recurring)"},{"level":2,"id":"59-skip-and-unskip-instance","text":"5.9 Skip and unskip instance"},{"level":2,"id":"510-dependency-operations","text":"5.10 Dependency operations"},{"level":3,"id":"5101-add-dependency","text":"5.10.1 Add dependency"},{"level":3,"id":"5102-remove-dependency","text":"5.10.2 Remove dependency"},{"level":3,"id":"5103-replace-dependency-list","text":"5.10.3 Replace dependency list"},{"level":2,"id":"511-reminder-operations","text":"5.11 Reminder operations"},{"level":3,"id":"5111-add-reminder","text":"5.11.1 Add reminder"},{"level":3,"id":"5112-update-reminder","text":"5.11.2 Update reminder"},{"level":3,"id":"5113-remove-reminder","text":"5.11.3 Remove reminder"},{"level":2,"id":"512-archive","text":"5.12 Archive"},{"level":2,"id":"513-delete","text":"5.13 Delete"},{"level":2,"id":"514-rename","text":"5.14 Rename"},{"level":3,"id":"5141-rename-interaction-with-title-storage-mode","text":"5.14.1 Rename interaction with title storage mode"},{"level":2,"id":"515-batch-operations","text":"5.15 Batch operations"},{"level":2,"id":"516-concurrency","text":"5.16 Concurrency"},{"level":2,"id":"517-dry-run","text":"5.17 Dry run"},{"level":2,"id":"518-error-model","text":"5.18 Error model"},{"level":2,"id":"519-time-tracking-management","text":"5.19 Time tracking management"},{"level":3,"id":"5191-start-time-tracking","text":"5.19.1 Start time tracking"},{"level":3,"id":"5192-stop-time-tracking","text":"5.19.2 Stop time tracking"},{"level":3,"id":"5193-edit-or-replace-time-entries","text":"5.19.3 Edit or replace time entries"},{"level":3,"id":"5194-remove-a-time-entry","text":"5.19.4 Remove a time entry"},{"level":3,"id":"5195-completion-triggered-auto-stop","text":"5.19.5 Completion-triggered auto-stop"},{"level":3,"id":"5196-reporting-tracked-time","text":"5.19.6 Reporting tracked time"},{"level":2,"id":"520-recurrence-materialization-operations","text":"5.20 Recurrence materialization operations"},{"level":3,"id":"5201-materialize-occurrence","text":"5.20.1 Materialize occurrence"},{"level":3,"id":"5202-complete-materialized-occurrence","text":"5.20.2 Complete materialized occurrence"},{"level":3,"id":"5203-skip-materialized-occurrence","text":"5.20.3 Skip materialized occurrence"},{"level":3,"id":"5204-uncomplete-and-unskip-materialized-occurrence","text":"5.20.4 Uncomplete and unskip materialized occurrence"},{"level":3,"id":"5205-delete-and-unmaterialize-occurrence","text":"5.20.5 Delete and unmaterialize occurrence"},{"level":2,"id":"521-attachment-operations","text":"5.21 Attachment operations"},{"level":3,"id":"5211-attach-a-file","text":"5.21.1 Attach a file"},{"level":3,"id":"5212-detach-a-file","text":"5.21.2 Detach a file"},{"level":3,"id":"5213-insert-an-attached-file-inline","text":"5.21.3 Insert an attached file inline"},{"level":3,"id":"5214-delete-an-attachment-file","text":"5.21.4 Delete an attachment file"},{"level":3,"id":"5215-materialized-occurrences","text":"5.21.5 Materialized occurrences"},{"level":2,"id":"522-operation-examples","text":"5.22 Operation examples"},{"level":3,"id":"5221-non-recurring-complete","text":"5.22.1 Non-recurring complete"},{"level":3,"id":"5222-recurring-complete-instance","text":"5.22.2 Recurring complete instance"},{"level":3,"id":"5223-recurring-skip-instance-overriding-completion","text":"5.22.3 Recurring skip instance overriding completion"},{"level":3,"id":"5224-preserve-unknown-fields-on-update","text":"5.22.4 Preserve unknown fields on update"},{"level":3,"id":"5225-add-dependency","text":"5.22.5 Add dependency"},{"level":3,"id":"5226-add-reminder","text":"5.22.6 Add reminder"},{"level":2,"id":"523-conformance-operation-interface","text":"5.23 Conformance operation interface"},{"level":3,"id":"general-operations","text":"General operations"},{"level":3,"id":"recurrence-operations","text":"Recurrence operations"},{"level":3,"id":"materialized-occurrence-operations","text":"Materialized occurrence operations"},{"level":3,"id":"time-tracking-operations","text":"Time-tracking operations"}],"html":"

5.1 Purpose#

\n

This section defines normative behavior for task mutations and read-facing resolution concerns that affect persisted state.

\n

5.2 General operation rules#

\n

For all mutating operations:

\n
    \n
  1. Validation MUST run before commit in strict mode.
  2. \n
  3. Writes MUST be atomic at file level (all-or-nothing per file).
  4. \n
  5. date_modified MUST be updated on successful state change.
  6. \n
  7. Unknown fields MUST be preserved unless explicit normalization is requested. This applies to every operation in this section: create, update, complete, uncomplete, skip, unskip, dependency mutations, reminder mutations, archive, and time-tracking operations.
  8. \n
  9. Operations identified as idempotent MUST remain safe under repetition.
  10. \n
\n

5.2.1 Target day/date resolution#

\n

Recurring instance operations act on a target day/date (complete instance, uncomplete instance, skip, unskip).\nNon-recurring complete uses completion-day semantics for completed_date.

\n

Resolution MUST be deterministic:

\n
    \n
  1. If caller provides an explicit target date/datetime, that value is authoritative.
  2. \n
  3. If caller omits target for recurring instance operations, implementations MUST resolve in this order:
      \n
    • task scheduled, if present and target-day-resolvable,
    • \n
    • else task due, if present and target-day-resolvable,
    • \n
    • else current local day in active runtime timezone (§3.6).
    • \n
    \n
  4. \n
  5. Target-day resolution for fallback task fields (scheduled / due) MUST use this extraction policy:
      \n
    • if stored value is canonical date (YYYY-MM-DD), use it as-is;
    • \n
    • if stored value is datetime, use the literal date token before T (YYYY-MM-DD) without timezone shifting;
    • \n
    • if stored value is non-canonical but accepted by compatibility policy, implementations MAY normalize to a date token and SHOULD emit a warning;
    • \n
    • if a candidate value is unusable, continue to the next fallback source.
    • \n
    \n
  6. \n
  7. For non-recurring complete, if caller omits explicit completion-day input, implementations MUST use current local day in active runtime timezone.
  8. \n
\n

When an explicit target is datetime:

\n
    \n
  • operations that require day semantics MUST use its calendar date part in active runtime timezone,
  • \n
  • for recurring complete instance with recurrence_anchor=completion, the same explicit datetime target MUST also drive DTSTART rewrite semantics in §4.4.3.
  • \n
\n

This explicit-target datetime rule is intentionally distinct from persisted-field fallback extraction above.

\n

5.2.2 Idempotency and date_modified#

\n

For operations marked idempotent:

\n
    \n
  • first application MAY change state and date_modified,
  • \n
  • repeated application with semantically equivalent input MUST leave persisted state unchanged.
  • \n
\n

When a repeated idempotent operation is a no-op, date_modified MUST remain unchanged.

\n

5.3 Create#

\n

5.3.1 Input requirements#

\n

Create MUST provide at minimum semantic roles required by §2, directly or via defaults.

\n

5.3.2 Required behavior#

\n

Create MUST:

\n
    \n
  • apply default values,
  • \n
  • generate date_created and date_modified when absent,
  • \n
  • resolve semantic title and filename/path behavior according to §9.13,
  • \n
  • apply create-time templating when enabled and supported (§5.3.5, §9.14, §7),
  • \n
  • serialize canonical keys and canonical temporal formats,
  • \n
  • when recurrence is present, canonicalize DTSTART per §4.4.5,
  • \n
  • preserve caller-provided semantic id when present,
  • \n
  • fail with validation errors if required constraints are unmet,
  • \n
  • apply default reminders according to §10.3.9 when configured.
  • \n
\n

5.3.3 Title and filename resolution on create#

\n

Create MUST produce a deterministic initial filename/path.

\n

Rules:

\n
    \n
  • Generated filenames MUST use filename-safe sanitization and MUST avoid invalid/empty basenames.
  • \n
  • If title.storage=filename:
      \n
    • basename MUST derive from semantic title,
    • \n
    • title changes after create are handled by update semantics (§5.4.4),
    • \n
    • implementations MAY also persist mapped title as a synchronized compatibility mirror,
    • \n
    • title.filename_format and title.custom_filename_template MUST be ignored.
    • \n
    \n
  • \n
  • If title.storage=frontmatter, create-time basename MUST follow title.filename_format:
      \n
    • title: sanitized semantic title,
    • \n
    • zettel: implementation-defined zettel pattern (MUST be documented),
    • \n
    • timestamp: implementation-defined timestamp pattern (MUST be documented),
    • \n
    • custom: title.custom_filename_template expansion.
    • \n
    \n
  • \n
  • If generated path already exists, implementation MUST resolve collision deterministically (for example numeric suffixing).
  • \n
\n

5.3.4 Example#

\n

Input intent:

\n
title: "Pay electricity bill"\n

Assume defaults:

\n
    \n
  • status default open
  • \n
  • priority default normal
  • \n
\n

Persisted frontmatter (example):

\n
title: Pay electricity bill\nstatus: open\npriority: normal\ndateCreated: 2026-02-20T14:00:00Z\ndateModified: 2026-02-20T14:00:00Z\n

5.3.5 Optional create-time templating#

\n

This subsection is required only for implementations claiming profile templating (§7.3.3).

\n

Create-time templating pipeline MUST be deterministic:

\n
    \n
  1. Compute base create payload from explicit input, defaults (§9.8), and generated/system values (date_created, date_modified, resolved title policy).
  2. \n
  3. Expand template variables using that base payload and active runtime date/time context.
  4. \n
  5. Merge template frontmatter into base frontmatter with base payload precedence (base keys MUST win on conflict).
  6. \n
  7. Resolve body output:
      \n
    • if expanded template body is non-empty, use it;
    • \n
    • otherwise use caller-provided body/details (if any).
    • \n
    \n
  8. \n
\n

Template parse rules:

\n
    \n
  • If template content begins with ---, implementations MUST treat the first --- ... --- block as template frontmatter and the remainder as template body.
  • \n
  • Frontmatter variable expansion MUST run before YAML parsing of template frontmatter.
  • \n
\n

Portable variable support:

\n

Implementations claiming templating MUST support all variables in the Required column of the table below. Implementations MAY support any variable in the Extended column.

\n

Required task-data variables:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableValueFormat / separator
{{title}}Semantic titlestring; YAML-quoted if needed
{{status}}Task status valuestring
{{priority}}Task priority valuestring
{{dueDate}}Due date if setYYYY-MM-DD or empty
{{scheduledDate}}Scheduled date if setYYYY-MM-DD or empty
{{details}}Caller-provided body/descriptionstring
{{contexts}}Contexts listcomma-separated, e.g. "work, home"
{{tags}}Tags listcomma-separated, e.g. "task, errands"
{{hashtags}}Tags list as hashtagsspace-separated, e.g. "#task #errands"
{{timeEstimate}}Time estimate in minutesinteger string or empty
{{parentNote}}Parent note name/pathstring; YAML-quoted if needed
\n

Required date/time variables (expansion time):

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableValueFormat
{{date}}Current dateyyyy-MM-dd
{{time}}Current time (24h)HH:mm
{{year}}Full yearyyyy
{{month}}Month numberMM
{{day}}Day of monthdd
\n

Extended variables (optional):

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableValueFormat
{{dateTime}}Date + timeyyyy-MM-dd-HHmm
{{timestamp}}Full timestampyyyy-MM-dd-HHmmss
{{shortDate}}Short dateyyMMdd
{{shortYear}}Two-digit yearyy
{{monthName}}Month full namee.g. February
{{monthNameShort}}Month short namee.g. Feb
{{dayName}}Weekday full namee.g. Monday
{{dayNameShort}}Weekday short namee.g. Mon
{{week}}ISO week numberww
{{quarter}}Quarter number1–4
{{hour}}Hour (24h)HH
{{minute}}Minutemm
{{second}}Secondss
{{time12}}Time with AM/PMhh:mm a
{{time24}}Time (24h)HH:mm
{{timezone}}UTC offset longe.g. +05:30
{{utcOffset}}UTC offset longe.g. +05:30
{{unix}}Unix timestamp (seconds)integer string
{{unixMs}}Unix timestamp (ms)integer string
{{zettel}}Zettelkasten IDdate + seconds-since-midnight base-36
{{titleLower}}Title lowercasestring
{{titleUpper}}Title uppercasestring
{{titleSnake}}Title snake_casestring
{{titleKebab}}Title kebab-casestring
{{titleCamel}}Title camelCasestring
{{titlePascal}}Title PascalCasestring
{{priorityShort}}First letter of priorityuppercase char
{{statusShort}}First letter of statusuppercase char
\n

Unknown variables (not in the above lists) MUST be handled per templating.unknown_variable_policy (§9.14):

\n
    \n
  • preserve: leave the {{...}} placeholder as-is.
  • \n
  • empty: replace with an empty string.
  • \n
\n

Deterministic expansion context:

\n
    \n
  • date/time variable expansion MUST use the active runtime timezone from §3.6.
  • \n
  • locale-sensitive variables (monthName, monthNameShort, dayName, dayNameShort, time12) MUST use English locale outputs for portability (January, Jan, Monday, Mon, AM/PM).
  • \n
  • template-generated datetime-like outputs used in frontmatter MUST normalize to second precision when written as canonical datetime roles (§3.3.2).
  • \n
\n

Failure behavior:

\n
    \n
  • templating.failure_mode=error: template read/parse failures MUST abort create.
  • \n
  • templating.failure_mode=warning_fallback: template read/parse failures MUST continue create using non-templated behavior (base frontmatter + caller body/details) and SHOULD emit warnings (template_missing or template_parse_failed).
  • \n
\n

5.3.6 Identity handling on create#

\n

If semantic id is provided on create, writers MUST preserve it.\nIf implementation supports auto-generation of semantic id, generation policy MUST be documented and resulting id MUST remain stable after create.

\n

5.4 Update#

\n

5.4.1 Patch semantics#

\n

Update MUST be patch-by-default: only targeted semantic roles are changed.

\n

5.4.2 Preservation rules#

\n

Update MUST preserve:

\n
    \n
  • unrelated known roles,
  • \n
  • unknown fields,
  • \n
  • original date/datetime granularity for untouched fields.
  • \n
\n

5.4.3 Example#

\n

Before:

\n
title: Weekly review\nscheduled: 2026-02-20\npriority: normal\ncustomClient: ACME\n

Operation: set priority to high.

\n

After:

\n
title: Weekly review\nscheduled: 2026-02-20\npriority: high\ncustomClient: ACME\n

5.4.4 Title updates and filename updates#

\n

If an update changes semantic title, behavior MUST follow title.storage:

\n
    \n
  • title.storage=filename: implementation MUST rename file basename to match updated title (with sanitization and deterministic collision handling), preserving parent folder unless caller requested a move.
  • \n
  • title.storage=frontmatter: implementation MUST update mapped title field and MUST NOT rename file unless an explicit rename operation is requested.
  • \n
\n

If implementation keeps frontmatter title for compatibility while title.storage=filename, it MUST keep stored title synchronized with effective filename-derived title.

\n

5.5 Complete (non-recurring)#

\n

For non-recurring tasks, complete MUST:

\n
    \n
  1. Set status to a configured completed value, unless already completed.\nIf multiple completed values are configured, implementation MUST choose deterministically (default: first entry in status.completed_values).
  2. \n
  3. Set completed_date to completion day:
      \n
    • explicit completion-day input when provided,
    • \n
    • otherwise current local day in active runtime timezone (§5.2.1).
    • \n
    \n
  4. \n
  5. Apply overwrite policy deterministically (overwrite or preserve_if_present).
  6. \n
  7. Update date_modified on state change.
  8. \n
\n

Implementations MUST document completion-day input handling and completed_date overwrite policy.

\n

Operation MUST be idempotent.

\n

5.6 Uncomplete (non-recurring)#

\n

For non-recurring tasks, uncomplete MUST:

\n
    \n
  1. Set status to configured active/default status according to policy (default: status.default).
  2. \n
  3. Clear or retain completed_date according to policy.
  4. \n
  5. Update date_modified on state change.
  6. \n
\n

Policy MUST be documented and deterministic.

\n

Operation MUST be idempotent.

\n

5.7 Complete instance (recurring)#

\n

For recurring tasks, complete with resolved target date D (§5.2.1) MUST follow §4.7.

\n

Writers MUST NOT convert recurring completion into a base status rewrite unless explicit configuration requires it.\nWhen recurrence_anchor=completion and caller supplies an explicit datetime target, implementations MUST apply §4.4.3 datetime DTSTART rewrite behavior.\nWhen recurrence_anchor=scheduled and DTSTART is absent, implementations MUST insert DTSTART deterministically per §4.4.5.\nNext-occurrence recalculation in this mode MUST follow §4.4.4.

\n

5.8 Uncomplete instance (recurring)#

\n

For recurring tasks, uncomplete with resolved target date D (§5.2.1) MUST follow §4.8.\nFor recurrence_anchor=completion, ordinary uncomplete is intentionally non-reversible and MUST NOT roll back DTSTART.

\n

5.9 Skip and unskip instance#

\n

Skip/unskip for recurring tasks with resolved target date D (§5.2.1) MUST follow §4.9 and §4.10.

\n

5.10 Dependency operations#

\n

Dependency operations MUST follow §10.2.

\n

5.10.1 Add dependency#

\n

Add dependency MUST:

\n
    \n
  • validate dependency entry schema,
  • \n
  • parse and resolve uid per §11,
  • \n
  • enforce duplicate and self-reference rules,
  • \n
  • preserve existing non-target dependency entries,
  • \n
  • update date_modified on change.
  • \n
\n

5.10.2 Remove dependency#

\n

Remove dependency by uid MUST be idempotent.

\n

5.10.3 Replace dependency list#

\n

Replace dependency list MUST be explicit (not default patch behavior).

\n

5.11 Reminder operations#

\n

Reminder operations MUST follow §10.3.

\n

5.11.1 Add reminder#

\n

Add reminder MUST:

\n
    \n
  • validate reminder schema,
  • \n
  • enforce unique id within task,
  • \n
  • update date_modified on change.
  • \n
\n

5.11.2 Update reminder#

\n

Update reminder MUST target a reminder by id and be patch-by-default.

\n

5.11.3 Remove reminder#

\n

Remove reminder by id MUST be idempotent.

\n

5.12 Archive#

\n

Implementations MAY support archive semantics through:

\n
    \n
  • archive tag,
  • \n
  • archive status,
  • \n
  • dedicated boolean/archive field.
  • \n
\n

Archive behavior MUST be documented.

\n

Archive MUST NOT implicitly delete the task.

\n

5.13 Delete#

\n

Delete MUST remove the task file.

\n

Delete MUST NOT implicitly delete files referenced by attachments. An\nimplementation MAY offer a separate, explicit cleanup action subject to\n§5.21.4.

\n

Optional safety behavior:

\n
    \n
  • Implementations MAY perform backlink/dependency checks.
  • \n
  • If checks are enabled, implementation MUST provide a bypass option for explicit force delete.
  • \n
\n

5.14 Rename#

\n

Rename operation changes file path/filename while preserving semantic record identity.

\n

5.14.1 Rename interaction with title storage mode#

\n
    \n
  • If title.storage=filename, basename changes from rename MUST update effective semantic title.
  • \n
  • If title.storage=frontmatter, rename MUST NOT implicitly rewrite mapped title unless explicitly requested.
  • \n
  • Implementations that persist frontmatter title in title.storage=filename mode MUST either update that field on rename or remove it to prevent divergence.
  • \n
  • If semantic id is present, rename/move MUST preserve its value unchanged.
  • \n
\n

If implementation supports link/reference updating, it MUST:

\n
    \n
  • update resolvable references deterministically,
  • \n
  • report unresolved or ambiguous updates,
  • \n
  • update dependency uid and projects references consistently with normal links.
  • \n
\n

If implementation does not support reference updates, this limitation MUST be disclosed in conformance claim.

\n

5.15 Batch operations#

\n

Batch operations MAY be supported.

\n

If supported, implementation MUST report per-item outcomes and summary counts:

\n
    \n
  • total
  • \n
  • succeeded
  • \n
  • failed
  • \n
\n

Partial success behavior MUST be documented.

\n

5.16 Concurrency#

\n

Implementations SHOULD provide write-conflict detection (for example based on modified timestamp or file hash).

\n

When conflict is detected, operation MUST fail safely unless explicit overwrite is requested.

\n

5.17 Dry run#

\n

If dry run mode is supported, operation MUST:

\n
    \n
  • execute validation and transformation logic,
  • \n
  • report intended changes,
  • \n
  • perform no file write.
  • \n
\n

5.18 Error model#

\n

Implementation-native operation failures MUST provide structured error information with:

\n
    \n
  • operation name,
  • \n
  • error code,
  • \n
  • message,
  • \n
  • optional field/path context.
  • \n
\n

For conformance adapter envelopes (§5.23), failures MAY be represented as a compact error string for transport compatibility, but implementations SHOULD also expose the structured fields (for example via error_details).

\n

5.19 Time tracking management#

\n

This subsection applies to implementations that support time_entries.

\n

5.19.1 Start time tracking#

\n

Start on task T MUST:

\n
    \n
  • fail when T already has an active time entry,
  • \n
  • append a new entry with canonical startTime and no endTime,
  • \n
  • MAY set a default description,
  • \n
  • update date_modified,
  • \n
  • persist canonical time_entries shape (including removal of legacy/stale duration fields when normalizing).
  • \n
\n

Recommended error code when already active: time_tracking_already_active.

\n

5.19.2 Stop time tracking#

\n

Stop on task T MUST:

\n
    \n
  • fail when T has no active time entry,
  • \n
  • set endTime on the active entry to canonical current datetime,
  • \n
  • update date_modified,
  • \n
  • preserve non-target entries and unknown frontmatter fields.
  • \n
\n

Recommended error code when no active session exists: no_active_time_entry.

\n

5.19.3 Edit or replace time entries#

\n

When replacing/editing time_entries explicitly, implementations MUST:

\n
    \n
  • validate each entry per §2.6.1 and §3.11,
  • \n
  • persist canonical datetime formats,
  • \n
  • treat duration as derived compatibility input and SHOULD remove it from canonical writes,
  • \n
  • update date_modified when persisted state changes.
  • \n
\n

5.19.4 Remove a time entry#

\n

Remove MUST target one deterministic entry (for example by index or stable selector) and update date_modified on change.\nSelector semantics MUST be documented.

\n

5.19.5 Completion-triggered auto-stop#

\n

If time_tracking.auto_stop_on_complete=true (§9.16), completion transitions MUST trigger stop behavior for the same task only.

\n

Rules:

\n
    \n
  • non-recurring tasks: trigger when status transitions from non-completed to completed status.
  • \n
  • recurring tasks: trigger when complete_instances grows.
  • \n
  • materialized occurrence notes: trigger on the occurrence note's own status transition to completed; parent reconciliation SHOULD NOT trigger a second stop on the parent unless the parent itself has an active time entry and the implementation documents that policy.
  • \n
  • implementations MUST NOT stop active sessions on unrelated tasks.
  • \n
  • if time_tracking.auto_stop_notification=true, implementations MAY emit a user-visible notice.
  • \n
\n

5.19.6 Reporting tracked time#

\n

For reporting surfaces (for example task summaries or stats), implementations MUST document whether totals use closed_minutes or live_minutes semantics from §3.11.5.

\n

5.20 Recurrence materialization operations#

\n

This subsection is required only for implementations claiming profile materialized-occurrences (§7.3.4).

\n

5.20.1 Materialize occurrence#

\n

Operation: materialize occurrence for parent recurring task P and target date D.

\n

Conforming behavior:

\n
    \n
  1. Resolve P and confirm it is recurring.
  2. \n
  3. If an occurrence note for (P, D) already exists, return that note without creating a duplicate.
  4. \n
  5. Create a task note using occurrence_template when configured, otherwise using normal create behavior.
  6. \n
  7. Persist recurrence_parent as a link to P and occurrence_date as D.
  8. \n
  9. Set scheduled to D unless caller input or template output explicitly supplies another per-occurrence scheduled value.
  10. \n
  11. Set initial status using normal create defaults unless caller input or template output explicitly supplies a status.
  12. \n
  13. Preserve template/body output as occurrence-owned content after creation.
  14. \n
  15. Update date_created and date_modified according to create semantics.
  16. \n
\n

The operation MUST be idempotent for (P, D).

\n

If D is not generated by the current recurrence rule, implementations MAY allow materialization as an explicit user action but SHOULD report materialization_target_not_generated.

\n

5.20.2 Complete materialized occurrence#

\n

Completing a materialized occurrence note MUST:

\n
    \n
  1. Complete the occurrence note using normal non-recurring completion semantics (§5.5).
  2. \n
  3. Reconcile the parent by adding D to complete_instances and removing D from skipped_instances.
  4. \n
  5. If the parent has recurrence_anchor=completion, advance parent progression according to §4.4.3 and §4.4.4.
  6. \n
  7. If occurrence_materialization=on_completion, compute the next occurrence from the parent after the completion transition and materialize that next occurrence note idempotently.
  8. \n
\n

The occurrence note's successful completion MUST NOT be rolled back solely because next-occurrence materialization fails.\nWhen the next note cannot be created, implementations SHOULD report next_occurrence_materialization_failed.

\n

5.20.3 Skip materialized occurrence#

\n

Skipping a materialized occurrence note MUST preserve the note.\nSkip is a state transition, not deletion.

\n

Conforming behavior:

\n
    \n
  1. Set the occurrence note to the configured skipped status (status.default_skipped, or the first status.skipped_values entry when default_skipped is absent).
  2. \n
  3. Clear or retain completed_date according to the same documented policy used for uncompletion unless the implementation documents a skip-specific policy.
  4. \n
  5. Reconcile the parent by adding D to skipped_instances and removing D from complete_instances.
  6. \n
  7. If occurrence_materialization=on_completion and occurrence_next_trigger=completion_or_skip, compute and materialize the next occurrence note idempotently.
  8. \n
\n

If no skipped status is configured, skip of a materialized occurrence MUST fail deterministically in strict mode and SHOULD report missing_skipped_status.

\n

5.20.4 Uncomplete and unskip materialized occurrence#

\n

Uncomplete of a materialized occurrence note MUST:

\n
    \n
  1. Reopen the occurrence note using normal uncomplete semantics (§5.6).
  2. \n
  3. Remove D from parent complete_instances.
  4. \n
  5. For recurrence_anchor=completion, MUST NOT roll back parent DTSTART, matching §4.8.
  6. \n
  7. MUST NOT delete any later materialized occurrence note.
  8. \n
\n

Unskip of a materialized occurrence note MUST:

\n
    \n
  1. Reopen the occurrence note to configured active/default status.
  2. \n
  3. Remove D from parent skipped_instances.
  4. \n
  5. MUST NOT add D to parent complete_instances implicitly.
  6. \n
  7. MUST NOT delete any later materialized occurrence note.
  8. \n
\n

5.20.5 Delete and unmaterialize occurrence#

\n

Deleting a materialized occurrence note removes the task file and MUST NOT be interpreted as skip.

\n

Implementations MAY provide an explicit unmaterialize occurrence operation.\nIf supported, it MUST document whether parent state is preserved, cleared, or reconciled.\nIn all cases, deleting or unmaterializing an occurrence MUST NOT silently delete the parent recurring task.

\n

If parent instance lists still refer to a deleted occurrence note's date, validators MAY report an orphan/cache warning such as orphan_occurrence_note.

\n

5.21 Attachment operations#

\n

These rules apply to implementations that support the attachments\ncapability.

\n

5.21.1 Attach a file#

\n

Attach MUST:

\n
    \n
  1. durably write the binary to a collection path before publishing its task\nreference;
  2. \n
  3. add one canonical reference to the mapped attachments list;
  4. \n
  5. preserve the existing list order and append new references by default;
  6. \n
  7. avoid duplicate normalized targets; and
  8. \n
  9. update date_modified only when membership changes.
  10. \n
\n

Binary write and task-frontmatter update are not assumed to be one atomic\nstorage transaction. Implementations MUST make interrupted operations\nrecoverable or idempotently retryable. If the binary write succeeds but the\ntask update does not, the implementation MUST retain enough durable intent to\nretry or identify the unreferenced file for explicit cleanup.

\n

5.21.2 Detach a file#

\n

Detach removes the matching reference from attachments and is idempotent.\nDetach MUST NOT delete the underlying file. It MUST preserve the relative order\nof all other references.

\n

5.21.3 Insert an attached file inline#

\n

An implementation MAY offer an inline-insert operation. It MUST first satisfy\nattach semantics, then insert a Markdown link or embed into the task body.\nRemoving that body markup MUST NOT detach the file; detaching MUST NOT silently\nrewrite body content unless the user explicitly requests both changes.

\n

5.21.4 Delete an attachment file#

\n

Physical deletion MUST be a distinct, explicit action. Before deleting, an\nimplementation MUST check authoritative, current task attachments lists and\nSHOULD check body links/embeds and other collection backlinks. A stale or\noffline replica is not sufficient evidence that a file is unreferenced. If the\nbinary authority and record authority can change independently, the check and\ndelete MUST use an authority-provided transaction or equivalent precondition\nthat closes the race. An implementation MUST NOT offer physical deletion when\nit cannot establish that guarantee; detach remains available and leaves a safe\norphan. If another reference exists, deletion MUST be rejected unless the\ncaller explicitly chooses a force action whose affected references are\ndisclosed.

\n

After a successful non-forced deletion, implementations MUST remove the\ncurrent task's matching attachment reference. Failed deletion MUST leave\nfrontmatter unchanged. An accepted local outbox entry is not a successful\nphysical deletion until the binary authority acknowledges it.

\n

5.21.5 Materialized occurrences#

\n

When an occurrence note is materialized, it SHOULD inherit the parent task's\nattachment references in the same order. This copies references, not file\nbytes. Subsequent edits to either task's membership list are independent, and\nphysical deletion remains governed by §5.21.4.

\n

5.22 Operation examples#

\n

5.22.1 Non-recurring complete#

\n

Before:

\n
title: Buy groceries\nstatus: open\ncompletedDate:\ndateModified: 2026-02-20T09:00:00Z\n

After complete on 2026-02-20:

\n
title: Buy groceries\nstatus: done\ncompletedDate: 2026-02-20\ndateModified: 2026-02-20T09:05:00Z\n

5.22.2 Recurring complete instance#

\n

Before:

\n
title: Weekly review\nstatus: open\nscheduled: 2026-02-20\nrecurrence: FREQ=WEEKLY;BYDAY=FR\ncompleteInstances: []\nskippedInstances: []\ndateModified: 2026-02-20T08:00:00Z\n

After complete instance on 2026-02-20:

\n
title: Weekly review\nstatus: open\nscheduled: 2026-02-20\nrecurrence: DTSTART:20260220;FREQ=WEEKLY;BYDAY=FR\ncompleteInstances: [2026-02-20]\nskippedInstances: []\ndateModified: 2026-02-20T08:10:00Z\n

5.22.3 Recurring skip instance overriding completion#

\n

Before:

\n
completeInstances: [2026-02-20]\nskippedInstances: []\n

After skip 2026-02-20:

\n
completeInstances: []\nskippedInstances: [2026-02-20]\n

5.22.4 Preserve unknown fields on update#

\n

Before:

\n
title: Plan Q2\nstatus: open\nvendorTicket: ZX-42\n

Update status to in-progress.

\n

After:

\n
title: Plan Q2\nstatus: in-progress\nvendorTicket: ZX-42\n

5.22.5 Add dependency#

\n

Before:

\n
blockedBy: []\n

Add dependency:

\n
uid: "[[prepare-metrics]]"\nreltype: FINISHTOSTART\n

After:

\n
blockedBy:\n  - uid: "[[prepare-metrics]]"\n    reltype: FINISHTOSTART\n

5.22.6 Add reminder#

\n

Before:

\n
reminders: []\n

Add reminder:

\n
id: due_minus_1h\ntype: relative\nrelatedTo: due\noffset: -PT1H\n

After:

\n
reminders:\n  - id: due_minus_1h\n    type: relative\n    relatedTo: due\n    offset: -PT1H\n

5.23 Conformance operation interface#

\n

The conformance suite exercises operations via the execute(operation, input) → envelope interface defined in the adapter contract. This section specifies the input/output contracts for each conformance-testable operation name.

\n

Unless otherwise noted, all operations return { ok: true, result: {...} } on success and { ok: false, error: "..." } on failure. Adapters MAY additionally return error_details with structured fields from §5.18.

\n

General operations#

\n

op.mutate_with_validation#

\n

Tests §5.2 rule 1: validation runs before commit.

\n

Input:

\n
{ "strict": true, "frontmatter": { ... } }\n

Behavior: validate frontmatter as a task record. In strict mode (strict=true), any validation error MUST produce ok=false.

\n

Output on validation error:

\n
{ "ok": false, "error": "validation|invalid_type|..." }\n

\n

op.atomic_write#

\n

Tests §5.2 rule 2: writes are all-or-nothing.

\n

Input:

\n
{\n  "original": { ... },\n  "patch": { ... },\n  "simulateFailureAfterWrite": true\n}\n

Behavior: apply patch to original, then simulate a post-write failure. The adapter MUST report whether the write was committed and what state the record is in after recovery.

\n

Output:

\n
{\n  "ok": true,\n  "result": {\n    "committed": false,\n    "persisted": { ... }\n  }\n}\n

committed=false means the write was rolled back. persisted reflects the actual frontmatter after recovery — it MUST match original (not the patched version) when simulateFailureAfterWrite=true.

\n
\n

op.idempotency_check#

\n

Tests §5.2 rule 5: operations are safe under repetition.

\n

Input:

\n
{\n  "operation": "complete_nonrecurring",\n  "first": { "status": "open", "completedDate": null },\n  "second": { "status": "done", "completedDate": "2026-02-20" }\n}\n

Behavior: applying the named operation to first state and then again to second state MUST produce identical persisted results (including unchanged dateModified on the second no-op application). The adapter checks whether this holds.

\n

Output:

\n
{ "ok": true, "result": { "idempotent": true } }\n

\n

op.update_patch#

\n

Tests §5.4 patch semantics and unknown-field preservation.

\n

Input:

\n
{\n  "original": { "title": "...", "vendorTicket": "ZX-42", ... },\n  "patch": { "priority": "high" },\n  "changed": true\n}\n

Behavior: apply patch to original. Return the merged frontmatter.

\n

Output:

\n
{\n  "ok": true,\n  "result": {\n    "changed": true,\n    "frontmatter": { "title": "...", "priority": "high", "vendorTicket": "ZX-42", ... }\n  }\n}\n
    \n
  • changed indicates whether any field actually changed value.
  • \n
  • frontmatter MUST include all unknown fields from original unchanged.
  • \n
\n
\n

op.complete_nonrecurring#

\n

Tests §5.5 non-recurring completion.

\n

Input:

\n
{\n  "frontmatter": { "title": "...", "status": "open" },\n  "completedValues": ["done", "cancelled"],\n  "explicitDate": "2026-02-20"\n}\n

Behavior: apply a complete operation to frontmatter using completedValues (ordered list) and explicitDate as the completion day (omit to use current local day).

\n

Output:

\n
{ "ok": true, "result": { "status": "done", "completedDate": "2026-02-20" } }\n
    \n
  • status MUST be the first entry in completedValues.
  • \n
  • completedDate MUST be explicitDate if provided; otherwise a valid YYYY-MM-DD date.
  • \n
  • If frontmatter.status is already a completed value, the operation MUST still succeed (idempotent).
  • \n
\n
\n

op.uncomplete_nonrecurring#

\n

Tests §5.6 non-recurring uncompletion.

\n

Input:

\n
{\n  "frontmatter": { "title": "...", "status": "done", "completedDate": "2026-02-20" },\n  "defaultStatus": "open",\n  "clearCompletedDate": true\n}\n

Output:

\n
{ "ok": true, "result": { "status": "open", "completedDate": null } }\n
    \n
  • status MUST be defaultStatus.
  • \n
  • If clearCompletedDate=true, completedDate MUST be null in the result.
  • \n
  • If clearCompletedDate=false, completedDate MUST be preserved.
  • \n
\n
\n

op.error_shape#

\n

Tests §5.18 error model.

\n

Input:

\n
{ "operation": "update", "code": "invalid_type", "message": "bad value", "field": "status" }\n

Behavior: construct and return a structured error object.

\n

Output:

\n
{\n  "ok": true,\n  "result": {\n    "operation": "update",\n    "code": "invalid_type",\n    "message": "..."\n  }\n}\n

The message field MUST be a non-empty string. The operation and code fields MUST match the input.

\n
\n

op.detect_conflict#

\n

Tests §5.16 write-conflict detection.

\n

Input:

\n
{ "expectedVersion": "a", "actualVersion": "b", "overwrite": false }\n

Behavior: when expectedVersion != actualVersion and overwrite=false, the operation MUST fail.

\n

Output on conflict:

\n
{ "ok": false, "error": "conflict|write_conflict|..." }\n

\n

op.dry_run#

\n

Tests §5.17 dry-run mode.

\n

Input:

\n
{ "operation": "update", "patch": { "status": "done" } }\n

Output:

\n
{\n  "ok": true,\n  "result": {\n    "wrote": false,\n    "plannedChanges": ["status", ...]\n  }\n}\n

wrote MUST be false. plannedChanges MUST list the field names that would have changed.

\n
\n

Recurrence operations#

\n

For recurrence.complete, recurrence.uncomplete_instance, recurrence.skip_instance, recurrence.unskip_instance, and recurrence.effective_state, the input and output contracts are defined by the respective sections of §4 and §5.7–5.9.

\n

Common input fields for recurrence operations:

\n
    \n
  • targetDate or completionDate: YYYY-MM-DD target day
  • \n
  • completeInstances: current list of completed dates
  • \n
  • skippedInstances: current list of skipped dates
  • \n
\n

recurrence.effective_state output:

\n
{ "ok": true, "result": { "value": "completed|skipped|open" } }\n

\n

Materialized occurrence operations#

\n

For occurrence.materialize, occurrence.complete, occurrence.skip, occurrence.uncomplete, occurrence.unskip, and occurrence.unmaterialize, input and output contracts are defined by §4.18 and §5.20.

\n

Common input fields for materialized occurrence operations:

\n
    \n
  • parent: frontmatter/path/link object for the recurring parent task
  • \n
  • occurrence: frontmatter/path/link object for an existing occurrence note when applicable
  • \n
  • targetDate: YYYY-MM-DD target day
  • \n
  • config: effective occurrence/status configuration needed by the operation
  • \n
\n

occurrence.materialize output:

\n
{ "ok": true, "result": { "created": true, "occurrence": { "...": "..." } } }\n

created MUST be false when the operation returns an already-existing occurrence note for the same parent/date.

\n
\n

Time-tracking operations#

\n

For time.start, time.stop, time.replace_entries, time.remove_entry, time.auto_stop_on_complete, and time.report_totals, the contracts are defined by §5.19.

\n

Common input patterns:

\n
    \n
  • entries: current time_entries array
  • \n
  • now: ISO 8601 datetime representing current instant
  • \n
  • dateModified: current date_modified value
  • \n
\n

time.report_totals output:

\n
{ "ok": true, "result": { "closed_minutes": N, "live_minutes": M } }\n

live_minutes is only present when an active (no endTime) entry exists.

\n","text":"5.1 Purpose# This section defines normative behavior for task mutations and read-facing resolution concerns that affect persisted state. 5.2 General operation rules# For all mutating operations: Validation MUST run before commit in strict mode. Writes MUST be atomic at file level (all-or-nothing per file). date_modified MUST be updated on successful state change. Unknown fields MUST be preserved unless explicit normalization is requested. This applies to every operation in this section: create, update, complete, uncomplete, skip, unskip, dependency mutations, reminder mutations, archive, and time-tracking operations. Operations identified as idempotent MUST remain safe under repetition. 5.2.1 Target day/date resolution# Recurring instance operations act on a target day/date (complete instance, uncomplete instance, skip, unskip). Non-recurring complete uses completion-day semantics for completed_date. Resolution MUST be deterministic: If caller provides an explicit target date/datetime, that value is authoritative. If caller omits target for recurring instance operations, implementations MUST resolve in this order: task scheduled, if present and target-day-resolvable, else task due, if present and target-day-resolvable, else current local day in active runtime timezone (§3.6). Target-day resolution for fallback task fields (scheduled / due) MUST use this extraction policy: if stored value is canonical date (YYYY-MM-DD), use it as-is; if stored value is datetime, use the literal date token before T (YYYY-MM-DD) without timezone shifting; if stored value is non-canonical but accepted by compatibility policy, implementations MAY normalize to a date token and SHOULD emit a warning; if a candidate value is unusable, continue to the next fallback source. For non-recurring complete, if caller omits explicit completion-day input, implementations MUST use current local day in active runtime timezone. When an explicit target is datetime: operations that require day semantics MUST use its calendar date part in active runtime timezone, for recurring complete instance with recurrence_anchor=completion, the same explicit datetime target MUST also drive DTSTART rewrite semantics in §4.4.3. This explicit-target datetime rule is intentionally distinct from persisted-field fallback extraction above. 5.2.2 Idempotency and date_modified# For operations marked idempotent: first application MAY change state and date_modified, repeated application with semantically equivalent input MUST leave persisted state unchanged. When a repeated idempotent operation is a no-op, date_modified MUST remain unchanged. 5.3 Create# 5.3.1 Input requirements# Create MUST provide at minimum semantic roles required by §2, directly or via defaults. 5.3.2 Required behavior# Create MUST: apply default values, generate date_created and date_modified when absent, resolve semantic title and filename/path behavior according to §9.13, apply create-time templating when enabled and supported (§5.3.5, §9.14, §7), serialize canonical keys and canonical temporal formats, when recurrence is present, canonicalize DTSTART per §4.4.5, preserve caller-provided semantic id when present, fail with validation errors if required constraints are unmet, apply default reminders according to §10.3.9 when configured. 5.3.3 Title and filename resolution on create# Create MUST produce a deterministic initial filename/path. Rules: Generated filenames MUST use filename-safe sanitization and MUST avoid invalid/empty basenames. If title.storage=filename: basename MUST derive from semantic title, title changes after create are handled by update semantics (§5.4.4), implementations MAY also persist mapped title as a synchronized compatibility mirror, title.filename_format and title.custom_filename_template MUST be ignored. If title.storage=frontmatter, create-time basename MUST follow title.filename_format: title: sanitized semantic title, zettel: implementation-defined zettel pattern (MUST be documented), timestamp: implementation-defined timestamp pattern (MUST be documented), custom: title.custom_filename_template expansion. If generated path already exists, implementation MUST resolve collision deterministically (for example numeric suffixing). 5.3.4 Example# Input intent: title: \"Pay electricity bill\" Assume defaults: status default open priority default normal Persisted frontmatter (example): title: Pay electricity bill status: open priority: normal dateCreated: 2026-02-20T14:00:00Z dateModified: 2026-02-20T14:00:00Z 5.3.5 Optional create-time templating# This subsection is required only for implementations claiming profile templating (§7.3.3). Create-time templating pipeline MUST be deterministic: Compute base create payload from explicit input, defaults (§9.8), and generated/system values (date_created, date_modified, resolved title policy). Expand template variables using that base payload and active runtime date/time context. Merge template frontmatter into base frontmatter with base payload precedence (base keys MUST win on conflict). Resolve body output: if expanded template body is non-empty, use it; otherwise use caller-provided body/details (if any). Template parse rules: If template content begins with ---, implementations MUST treat the first --- ... --- block as template frontmatter and the remainder as template body. Frontmatter variable expansion MUST run before YAML parsing of template frontmatter. Portable variable support: Implementations claiming templating MUST support all variables in the Required column of the table below. Implementations MAY support any variable in the Extended column. Required task-data variables: Variable Value Format / separator {{title}} Semantic title string; YAML-quoted if needed {{status}} Task status value string {{priority}} Task priority value string {{dueDate}} Due date if set YYYY-MM-DD or empty {{scheduledDate}} Scheduled date if set YYYY-MM-DD or empty {{details}} Caller-provided body/description string {{contexts}} Contexts list comma-separated, e.g. \"work, home\" {{tags}} Tags list comma-separated, e.g. \"task, errands\" {{hashtags}} Tags list as hashtags space-separated, e.g. \"#task #errands\" {{timeEstimate}} Time estimate in minutes integer string or empty {{parentNote}} Parent note name/path string; YAML-quoted if needed Required date/time variables (expansion time): Variable Value Format {{date}} Current date yyyy-MM-dd {{time}} Current time (24h) HH:mm {{year}} Full year yyyy {{month}} Month number MM {{day}} Day of month dd Extended variables (optional): Variable Value Format {{dateTime}} Date + time yyyy-MM-dd-HHmm {{timestamp}} Full timestamp yyyy-MM-dd-HHmmss {{shortDate}} Short date yyMMdd {{shortYear}} Two-digit year yy {{monthName}} Month full name e.g. February {{monthNameShort}} Month short name e.g. Feb {{dayName}} Weekday full name e.g. Monday {{dayNameShort}} Weekday short name e.g. Mon {{week}} ISO week number ww {{quarter}} Quarter number 1–4 {{hour}} Hour (24h) HH {{minute}} Minute mm {{second}} Second ss {{time12}} Time with AM/PM hh:mm a {{time24}} Time (24h) HH:mm {{timezone}} UTC offset long e.g. +05:30 {{utcOffset}} UTC offset long e.g. +05:30 {{unix}} Unix timestamp (seconds) integer string {{unixMs}} Unix timestamp (ms) integer string {{zettel}} Zettelkasten ID date + seconds-since-midnight base-36 {{titleLower}} Title lowercase string {{titleUpper}} Title uppercase string {{titleSnake}} Title snake_case string {{titleKebab}} Title kebab-case string {{titleCamel}} Title camelCase string {{titlePascal}} Title PascalCase string {{priorityShort}} First letter of priority uppercase char {{statusShort}} First letter of status uppercase char Unknown variables (not in the above lists) MUST be handled per templating.unknown_variable_policy (§9.14): preserve: leave the {{...}} placeholder as-is. empty: replace with an empty string. Deterministic expansion context: date/time variable expansion MUST use the active runtime timezone from §3.6. locale-sensitive variables (monthName, monthNameShort, dayName, dayNameShort, time12) MUST use English locale outputs for portability (January, Jan, Monday, Mon, AM/PM). template-generated datetime-like outputs used in frontmatter MUST normalize to second precision when written as canonical datetime roles (§3.3.2). Failure behavior: templating.failure_mode=error: template read/parse failures MUST abort create. templating.failure_mode=warning_fallback: template read/parse failures MUST continue create using non-templated behavior (base frontmatter + caller body/details) and SHOULD emit warnings (template_missing or template_parse_failed). 5.3.6 Identity handling on create# If semantic id is provided on create, writers MUST preserve it. If implementation supports auto-generation of semantic id, generation policy MUST be documented and resulting id MUST remain stable after create. 5.4 Update# 5.4.1 Patch semantics# Update MUST be patch-by-default: only targeted semantic roles are changed. 5.4.2 Preservation rules# Update MUST preserve: unrelated known roles, unknown fields, original date/datetime granularity for untouched fields. 5.4.3 Example# Before: title: Weekly review scheduled: 2026-02-20 priority: normal customClient: ACME Operation: set priority to high. After: title: Weekly review scheduled: 2026-02-20 priority: high customClient: ACME 5.4.4 Title updates and filename updates# If an update changes semantic title, behavior MUST follow title.storage: title.storage=filename: implementation MUST rename file basename to match updated title (with sanitization and deterministic collision handling), preserving parent folder unless caller requested a move. title.storage=frontmatter: implementation MUST update mapped title field and MUST NOT rename file unless an explicit rename operation is requested. If implementation keeps frontmatter title for compatibility while title.storage=filename, it MUST keep stored title synchronized with effective filename-derived title. 5.5 Complete (non-recurring)# For non-recurring tasks, complete MUST: Set status to a configured completed value, unless already completed. If multiple completed values are configured, implementation MUST choose deterministically (default: first entry in status.completed_values). Set completed_date to completion day: explicit completion-day input when provided, otherwise current local day in active runtime timezone (§5.2.1). Apply overwrite policy deterministically (overwrite or preserve_if_present). Update date_modified on state change. Implementations MUST document completion-day input handling and completed_date overwrite policy. Operation MUST be idempotent. 5.6 Uncomplete (non-recurring)# For non-recurring tasks, uncomplete MUST: Set status to configured active/default status according to policy (default: status.default). Clear or retain completed_date according to policy. Update date_modified on state change. Policy MUST be documented and deterministic. Operation MUST be idempotent. 5.7 Complete instance (recurring)# For recurring tasks, complete with resolved target date D (§5.2.1) MUST follow §4.7. Writers MUST NOT convert recurring completion into a base status rewrite unless explicit configuration requires it. When recurrence_anchor=completion and caller supplies an explicit datetime target, implementations MUST apply §4.4.3 datetime DTSTART rewrite behavior. When recurrence_anchor=scheduled and DTSTART is absent, implementations MUST insert DTSTART deterministically per §4.4.5. Next-occurrence recalculation in this mode MUST follow §4.4.4. 5.8 Uncomplete instance (recurring)# For recurring tasks, uncomplete with resolved target date D (§5.2.1) MUST follow §4.8. For recurrence_anchor=completion, ordinary uncomplete is intentionally non-reversible and MUST NOT roll back DTSTART. 5.9 Skip and unskip instance# Skip/unskip for recurring tasks with resolved target date D (§5.2.1) MUST follow §4.9 and §4.10. 5.10 Dependency operations# Dependency operations MUST follow §10.2. 5.10.1 Add dependency# Add dependency MUST: validate dependency entry schema, parse and resolve uid per §11, enforce duplicate and self-reference rules, preserve existing non-target dependency entries, update date_modified on change. 5.10.2 Remove dependency# Remove dependency by uid MUST be idempotent. 5.10.3 Replace dependency list# Replace dependency list MUST be explicit (not default patch behavior). 5.11 Reminder operations# Reminder operations MUST follow §10.3. 5.11.1 Add reminder# Add reminder MUST: validate reminder schema, enforce unique id within task, update date_modified on change. 5.11.2 Update reminder# Update reminder MUST target a reminder by id and be patch-by-default. 5.11.3 Remove reminder# Remove reminder by id MUST be idempotent. 5.12 Archive# Implementations MAY support archive semantics through: archive tag, archive status, dedicated boolean/archive field. Archive behavior MUST be documented. Archive MUST NOT implicitly delete the task. 5.13 Delete# Delete MUST remove the task file. Delete MUST NOT implicitly delete files referenced by attachments. An implementation MAY offer a separate, explicit cleanup action subject to §5.21.4. Optional safety behavior: Implementations MAY perform backlink/dependency checks. If checks are enabled, implementation MUST provide a bypass option for explicit force delete. 5.14 Rename# Rename operation changes file path/filename while preserving semantic record identity. 5.14.1 Rename interaction with title storage mode# If title.storage=filename, basename changes from rename MUST update effective semantic title. If title.storage=frontmatter, rename MUST NOT implicitly rewrite mapped title unless explicitly requested. Implementations that persist frontmatter title in title.storage=filename mode MUST either update that field on rename or remove it to prevent divergence. If semantic id is present, rename/move MUST preserve its value unchanged. If implementation supports link/reference updating, it MUST: update resolvable references deterministically, report unresolved or ambiguous updates, update dependency uid and projects references consistently with normal links. If implementation does not support reference updates, this limitation MUST be disclosed in conformance claim. 5.15 Batch operations# Batch operations MAY be supported. If supported, implementation MUST report per-item outcomes and summary counts: total succeeded failed Partial success behavior MUST be documented. 5.16 Concurrency# Implementations SHOULD provide write-conflict detection (for example based on modified timestamp or file hash). When conflict is detected, operation MUST fail safely unless explicit overwrite is requested. 5.17 Dry run# If dry run mode is supported, operation MUST: execute validation and transformation logic, report intended changes, perform no file write. 5.18 Error model# Implementation-native operation failures MUST provide structured error information with: operation name, error code, message, optional field/path context. For conformance adapter envelopes (§5.23), failures MAY be represented as a compact error string for transport compatibility, but implementations SHOULD also expose the structured fields (for example via error_details). 5.19 Time tracking management# This subsection applies to implementations that support time_entries. 5.19.1 Start time tracking# Start on task T MUST: fail when T already has an active time entry, append a new entry with canonical startTime and no endTime, MAY set a default description, update date_modified, persist canonical time_entries shape (including removal of legacy/stale duration fields when normalizing). Recommended error code when already active: time_tracking_already_active. 5.19.2 Stop time tracking# Stop on task T MUST: fail when T has no active time entry, set endTime on the active entry to canonical current datetime, update date_modified, preserve non-target entries and unknown frontmatter fields. Recommended error code when no active"},{"route":"/developers/specification/06-validation/","title":"6. Validation","description":"Validation ensures persisted task records conform to this specification and collection configuration.","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:06-validation.md","namespace":"specification","relativePath":"06-validation.md","raw":"# 6. Validation\n\n## 6.1 Purpose\n\nValidation ensures persisted task records conform to this specification and collection configuration.\n\n## 6.2 Validation phases\n\nImplementations SHOULD validate in these phases:\n\n1. Parse validation (YAML/frontmatter structure)\n2. Schema validation (types and role constraints)\n3. Semantic validation (cross-field invariants)\n\n## 6.3 Validation modes\n\nConforming implementations MUST support:\n\n- `strict`: errors block writes.\n\nImplementations MAY additionally support:\n\n- `permissive`: writes may continue with warnings.\n\nCurrent mode MUST be discoverable.\n\n## 6.4 Required checks\n\nA conforming validator MUST implement checks required by the claimed profile(s):\n\n| Check ID | Requirement | Required for |\n|---|---|---|\n| 1 | Unconditionally required semantic roles are present (`status`, `date_created`, `date_modified`). | `core-lite` and above |\n| 1a | `completed_date` conditional requiredness is enforced per §2.2.1. | `core-lite` and above |\n| 1b | `title` resolves via active title policy (§2.2.2 and §9.13): storage-mode-aware precedence and fallback. | `core-lite` and above |\n| 2 | Field values match role type requirements. | `core-lite` and above |\n| 3 | Temporal values conform to §3. | `core-lite` and above |\n| 4 | Recurrence values conform to §4 (including tasknotes recurrence-string syntax and anchor-seed resolution rules). | `recurrence` and above |\n| 5 | Per-instance lists contain valid dates with no overlap. | `recurrence` and above |\n| 6 | `date_modified` is not earlier than `date_created` when both exist. | `core-lite` and above |\n| 7 | `time_estimate` is non-negative when present. | any profile that supports `time_estimate` |\n| 8 | `time_entries` entries include required `startTime`, ranges are valid when `endTime` exists, and at most one active entry exists per task. | any profile that supports `time_entries` |\n| 9 | `blocked_by` entries conform to §10.2 (shape, enum, duplicates, self-reference). | `extended` |\n| 10 | `reminders` entries conform to §10.3 (shape, type-specific fields, unique ids). | `extended` |\n| 11 | relative reminders have resolvable base fields or produce configured error/warning behavior. | `extended` |\n| 12 | link-bearing fields (`projects`, `blocked_by.uid`, and supported `attachments`) conform to §11 parsing/resolution and traversal safety. | `extended`, or any implementation supporting `attachments` |\n| 13 | templating configuration is valid when provided (`templating` schema and enums). | `templating` |\n| 14 | create-time template failures obey configured failure mode (`error` vs fallback). | `templating` |\n| 15 | semantic `id` (when present) is a non-empty string; duplicate collection-level IDs SHOULD be reported when detectable. | any profile that supports semantic `id` |\n| 16 | materialized occurrence notes contain valid `recurrence_parent` and `occurrence_date` roles. | `materialized-occurrences` |\n| 17 | no duplicate materialized occurrence notes exist for the same resolved `(recurrence_parent, occurrence_date)` pair. | `materialized-occurrences` |\n| 18 | materialization policy values and rolling horizons conform to §4.18 and §9.17. | `materialized-occurrences` |\n| 19 | `attachments` is a list of non-empty, unique normalized file references with explicit extensions. | any implementation supporting `attachments` |\n\n## 6.5 Unknown field policy\n\nUnknown fields:\n\n- MUST NOT fail validation by default unless collection is configured for strict schema closure.\n- SHOULD generate informational warnings when strict schema closure is desired but not enabled.\n\n## 6.6 Issue structure\n\nValidation issues MUST include:\n\n- `code` (machine-readable)\n- `severity` (`error`, `warning`, or `info`)\n- `message` (human-readable)\n\nIssues SHOULD include:\n\n- `field` or path\n- `expected` and `actual` details where useful\n\n## 6.7 Recommended issue codes\n\n| Code | Severity (default) | Meaning |\n|---|---|---|\n| `missing_required` | error | required role missing |\n| `invalid_type` | error | value type mismatch |\n| `invalid_enum_value` | error | value not in configured set |\n| `invalid_date_value` | error | malformed or impossible date |\n| `invalid_datetime_value` | error | malformed datetime |\n| `invalid_recurrence_rule` | error | recurrence not valid tasknotes recurrence syntax |\n| `missing_recurrence_seed` | error | recurrence has no resolvable seed/start date |\n| `invalid_recurrence_anchor` | error | anchor not allowed |\n| `instance_state_overlap` | error | same date in complete and skipped lists |\n| `invalid_time_range` | error | end before start in time entry |\n| `missing_time_entry_start` | error | time entry is missing required startTime |\n| `multiple_active_time_entries` | error | more than one active time entry exists in one task |\n| `invalid_dependency_entry` | error | dependency object missing required fields |\n| `invalid_dependency_reltype` | error | dependency reltype not allowed |\n| `invalid_dependency_gap` | error | dependency gap not valid ISO 8601 duration |\n| `duplicate_dependency_uid` | error in strict mode when `dependencies.enforce_unique_uid=true`; warning otherwise by policy | repeated dependency uid in task |\n| `self_dependency` | error | task depends on itself |\n| `unresolved_dependency_target` | warning | dependency target not resolvable |\n| `invalid_reminder_entry` | error | reminder object missing required fields |\n| `duplicate_reminder_id` | error | repeated reminder id in task |\n| `invalid_reminder_type` | error | reminder type not allowed |\n| `invalid_reminder_offset` | error | relative reminder offset not valid duration |\n| `invalid_reminder_related_to` | error | relatedTo must be due or scheduled |\n| `invalid_reminder_absolute_time` | error | absoluteTime invalid datetime |\n| `unresolvable_reminder_base` | error | relative reminder base field missing/unusable |\n| `invalid_link_format` | error | link value cannot be parsed as supported format |\n| `ambiguous_link` | warning | link resolves to multiple candidates |\n| `path_traversal` | error | resolved path escapes collection root |\n| `unresolved_link_target` | warning | link target cannot be resolved |\n| `invalid_attachment_reference` | error | attachment reference is empty, lacks an explicit extension, or targets a directory |\n| `duplicate_attachment_reference` | error | attachment list repeats the same normalized target |\n| `invalid_task_id` | error | semantic `id` is empty or invalid type |\n| `duplicate_task_id` | warning | duplicate semantic `id` detected in collection scope |\n| `alias_conflict_ignored` | warning | alias key ignored due to canonical conflict |\n| `unresolvable_title` | error | title cannot be resolved from title resolution policy |\n| `title_source_conflict` | warning | mapped title and filename title differ; active title-storage policy selected authoritative source |\n| `template_missing` | warning | configured template file cannot be read/found |\n| `template_parse_failed` | warning | template frontmatter/body parsing or expansion failed |\n| `missing_recurrence_parent` | error | materialized occurrence note omits recurrence_parent |\n| `invalid_recurrence_parent` | warning | occurrence note parent reference cannot be resolved or does not reference a recurring task |\n| `missing_occurrence_date` | error | materialized occurrence note omits occurrence_date |\n| `duplicate_occurrence_note` | warning | more than one materialized occurrence note exists for the same parent/date |\n| `occurrence_state_conflict` | warning | materialized occurrence state disagrees with parent instance lists |\n| `materialization_target_not_generated` | warning | occurrence date is not generated by current parent recurrence rule |\n| `missing_skipped_status` | error | skip of materialized occurrence requires configured skipped status |\n| `next_occurrence_materialization_failed` | warning | triggering operation succeeded but next occurrence note could not be created |\n| `orphan_occurrence_note` | warning | materialized occurrence note has no resolvable recurring parent or parent state references a deleted occurrence note |\n| `unknown_field` | info | unmapped field encountered |\n\nImplementations MAY extend this code set but SHOULD preserve existing meanings.\n\n## 6.8 Write-time validation behavior\n\nIn strict mode, mutating operations MUST fail if any error-severity issue is present after applying intended changes.\n\nWarnings SHOULD NOT block writes unless explicitly configured.\n\nDatetime/date acceptance and rejection in validation MUST follow the normative matrix in §3.4.4.\n\n## 6.9 Validation examples\n\n### 6.9.1 Missing required role\n\nInput:\n\n```yaml\ntitle: Plan workshop\nstatus: open\ndateCreated: 2026-02-20T09:00:00Z\n```\n\nIssue:\n\n```yaml\ncode: missing_required\nseverity: error\nfield: dateModified\nmessage: Required field 'dateModified' is missing.\n```\n\n### 6.9.2 Invalid recurrence anchor\n\nInput:\n\n```yaml\nrecurrence: FREQ=DAILY\nrecurrenceAnchor: due\n```\n\nIssue:\n\n```yaml\ncode: invalid_recurrence_anchor\nseverity: error\nfield: recurrenceAnchor\nmessage: recurrence anchor must be 'scheduled' or 'completion'.\n```\n\n### 6.9.3 Overlap in instance state\n\nInput:\n\n```yaml\ncompleteInstances: [2026-02-20]\nskippedInstances: [2026-02-20]\n```\n\nIssue:\n\n```yaml\ncode: instance_state_overlap\nseverity: error\nmessage: same date exists in complete and skipped instance lists.\n```\n\n### 6.9.4 Invalid dependency reltype\n\nInput:\n\n```yaml\nblockedBy:\n - uid: \"[[task-a]]\"\n reltype: BLOCKS\n```\n\nIssue:\n\n```yaml\ncode: invalid_dependency_reltype\nseverity: error\nfield: blockedBy[0].reltype\nmessage: reltype must be one of FINISHTOSTART, STARTTOSTART, FINISHTOFINISH, STARTTOFINISH.\n```\n\n### 6.9.5 Unresolvable reminder base\n\nInput:\n\n```yaml\nreminders:\n - id: due_minus_1d\n type: relative\n relatedTo: due\n offset: -P1D\n```\n\nIssue when `due` missing:\n\n```yaml\ncode: unresolvable_reminder_base\nseverity: error\nfield: reminders[0]\nmessage: relative reminder references due but no due value exists.\n```\n\n### 6.9.6 Unknown field in permissive mode\n\nInput:\n\n```yaml\ntitle: Plan workshop\nstatus: open\nvendorPriority: p1\n```\n\nIssue example:\n\n```yaml\ncode: unknown_field\nseverity: info\nfield: vendorPriority\nmessage: field is not mapped to a known semantic role.\n```\n\n### 6.9.7 Multiple active time entries\n\nInput:\n\n```yaml\ntimeEntries:\n - startTime: 2026-02-20T10:00:00Z\n - startTime: 2026-02-20T11:00:00Z\n```\n\nIssue:\n\n```yaml\ncode: multiple_active_time_entries\nseverity: error\nfield: timeEntries\nmessage: task contains more than one active time entry.\n```\n","aliases":["/spec/06-validation/"],"toc":[{"level":2,"id":"61-purpose","text":"6.1 Purpose"},{"level":2,"id":"62-validation-phases","text":"6.2 Validation phases"},{"level":2,"id":"63-validation-modes","text":"6.3 Validation modes"},{"level":2,"id":"64-required-checks","text":"6.4 Required checks"},{"level":2,"id":"65-unknown-field-policy","text":"6.5 Unknown field policy"},{"level":2,"id":"66-issue-structure","text":"6.6 Issue structure"},{"level":2,"id":"67-recommended-issue-codes","text":"6.7 Recommended issue codes"},{"level":2,"id":"68-write-time-validation-behavior","text":"6.8 Write-time validation behavior"},{"level":2,"id":"69-validation-examples","text":"6.9 Validation examples"},{"level":3,"id":"691-missing-required-role","text":"6.9.1 Missing required role"},{"level":3,"id":"692-invalid-recurrence-anchor","text":"6.9.2 Invalid recurrence anchor"},{"level":3,"id":"693-overlap-in-instance-state","text":"6.9.3 Overlap in instance state"},{"level":3,"id":"694-invalid-dependency-reltype","text":"6.9.4 Invalid dependency reltype"},{"level":3,"id":"695-unresolvable-reminder-base","text":"6.9.5 Unresolvable reminder base"},{"level":3,"id":"696-unknown-field-in-permissive-mode","text":"6.9.6 Unknown field in permissive mode"},{"level":3,"id":"697-multiple-active-time-entries","text":"6.9.7 Multiple active time entries"}],"html":"

6.1 Purpose#

\n

Validation ensures persisted task records conform to this specification and collection configuration.

\n

6.2 Validation phases#

\n

Implementations SHOULD validate in these phases:

\n
    \n
  1. Parse validation (YAML/frontmatter structure)
  2. \n
  3. Schema validation (types and role constraints)
  4. \n
  5. Semantic validation (cross-field invariants)
  6. \n
\n

6.3 Validation modes#

\n

Conforming implementations MUST support:

\n
    \n
  • strict: errors block writes.
  • \n
\n

Implementations MAY additionally support:

\n
    \n
  • permissive: writes may continue with warnings.
  • \n
\n

Current mode MUST be discoverable.

\n

6.4 Required checks#

\n

A conforming validator MUST implement checks required by the claimed profile(s):

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Check IDRequirementRequired for
1Unconditionally required semantic roles are present (status, date_created, date_modified).core-lite and above
1acompleted_date conditional requiredness is enforced per §2.2.1.core-lite and above
1btitle resolves via active title policy (§2.2.2 and §9.13): storage-mode-aware precedence and fallback.core-lite and above
2Field values match role type requirements.core-lite and above
3Temporal values conform to §3.core-lite and above
4Recurrence values conform to §4 (including tasknotes recurrence-string syntax and anchor-seed resolution rules).recurrence and above
5Per-instance lists contain valid dates with no overlap.recurrence and above
6date_modified is not earlier than date_created when both exist.core-lite and above
7time_estimate is non-negative when present.any profile that supports time_estimate
8time_entries entries include required startTime, ranges are valid when endTime exists, and at most one active entry exists per task.any profile that supports time_entries
9blocked_by entries conform to §10.2 (shape, enum, duplicates, self-reference).extended
10reminders entries conform to §10.3 (shape, type-specific fields, unique ids).extended
11relative reminders have resolvable base fields or produce configured error/warning behavior.extended
12link-bearing fields (projects, blocked_by.uid, and supported attachments) conform to §11 parsing/resolution and traversal safety.extended, or any implementation supporting attachments
13templating configuration is valid when provided (templating schema and enums).templating
14create-time template failures obey configured failure mode (error vs fallback).templating
15semantic id (when present) is a non-empty string; duplicate collection-level IDs SHOULD be reported when detectable.any profile that supports semantic id
16materialized occurrence notes contain valid recurrence_parent and occurrence_date roles.materialized-occurrences
17no duplicate materialized occurrence notes exist for the same resolved (recurrence_parent, occurrence_date) pair.materialized-occurrences
18materialization policy values and rolling horizons conform to §4.18 and §9.17.materialized-occurrences
19attachments is a list of non-empty, unique normalized file references with explicit extensions.any implementation supporting attachments
\n

6.5 Unknown field policy#

\n

Unknown fields:

\n
    \n
  • MUST NOT fail validation by default unless collection is configured for strict schema closure.
  • \n
  • SHOULD generate informational warnings when strict schema closure is desired but not enabled.
  • \n
\n

6.6 Issue structure#

\n

Validation issues MUST include:

\n
    \n
  • code (machine-readable)
  • \n
  • severity (error, warning, or info)
  • \n
  • message (human-readable)
  • \n
\n

Issues SHOULD include:

\n
    \n
  • field or path
  • \n
  • expected and actual details where useful
  • \n
\n\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
CodeSeverity (default)Meaning
missing_requirederrorrequired role missing
invalid_typeerrorvalue type mismatch
invalid_enum_valueerrorvalue not in configured set
invalid_date_valueerrormalformed or impossible date
invalid_datetime_valueerrormalformed datetime
invalid_recurrence_ruleerrorrecurrence not valid tasknotes recurrence syntax
missing_recurrence_seederrorrecurrence has no resolvable seed/start date
invalid_recurrence_anchorerroranchor not allowed
instance_state_overlaperrorsame date in complete and skipped lists
invalid_time_rangeerrorend before start in time entry
missing_time_entry_starterrortime entry is missing required startTime
multiple_active_time_entrieserrormore than one active time entry exists in one task
invalid_dependency_entryerrordependency object missing required fields
invalid_dependency_reltypeerrordependency reltype not allowed
invalid_dependency_gaperrordependency gap not valid ISO 8601 duration
duplicate_dependency_uiderror in strict mode when dependencies.enforce_unique_uid=true; warning otherwise by policyrepeated dependency uid in task
self_dependencyerrortask depends on itself
unresolved_dependency_targetwarningdependency target not resolvable
invalid_reminder_entryerrorreminder object missing required fields
duplicate_reminder_iderrorrepeated reminder id in task
invalid_reminder_typeerrorreminder type not allowed
invalid_reminder_offseterrorrelative reminder offset not valid duration
invalid_reminder_related_toerrorrelatedTo must be due or scheduled
invalid_reminder_absolute_timeerrorabsoluteTime invalid datetime
unresolvable_reminder_baseerrorrelative reminder base field missing/unusable
invalid_link_formaterrorlink value cannot be parsed as supported format
ambiguous_linkwarninglink resolves to multiple candidates
path_traversalerrorresolved path escapes collection root
unresolved_link_targetwarninglink target cannot be resolved
invalid_attachment_referenceerrorattachment reference is empty, lacks an explicit extension, or targets a directory
duplicate_attachment_referenceerrorattachment list repeats the same normalized target
invalid_task_iderrorsemantic id is empty or invalid type
duplicate_task_idwarningduplicate semantic id detected in collection scope
alias_conflict_ignoredwarningalias key ignored due to canonical conflict
unresolvable_titleerrortitle cannot be resolved from title resolution policy
title_source_conflictwarningmapped title and filename title differ; active title-storage policy selected authoritative source
template_missingwarningconfigured template file cannot be read/found
template_parse_failedwarningtemplate frontmatter/body parsing or expansion failed
missing_recurrence_parenterrormaterialized occurrence note omits recurrence_parent
invalid_recurrence_parentwarningoccurrence note parent reference cannot be resolved or does not reference a recurring task
missing_occurrence_dateerrormaterialized occurrence note omits occurrence_date
duplicate_occurrence_notewarningmore than one materialized occurrence note exists for the same parent/date
occurrence_state_conflictwarningmaterialized occurrence state disagrees with parent instance lists
materialization_target_not_generatedwarningoccurrence date is not generated by current parent recurrence rule
missing_skipped_statuserrorskip of materialized occurrence requires configured skipped status
next_occurrence_materialization_failedwarningtriggering operation succeeded but next occurrence note could not be created
orphan_occurrence_notewarningmaterialized occurrence note has no resolvable recurring parent or parent state references a deleted occurrence note
unknown_fieldinfounmapped field encountered
\n

Implementations MAY extend this code set but SHOULD preserve existing meanings.

\n

6.8 Write-time validation behavior#

\n

In strict mode, mutating operations MUST fail if any error-severity issue is present after applying intended changes.

\n

Warnings SHOULD NOT block writes unless explicitly configured.

\n

Datetime/date acceptance and rejection in validation MUST follow the normative matrix in §3.4.4.

\n

6.9 Validation examples#

\n

6.9.1 Missing required role#

\n

Input:

\n
title: Plan workshop\nstatus: open\ndateCreated: 2026-02-20T09:00:00Z\n

Issue:

\n
code: missing_required\nseverity: error\nfield: dateModified\nmessage: Required field 'dateModified' is missing.\n

6.9.2 Invalid recurrence anchor#

\n

Input:

\n
recurrence: FREQ=DAILY\nrecurrenceAnchor: due\n

Issue:

\n
code: invalid_recurrence_anchor\nseverity: error\nfield: recurrenceAnchor\nmessage: recurrence anchor must be 'scheduled' or 'completion'.\n

6.9.3 Overlap in instance state#

\n

Input:

\n
completeInstances: [2026-02-20]\nskippedInstances: [2026-02-20]\n

Issue:

\n
code: instance_state_overlap\nseverity: error\nmessage: same date exists in complete and skipped instance lists.\n

6.9.4 Invalid dependency reltype#

\n

Input:

\n
blockedBy:\n  - uid: "[[task-a]]"\n    reltype: BLOCKS\n

Issue:

\n
code: invalid_dependency_reltype\nseverity: error\nfield: blockedBy[0].reltype\nmessage: reltype must be one of FINISHTOSTART, STARTTOSTART, FINISHTOFINISH, STARTTOFINISH.\n

6.9.5 Unresolvable reminder base#

\n

Input:

\n
reminders:\n  - id: due_minus_1d\n    type: relative\n    relatedTo: due\n    offset: -P1D\n

Issue when due missing:

\n
code: unresolvable_reminder_base\nseverity: error\nfield: reminders[0]\nmessage: relative reminder references due but no due value exists.\n

6.9.6 Unknown field in permissive mode#

\n

Input:

\n
title: Plan workshop\nstatus: open\nvendorPriority: p1\n

Issue example:

\n
code: unknown_field\nseverity: info\nfield: vendorPriority\nmessage: field is not mapped to a known semantic role.\n

6.9.7 Multiple active time entries#

\n

Input:

\n
timeEntries:\n  - startTime: 2026-02-20T10:00:00Z\n  - startTime: 2026-02-20T11:00:00Z\n

Issue:

\n
code: multiple_active_time_entries\nseverity: error\nfield: timeEntries\nmessage: task contains more than one active time entry.\n
","text":"6.1 Purpose# Validation ensures persisted task records conform to this specification and collection configuration. 6.2 Validation phases# Implementations SHOULD validate in these phases: Parse validation (YAML/frontmatter structure) Schema validation (types and role constraints) Semantic validation (cross-field invariants) 6.3 Validation modes# Conforming implementations MUST support: strict: errors block writes. Implementations MAY additionally support: permissive: writes may continue with warnings. Current mode MUST be discoverable. 6.4 Required checks# A conforming validator MUST implement checks required by the claimed profile(s): Check ID Requirement Required for 1 Unconditionally required semantic roles are present (status, date_created, date_modified). core-lite and above 1a completed_date conditional requiredness is enforced per §2.2.1. core-lite and above 1b title resolves via active title policy (§2.2.2 and §9.13): storage-mode-aware precedence and fallback. core-lite and above 2 Field values match role type requirements. core-lite and above 3 Temporal values conform to §3. core-lite and above 4 Recurrence values conform to §4 (including tasknotes recurrence-string syntax and anchor-seed resolution rules). recurrence and above 5 Per-instance lists contain valid dates with no overlap. recurrence and above 6 date_modified is not earlier than date_created when both exist. core-lite and above 7 time_estimate is non-negative when present. any profile that supports time_estimate 8 time_entries entries include required startTime, ranges are valid when endTime exists, and at most one active entry exists per task. any profile that supports time_entries 9 blocked_by entries conform to §10.2 (shape, enum, duplicates, self-reference). extended 10 reminders entries conform to §10.3 (shape, type-specific fields, unique ids). extended 11 relative reminders have resolvable base fields or produce configured error/warning behavior. extended 12 link-bearing fields (projects, blocked_by.uid, and supported attachments) conform to §11 parsing/resolution and traversal safety. extended, or any implementation supporting attachments 13 templating configuration is valid when provided (templating schema and enums). templating 14 create-time template failures obey configured failure mode (error vs fallback). templating 15 semantic id (when present) is a non-empty string; duplicate collection-level IDs SHOULD be reported when detectable. any profile that supports semantic id 16 materialized occurrence notes contain valid recurrence_parent and occurrence_date roles. materialized-occurrences 17 no duplicate materialized occurrence notes exist for the same resolved (recurrence_parent, occurrence_date) pair. materialized-occurrences 18 materialization policy values and rolling horizons conform to §4.18 and §9.17. materialized-occurrences 19 attachments is a list of non-empty, unique normalized file references with explicit extensions. any implementation supporting attachments 6.5 Unknown field policy# Unknown fields: MUST NOT fail validation by default unless collection is configured for strict schema closure. SHOULD generate informational warnings when strict schema closure is desired but not enabled. 6.6 Issue structure# Validation issues MUST include: code (machine-readable) severity (error, warning, or info) message (human-readable) Issues SHOULD include: field or path expected and actual details where useful 6.7 Recommended issue codes# Code Severity (default) Meaning missing_required error required role missing invalid_type error value type mismatch invalid_enum_value error value not in configured set invalid_date_value error malformed or impossible date invalid_datetime_value error malformed datetime invalid_recurrence_rule error recurrence not valid tasknotes recurrence syntax missing_recurrence_seed error recurrence has no resolvable seed/start date invalid_recurrence_anchor error anchor not allowed instance_state_overlap error same date in complete and skipped lists invalid_time_range error end before start in time entry missing_time_entry_start error time entry is missing required startTime multiple_active_time_entries error more than one active time entry exists in one task invalid_dependency_entry error dependency object missing required fields invalid_dependency_reltype error dependency reltype not allowed invalid_dependency_gap error dependency gap not valid ISO 8601 duration duplicate_dependency_uid error in strict mode when dependencies.enforce_unique_uid=true; warning otherwise by policy repeated dependency uid in task self_dependency error task depends on itself unresolved_dependency_target warning dependency target not resolvable invalid_reminder_entry error reminder object missing required fields duplicate_reminder_id error repeated reminder id in task invalid_reminder_type error reminder type not allowed invalid_reminder_offset error relative reminder offset not valid duration invalid_reminder_related_to error relatedTo must be due or scheduled invalid_reminder_absolute_time error absoluteTime invalid datetime unresolvable_reminder_base error relative reminder base field missing/unusable invalid_link_format error link value cannot be parsed as supported format ambiguous_link warning link resolves to multiple candidates path_traversal error resolved path escapes collection root unresolved_link_target warning link target cannot be resolved invalid_attachment_reference error attachment reference is empty, lacks an explicit extension, or targets a directory duplicate_attachment_reference error attachment list repeats the same normalized target invalid_task_id error semantic id is empty or invalid type duplicate_task_id warning duplicate semantic id detected in collection scope alias_conflict_ignored warning alias key ignored due to canonical conflict unresolvable_title error title cannot be resolved from title resolution policy title_source_conflict warning mapped title and filename title differ; active title-storage policy selected authoritative source template_missing warning configured template file cannot be read/found template_parse_failed warning template frontmatter/body parsing or expansion failed missing_recurrence_parent error materialized occurrence note omits recurrence_parent invalid_recurrence_parent warning occurrence note parent reference cannot be resolved or does not reference a recurring task missing_occurrence_date error materialized occurrence note omits occurrence_date duplicate_occurrence_note warning more than one materialized occurrence note exists for the same parent/date occurrence_state_conflict warning materialized occurrence state disagrees with parent instance lists materialization_target_not_generated warning occurrence date is not generated by current parent recurrence rule missing_skipped_status error skip of materialized occurrence requires configured skipped status next_occurrence_materialization_failed warning triggering operation succeeded but next occurrence note could not be created orphan_occurrence_note warning materialized occurrence note has no resolvable recurring parent or parent state references a deleted occurrence note unknown_field info unmapped field encountered Implementations MAY extend this code set but SHOULD preserve existing meanings. 6.8 Write-time validation behavior# In strict mode, mutating operations MUST fail if any error-severity issue is present after applying intended changes. Warnings SHOULD NOT block writes unless explicitly configured. Datetime/date acceptance and rejection in validation MUST follow the normative matrix in §3.4.4. 6.9 Validation examples# 6.9.1 Missing required role# Input: title: Plan workshop status: open dateCreated: 2026-02-20T09:00:00Z Issue: code: missing_required severity: error field: dateModified message: Required field 'dateModified' is missing. 6.9.2 Invalid recurrence anchor# Input: recurrence: FREQ=DAILY recurrenceAnchor: due Issue: code: invalid_recurrence_anchor severity: error field: recurrenceAnchor message: recurrence anchor must be 'scheduled' or 'completion'. 6.9.3 Overlap in instance state# Input: completeInstances: [2026-02-20] skippedInstances: [2026-02-20] Issue: code: instance_state_overlap severity: error message: same date exists in complete and skipped instance lists. 6.9.4 Invalid dependency reltype# Input: blockedBy: - uid: \"[[task-a]]\" reltype: BLOCKS Issue: code: invalid_dependency_reltype severity: error field: blockedBy[0].reltype message: reltype must be one of FINISHTOSTART, STARTTOSTART, FINISHTOFINISH, STARTTOFINISH. 6.9.5 Unresolvable reminder base# Input: reminders: - id: due_minus_1d type: relative relatedTo: due offset: -P1D Issue when due missing: code: unresolvable_reminder_base severity: error field: reminders[0] message: relative reminder references due but no due value exists. 6.9.6 Unknown field in permissive mode# Input: title: Plan workshop status: open vendorPriority: p1 Issue example: code: unknown_field severity: info field: vendorPriority message: field is not mapped to a known semantic role. 6.9.7 Multiple active time entries# Input: timeEntries: - startTime: 2026-02-20T10:00:00Z - startTime: 2026-02-20T11:00:00Z Issue: code: multiple_active_time_entries severity: error field: timeEntries message: task contains more than one active time entry."},{"route":"/developers/specification/07-conformance/","title":"7. Conformance","description":"This section defines conformance profiles and claim requirements for implementations.","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:07-conformance.md","namespace":"specification","relativePath":"07-conformance.md","raw":"# 7. Conformance\n\n## 7.1 Purpose\n\nThis section defines conformance profiles and claim requirements for implementations.\n\n## 7.2 Conformance principles\n\nAn implementation MUST NOT claim conformance to a profile unless all required capabilities of that profile are implemented.\n\nImplementations MAY implement additional behavior beyond a profile, but extra behavior MUST NOT violate profile requirements.\n\n## 7.3 Profile model\n\nProfiles are cumulative unless explicitly marked otherwise.\n\n### 7.3.1 Profile: `core-lite`\n\nRequired capabilities:\n\n- task identification and loading\n- semantic-role mapping and canonical writes (§2)\n- required role support (`title`, `status`, `completed_date`, `date_created`, `date_modified`)\n- create, update, delete operations (§5)\n- non-recurring complete/uncomplete (§5)\n- temporal parsing/canonical serialization basics (§3)\n- strict validation mode support (§6.3)\n- validation core checks (§6.4 items 1,1a,1b,2,3,6)\n\n### 7.3.2 Profile: `recurrence`\n\nAdditional required capabilities:\n\n- tasknotes recurrence-string parsing/validation, including RRULE parameter syntax and inline `DTSTART` handling\n- recurrence anchor semantics, including seed precedence and completion-anchor progression\n- complete/uncomplete instance\n- skip/unskip instance\n- instance-list invariants and effective state resolution\n- validation checks for recurrence and instance overlap\n\n### 7.3.3 Profile: `templating` (non-cumulative extension)\n\nThis profile is not cumulative; it MAY be claimed alongside `core-lite`, `recurrence`, `materialized-occurrences`, and/or `extended`.\n`templating` MUST NOT be claimed alone.\n\nRequired capabilities:\n\n- create-time template processing semantics per §5.3.5\n- `templating` configuration support per §9.14\n- deterministic template/frontmatter/body merge behavior\n- deterministic failure-mode behavior for template read/parse failures\n- support for portable double-brace template variables defined in §5.3.5\n\n### 7.3.4 Profile: `materialized-occurrences` (non-cumulative extension)\n\nThis profile is not cumulative; it MUST be claimed alongside `recurrence`.\nIt MAY be claimed alongside `extended` and/or `templating`, but it does not require either.\n\nRequired capabilities:\n\n- materialized occurrence roles and identity semantics (§2.6.6)\n- recurrence materialization semantics (§4.18)\n- materialize/complete/skip/uncomplete/unskip materialized occurrence operations (§5.20)\n- `occurrences` configuration defaults (§9.17)\n- parent-reference link parsing/resolution for `recurrence_parent` (§11), without requiring full `extended`\n- validation checks for materialized occurrence identity, duplicates, and state conflicts (§6.4 items 16-18)\n\nClaiming `materialized-occurrences` also has required capability-token implications:\n\n- `meta.claim.capabilities` MUST include `materialized-occurrences`.\n- `meta.claim.profiles` MUST also include `recurrence`.\n- Omitting either token while claiming `materialized-occurrences` is a non-conformant claim.\n\n### 7.3.5 Profile: `extended`\n\nAdditional required capabilities:\n\n- dependency schema support (`blocked_by`)\n- reminder schema support (`reminders`)\n- link parsing/resolution semantics for link-bearing fields (§11)\n- time-tracking management semantics for `time_entries` (§5.19), including per-task active-session constraints\n- dependency operations and validation per §10.2\n- reminder operations and validation per §10.3\n\nIf `extended` is claimed, all of the above baseline capabilities MUST conform to documented semantics.\n\nClaiming `extended` also has required capability-token implications:\n\n- `meta.claim.capabilities` MUST include `dependencies`, `reminders`, `links`, and `time-tracking`.\n- Omitting any of these tokens while claiming `extended` is a non-conformant claim (even if capability-gated fixtures are skipped by a runner).\n\nOptional capability extensions within `extended`:\n\n- `rename` capability: reference-aware rename behavior (including dependency UID references)\n- `archive` capability: archive semantics (§5.12)\n- `batch` capability: batch operations with per-item outcomes (§5.15)\n- `concurrency` capability: write-conflict detection semantics (§5.16)\n- `dry-run` capability: dry-run semantics (§5.17)\n\nWhen an optional capability token is claimed, corresponding behavior MUST conform to documented semantics.\n\n## 7.4 Conformance claim format\n\nA conformance claim MUST include:\n\n- implementation name and version,\n- `tasknotes-spec` version,\n- claimed profile list,\n- validation mode support (`strict` required; `permissive` optional),\n- known deviations,\n- compatibility mode status (if any),\n- configuration provider status (active provider chain, precedence policy, and fallback state).\n\nExample:\n\n```text\nImplementation: example-task-cli v1.4.0\nSpec: tasknotes-spec 0.3.0-rc.3\nProfiles: core-lite, recurrence, templating\nValidation modes: strict, permissive\nKnown deviations: none\nCompatibility mode: disabled\nConfiguration providers: tasknotes_plugin_data_json > built_in_defaults\nConfiguration fallback: none\n```\n\n## 7.5 Deviation disclosure\n\nAny known deviation from normative text MUST be explicitly disclosed in conformance output/documentation.\n\nA deviation entry SHOULD include:\n\n- affected section,\n- deviation summary,\n- impact,\n- planned resolution version.\n\n## 7.6 Feature detection\n\nImplementations SHOULD expose machine-readable capability metadata, including:\n\n- profiles\n- effective runtime timezone\n- active configuration providers and precedence chain\n- enabled compatibility modes\n- configurable status sets\n- supported mapping aliases\n- templating support flags and effective templating failure mode\n- dependency and reminder support flags\n- attachment membership, reference normalization, and host-provided binary\n operation flags (including whether physical deletion is available)\n- time-tracking support flags, including active-session policy and auto-stop-on-complete behavior\n- materialized occurrence support flags, including materialization mode, next trigger, and rolling bounds\n- configured natural-language capture triggers when the optional `nlp` block is\n present\n\n## 7.7 Strictness disclosure\n\nConformance requires `strict` validation mode support (§6.3).\n\nConformance claims MUST indicate whether `permissive` mode is also supported.\n\n## 7.8 Example profile matrix\n\n| Capability | core-lite | recurrence | templating | materialized-occurrences | extended |\n|---|---:|---:|---:|---:|---:|\n| create/update/delete | required | required | companion-profile required | companion-profile required | required |\n| non-recurring complete | required | required | companion-profile required | companion-profile required | required |\n| recurring instance complete/skip | - | required | optional | required via companion `recurrence` claim | required |\n| materialize occurrence notes (§4.18, §5.20) | - | - | optional | required | optional |\n| recurrence parent link resolution | - | - | optional | required for `recurrence_parent` only | required |\n| template expansion/merge (§5.3.5) | - | - | required | optional | optional |\n| double-brace portable variable support | - | - | required | optional | optional |\n| recurrence-string validation | - | required | optional | required via companion `recurrence` claim | required |\n| link parsing/resolution (§11) | - | - | optional | required for `recurrence_parent` only | required |\n| attachment membership and ops (§5.21) | optional via `attachments` capability | optional via `attachments` capability | optional via `attachments` capability | optional via `attachments` capability | optional via `attachments` capability |\n| dependency schema and ops | - | - | optional | optional | required |\n| reminder schema and ops | - | - | optional | optional | required |\n| time tracking start/stop/edit semantics (§5.19) | - | - | optional | optional | required |\n| rename updates dependency/project links | - | - | optional | optional | optional via `rename` capability |\n| archive semantics (§5.12) | - | - | optional | optional | optional via `archive` capability |\n| batch per-item outcomes (§5.15) | - | - | optional | optional | optional via `batch` capability |\n| write-conflict detection (§5.16) | - | - | optional | optional | optional via `concurrency` capability |\n| dry-run reporting (§5.17) | - | - | optional | optional | optional via `dry-run` capability |\n\n## 7.9 Executable fixture suite\n\nThis specification includes an executable fixture suite in `conformance/`.\n\n- language-neutral fixtures are stored in `conformance/fixtures/*.json`\n- section/profile/operation coverage is tracked in `conformance/manifest.json`\n- coverage guard tests MUST enforce both section representation and minimum-depth thresholds for key sections/operations.\n- adapters execute fixture operations per `conformance/docs/ADAPTER_CONTRACT.md`\n- runners MUST execute fixtures only when both conditions hold:\n - fixture `profile` is satisfied by claimed adapter profiles under cumulative profile rules (§7.3),\n - all fixture `requires` capability tokens are present.\n\nFixture expectations MUST be profile-modular: they MUST NOT assume capability values or profile memberships beyond what the fixture's own `profile`/`requires` gating guarantees.\nFixtures for optional extension capabilities (`rename`, `archive`, `batch`, `concurrency`, `dry-run`) MUST be capability-gated via `requires` and MUST NOT rely on `extended` profile membership alone.\n\nConformance claims SHOULD report fixture pass/fail results against the claimed profiles.\n\n## 7.10 Meta operations\n\nThe following operations are part of the conformance interface and MUST be supported by any adapter that participates in the conformance suite, regardless of claimed profile. These meta operations MUST be callable without requiring any capability token.\n\n### `meta.claim`\n\nReturns the adapter's self-reported metadata.\n\nInput: `{}` (empty object)\n\nOutput:\n```json\n{\n \"ok\": true,\n \"result\": {\n \"implementation\": \"my-tool\",\n \"version\": \"1.0.0\",\n \"spec_version\": \"0.3.0-rc.3\",\n \"validation_modes\": [\"strict\"],\n \"profiles\": [\"core-lite\", \"recurrence\"],\n \"capabilities\": [\"dependencies\", \"links\"]\n }\n}\n```\n\nFields:\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `implementation` | string | yes | Human-readable implementation name |\n| `version` | string | yes | Implementation version string |\n| `spec_version` | string | yes | `tasknotes-spec` version targeted by this adapter |\n| `validation_modes` | string[] | yes | Supported validation modes; MUST include `strict` |\n| `profiles` | string[] | yes | Claimed conformance profiles; valid values: `core-lite`, `recurrence`, `extended`, `templating`, `materialized-occurrences` |\n| `capabilities` | string[] | yes | Optional capability tokens; known tokens listed in §7.11 |\n\n`profiles` lists explicitly claimed profiles. Cumulative profile expansion is applied by runners for fixture selection (§7.3, §7.9), but does not change literal membership semantics of `meta.has_profile`.\n\nProfile-token consistency rules:\n\n- If `profiles` contains `extended`, `capabilities` MUST include `dependencies`, `reminders`, `links`, and `time-tracking`.\n- If `profiles` contains `templating`, `capabilities` MUST include `templating`.\n- If `profiles` contains `materialized-occurrences`, `profiles` MUST also contain `recurrence` and `capabilities` MUST include `materialized-occurrences`.\n- Runners and fixture suites SHOULD validate these claim-consistency rules directly from `meta.claim`, not only by capability-gating feature fixtures.\n\n### `meta.has_capability`\n\nTests whether the adapter claims a specific capability.\n\nInput:\n```json\n{ \"capability\": \"dependencies\" }\n```\n\nOutput:\n```json\n{ \"ok\": true, \"result\": { \"value\": true } }\n```\n\n`result.value` MUST be `true` if the capability is in the `capabilities` array returned by `meta.claim`, and `false` otherwise.\n\n### `meta.has_profile`\n\nTests whether the adapter claims a specific conformance profile.\n\nInput:\n```json\n{ \"profile\": \"recurrence\" }\n```\n\nOutput:\n```json\n{ \"ok\": true, \"result\": { \"value\": true } }\n```\n\n`result.value` MUST be `true` if the profile is in the `profiles` array returned by `meta.claim`, and `false` otherwise.\n\n## 7.11 Known capability tokens\n\nThe following capability tokens are defined by this specification. Implementations MAY define additional tokens.\n\n| Token | Required by profile | Meaning |\n|---|---|---|\n| `dependencies` | `extended` | Supports `blocked_by`, dependency operations, and dependency validation |\n| `reminders` | `extended` | Supports `reminders`, reminder operations, and reminder validation |\n| `attachments` | optional extension under any profile | Treats the mapped `attachments` list as authoritative membership; validates and normalizes its collection-file references; and implements §5.21 attachment operations using host-owned binary storage. A claim MUST separately disclose which host file actions are available; it does not by itself promise physical deletion where the host cannot perform an authoritative reference check. |\n| `links` | `extended` | Supports link parsing and resolution (§11) |\n| `time-tracking` | `extended` | Supports time-tracking management operations (§5.19) |\n| `materialized-occurrences` | `materialized-occurrences` | Supports recurrence materialization and materialized occurrence operations (§4.18, §5.20) |\n| `rename` | optional extension under `extended` | Supports file rename with reference updates |\n| `archive` | optional extension under `extended` | Supports archive semantics (§5.12) |\n| `batch` | optional extension under `extended` | Supports batch operations with per-item outcomes (§5.15) |\n| `concurrency` | optional extension under `extended` | Supports write-conflict detection (§5.16) |\n| `dry-run` | optional extension under `extended` | Supports dry-run mode (§5.17) |\n| `migration` | — | Supports migration operations (§8) |\n| `templating` | `templating` | Supports create-time templating (§5.3.5) |\n","aliases":["/spec/07-conformance/"],"toc":[{"level":2,"id":"71-purpose","text":"7.1 Purpose"},{"level":2,"id":"72-conformance-principles","text":"7.2 Conformance principles"},{"level":2,"id":"73-profile-model","text":"7.3 Profile model"},{"level":3,"id":"731-profile-core-lite","text":"7.3.1 Profile: core-lite"},{"level":3,"id":"732-profile-recurrence","text":"7.3.2 Profile: recurrence"},{"level":3,"id":"733-profile-templating-non-cumulative-extension","text":"7.3.3 Profile: templating (non-cumulative extension)"},{"level":3,"id":"734-profile-materialized-occurrences-non-cumulative-extension","text":"7.3.4 Profile: materialized-occurrences (non-cumulative extension)"},{"level":3,"id":"735-profile-extended","text":"7.3.5 Profile: extended"},{"level":2,"id":"74-conformance-claim-format","text":"7.4 Conformance claim format"},{"level":2,"id":"75-deviation-disclosure","text":"7.5 Deviation disclosure"},{"level":2,"id":"76-feature-detection","text":"7.6 Feature detection"},{"level":2,"id":"77-strictness-disclosure","text":"7.7 Strictness disclosure"},{"level":2,"id":"78-example-profile-matrix","text":"7.8 Example profile matrix"},{"level":2,"id":"79-executable-fixture-suite","text":"7.9 Executable fixture suite"},{"level":2,"id":"710-meta-operations","text":"7.10 Meta operations"},{"level":3,"id":"metaclaim","text":"meta.claim"},{"level":3,"id":"metahascapability","text":"meta.has_capability"},{"level":3,"id":"metahasprofile","text":"meta.has_profile"},{"level":2,"id":"711-known-capability-tokens","text":"7.11 Known capability tokens"}],"html":"

7.1 Purpose#

\n

This section defines conformance profiles and claim requirements for implementations.

\n

7.2 Conformance principles#

\n

An implementation MUST NOT claim conformance to a profile unless all required capabilities of that profile are implemented.

\n

Implementations MAY implement additional behavior beyond a profile, but extra behavior MUST NOT violate profile requirements.

\n

7.3 Profile model#

\n

Profiles are cumulative unless explicitly marked otherwise.

\n

7.3.1 Profile: core-lite#

\n

Required capabilities:

\n
    \n
  • task identification and loading
  • \n
  • semantic-role mapping and canonical writes (§2)
  • \n
  • required role support (title, status, completed_date, date_created, date_modified)
  • \n
  • create, update, delete operations (§5)
  • \n
  • non-recurring complete/uncomplete (§5)
  • \n
  • temporal parsing/canonical serialization basics (§3)
  • \n
  • strict validation mode support (§6.3)
  • \n
  • validation core checks (§6.4 items 1,1a,1b,2,3,6)
  • \n
\n

7.3.2 Profile: recurrence#

\n

Additional required capabilities:

\n
    \n
  • tasknotes recurrence-string parsing/validation, including RRULE parameter syntax and inline DTSTART handling
  • \n
  • recurrence anchor semantics, including seed precedence and completion-anchor progression
  • \n
  • complete/uncomplete instance
  • \n
  • skip/unskip instance
  • \n
  • instance-list invariants and effective state resolution
  • \n
  • validation checks for recurrence and instance overlap
  • \n
\n

7.3.3 Profile: templating (non-cumulative extension)#

\n

This profile is not cumulative; it MAY be claimed alongside core-lite, recurrence, materialized-occurrences, and/or extended.\ntemplating MUST NOT be claimed alone.

\n

Required capabilities:

\n
    \n
  • create-time template processing semantics per §5.3.5
  • \n
  • templating configuration support per §9.14
  • \n
  • deterministic template/frontmatter/body merge behavior
  • \n
  • deterministic failure-mode behavior for template read/parse failures
  • \n
  • support for portable double-brace template variables defined in §5.3.5
  • \n
\n

7.3.4 Profile: materialized-occurrences (non-cumulative extension)#

\n

This profile is not cumulative; it MUST be claimed alongside recurrence.\nIt MAY be claimed alongside extended and/or templating, but it does not require either.

\n

Required capabilities:

\n
    \n
  • materialized occurrence roles and identity semantics (§2.6.6)
  • \n
  • recurrence materialization semantics (§4.18)
  • \n
  • materialize/complete/skip/uncomplete/unskip materialized occurrence operations (§5.20)
  • \n
  • occurrences configuration defaults (§9.17)
  • \n
  • parent-reference link parsing/resolution for recurrence_parent (§11), without requiring full extended
  • \n
  • validation checks for materialized occurrence identity, duplicates, and state conflicts (§6.4 items 16-18)
  • \n
\n

Claiming materialized-occurrences also has required capability-token implications:

\n
    \n
  • meta.claim.capabilities MUST include materialized-occurrences.
  • \n
  • meta.claim.profiles MUST also include recurrence.
  • \n
  • Omitting either token while claiming materialized-occurrences is a non-conformant claim.
  • \n
\n

7.3.5 Profile: extended#

\n

Additional required capabilities:

\n
    \n
  • dependency schema support (blocked_by)
  • \n
  • reminder schema support (reminders)
  • \n
  • link parsing/resolution semantics for link-bearing fields (§11)
  • \n
  • time-tracking management semantics for time_entries (§5.19), including per-task active-session constraints
  • \n
  • dependency operations and validation per §10.2
  • \n
  • reminder operations and validation per §10.3
  • \n
\n

If extended is claimed, all of the above baseline capabilities MUST conform to documented semantics.

\n

Claiming extended also has required capability-token implications:

\n
    \n
  • meta.claim.capabilities MUST include dependencies, reminders, links, and time-tracking.
  • \n
  • Omitting any of these tokens while claiming extended is a non-conformant claim (even if capability-gated fixtures are skipped by a runner).
  • \n
\n

Optional capability extensions within extended:

\n
    \n
  • rename capability: reference-aware rename behavior (including dependency UID references)
  • \n
  • archive capability: archive semantics (§5.12)
  • \n
  • batch capability: batch operations with per-item outcomes (§5.15)
  • \n
  • concurrency capability: write-conflict detection semantics (§5.16)
  • \n
  • dry-run capability: dry-run semantics (§5.17)
  • \n
\n

When an optional capability token is claimed, corresponding behavior MUST conform to documented semantics.

\n

7.4 Conformance claim format#

\n

A conformance claim MUST include:

\n
    \n
  • implementation name and version,
  • \n
  • tasknotes-spec version,
  • \n
  • claimed profile list,
  • \n
  • validation mode support (strict required; permissive optional),
  • \n
  • known deviations,
  • \n
  • compatibility mode status (if any),
  • \n
  • configuration provider status (active provider chain, precedence policy, and fallback state).
  • \n
\n

Example:

\n
Implementation: example-task-cli v1.4.0\nSpec: tasknotes-spec 0.3.0-rc.3\nProfiles: core-lite, recurrence, templating\nValidation modes: strict, permissive\nKnown deviations: none\nCompatibility mode: disabled\nConfiguration providers: tasknotes_plugin_data_json > built_in_defaults\nConfiguration fallback: none\n

7.5 Deviation disclosure#

\n

Any known deviation from normative text MUST be explicitly disclosed in conformance output/documentation.

\n

A deviation entry SHOULD include:

\n
    \n
  • affected section,
  • \n
  • deviation summary,
  • \n
  • impact,
  • \n
  • planned resolution version.
  • \n
\n

7.6 Feature detection#

\n

Implementations SHOULD expose machine-readable capability metadata, including:

\n
    \n
  • profiles
  • \n
  • effective runtime timezone
  • \n
  • active configuration providers and precedence chain
  • \n
  • enabled compatibility modes
  • \n
  • configurable status sets
  • \n
  • supported mapping aliases
  • \n
  • templating support flags and effective templating failure mode
  • \n
  • dependency and reminder support flags
  • \n
  • attachment membership, reference normalization, and host-provided binary\noperation flags (including whether physical deletion is available)
  • \n
  • time-tracking support flags, including active-session policy and auto-stop-on-complete behavior
  • \n
  • materialized occurrence support flags, including materialization mode, next trigger, and rolling bounds
  • \n
  • configured natural-language capture triggers when the optional nlp block is\npresent
  • \n
\n

7.7 Strictness disclosure#

\n

Conformance requires strict validation mode support (§6.3).

\n

Conformance claims MUST indicate whether permissive mode is also supported.

\n

7.8 Example profile matrix#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Capabilitycore-literecurrencetemplatingmaterialized-occurrencesextended
create/update/deleterequiredrequiredcompanion-profile requiredcompanion-profile requiredrequired
non-recurring completerequiredrequiredcompanion-profile requiredcompanion-profile requiredrequired
recurring instance complete/skip-requiredoptionalrequired via companion recurrence claimrequired
materialize occurrence notes (§4.18, §5.20)--optionalrequiredoptional
recurrence parent link resolution--optionalrequired for recurrence_parent onlyrequired
template expansion/merge (§5.3.5)--requiredoptionaloptional
double-brace portable variable support--requiredoptionaloptional
recurrence-string validation-requiredoptionalrequired via companion recurrence claimrequired
link parsing/resolution (§11)--optionalrequired for recurrence_parent onlyrequired
attachment membership and ops (§5.21)optional via attachments capabilityoptional via attachments capabilityoptional via attachments capabilityoptional via attachments capabilityoptional via attachments capability
dependency schema and ops--optionaloptionalrequired
reminder schema and ops--optionaloptionalrequired
time tracking start/stop/edit semantics (§5.19)--optionaloptionalrequired
rename updates dependency/project links--optionaloptionaloptional via rename capability
archive semantics (§5.12)--optionaloptionaloptional via archive capability
batch per-item outcomes (§5.15)--optionaloptionaloptional via batch capability
write-conflict detection (§5.16)--optionaloptionaloptional via concurrency capability
dry-run reporting (§5.17)--optionaloptionaloptional via dry-run capability
\n

7.9 Executable fixture suite#

\n

This specification includes an executable fixture suite in conformance/.

\n
    \n
  • language-neutral fixtures are stored in conformance/fixtures/*.json
  • \n
  • section/profile/operation coverage is tracked in conformance/manifest.json
  • \n
  • coverage guard tests MUST enforce both section representation and minimum-depth thresholds for key sections/operations.
  • \n
  • adapters execute fixture operations per conformance/docs/ADAPTER_CONTRACT.md
  • \n
  • runners MUST execute fixtures only when both conditions hold:
      \n
    • fixture profile is satisfied by claimed adapter profiles under cumulative profile rules (§7.3),
    • \n
    • all fixture requires capability tokens are present.
    • \n
    \n
  • \n
\n

Fixture expectations MUST be profile-modular: they MUST NOT assume capability values or profile memberships beyond what the fixture's own profile/requires gating guarantees.\nFixtures for optional extension capabilities (rename, archive, batch, concurrency, dry-run) MUST be capability-gated via requires and MUST NOT rely on extended profile membership alone.

\n

Conformance claims SHOULD report fixture pass/fail results against the claimed profiles.

\n

7.10 Meta operations#

\n

The following operations are part of the conformance interface and MUST be supported by any adapter that participates in the conformance suite, regardless of claimed profile. These meta operations MUST be callable without requiring any capability token.

\n

meta.claim#

\n

Returns the adapter's self-reported metadata.

\n

Input: {} (empty object)

\n

Output:

\n
{\n  "ok": true,\n  "result": {\n    "implementation": "my-tool",\n    "version": "1.0.0",\n    "spec_version": "0.3.0-rc.3",\n    "validation_modes": ["strict"],\n    "profiles": ["core-lite", "recurrence"],\n    "capabilities": ["dependencies", "links"]\n  }\n}\n

Fields:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
FieldTypeRequiredDescription
implementationstringyesHuman-readable implementation name
versionstringyesImplementation version string
spec_versionstringyestasknotes-spec version targeted by this adapter
validation_modesstring[]yesSupported validation modes; MUST include strict
profilesstring[]yesClaimed conformance profiles; valid values: core-lite, recurrence, extended, templating, materialized-occurrences
capabilitiesstring[]yesOptional capability tokens; known tokens listed in §7.11
\n

profiles lists explicitly claimed profiles. Cumulative profile expansion is applied by runners for fixture selection (§7.3, §7.9), but does not change literal membership semantics of meta.has_profile.

\n

Profile-token consistency rules:

\n
    \n
  • If profiles contains extended, capabilities MUST include dependencies, reminders, links, and time-tracking.
  • \n
  • If profiles contains templating, capabilities MUST include templating.
  • \n
  • If profiles contains materialized-occurrences, profiles MUST also contain recurrence and capabilities MUST include materialized-occurrences.
  • \n
  • Runners and fixture suites SHOULD validate these claim-consistency rules directly from meta.claim, not only by capability-gating feature fixtures.
  • \n
\n

meta.has_capability#

\n

Tests whether the adapter claims a specific capability.

\n

Input:

\n
{ "capability": "dependencies" }\n

Output:

\n
{ "ok": true, "result": { "value": true } }\n

result.value MUST be true if the capability is in the capabilities array returned by meta.claim, and false otherwise.

\n

meta.has_profile#

\n

Tests whether the adapter claims a specific conformance profile.

\n

Input:

\n
{ "profile": "recurrence" }\n

Output:

\n
{ "ok": true, "result": { "value": true } }\n

result.value MUST be true if the profile is in the profiles array returned by meta.claim, and false otherwise.

\n

7.11 Known capability tokens#

\n

The following capability tokens are defined by this specification. Implementations MAY define additional tokens.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
TokenRequired by profileMeaning
dependenciesextendedSupports blocked_by, dependency operations, and dependency validation
remindersextendedSupports reminders, reminder operations, and reminder validation
attachmentsoptional extension under any profileTreats the mapped attachments list as authoritative membership; validates and normalizes its collection-file references; and implements §5.21 attachment operations using host-owned binary storage. A claim MUST separately disclose which host file actions are available; it does not by itself promise physical deletion where the host cannot perform an authoritative reference check.
linksextendedSupports link parsing and resolution (§11)
time-trackingextendedSupports time-tracking management operations (§5.19)
materialized-occurrencesmaterialized-occurrencesSupports recurrence materialization and materialized occurrence operations (§4.18, §5.20)
renameoptional extension under extendedSupports file rename with reference updates
archiveoptional extension under extendedSupports archive semantics (§5.12)
batchoptional extension under extendedSupports batch operations with per-item outcomes (§5.15)
concurrencyoptional extension under extendedSupports write-conflict detection (§5.16)
dry-runoptional extension under extendedSupports dry-run mode (§5.17)
migration—Supports migration operations (§8)
templatingtemplatingSupports create-time templating (§5.3.5)
\n","text":"7.1 Purpose# This section defines conformance profiles and claim requirements for implementations. 7.2 Conformance principles# An implementation MUST NOT claim conformance to a profile unless all required capabilities of that profile are implemented. Implementations MAY implement additional behavior beyond a profile, but extra behavior MUST NOT violate profile requirements. 7.3 Profile model# Profiles are cumulative unless explicitly marked otherwise. 7.3.1 Profile: core-lite# Required capabilities: task identification and loading semantic-role mapping and canonical writes (§2) required role support (title, status, completed_date, date_created, date_modified) create, update, delete operations (§5) non-recurring complete/uncomplete (§5) temporal parsing/canonical serialization basics (§3) strict validation mode support (§6.3) validation core checks (§6.4 items 1,1a,1b,2,3,6) 7.3.2 Profile: recurrence# Additional required capabilities: tasknotes recurrence-string parsing/validation, including RRULE parameter syntax and inline DTSTART handling recurrence anchor semantics, including seed precedence and completion-anchor progression complete/uncomplete instance skip/unskip instance instance-list invariants and effective state resolution validation checks for recurrence and instance overlap 7.3.3 Profile: templating (non-cumulative extension)# This profile is not cumulative; it MAY be claimed alongside core-lite, recurrence, materialized-occurrences, and/or extended. templating MUST NOT be claimed alone. Required capabilities: create-time template processing semantics per §5.3.5 templating configuration support per §9.14 deterministic template/frontmatter/body merge behavior deterministic failure-mode behavior for template read/parse failures support for portable double-brace template variables defined in §5.3.5 7.3.4 Profile: materialized-occurrences (non-cumulative extension)# This profile is not cumulative; it MUST be claimed alongside recurrence. It MAY be claimed alongside extended and/or templating, but it does not require either. Required capabilities: materialized occurrence roles and identity semantics (§2.6.6) recurrence materialization semantics (§4.18) materialize/complete/skip/uncomplete/unskip materialized occurrence operations (§5.20) occurrences configuration defaults (§9.17) parent-reference link parsing/resolution for recurrence_parent (§11), without requiring full extended validation checks for materialized occurrence identity, duplicates, and state conflicts (§6.4 items 16-18) Claiming materialized-occurrences also has required capability-token implications: meta.claim.capabilities MUST include materialized-occurrences. meta.claim.profiles MUST also include recurrence. Omitting either token while claiming materialized-occurrences is a non-conformant claim. 7.3.5 Profile: extended# Additional required capabilities: dependency schema support (blocked_by) reminder schema support (reminders) link parsing/resolution semantics for link-bearing fields (§11) time-tracking management semantics for time_entries (§5.19), including per-task active-session constraints dependency operations and validation per §10.2 reminder operations and validation per §10.3 If extended is claimed, all of the above baseline capabilities MUST conform to documented semantics. Claiming extended also has required capability-token implications: meta.claim.capabilities MUST include dependencies, reminders, links, and time-tracking. Omitting any of these tokens while claiming extended is a non-conformant claim (even if capability-gated fixtures are skipped by a runner). Optional capability extensions within extended: rename capability: reference-aware rename behavior (including dependency UID references) archive capability: archive semantics (§5.12) batch capability: batch operations with per-item outcomes (§5.15) concurrency capability: write-conflict detection semantics (§5.16) dry-run capability: dry-run semantics (§5.17) When an optional capability token is claimed, corresponding behavior MUST conform to documented semantics. 7.4 Conformance claim format# A conformance claim MUST include: implementation name and version, tasknotes-spec version, claimed profile list, validation mode support (strict required; permissive optional), known deviations, compatibility mode status (if any), configuration provider status (active provider chain, precedence policy, and fallback state). Example: Implementation: example-task-cli v1.4.0 Spec: tasknotes-spec 0.3.0-rc.3 Profiles: core-lite, recurrence, templating Validation modes: strict, permissive Known deviations: none Compatibility mode: disabled Configuration providers: tasknotes_plugin_data_json > built_in_defaults Configuration fallback: none 7.5 Deviation disclosure# Any known deviation from normative text MUST be explicitly disclosed in conformance output/documentation. A deviation entry SHOULD include: affected section, deviation summary, impact, planned resolution version. 7.6 Feature detection# Implementations SHOULD expose machine-readable capability metadata, including: profiles effective runtime timezone active configuration providers and precedence chain enabled compatibility modes configurable status sets supported mapping aliases templating support flags and effective templating failure mode dependency and reminder support flags attachment membership, reference normalization, and host-provided binary operation flags (including whether physical deletion is available) time-tracking support flags, including active-session policy and auto-stop-on-complete behavior materialized occurrence support flags, including materialization mode, next trigger, and rolling bounds configured natural-language capture triggers when the optional nlp block is present 7.7 Strictness disclosure# Conformance requires strict validation mode support (§6.3). Conformance claims MUST indicate whether permissive mode is also supported. 7.8 Example profile matrix# Capability core-lite recurrence templating materialized-occurrences extended create/update/delete required required companion-profile required companion-profile required required non-recurring complete required required companion-profile required companion-profile required required recurring instance complete/skip - required optional required via companion recurrence claim required materialize occurrence notes (§4.18, §5.20) - - optional required optional recurrence parent link resolution - - optional required for recurrence_parent only required template expansion/merge (§5.3.5) - - required optional optional double-brace portable variable support - - required optional optional recurrence-string validation - required optional required via companion recurrence claim required link parsing/resolution (§11) - - optional required for recurrence_parent only required attachment membership and ops (§5.21) optional via attachments capability optional via attachments capability optional via attachments capability optional via attachments capability optional via attachments capability dependency schema and ops - - optional optional required reminder schema and ops - - optional optional required time tracking start/stop/edit semantics (§5.19) - - optional optional required rename updates dependency/project links - - optional optional optional via rename capability archive semantics (§5.12) - - optional optional optional via archive capability batch per-item outcomes (§5.15) - - optional optional optional via batch capability write-conflict detection (§5.16) - - optional optional optional via concurrency capability dry-run reporting (§5.17) - - optional optional optional via dry-run capability 7.9 Executable fixture suite# This specification includes an executable fixture suite in conformance/. language-neutral fixtures are stored in conformance/fixtures/*.json section/profile/operation coverage is tracked in conformance/manifest.json coverage guard tests MUST enforce both section representation and minimum-depth thresholds for key sections/operations. adapters execute fixture operations per conformance/docs/ADAPTER_CONTRACT.md runners MUST execute fixtures only when both conditions hold: fixture profile is satisfied by claimed adapter profiles under cumulative profile rules (§7.3), all fixture requires capability tokens are present. Fixture expectations MUST be profile-modular: they MUST NOT assume capability values or profile memberships beyond what the fixture's own profile/requires gating guarantees. Fixtures for optional extension capabilities (rename, archive, batch, concurrency, dry-run) MUST be capability-gated via requires and MUST NOT rely on extended profile membership alone. Conformance claims SHOULD report fixture pass/fail results against the claimed profiles. 7.10 Meta operations# The following operations are part of the conformance interface and MUST be supported by any adapter that participates in the conformance suite, regardless of claimed profile. These meta operations MUST be callable without requiring any capability token. meta.claim# Returns the adapter's self-reported metadata. Input: {} (empty object) Output: { \"ok\": true, \"result\": { \"implementation\": \"my-tool\", \"version\": \"1.0.0\", \"spec_version\": \"0.3.0-rc.3\", \"validation_modes\": [\"strict\"], \"profiles\": [\"core-lite\", \"recurrence\"], \"capabilities\": [\"dependencies\", \"links\"] } } Fields: Field Type Required Description implementation string yes Human-readable implementation name version string yes Implementation version string spec_version string yes tasknotes-spec version targeted by this adapter validation_modes string[] yes Supported validation modes; MUST include strict profiles string[] yes Claimed conformance profiles; valid values: core-lite, recurrence, extended, templating, materialized-occurrences capabilities string[] yes Optional capability tokens; known tokens listed in §7.11 profiles lists explicitly claimed profiles. Cumulative profile expansion is applied by runners for fixture selection (§7.3, §7.9), but does not change literal membership semantics of meta.has_profile. Profile-token consistency rules: If profiles contains extended, capabilities MUST include dependencies, reminders, links, and time-tracking. If profiles contains templating, capabilities MUST include templating. If profiles contains materialized-occurrences, profiles MUST also contain recurrence and capabilities MUST include materialized-occurrences. Runners and fixture suites SHOULD validate these claim-consistency rules directly from meta.claim, not only by capability-gating feature fixtures. meta.has_capability# Tests whether the adapter claims a specific capability. Input: { \"capability\": \"dependencies\" } Output: { \"ok\": true, \"result\": { \"value\": true } } result.value MUST be true if the capability is in the capabilities array returned by meta.claim, and false otherwise. meta.has_profile# Tests whether the adapter claims a specific conformance profile. Input: { \"profile\": \"recurrence\" } Output: { \"ok\": true, \"result\": { \"value\": true } } result.value MUST be true if the profile is in the profiles array returned by meta.claim, and false otherwise. 7.11 Known capability tokens# The following capability tokens are defined by this specification. Implementations MAY define additional tokens. Token Required by profile Meaning dependencies extended Supports blocked_by, dependency operations, and dependency validation reminders extended Supports reminders, reminder operations, and reminder validation attachments optional extension under any profile Treats the mapped attachments list as authoritative membership; validates and normalizes its collection-file references; and implements §5.21 attachment operations using host-owned binary storage. A claim MUST separately disclose which host file actions are available; it does not by itself promise physical deletion where the host cannot perform an authoritative reference check. links extended Supports link parsing and resolution (§11) time-tracking extended Supports time-tracking management operations (§5.19) materialized-occurrences materialized-occurrences Supports recurrence materialization and materialized occurrence operations (§4.18, §5.20) rename optional extension under extended Supports file rename with reference updates archive optional extension under extended Supports archive semantics (§5.12) batch optional extension under extended Supports batch operations with per-item outcomes (§5.15) concurrency optional extension under extended Supports write-conflict detection (§5.16) dry-run optional extension under extended Supports dry-run mode (§5.17) migration — Supports migration operations (§8) templating templating Supports create-time templating (§5.3.5)"},{"route":"/developers/specification/08-compatibility-and-migrations/","title":"8. Compatibility and Migrations","description":"This section defines how implementations transition from historical behavior to canonical specification behavior without silent data breakage.","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:08-compatibility-and-migrations.md","namespace":"specification","relativePath":"08-compatibility-and-migrations.md","raw":"# 8. Compatibility and Migrations\n\n## 8.1 Purpose\n\nThis section defines how implementations transition from historical behavior to canonical specification behavior without silent data breakage.\n\n## 8.2 Compatibility modes\n\nImplementations MAY support compatibility modes for legacy behavior.\n\nIf supported, compatibility modes MUST:\n\n- be explicitly enabled or disabled,\n- be discoverable through configuration or capability metadata,\n- not be silently enabled by default in new collections.\n\n## 8.3 Migration expectations\n\nWhen canonical behavior differs from historical behavior, implementations SHOULD provide:\n\n1. deterministic migration rules,\n2. dry-run preview support,\n3. rollback-safe workflow guidance.\n\n## 8.4 Alias normalization migration\n\nFor legacy key aliases, a migration SHOULD:\n\n- read both canonical and alias keys,\n- choose canonical value deterministically (recommended: canonical key precedence),\n- rewrite persisted file using canonical keys,\n- preserve unrelated unknown fields.\n\n### 8.4.1 Example\n\nBefore:\n\n```yaml\nrecurrenceAnchor: scheduled\nrecurrence_anchor: completion\n```\n\nAfter normalization:\n\n```yaml\nrecurrenceAnchor: scheduled\n```\n\nWith warning:\n\n- `alias_conflict_ignored`: alias value ignored because canonical key present.\n\n## 8.5 Temporal normalization migration\n\nIf historical writes include mixed datetime styles, migration SHOULD normalize to canonical UTC ISO `Z` for datetime roles while preserving date-only roles as dates.\n\nExample:\n\nBefore:\n\n```yaml\ndateCreated: 2026-02-20 10:00:00+00:00\n```\n\nAfter:\n\n```yaml\ndateCreated: 2026-02-20T10:00:00Z\n```\n\n## 8.6 Recurrence state migration\n\nIf historical data allows overlapping complete/skip dates, migration MUST resolve overlap deterministically.\n\nRecommended resolution policy:\n\n- if overlap exists, prefer most recent user action where recoverable,\n- otherwise prefer `complete_instances` and remove overlapping skip entries,\n- emit migration report for affected dates.\n\nPolicy choice MUST be documented.\n\n## 8.7 Materialized occurrence migration\n\nWhen introducing materialized occurrence notes into an existing collection, implementations SHOULD avoid automatic bulk creation.\nRecommended migration behavior:\n\n- do not materialize historical or future occurrence notes unless explicitly requested;\n- preserve existing parent `complete_instances` and `skipped_instances`;\n- when importing existing per-occurrence task files, require deterministic parent/date matching before adding `recurrence_parent` and `occurrence_date`;\n- when materialized occurrence state conflicts with parent instance lists, prefer the occurrence note for that date and report `occurrence_state_conflict`;\n- provide a dry-run report before converting existing task files into materialized occurrence notes.\n\nMigration tooling MUST NOT silently delete occurrence notes or parent recurring tasks.\n\n## 8.8 Dependency migration\n\nWhen migrating legacy dependency data, implementations SHOULD:\n\n- normalize dependency key names to mapped canonical key,\n- ensure each entry has `uid` and canonical `reltype`,\n- normalize legacy string/path references into configured canonical reference style,\n- remove duplicate dependency entries by policy.\n\nIf historical data omits `reltype`, migration MAY apply `dependencies.default_reltype` and SHOULD report count of inferred values.\n\n## 8.9 Reminder migration\n\nWhen migrating legacy reminder data, implementations SHOULD:\n\n- normalize reminder key names,\n- normalize `type` values to canonical enum (`absolute` or `relative`),\n- normalize `relatedTo` values to canonical enum (`due` or `scheduled`),\n- normalize `absoluteTime` to canonical UTC ISO `Z`,\n- validate and normalize offsets to ISO 8601 duration syntax.\n\nIf reminder `id` values are missing, migration MAY generate IDs and MUST report generated count.\n\n## 8.10 Link migration\n\nWhen migrating legacy link values, implementations SHOULD:\n\n- normalize supported link syntaxes according to §11 parsing rules,\n- preserve alias and anchor components where possible,\n- normalize resolved targets into canonical write format by policy,\n- detect and report ambiguous links instead of silently choosing non-deterministically.\n\n## 8.11 Divergence register\n\nImplementations SHOULD maintain a divergence register with columns:\n\n- section\n- current behavior\n- target canonical behavior\n- migration strategy\n- deprecation timeline\n\n## 8.12 Deprecation policy\n\nFor any behavior deprecated by the specification:\n\n1. announce deprecation in release notes,\n2. provide warning period,\n3. provide migration tooling where feasible,\n4. remove deprecated behavior only in a version aligned with compatibility commitments.\n\n## 8.13 Data safety requirements\n\nMigrations MUST NOT:\n\n- silently drop unknown fields,\n- silently convert valid date-only fields to datetime,\n- silently rewrite recurrence semantics without explicit policy,\n- silently materialize occurrence notes outside explicit user/configured materialization policy,\n- silently delete materialized occurrence notes during recurrence edits,\n- silently drop unresolved dependency entries,\n- silently rewrite link targets to different destinations without explicit policy,\n- silently delete reminders unless explicitly requested.\n\n## 8.14 Suggested migration report format\n\n```yaml\nspec_version_from: 0.1.0-draft\nspec_version_to: 0.3.0-rc.3\nfiles_scanned: 214\nfiles_changed: 67\nwarnings:\n alias_conflict_ignored: 3\n instance_state_overlap_resolved: 2\n occurrence_state_conflict: 1\n unresolved_dependency_target: 4\nchanges:\n normalized_datetime_fields: 41\n alias_keys_removed: 29\n instance_overlaps_fixed: 2\n occurrence_state_conflicts: 1\n inferred_dependency_reltype: 5\n generated_reminder_ids: 8\n normalized_link_targets: 14\n```\n\n## 8.15 Compatibility statement example\n\n```text\nCompatibility mode: legacy-aliases=true, legacy-timeentry-duration=true\nPlanned removal: v2.0.0\nMigration command: tasknotes migrate --normalize-frontmatter\n```\n","aliases":["/spec/08-compatibility-and-migrations/"],"toc":[{"level":2,"id":"81-purpose","text":"8.1 Purpose"},{"level":2,"id":"82-compatibility-modes","text":"8.2 Compatibility modes"},{"level":2,"id":"83-migration-expectations","text":"8.3 Migration expectations"},{"level":2,"id":"84-alias-normalization-migration","text":"8.4 Alias normalization migration"},{"level":3,"id":"841-example","text":"8.4.1 Example"},{"level":2,"id":"85-temporal-normalization-migration","text":"8.5 Temporal normalization migration"},{"level":2,"id":"86-recurrence-state-migration","text":"8.6 Recurrence state migration"},{"level":2,"id":"87-materialized-occurrence-migration","text":"8.7 Materialized occurrence migration"},{"level":2,"id":"88-dependency-migration","text":"8.8 Dependency migration"},{"level":2,"id":"89-reminder-migration","text":"8.9 Reminder migration"},{"level":2,"id":"810-link-migration","text":"8.10 Link migration"},{"level":2,"id":"811-divergence-register","text":"8.11 Divergence register"},{"level":2,"id":"812-deprecation-policy","text":"8.12 Deprecation policy"},{"level":2,"id":"813-data-safety-requirements","text":"8.13 Data safety requirements"},{"level":2,"id":"814-suggested-migration-report-format","text":"8.14 Suggested migration report format"},{"level":2,"id":"815-compatibility-statement-example","text":"8.15 Compatibility statement example"}],"html":"

8.1 Purpose#

\n

This section defines how implementations transition from historical behavior to canonical specification behavior without silent data breakage.

\n

8.2 Compatibility modes#

\n

Implementations MAY support compatibility modes for legacy behavior.

\n

If supported, compatibility modes MUST:

\n
    \n
  • be explicitly enabled or disabled,
  • \n
  • be discoverable through configuration or capability metadata,
  • \n
  • not be silently enabled by default in new collections.
  • \n
\n

8.3 Migration expectations#

\n

When canonical behavior differs from historical behavior, implementations SHOULD provide:

\n
    \n
  1. deterministic migration rules,
  2. \n
  3. dry-run preview support,
  4. \n
  5. rollback-safe workflow guidance.
  6. \n
\n

8.4 Alias normalization migration#

\n

For legacy key aliases, a migration SHOULD:

\n
    \n
  • read both canonical and alias keys,
  • \n
  • choose canonical value deterministically (recommended: canonical key precedence),
  • \n
  • rewrite persisted file using canonical keys,
  • \n
  • preserve unrelated unknown fields.
  • \n
\n

8.4.1 Example#

\n

Before:

\n
recurrenceAnchor: scheduled\nrecurrence_anchor: completion\n

After normalization:

\n
recurrenceAnchor: scheduled\n

With warning:

\n
    \n
  • alias_conflict_ignored: alias value ignored because canonical key present.
  • \n
\n

8.5 Temporal normalization migration#

\n

If historical writes include mixed datetime styles, migration SHOULD normalize to canonical UTC ISO Z for datetime roles while preserving date-only roles as dates.

\n

Example:

\n

Before:

\n
dateCreated: 2026-02-20 10:00:00+00:00\n

After:

\n
dateCreated: 2026-02-20T10:00:00Z\n

8.6 Recurrence state migration#

\n

If historical data allows overlapping complete/skip dates, migration MUST resolve overlap deterministically.

\n

Recommended resolution policy:

\n
    \n
  • if overlap exists, prefer most recent user action where recoverable,
  • \n
  • otherwise prefer complete_instances and remove overlapping skip entries,
  • \n
  • emit migration report for affected dates.
  • \n
\n

Policy choice MUST be documented.

\n

8.7 Materialized occurrence migration#

\n

When introducing materialized occurrence notes into an existing collection, implementations SHOULD avoid automatic bulk creation.\nRecommended migration behavior:

\n
    \n
  • do not materialize historical or future occurrence notes unless explicitly requested;
  • \n
  • preserve existing parent complete_instances and skipped_instances;
  • \n
  • when importing existing per-occurrence task files, require deterministic parent/date matching before adding recurrence_parent and occurrence_date;
  • \n
  • when materialized occurrence state conflicts with parent instance lists, prefer the occurrence note for that date and report occurrence_state_conflict;
  • \n
  • provide a dry-run report before converting existing task files into materialized occurrence notes.
  • \n
\n

Migration tooling MUST NOT silently delete occurrence notes or parent recurring tasks.

\n

8.8 Dependency migration#

\n

When migrating legacy dependency data, implementations SHOULD:

\n
    \n
  • normalize dependency key names to mapped canonical key,
  • \n
  • ensure each entry has uid and canonical reltype,
  • \n
  • normalize legacy string/path references into configured canonical reference style,
  • \n
  • remove duplicate dependency entries by policy.
  • \n
\n

If historical data omits reltype, migration MAY apply dependencies.default_reltype and SHOULD report count of inferred values.

\n

8.9 Reminder migration#

\n

When migrating legacy reminder data, implementations SHOULD:

\n
    \n
  • normalize reminder key names,
  • \n
  • normalize type values to canonical enum (absolute or relative),
  • \n
  • normalize relatedTo values to canonical enum (due or scheduled),
  • \n
  • normalize absoluteTime to canonical UTC ISO Z,
  • \n
  • validate and normalize offsets to ISO 8601 duration syntax.
  • \n
\n

If reminder id values are missing, migration MAY generate IDs and MUST report generated count.

\n\n

When migrating legacy link values, implementations SHOULD:

\n
    \n
  • normalize supported link syntaxes according to §11 parsing rules,
  • \n
  • preserve alias and anchor components where possible,
  • \n
  • normalize resolved targets into canonical write format by policy,
  • \n
  • detect and report ambiguous links instead of silently choosing non-deterministically.
  • \n
\n

8.11 Divergence register#

\n

Implementations SHOULD maintain a divergence register with columns:

\n
    \n
  • section
  • \n
  • current behavior
  • \n
  • target canonical behavior
  • \n
  • migration strategy
  • \n
  • deprecation timeline
  • \n
\n

8.12 Deprecation policy#

\n

For any behavior deprecated by the specification:

\n
    \n
  1. announce deprecation in release notes,
  2. \n
  3. provide warning period,
  4. \n
  5. provide migration tooling where feasible,
  6. \n
  7. remove deprecated behavior only in a version aligned with compatibility commitments.
  8. \n
\n

8.13 Data safety requirements#

\n

Migrations MUST NOT:

\n
    \n
  • silently drop unknown fields,
  • \n
  • silently convert valid date-only fields to datetime,
  • \n
  • silently rewrite recurrence semantics without explicit policy,
  • \n
  • silently materialize occurrence notes outside explicit user/configured materialization policy,
  • \n
  • silently delete materialized occurrence notes during recurrence edits,
  • \n
  • silently drop unresolved dependency entries,
  • \n
  • silently rewrite link targets to different destinations without explicit policy,
  • \n
  • silently delete reminders unless explicitly requested.
  • \n
\n

8.14 Suggested migration report format#

\n
spec_version_from: 0.1.0-draft\nspec_version_to: 0.3.0-rc.3\nfiles_scanned: 214\nfiles_changed: 67\nwarnings:\n  alias_conflict_ignored: 3\n  instance_state_overlap_resolved: 2\n  occurrence_state_conflict: 1\n  unresolved_dependency_target: 4\nchanges:\n  normalized_datetime_fields: 41\n  alias_keys_removed: 29\n  instance_overlaps_fixed: 2\n  occurrence_state_conflicts: 1\n  inferred_dependency_reltype: 5\n  generated_reminder_ids: 8\n  normalized_link_targets: 14\n

8.15 Compatibility statement example#

\n
Compatibility mode: legacy-aliases=true, legacy-timeentry-duration=true\nPlanned removal: v2.0.0\nMigration command: tasknotes migrate --normalize-frontmatter\n
","text":"8.1 Purpose# This section defines how implementations transition from historical behavior to canonical specification behavior without silent data breakage. 8.2 Compatibility modes# Implementations MAY support compatibility modes for legacy behavior. If supported, compatibility modes MUST: be explicitly enabled or disabled, be discoverable through configuration or capability metadata, not be silently enabled by default in new collections. 8.3 Migration expectations# When canonical behavior differs from historical behavior, implementations SHOULD provide: deterministic migration rules, dry-run preview support, rollback-safe workflow guidance. 8.4 Alias normalization migration# For legacy key aliases, a migration SHOULD: read both canonical and alias keys, choose canonical value deterministically (recommended: canonical key precedence), rewrite persisted file using canonical keys, preserve unrelated unknown fields. 8.4.1 Example# Before: recurrenceAnchor: scheduled recurrence_anchor: completion After normalization: recurrenceAnchor: scheduled With warning: alias_conflict_ignored: alias value ignored because canonical key present. 8.5 Temporal normalization migration# If historical writes include mixed datetime styles, migration SHOULD normalize to canonical UTC ISO Z for datetime roles while preserving date-only roles as dates. Example: Before: dateCreated: 2026-02-20 10:00:00+00:00 After: dateCreated: 2026-02-20T10:00:00Z 8.6 Recurrence state migration# If historical data allows overlapping complete/skip dates, migration MUST resolve overlap deterministically. Recommended resolution policy: if overlap exists, prefer most recent user action where recoverable, otherwise prefer complete_instances and remove overlapping skip entries, emit migration report for affected dates. Policy choice MUST be documented. 8.7 Materialized occurrence migration# When introducing materialized occurrence notes into an existing collection, implementations SHOULD avoid automatic bulk creation. Recommended migration behavior: do not materialize historical or future occurrence notes unless explicitly requested; preserve existing parent complete_instances and skipped_instances; when importing existing per-occurrence task files, require deterministic parent/date matching before adding recurrence_parent and occurrence_date; when materialized occurrence state conflicts with parent instance lists, prefer the occurrence note for that date and report occurrence_state_conflict; provide a dry-run report before converting existing task files into materialized occurrence notes. Migration tooling MUST NOT silently delete occurrence notes or parent recurring tasks. 8.8 Dependency migration# When migrating legacy dependency data, implementations SHOULD: normalize dependency key names to mapped canonical key, ensure each entry has uid and canonical reltype, normalize legacy string/path references into configured canonical reference style, remove duplicate dependency entries by policy. If historical data omits reltype, migration MAY apply dependencies.default_reltype and SHOULD report count of inferred values. 8.9 Reminder migration# When migrating legacy reminder data, implementations SHOULD: normalize reminder key names, normalize type values to canonical enum (absolute or relative), normalize relatedTo values to canonical enum (due or scheduled), normalize absoluteTime to canonical UTC ISO Z, validate and normalize offsets to ISO 8601 duration syntax. If reminder id values are missing, migration MAY generate IDs and MUST report generated count. 8.10 Link migration# When migrating legacy link values, implementations SHOULD: normalize supported link syntaxes according to §11 parsing rules, preserve alias and anchor components where possible, normalize resolved targets into canonical write format by policy, detect and report ambiguous links instead of silently choosing non-deterministically. 8.11 Divergence register# Implementations SHOULD maintain a divergence register with columns: section current behavior target canonical behavior migration strategy deprecation timeline 8.12 Deprecation policy# For any behavior deprecated by the specification: announce deprecation in release notes, provide warning period, provide migration tooling where feasible, remove deprecated behavior only in a version aligned with compatibility commitments. 8.13 Data safety requirements# Migrations MUST NOT: silently drop unknown fields, silently convert valid date-only fields to datetime, silently rewrite recurrence semantics without explicit policy, silently materialize occurrence notes outside explicit user/configured materialization policy, silently delete materialized occurrence notes during recurrence edits, silently drop unresolved dependency entries, silently rewrite link targets to different destinations without explicit policy, silently delete reminders unless explicitly requested. 8.14 Suggested migration report format# spec_version_from: 0.1.0-draft spec_version_to: 0.3.0-rc.3 files_scanned: 214 files_changed: 67 warnings: alias_conflict_ignored: 3 instance_state_overlap_resolved: 2 occurrence_state_conflict: 1 unresolved_dependency_target: 4 changes: normalized_datetime_fields: 41 alias_keys_removed: 29 instance_overlaps_fixed: 2 occurrence_state_conflicts: 1 inferred_dependency_reltype: 5 generated_reminder_ids: 8 normalized_link_targets: 14 8.15 Compatibility statement example# Compatibility mode: legacy-aliases=true, legacy-timeentry-duration=true Planned removal: v2.0.0 Migration command: tasknotes migrate --normalize-frontmatter"},{"route":"/developers/specification/09-configuration/","title":"9. Configuration","description":"This section defines the normative configuration model for collections using tasknotes-spec.","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:09-configuration.md","namespace":"specification","relativePath":"09-configuration.md","raw":"# 9. Configuration\n\n## 9.1 Purpose\n\nThis section defines the normative configuration model for collections using `tasknotes-spec`.\n\n## 9.2 Configuration provider model\n\nImplementations MUST derive an **effective configuration** from one or more configuration providers.\n\nA provider is a source adapter that returns a partial configuration normalized to this section's schema.\n\nImplementations MUST:\n\n- support at least one provider,\n- document supported providers,\n- document provider precedence order,\n- disclose active providers and fallback behavior in conformance output (§7).\n\n### 9.2.1 Common provider types\n\nCommon providers include:\n\n- `yaml_file`: a `tasknotes.yaml` document at collection root,\n- `tasknotes_plugin_data_json`: `.obsidian/plugins/tasknotes/data.json`,\n- `built_in_defaults`: implementation defaults,\n- optional runtime/CLI/env overrides.\n\nThis list is not exhaustive.\n\n### 9.2.2 Deterministic precedence and merge\n\nProvider precedence MUST be deterministic.\n\nUnless explicitly documented otherwise, implementations MUST resolve configuration per top-level key:\n\n- for each key in §9.3/§9.4, the highest-precedence provider that supplies that key wins,\n- winning object values replace lower-precedence object values as whole objects (no implicit deep merge),\n- after top-level selection, implementations MUST apply documented schema defaults for missing nested keys before exposing effective configuration.\n\nIf an implementation supports deep-merge behavior, it MUST be explicitly documented and deterministic.\n\n### 9.2.3 Strict vs permissive provider behavior\n\nIn strict mode:\n\n- failure to resolve required effective keys (`spec_version`, `mapping`) MUST be a configuration error.\n\nIf permissive mode is implemented, then in permissive mode:\n\n- implementations MAY continue with defaults when providers are missing/unreadable,\n- implementations MUST emit configuration warnings,\n- implementations MUST disclose that effective configuration is partial/default-derived.\n\n### 9.2.4 TaskNotes plugin provider (`data.json`)\n\nThe TaskNotes plugin stores settings in `.obsidian/plugins/tasknotes/data.json` within the vault root. When using this file as a configuration provider, normalization MUST apply the field mapping in the table below.\n\n**Key mapping table** (`data.json` key → spec effective config):\n\n| `data.json` key | Spec key | Notes |\n|---|---|---|\n| `fieldMapping` | `mapping` | Normalize role names: `dateCreated`→`date_created`, `completedDate`→`completed_date`, `recurrenceAnchor`→`recurrence_anchor`, `completeInstances`→`complete_instances`, `skippedInstances`→`skipped_instances`, `recurrenceParent`→`recurrence_parent`, `occurrenceDate`→`occurrence_date`, `occurrenceMaterialization`→`occurrence_materialization`, `occurrenceNextTrigger`→`occurrence_next_trigger`, `occurrenceTemplate`→`occurrence_template`, `occurrencePastHorizon`→`occurrence_past_horizon`, `occurrenceFutureHorizon`→`occurrence_future_horizon`, `blockedBy`→`blocked_by`, `timeEntries`→`time_entries`, `timeEstimate`→`time_estimate` |\n| `storeTitleInFilename` | `title.storage` | `true` → `\"filename\"`, `false` → `\"frontmatter\"` |\n| `taskFilenameFormat` | `title.filename_format` | Values: `\"title\"`, `\"zettel\"`, `\"timestamp\"`, `\"custom\"`; used only when `title.storage=frontmatter` for canonical writes, but preserved as compatibility input when present |\n| `customFilenameTemplate` | `title.custom_filename_template` | Template string, e.g. `\"{title}\"`; used only when `title.storage=frontmatter` and `filename_format=custom` |\n| `taskCreationDefaults.useBodyTemplate` | `templating.enabled` | boolean |\n| `taskCreationDefaults.bodyTemplate` | `templating.template_path` | Path to template file |\n| `customStatuses[*].value` | `status.values` | Ordered array of status value strings |\n| `defaultTaskStatus` | `status.default` | Default status string |\n| `customStatuses[isCompleted=true][*].value` | `status.completed_values` | Statuses where `isCompleted: true` |\n| `defaultTaskPriority` | `defaults.priority` | Default priority string |\n| `autoStopTimeTrackingOnComplete` | `time_tracking.auto_stop_on_complete` | boolean |\n| `autoStopTimeTrackingNotification` | `time_tracking.auto_stop_notification` | boolean |\n| `taskIdentificationMethod` | `task_detection.method` | `\"tag\"` or `\"property\"` |\n| `taskTag` | `task_detection.tag` | Tag string used when `method=\"tag\"` |\n| `taskPropertyName` | `task_detection.property_name` | Frontmatter key used when `method=\"property\"` |\n| `taskPropertyValue` | `task_detection.property_value` | Expected value; empty means key must exist |\n| `tasksFolder` | `task_detection.default_folder` | Default folder for new tasks |\n| `excludedFolders` | `task_detection.excluded_folders` | Comma-separated folder paths to exclude |\n| `moveArchivedTasks` | `archive.move_on_archive` | boolean |\n| `archiveFolder` | `archive.folder` | Archive destination folder |\n| `useFrontmatterMarkdownLinks` | `links.use_markdown_format` | boolean; see §11 |\n\n**Key `data.json` fields with defaults** (for cold-start reading of a vault with no `tasknotes.yaml`):\n\n| Field | Type | Default | Meaning |\n|---|---|---|---|\n| `tasksFolder` | string | `\"TaskNotes/Tasks\"` | Default folder for new task files |\n| `taskIdentificationMethod` | `\"tag\" \\| \"property\"` | `\"tag\"` | How task files are identified |\n| `taskTag` | string | `\"task\"` | Tag that identifies task files (when `method=\"tag\"`) |\n| `taskPropertyName` | string | `\"\"` | Frontmatter key for property-based identification |\n| `taskPropertyValue` | string | `\"\"` | Expected value for property-based identification (empty = key presence) |\n| `storeTitleInFilename` | boolean | `true` | Title storage mode |\n| `taskFilenameFormat` | `\"title\" \\| \"zettel\" \\| \"timestamp\" \\| \"custom\"` | `\"title\"` | Filename generation format |\n| `customFilenameTemplate` | string | `\"{title}\"` | Template for `\"custom\"` filename format |\n| `defaultTaskStatus` | string | `\"open\"` | Default status on create |\n| `defaultTaskPriority` | string | `\"normal\"` | Default priority on create |\n| `customStatuses` | StatusConfig[] | see object shape below | Ordered status definitions |\n| `autoStopTimeTrackingOnComplete` | boolean | `true` | Auto-stop active session on completion |\n| `autoStopTimeTrackingNotification` | boolean | `false` | Show notification when auto-stopping |\n| `useFrontmatterMarkdownLinks` | boolean | `false` | Use markdown links in frontmatter (requires obsidian-frontmatter-markdown-links plugin) |\n| `moveArchivedTasks` | boolean | `false` | Move task file to archive folder on archive |\n| `archiveFolder` | string | `\"TaskNotes/Archive\"` | Archive destination folder |\n| `excludedFolders` | string | `\"\"` | Comma-separated folders to exclude from task indexing |\n\n**StatusConfig object shape:**\n\n```json\n{\n \"id\": \"done\",\n \"value\": \"done\",\n \"label\": \"Done\",\n \"color\": \"#00aa00\",\n \"isCompleted\": true,\n \"order\": 3,\n \"autoArchive\": false,\n \"autoArchiveDelay\": 5\n}\n```\n\n`spec_version` is not present in `data.json`. Implementations MUST synthesize an effective `spec_version` as described in §9.5.\n\nProvider keys not listed above MAY be ignored by `tasknotes-spec` consumers.\n\n## 9.3 Required top-level keys\n\nRequired keys apply to the effective configuration after provider resolution.\n\n| Key | Type | Required | Description |\n|---|---|---|---|\n| `spec_version` | string | yes | target spec version (provider-supplied or synthesized per §9.5) |\n| `mapping` | object | yes | semantic role to storage key mapping |\n\n## 9.4 Recommended top-level keys\n\n| Key | Type | Description |\n|---|---|---|\n| `task_detection` | object | task file identification rules |\n| `defaults` | object | role defaults used during create |\n| `status` | object | status set and completed-value semantics |\n| `validation` | object | validation behavior (`strict` required, `permissive` optional) |\n| `links` | object | link parsing/resolution behavior |\n| `title` | object | title source and filename behavior policy |\n| `templating` | object | optional create-time templating behavior policy |\n| `dependencies` | object | dependency behavior policy |\n| `reminders` | object | reminder behavior policy |\n| `time_tracking` | object | time-tracking management behavior policy |\n| `occurrences` | object | recurrence materialization defaults and bounds |\n| `compatibility` | object | legacy alias/behavior switches |\n\n## 9.5 spec_version behavior\n\n`spec_version` MUST be a semantic version string.\nPre-release identifiers are valid (for example `0.3.0-rc.3`).\n\nImplementations in strict mode MUST reject unsupported major versions.\n\nIf permissive mode is implemented, permissive mode MAY proceed with warning when major version differs.\n\nIf a provider does not supply `spec_version` (for example TaskNotes `data.json`), implementations MUST synthesize an effective `spec_version` matching their target `tasknotes-spec` version and SHOULD disclose that it was synthesized.\n\n## 9.6 mapping schema\n\n`mapping` MUST map semantic roles (from §2) to string storage keys.\n\nMinimum required roles in mapping:\n\n- `title`\n- `status`\n- `completed_date`\n- `date_created`\n- `date_modified`\n\nIf semantic role `id` is supported (§2.6.5), mapping SHOULD include `id`.\nIf profile `materialized-occurrences` is claimed, mapping MUST include `recurrence_parent` and `occurrence_date`, and SHOULD include parent policy roles (`occurrence_materialization`, `occurrence_next_trigger`, `occurrence_template`, `occurrence_past_horizon`, `occurrence_future_horizon`).\n\nExample:\n\n```yaml\nmapping:\n title: title\n status: status\n date_created: dateCreated\n date_modified: dateModified\n completed_date: completedDate\n recurrence: recurrence\n recurrence_anchor: recurrenceAnchor\n complete_instances: completeInstances\n skipped_instances: skippedInstances\n recurrence_parent: recurrence_parent\n occurrence_date: occurrence_date\n occurrence_materialization: occurrence_materialization\n occurrence_next_trigger: occurrence_next_trigger\n occurrence_template: occurrence_template\n occurrence_past_horizon: occurrence_past_horizon\n occurrence_future_horizon: occurrence_future_horizon\n time_entries: timeEntries\n blocked_by: blockedBy\n reminders: reminders\n attachments: attachments\n```\n\n## 9.7 task_detection schema\n\n`task_detection` controls how task files are identified within the vault.\n\n### Detection methods\n\nThe tasknotes plugin natively supports two identification methods, controlled by `taskIdentificationMethod` in `data.json` (mapped to `task_detection.method`):\n\n**`tag` (default)** — A markdown file is a task if it contains the configured tag (default `#task`) in its frontmatter `tags` array or inline in the body. Configured by `task_detection.tag`.\n\n**`property`** — A markdown file is a task if a specified frontmatter property has a specified value (or exists, if value is empty). Configured by `task_detection.property_name` and `task_detection.property_value`.\n\nSchema and selection rules:\n\n1. `task_detection` MAY specify either:\n - `method` (single-method form), or\n - `methods` (multi-method form; non-empty list).\n2. If both are present, `methods` MUST take precedence and implementations SHOULD emit a configuration warning.\n3. If neither is present, effective detection method MUST default to `tag`.\n4. `method` MUST be `tag` or `property`.\n5. `methods` entries MUST be unique and MUST be from:\n - `tag`\n - `property`\n - `field_presence`\n - `field_match`\n6. Method-specific required keys:\n - when `tag` is enabled, effective `task_detection.tag` MUST be non-empty (default `task` when absent);\n - when `property` is enabled, `task_detection.property_name` MUST be provided and non-empty; `task_detection.property_value` MAY be empty (empty means key-exists semantics).\n7. If `methods` has more than one entry, `task_detection.combine` controls combination semantics (§9.7.3). If omitted, it MUST default to `or`.\n\n### 9.7.1 Tag matching semantics\n\nWhen `task_detection.method=tag`, matching MUST follow these rules:\n\n1. Normalize configured `task_detection.tag` by stripping one leading `#` when present.\n2. Compare tag names case-insensitively after normalization.\n3. Frontmatter matching:\n - `tags` MAY be a list of strings or a single string.\n - each tag value is normalized by trimming surrounding whitespace and stripping one leading `#`.\n - match requires exact normalized equality (for example `task` matches `#task`; `task` does not match `tasking`).\n4. Body matching:\n - only markdown text outside fenced code blocks and inline code spans is considered,\n - a match requires a hashtag token with exact normalized name (for example `#task`),\n - partial-word matches MUST NOT count (for example `#tasking` does not match configured `task`).\n\nIf either frontmatter or body matches, the file is identified as a task.\n\n### 9.7.2 Property matching semantics\n\nWhen property detection is enabled (`method=property` or `methods` includes `property`):\n\n1. `task_detection.property_name` MUST name the frontmatter key to inspect.\n2. If `task_detection.property_value` is non-empty, match requires semantic equality with the configured value.\n3. If `task_detection.property_value` is empty or absent, match requires key presence only.\n\n### 9.7.3 Multi-method extension semantics\n\n`tasknotes.yaml`-level providers MAY additionally support:\n\n- `field_presence` (example: required key `status`)\n- `field_match` (example: `type == \"task\"`)\n\nExtension-key shape:\n\n- `field_presence`: string or list of required frontmatter keys.\n- `field_match`: object map of `key -> expected scalar value` for exact semantic equality checks.\n\nIf multiple methods are configured in `tasknotes.yaml`, `task_detection.combine` MUST define combinator semantics:\n\n- `or` (default): file is a task if any enabled method matches.\n- `and`: file is a task only if all enabled methods match.\n\nIf `task_detection.combine` is absent, implementations MUST default to `or`.\n\nImplementations MUST exclude folders listed in `task_detection.excluded_folders` from task indexing.\n\nExecutable conformance: adapters participating in the fixture suite SHOULD expose `config.detect_task_file` to evaluate these detection semantics against fixture inputs.\n\nExample (`tasknotes.yaml`, equivalent to tag-based default):\n\n```yaml\ntask_detection:\n method: tag\n tag: task\n default_folder: TaskNotes/Tasks\n```\n\nExample (property-based):\n\n```yaml\ntask_detection:\n method: property\n property_name: type\n property_value: task\n```\n\n## 9.8 defaults schema\n\n`defaults` defines values used at create time when caller input omits a role.\n\nDefaults MUST NOT override explicit user input.\n\nExample:\n\n```yaml\ndefaults:\n status: open\n priority: normal\n recurrence_anchor: scheduled\n reminders:\n - id: due_minus_1d\n type: relative\n relatedTo: due\n offset: -P1D\n```\n\n`defaults.reminders` behavior is defined in §10.3.9.\n\n## 9.9 status schema\n\n`status` defines known status values and completion semantics.\n\nExample:\n\n```yaml\nstatus:\n values: [open, in-progress, done, cancelled]\n default: open\n completed_values: [done]\n skipped_values: [cancelled]\n default_skipped: cancelled\n```\n\nRules:\n\n- `default` MUST be one of `values`.\n- `completed_values` MUST be a non-empty list.\n- Each `completed_values` entry MUST be in `values`.\n- `skipped_values`, when present, MUST be a list whose entries are in `values`.\n- `default_skipped`, when present, MUST be in `skipped_values`.\n- For implementations claiming `materialized-occurrences`, `skipped_values` MUST NOT overlap `completed_values`.\n- Implementations claiming `materialized-occurrences` MUST provide at least one skipped value or fail skip of materialized occurrence notes deterministically (§5.20.3).\n- Non-recurring completion MUST use this list, not hardcoded literals.\n- When a complete operation does not provide an explicit target status, writers MUST use the first entry of `completed_values`.\n- When a materialized occurrence skip operation does not provide an explicit skipped status, writers MUST use `default_skipped` when present, otherwise the first entry of `skipped_values`.\n\n## 9.10 validation schema\n\nExample:\n\n```yaml\nvalidation:\n mode: strict\n reject_unknown_fields: false\n```\n\nRules:\n\n- `mode` MUST be `strict` or `permissive` when present.\n- If `mode` is absent, effective mode MUST default to `strict`.\n- Conforming implementations MUST support `strict`.\n- Implementations MAY support `permissive`.\n- If `mode=permissive` is configured but not implemented, configuration MUST fail in strict mode and SHOULD emit warning/fallback in permissive mode.\n- `reject_unknown_fields=true` enforces closed-schema behavior for mapped roles.\n\n## 9.11 dependencies schema\n\nExample:\n\n```yaml\ndependencies:\n default_reltype: FINISHTOSTART\n treat_missing_target_as_blocked: true\n enforce_unique_uid: true\n unresolved_target_severity: warning\n require_resolved_uid_on_write: false\n```\n\nRules:\n\n- `default_reltype` MUST be one of the allowed reltype values in §10.2.\n- `treat_missing_target_as_blocked` controls whether missing/unresolvable dependency targets contribute to blocked-state evaluation (§10.2.5).\n- If `treat_missing_target_as_blocked` is absent, effective value MUST default to `true`.\n- `enforce_unique_uid=true` enforces uniqueness at validation/write time.\n- If `enforce_unique_uid` is absent, effective value MUST default to `true`.\n- `unresolved_target_severity` MUST be `warning` or `error`.\n- `require_resolved_uid_on_write=true` requires dependency UID resolution success for add/update operations.\n\n## 9.12 links schema\n\nExample:\n\n```yaml\nlinks:\n extensions: [\".md\"]\n unresolved_default_severity: warning\n update_references_on_rename: true\n```\n\nRules:\n\n- `extensions` defines extension trial order for extensionless targets.\n- `unresolved_default_severity` MUST be `warning` or `error`.\n- `update_references_on_rename=true` enables rename-time link rewrite behavior when supported.\n\n## 9.13 title schema\n\nExample (`storage=frontmatter`):\n\n```yaml\ntitle:\n storage: frontmatter\n filename_format: custom\n custom_filename_template: \"{{date}} {{title}}\"\n```\n\nExample (`storage=filename`):\n\n```yaml\ntitle:\n storage: filename\n```\n\nRules:\n\n- `storage` MUST be `frontmatter` or `filename`.\n- when `storage=frontmatter`, `filename_format` MUST be `title`, `zettel`, `timestamp`, or `custom`.\n- when `storage=frontmatter` and `filename_format=custom`, `custom_filename_template` MUST be provided and non-empty.\n- when `storage=filename`, `filename_format` and `custom_filename_template` MAY be present for compatibility input but MUST be ignored for canonical write behavior.\n- Read precedence MUST be storage-mode-aware:\n 1. when `storage=frontmatter`, use mapped `title` key when present and non-empty, then file basename fallback;\n 2. when `storage=filename`, use file basename first, then mapped `title` fallback when basename is unavailable.\n- If frontmatter and basename titles both exist and differ, the source authoritative for active `storage` MUST win.\n- If `storage=filename`, canonical writes MUST treat filename as title source, MUST rename on title change, and MUST ignore `filename_format` and `custom_filename_template`.\n- If `storage=frontmatter`, canonical writes MUST persist mapped title key; `filename_format` and `custom_filename_template` govern create-time filename generation.\n\nInformative mapping to TaskNotes settings:\n\n- `title.storage=filename` corresponds to `storeTitleInFilename=true`.\n- `title.filename_format` corresponds to `taskFilenameFormat`.\n- `title.custom_filename_template` corresponds to `customFilenameTemplate`.\n\n## 9.14 templating schema\n\n`templating` defines optional create-time template behavior.\nThis schema is required only for implementations claiming profile `templating` (§7.3.3).\n\nExample:\n\n```yaml\ntemplating:\n enabled: true\n template_path: Templates/Task.md\n failure_mode: warning_fallback\n unknown_variable_policy: preserve\n```\n\nRules:\n\n- `enabled` MUST be boolean.\n- If `enabled=true`, `template_path` MUST be provided and non-empty.\n- `failure_mode` MUST be `error` or `warning_fallback` when present.\n- `unknown_variable_policy` MUST be `preserve` or `empty` when present.\n- If `failure_mode` is absent, effective value MUST default to `warning_fallback`.\n- If `unknown_variable_policy` is absent, effective value MUST default to `preserve`.\n- Implementations claiming `templating` MUST support portable double-brace variables from §5.3.5.\n- Implementations not claiming `templating` MAY ignore `templating` settings.\n\n## 9.15 reminders schema\n\nExample:\n\n```yaml\nreminders:\n date_only_anchor_time: \"00:00\"\n apply_defaults_when_explicit: false\n```\n\nRules:\n\n- `date_only_anchor_time` MUST be `HH:MM` 24-hour local time format.\n- `date_only_anchor_time` is used by §10.3.4 for relative reminders against date-only bases.\n- `apply_defaults_when_explicit` MUST be boolean when present.\n- if `apply_defaults_when_explicit` is absent, effective value MUST default to `false`.\n- `apply_defaults_when_explicit=false` means explicit input reminders replace default-reminder application at create time.\n- `apply_defaults_when_explicit=true` means explicit create-time reminders are merged with defaults using §10.3.9 deterministic merge rules.\n\n## 9.16 time_tracking schema\n\nExample:\n\n```yaml\ntime_tracking:\n auto_stop_on_complete: true\n auto_stop_notification: false\n```\n\nRules:\n\n- `auto_stop_on_complete` MUST be boolean when present.\n- `auto_stop_notification` MUST be boolean when present.\n- if `auto_stop_on_complete=true`, completion-triggered stop behavior MUST follow §5.19.5.\n- if `auto_stop_notification` is absent, effective value MUST default to `false`.\n\n## 9.17 occurrences schema\n\n`occurrences` defines collection-level defaults for recurrence materialization.\nThis schema is required only for implementations claiming profile `materialized-occurrences` (§7.3.4).\n\nExample:\n\n```yaml\noccurrences:\n default_materialization: manual\n default_next_trigger: completion\n past_horizon: P0D\n future_horizon: P14D\n```\n\nRules:\n\n- `default_materialization` MUST be one of `manual`, `on_completion`, or `rolling`.\n- If `default_materialization` is absent, effective value MUST default to `manual`.\n- `default_next_trigger` MUST be `completion` or `completion_or_skip`.\n- If `default_next_trigger` is absent, effective value MUST default to `completion`.\n- `past_horizon` and `future_horizon`, when present, MUST be ISO 8601 duration strings.\n- If `default_materialization=rolling`, implementations MUST use finite rolling bounds. If bounds are absent, documented finite defaults MUST be used.\n- Parent task fields override collection defaults: `occurrence_materialization` overrides `occurrences.default_materialization`; `occurrence_next_trigger` overrides `occurrences.default_next_trigger`; `occurrence_past_horizon` and `occurrence_future_horizon` override `occurrences.past_horizon` and `occurrences.future_horizon`.\n- If `occurrences` is absent, the effective behavior is `manual` materialization and `completion` next trigger.\n\n## 9.17.1 nlp schema\n\n`nlp` advertises optional natural-language capture triggers. These settings\nallow another TaskNotes client to preserve the same capture vocabulary without\nmaking natural-language parsing a requirement of the core profile.\n\nExample:\n\n```yaml\nnlp:\n triggers:\n - property_id: tags\n trigger: \"#\"\n enabled: true\n - property_id: contexts\n trigger: \"@\"\n enabled: true\n - property_id: priority\n trigger: \"!\"\n enabled: false\n```\n\nRules:\n\n- `triggers` MUST be a list when present.\n- Every trigger entry MUST contain non-empty `property_id` and `trigger`\n strings.\n- `property_id` SHOULD use a stable TaskNotes role (`tags`, `contexts`,\n `projects`, `status`, or `priority`) or the stable identifier of a configured\n user field.\n- `enabled` MUST be boolean when present and MUST default to `true`.\n- Trigger strings MAY contain more than one character.\n- Trigger entries with unknown `property_id` values MUST be preserved by\n configuration round-trips and MAY be ignored by clients that cannot resolve\n the property.\n- If `nlp` is absent, clients MAY use documented local defaults.\n- This block controls capture parsing and suggestions only. It MUST NOT change\n persisted task field names or values.\n\nInformative mapping to TaskNotes settings:\n\n- `nlp.triggers` corresponds to `nlpTriggers.triggers`.\n- `property_id`, `trigger`, and `enabled` correspond to the plugin fields\n `propertyId`, `trigger`, and `enabled`.\n\n## 9.18 compatibility schema\n\nExample:\n\n```yaml\ncompatibility:\n read_aliases: true\n legacy_duration_field: true\n legacy_local_datetime_input: false\n```\n\nRules:\n\n- Compatibility flags MUST default to conservative behavior in new collections.\n- `legacy_local_datetime_input=true` MAY relax strict parsing for offset-less datetimes only in permissive mode; strict mode parsing rules in §3.4.2 still apply.\n- Enabled compatibility flags SHOULD be disclosed in conformance output (§7).\n\n## 9.19 Complete configuration example (`yaml_file` provider)\n\n```yaml\nspec_version: 0.3.0-rc.3\n\nmapping:\n title: title\n status: status\n priority: priority\n due: due\n scheduled: scheduled\n attachments: attachments\n completed_date: completedDate\n date_created: dateCreated\n date_modified: dateModified\n recurrence: recurrence\n recurrence_anchor: recurrenceAnchor\n complete_instances: completeInstances\n skipped_instances: skippedInstances\n recurrence_parent: recurrence_parent\n occurrence_date: occurrence_date\n occurrence_materialization: occurrence_materialization\n occurrence_next_trigger: occurrence_next_trigger\n occurrence_template: occurrence_template\n occurrence_past_horizon: occurrence_past_horizon\n occurrence_future_horizon: occurrence_future_horizon\n time_entries: timeEntries\n blocked_by: blockedBy\n reminders: reminders\n\ntask_detection:\n method: tag\n tag: task\n default_folder: TaskNotes/Tasks\n\ndefaults:\n status: open\n priority: normal\n recurrence_anchor: scheduled\n reminders:\n - id: due_minus_1d\n type: relative\n relatedTo: due\n offset: -P1D\n\nstatus:\n values: [open, in-progress, done, cancelled]\n default: open\n completed_values: [done]\n skipped_values: [cancelled]\n default_skipped: cancelled\n\nvalidation:\n mode: strict\n reject_unknown_fields: false\n\ndependencies:\n default_reltype: FINISHTOSTART\n treat_missing_target_as_blocked: true\n enforce_unique_uid: true\n unresolved_target_severity: warning\n require_resolved_uid_on_write: false\n\nlinks:\n extensions: [\".md\"]\n unresolved_default_severity: warning\n update_references_on_rename: true\n\ntitle:\n storage: filename\n\ntemplating:\n enabled: false\n failure_mode: warning_fallback\n unknown_variable_policy: preserve\n\nreminders:\n date_only_anchor_time: \"00:00\"\n apply_defaults_when_explicit: false\n\ntime_tracking:\n auto_stop_on_complete: true\n auto_stop_notification: false\n\noccurrences:\n default_materialization: manual\n default_next_trigger: completion\n past_horizon: P0D\n future_horizon: P14D\n\nnlp:\n triggers:\n - property_id: tags\n trigger: \"#\"\n enabled: true\n - property_id: contexts\n trigger: \"@\"\n enabled: true\n - property_id: projects\n trigger: \"+\"\n enabled: true\n - property_id: status\n trigger: \"*\"\n enabled: true\n - property_id: priority\n trigger: \"!\"\n enabled: false\n\ncompatibility:\n read_aliases: true\n legacy_duration_field: true\n```\n\n## 9.20 Configuration errors\n\nConfiguration validation MUST report structured errors with key path context.\n\nExamples:\n\n- no readable configuration provider available in strict mode\n- required effective key unresolved after provider resolution (`spec_version` or `mapping`)\n- missing `mapping.title`\n- `status.default` not present in `status.values`\n- `status.completed_values` contains a value not present in `status.values`\n- `status.skipped_values` contains a value not present in `status.values`\n- `status.default_skipped` not present in `status.skipped_values`\n- `status.skipped_values` overlaps `status.completed_values` when `materialized-occurrences` is claimed\n- unsupported `validation.mode`\n- `validation.mode=permissive` but permissive mode is not implemented\n- invalid `task_detection.method`\n- invalid `task_detection.methods` entry\n- empty `task_detection.tag` when `tag` method is enabled\n- missing `task_detection.property_name` when `property` method is enabled\n- invalid `task_detection.combine`\n- invalid `dependencies.default_reltype`\n- invalid `dependencies.unresolved_target_severity`\n- invalid `links.unresolved_default_severity`\n- invalid `title.storage`\n- invalid `title.filename_format`\n- missing `title.filename_format` when `title.storage=frontmatter`\n- missing `title.custom_filename_template` when `title.storage=frontmatter` and `title.filename_format=custom`\n- missing `templating.template_path` when `templating.enabled=true`\n- invalid `templating.failure_mode`\n- invalid `templating.unknown_variable_policy`\n- invalid `reminders.date_only_anchor_time`\n- invalid `reminders.apply_defaults_when_explicit`\n- invalid `time_tracking.auto_stop_on_complete`\n- invalid `time_tracking.auto_stop_notification`\n- invalid `occurrences.default_materialization`\n- invalid `occurrences.default_next_trigger`\n- invalid `occurrences.past_horizon`\n- invalid `occurrences.future_horizon`\n- invalid `nlp.triggers`\n- empty `nlp.triggers[].property_id`\n- empty `nlp.triggers[].trigger`\n- invalid `nlp.triggers[].enabled`\n\n## 9.21 Default collection state\n\nThis section describes what a fresh tasknotes vault looks like before any user customization. Implementations that read an existing tasknotes vault without a `tasknotes.yaml` SHOULD apply these defaults when `data.json` is absent or fields are missing.\n\n### Folder layout\n\n```text\nMyVault/\n├── TaskNotes/\n│ ├── Tasks/ ← new tasks created here by default\n│ └── Archive/ ← archived tasks moved here (if moveArchivedTasks=true)\n└── .obsidian/\n └── plugins/\n └── tasknotes/\n └── data.json\n```\n\n### Task detection\n\nDefault method: `tag`. A file is a task if it contains the tag `#task` in its frontmatter `tags` array or inline in the body.\n\n### Default field mapping\n\n| Semantic role | Default storage key |\n|---|---|\n| `title` | `title` |\n| `status` | `status` |\n| `priority` | `priority` |\n| `due` | `due` |\n| `scheduled` | `scheduled` |\n| `contexts` | `contexts` |\n| `projects` | `projects` |\n| `time_estimate` | `timeEstimate` |\n| `completed_date` | `completedDate` |\n| `date_created` | `dateCreated` |\n| `date_modified` | `dateModified` |\n| `recurrence` | `recurrence` |\n| `recurrence_anchor` | `recurrence_anchor` |\n| `complete_instances` | `complete_instances` |\n| `skipped_instances` | `skipped_instances` |\n| `recurrence_parent` | `recurrence_parent` |\n| `occurrence_date` | `occurrence_date` |\n| `occurrence_materialization` | `occurrence_materialization` |\n| `occurrence_next_trigger` | `occurrence_next_trigger` |\n| `occurrence_template` | `occurrence_template` |\n| `occurrence_past_horizon` | `occurrence_past_horizon` |\n| `occurrence_future_horizon` | `occurrence_future_horizon` |\n| `time_entries` | `timeEntries` |\n| `blocked_by` | `blockedBy` |\n| `reminders` | `reminders` |\n\nNote: `recurrenceAnchor`, `completeInstances`, and `skippedInstances` are accepted as aliases on read (§2.5). The mixed camelCase/snake_case defaults are intentional for compatibility with historical TaskNotes frontmatter.\n\n### Default statuses\n\n| Value | Label | `isCompleted` | Order |\n|---|---|---|---|\n| `none` | None | false | 0 |\n| `open` | Open | false | 1 |\n| `in-progress` | In progress | false | 2 |\n| `done` | Done | true | 3 |\n\nDefault status on create: `open`. Default completed status (first `isCompleted=true`): `done`.\nNo skipped status is configured by default; implementations that support materialized occurrence skips MUST require configuration or expose a documented default before writing skipped occurrence state.\n\n### Default priorities\n\n| Value | Label | Weight |\n|---|---|---|\n| `none` | None | 0 |\n| `low` | Low | 1 |\n| `normal` | Normal | 2 |\n| `high` | High | 3 |\n\nDefault priority on create: `normal`.\n\n### Title and filename defaults\n\n- `title.storage`: `filename` (filename/path is the authoritative title source)\n- default basename generation under `title.storage=filename` derives from semantic title using filename-safe sanitization\n- implementations MAY also keep mapped `title` in frontmatter as a synchronized compatibility mirror\n- TaskNotes `data.json` may still contain legacy `taskFilenameFormat` values such as `zettel`, but these are compatibility inputs rather than the forward default when `title.storage=filename`\n- title is read from filename first; frontmatter `title` is compatibility fallback when filename-derived title is unavailable (§2.2.2)\n\n### Time tracking defaults\n\n- `auto_stop_on_complete`: `true`\n- `auto_stop_notification`: `false`\n\n### Link format defaults\n\n- `useFrontmatterMarkdownLinks`: `false` — wikilinks used by default (e.g. `[[task-name]]`)\n- To use markdown link format, the `obsidian-frontmatter-markdown-links` plugin must also be installed\n\n### Effective configuration for a minimal fresh vault\n\nWhen neither `data.json` nor `tasknotes.yaml` is present, implementations MUST use the following effective configuration:\n\n```yaml\nspec_version: 0.3.0-rc.3 # synthesized\nmapping:\n title: title\n status: status\n priority: priority\n due: due\n scheduled: scheduled\n contexts: contexts\n projects: projects\n attachments: attachments\n time_estimate: timeEstimate\n completed_date: completedDate\n date_created: dateCreated\n date_modified: dateModified\n recurrence: recurrence\n recurrence_anchor: recurrence_anchor\n complete_instances: complete_instances\n skipped_instances: skipped_instances\n recurrence_parent: recurrence_parent\n occurrence_date: occurrence_date\n occurrence_materialization: occurrence_materialization\n occurrence_next_trigger: occurrence_next_trigger\n occurrence_template: occurrence_template\n occurrence_past_horizon: occurrence_past_horizon\n occurrence_future_horizon: occurrence_future_horizon\n time_entries: timeEntries\n blocked_by: blockedBy\n reminders: reminders\ntask_detection:\n method: tag\n tag: task\n default_folder: TaskNotes/Tasks\nstatus:\n values: [none, open, in-progress, done]\n default: open\n completed_values: [done]\ntitle:\n storage: filename\ntime_tracking:\n auto_stop_on_complete: true\n auto_stop_notification: false\nlinks:\n use_markdown_format: false\n extensions: [\".md\"]\n unresolved_default_severity: warning\n update_references_on_rename: true\n```\n","aliases":["/spec/09-configuration/"],"toc":[{"level":2,"id":"91-purpose","text":"9.1 Purpose"},{"level":2,"id":"92-configuration-provider-model","text":"9.2 Configuration provider model"},{"level":3,"id":"921-common-provider-types","text":"9.2.1 Common provider types"},{"level":3,"id":"922-deterministic-precedence-and-merge","text":"9.2.2 Deterministic precedence and merge"},{"level":3,"id":"923-strict-vs-permissive-provider-behavior","text":"9.2.3 Strict vs permissive provider behavior"},{"level":3,"id":"924-tasknotes-plugin-provider-datajson","text":"9.2.4 TaskNotes plugin provider (data.json)"},{"level":2,"id":"93-required-top-level-keys","text":"9.3 Required top-level keys"},{"level":2,"id":"94-recommended-top-level-keys","text":"9.4 Recommended top-level keys"},{"level":2,"id":"95-specversion-behavior","text":"9.5 spec_version behavior"},{"level":2,"id":"96-mapping-schema","text":"9.6 mapping schema"},{"level":2,"id":"97-taskdetection-schema","text":"9.7 task_detection schema"},{"level":3,"id":"detection-methods","text":"Detection methods"},{"level":3,"id":"971-tag-matching-semantics","text":"9.7.1 Tag matching semantics"},{"level":3,"id":"972-property-matching-semantics","text":"9.7.2 Property matching semantics"},{"level":3,"id":"973-multi-method-extension-semantics","text":"9.7.3 Multi-method extension semantics"},{"level":2,"id":"98-defaults-schema","text":"9.8 defaults schema"},{"level":2,"id":"99-status-schema","text":"9.9 status schema"},{"level":2,"id":"910-validation-schema","text":"9.10 validation schema"},{"level":2,"id":"911-dependencies-schema","text":"9.11 dependencies schema"},{"level":2,"id":"912-links-schema","text":"9.12 links schema"},{"level":2,"id":"913-title-schema","text":"9.13 title schema"},{"level":2,"id":"914-templating-schema","text":"9.14 templating schema"},{"level":2,"id":"915-reminders-schema","text":"9.15 reminders schema"},{"level":2,"id":"916-timetracking-schema","text":"9.16 time_tracking schema"},{"level":2,"id":"917-occurrences-schema","text":"9.17 occurrences schema"},{"level":2,"id":"9171-nlp-schema","text":"9.17.1 nlp schema"},{"level":2,"id":"918-compatibility-schema","text":"9.18 compatibility schema"},{"level":2,"id":"919-complete-configuration-example-yamlfile-provider","text":"9.19 Complete configuration example (yaml_file provider)"},{"level":2,"id":"920-configuration-errors","text":"9.20 Configuration errors"},{"level":2,"id":"921-default-collection-state","text":"9.21 Default collection state"},{"level":3,"id":"folder-layout","text":"Folder layout"},{"level":3,"id":"task-detection","text":"Task detection"},{"level":3,"id":"default-field-mapping","text":"Default field mapping"},{"level":3,"id":"default-statuses","text":"Default statuses"},{"level":3,"id":"default-priorities","text":"Default priorities"},{"level":3,"id":"title-and-filename-defaults","text":"Title and filename defaults"},{"level":3,"id":"time-tracking-defaults","text":"Time tracking defaults"},{"level":3,"id":"link-format-defaults","text":"Link format defaults"},{"level":3,"id":"effective-configuration-for-a-minimal-fresh-vault","text":"Effective configuration for a minimal fresh vault"}],"html":"

9.1 Purpose#

\n

This section defines the normative configuration model for collections using tasknotes-spec.

\n

9.2 Configuration provider model#

\n

Implementations MUST derive an effective configuration from one or more configuration providers.

\n

A provider is a source adapter that returns a partial configuration normalized to this section's schema.

\n

Implementations MUST:

\n
    \n
  • support at least one provider,
  • \n
  • document supported providers,
  • \n
  • document provider precedence order,
  • \n
  • disclose active providers and fallback behavior in conformance output (§7).
  • \n
\n

9.2.1 Common provider types#

\n

Common providers include:

\n
    \n
  • yaml_file: a tasknotes.yaml document at collection root,
  • \n
  • tasknotes_plugin_data_json: .obsidian/plugins/tasknotes/data.json,
  • \n
  • built_in_defaults: implementation defaults,
  • \n
  • optional runtime/CLI/env overrides.
  • \n
\n

This list is not exhaustive.

\n

9.2.2 Deterministic precedence and merge#

\n

Provider precedence MUST be deterministic.

\n

Unless explicitly documented otherwise, implementations MUST resolve configuration per top-level key:

\n
    \n
  • for each key in §9.3/§9.4, the highest-precedence provider that supplies that key wins,
  • \n
  • winning object values replace lower-precedence object values as whole objects (no implicit deep merge),
  • \n
  • after top-level selection, implementations MUST apply documented schema defaults for missing nested keys before exposing effective configuration.
  • \n
\n

If an implementation supports deep-merge behavior, it MUST be explicitly documented and deterministic.

\n

9.2.3 Strict vs permissive provider behavior#

\n

In strict mode:

\n
    \n
  • failure to resolve required effective keys (spec_version, mapping) MUST be a configuration error.
  • \n
\n

If permissive mode is implemented, then in permissive mode:

\n
    \n
  • implementations MAY continue with defaults when providers are missing/unreadable,
  • \n
  • implementations MUST emit configuration warnings,
  • \n
  • implementations MUST disclose that effective configuration is partial/default-derived.
  • \n
\n

9.2.4 TaskNotes plugin provider (data.json)#

\n

The TaskNotes plugin stores settings in .obsidian/plugins/tasknotes/data.json within the vault root. When using this file as a configuration provider, normalization MUST apply the field mapping in the table below.

\n

Key mapping table (data.json key → spec effective config):

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
data.json keySpec keyNotes
fieldMappingmappingNormalize role names: dateCreated→date_created, completedDate→completed_date, recurrenceAnchor→recurrence_anchor, completeInstances→complete_instances, skippedInstances→skipped_instances, recurrenceParent→recurrence_parent, occurrenceDate→occurrence_date, occurrenceMaterialization→occurrence_materialization, occurrenceNextTrigger→occurrence_next_trigger, occurrenceTemplate→occurrence_template, occurrencePastHorizon→occurrence_past_horizon, occurrenceFutureHorizon→occurrence_future_horizon, blockedBy→blocked_by, timeEntries→time_entries, timeEstimate→time_estimate
storeTitleInFilenametitle.storagetrue → "filename", false → "frontmatter"
taskFilenameFormattitle.filename_formatValues: "title", "zettel", "timestamp", "custom"; used only when title.storage=frontmatter for canonical writes, but preserved as compatibility input when present
customFilenameTemplatetitle.custom_filename_templateTemplate string, e.g. "{title}"; used only when title.storage=frontmatter and filename_format=custom
taskCreationDefaults.useBodyTemplatetemplating.enabledboolean
taskCreationDefaults.bodyTemplatetemplating.template_pathPath to template file
customStatuses[*].valuestatus.valuesOrdered array of status value strings
defaultTaskStatusstatus.defaultDefault status string
customStatuses[isCompleted=true][*].valuestatus.completed_valuesStatuses where isCompleted: true
defaultTaskPrioritydefaults.priorityDefault priority string
autoStopTimeTrackingOnCompletetime_tracking.auto_stop_on_completeboolean
autoStopTimeTrackingNotificationtime_tracking.auto_stop_notificationboolean
taskIdentificationMethodtask_detection.method"tag" or "property"
taskTagtask_detection.tagTag string used when method="tag"
taskPropertyNametask_detection.property_nameFrontmatter key used when method="property"
taskPropertyValuetask_detection.property_valueExpected value; empty means key must exist
tasksFoldertask_detection.default_folderDefault folder for new tasks
excludedFolderstask_detection.excluded_foldersComma-separated folder paths to exclude
moveArchivedTasksarchive.move_on_archiveboolean
archiveFolderarchive.folderArchive destination folder
useFrontmatterMarkdownLinkslinks.use_markdown_formatboolean; see §11
\n

Key data.json fields with defaults (for cold-start reading of a vault with no tasknotes.yaml):

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
FieldTypeDefaultMeaning
tasksFolderstring"TaskNotes/Tasks"Default folder for new task files
taskIdentificationMethod"tag" | "property""tag"How task files are identified
taskTagstring"task"Tag that identifies task files (when method="tag")
taskPropertyNamestring""Frontmatter key for property-based identification
taskPropertyValuestring""Expected value for property-based identification (empty = key presence)
storeTitleInFilenamebooleantrueTitle storage mode
taskFilenameFormat"title" | "zettel" | "timestamp" | "custom""title"Filename generation format
customFilenameTemplatestring"{title}"Template for "custom" filename format
defaultTaskStatusstring"open"Default status on create
defaultTaskPrioritystring"normal"Default priority on create
customStatusesStatusConfig[]see object shape belowOrdered status definitions
autoStopTimeTrackingOnCompletebooleantrueAuto-stop active session on completion
autoStopTimeTrackingNotificationbooleanfalseShow notification when auto-stopping
useFrontmatterMarkdownLinksbooleanfalseUse markdown links in frontmatter (requires obsidian-frontmatter-markdown-links plugin)
moveArchivedTasksbooleanfalseMove task file to archive folder on archive
archiveFolderstring"TaskNotes/Archive"Archive destination folder
excludedFoldersstring""Comma-separated folders to exclude from task indexing
\n

StatusConfig object shape:

\n
{\n  "id": "done",\n  "value": "done",\n  "label": "Done",\n  "color": "#00aa00",\n  "isCompleted": true,\n  "order": 3,\n  "autoArchive": false,\n  "autoArchiveDelay": 5\n}\n

spec_version is not present in data.json. Implementations MUST synthesize an effective spec_version as described in §9.5.

\n

Provider keys not listed above MAY be ignored by tasknotes-spec consumers.

\n

9.3 Required top-level keys#

\n

Required keys apply to the effective configuration after provider resolution.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
KeyTypeRequiredDescription
spec_versionstringyestarget spec version (provider-supplied or synthesized per §9.5)
mappingobjectyessemantic role to storage key mapping
\n\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
KeyTypeDescription
task_detectionobjecttask file identification rules
defaultsobjectrole defaults used during create
statusobjectstatus set and completed-value semantics
validationobjectvalidation behavior (strict required, permissive optional)
linksobjectlink parsing/resolution behavior
titleobjecttitle source and filename behavior policy
templatingobjectoptional create-time templating behavior policy
dependenciesobjectdependency behavior policy
remindersobjectreminder behavior policy
time_trackingobjecttime-tracking management behavior policy
occurrencesobjectrecurrence materialization defaults and bounds
compatibilityobjectlegacy alias/behavior switches
\n

9.5 spec_version behavior#

\n

spec_version MUST be a semantic version string.\nPre-release identifiers are valid (for example 0.3.0-rc.3).

\n

Implementations in strict mode MUST reject unsupported major versions.

\n

If permissive mode is implemented, permissive mode MAY proceed with warning when major version differs.

\n

If a provider does not supply spec_version (for example TaskNotes data.json), implementations MUST synthesize an effective spec_version matching their target tasknotes-spec version and SHOULD disclose that it was synthesized.

\n

9.6 mapping schema#

\n

mapping MUST map semantic roles (from §2) to string storage keys.

\n

Minimum required roles in mapping:

\n
    \n
  • title
  • \n
  • status
  • \n
  • completed_date
  • \n
  • date_created
  • \n
  • date_modified
  • \n
\n

If semantic role id is supported (§2.6.5), mapping SHOULD include id.\nIf profile materialized-occurrences is claimed, mapping MUST include recurrence_parent and occurrence_date, and SHOULD include parent policy roles (occurrence_materialization, occurrence_next_trigger, occurrence_template, occurrence_past_horizon, occurrence_future_horizon).

\n

Example:

\n
mapping:\n  title: title\n  status: status\n  date_created: dateCreated\n  date_modified: dateModified\n  completed_date: completedDate\n  recurrence: recurrence\n  recurrence_anchor: recurrenceAnchor\n  complete_instances: completeInstances\n  skipped_instances: skippedInstances\n  recurrence_parent: recurrence_parent\n  occurrence_date: occurrence_date\n  occurrence_materialization: occurrence_materialization\n  occurrence_next_trigger: occurrence_next_trigger\n  occurrence_template: occurrence_template\n  occurrence_past_horizon: occurrence_past_horizon\n  occurrence_future_horizon: occurrence_future_horizon\n  time_entries: timeEntries\n  blocked_by: blockedBy\n  reminders: reminders\n  attachments: attachments\n

9.7 task_detection schema#

\n

task_detection controls how task files are identified within the vault.

\n

Detection methods#

\n

The tasknotes plugin natively supports two identification methods, controlled by taskIdentificationMethod in data.json (mapped to task_detection.method):

\n

tag (default) — A markdown file is a task if it contains the configured tag (default #task) in its frontmatter tags array or inline in the body. Configured by task_detection.tag.

\n

property — A markdown file is a task if a specified frontmatter property has a specified value (or exists, if value is empty). Configured by task_detection.property_name and task_detection.property_value.

\n

Schema and selection rules:

\n
    \n
  1. task_detection MAY specify either:
      \n
    • method (single-method form), or
    • \n
    • methods (multi-method form; non-empty list).
    • \n
    \n
  2. \n
  3. If both are present, methods MUST take precedence and implementations SHOULD emit a configuration warning.
  4. \n
  5. If neither is present, effective detection method MUST default to tag.
  6. \n
  7. method MUST be tag or property.
  8. \n
  9. methods entries MUST be unique and MUST be from:
      \n
    • tag
    • \n
    • property
    • \n
    • field_presence
    • \n
    • field_match
    • \n
    \n
  10. \n
  11. Method-specific required keys:
      \n
    • when tag is enabled, effective task_detection.tag MUST be non-empty (default task when absent);
    • \n
    • when property is enabled, task_detection.property_name MUST be provided and non-empty; task_detection.property_value MAY be empty (empty means key-exists semantics).
    • \n
    \n
  12. \n
  13. If methods has more than one entry, task_detection.combine controls combination semantics (§9.7.3). If omitted, it MUST default to or.
  14. \n
\n

9.7.1 Tag matching semantics#

\n

When task_detection.method=tag, matching MUST follow these rules:

\n
    \n
  1. Normalize configured task_detection.tag by stripping one leading # when present.
  2. \n
  3. Compare tag names case-insensitively after normalization.
  4. \n
  5. Frontmatter matching:
      \n
    • tags MAY be a list of strings or a single string.
    • \n
    • each tag value is normalized by trimming surrounding whitespace and stripping one leading #.
    • \n
    • match requires exact normalized equality (for example task matches #task; task does not match tasking).
    • \n
    \n
  6. \n
  7. Body matching:
      \n
    • only markdown text outside fenced code blocks and inline code spans is considered,
    • \n
    • a match requires a hashtag token with exact normalized name (for example #task),
    • \n
    • partial-word matches MUST NOT count (for example #tasking does not match configured task).
    • \n
    \n
  8. \n
\n

If either frontmatter or body matches, the file is identified as a task.

\n

9.7.2 Property matching semantics#

\n

When property detection is enabled (method=property or methods includes property):

\n
    \n
  1. task_detection.property_name MUST name the frontmatter key to inspect.
  2. \n
  3. If task_detection.property_value is non-empty, match requires semantic equality with the configured value.
  4. \n
  5. If task_detection.property_value is empty or absent, match requires key presence only.
  6. \n
\n

9.7.3 Multi-method extension semantics#

\n

tasknotes.yaml-level providers MAY additionally support:

\n
    \n
  • field_presence (example: required key status)
  • \n
  • field_match (example: type == "task")
  • \n
\n

Extension-key shape:

\n
    \n
  • field_presence: string or list of required frontmatter keys.
  • \n
  • field_match: object map of key -> expected scalar value for exact semantic equality checks.
  • \n
\n

If multiple methods are configured in tasknotes.yaml, task_detection.combine MUST define combinator semantics:

\n
    \n
  • or (default): file is a task if any enabled method matches.
  • \n
  • and: file is a task only if all enabled methods match.
  • \n
\n

If task_detection.combine is absent, implementations MUST default to or.

\n

Implementations MUST exclude folders listed in task_detection.excluded_folders from task indexing.

\n

Executable conformance: adapters participating in the fixture suite SHOULD expose config.detect_task_file to evaluate these detection semantics against fixture inputs.

\n

Example (tasknotes.yaml, equivalent to tag-based default):

\n
task_detection:\n  method: tag\n  tag: task\n  default_folder: TaskNotes/Tasks\n

Example (property-based):

\n
task_detection:\n  method: property\n  property_name: type\n  property_value: task\n

9.8 defaults schema#

\n

defaults defines values used at create time when caller input omits a role.

\n

Defaults MUST NOT override explicit user input.

\n

Example:

\n
defaults:\n  status: open\n  priority: normal\n  recurrence_anchor: scheduled\n  reminders:\n    - id: due_minus_1d\n      type: relative\n      relatedTo: due\n      offset: -P1D\n

defaults.reminders behavior is defined in §10.3.9.

\n

9.9 status schema#

\n

status defines known status values and completion semantics.

\n

Example:

\n
status:\n  values: [open, in-progress, done, cancelled]\n  default: open\n  completed_values: [done]\n  skipped_values: [cancelled]\n  default_skipped: cancelled\n

Rules:

\n
    \n
  • default MUST be one of values.
  • \n
  • completed_values MUST be a non-empty list.
  • \n
  • Each completed_values entry MUST be in values.
  • \n
  • skipped_values, when present, MUST be a list whose entries are in values.
  • \n
  • default_skipped, when present, MUST be in skipped_values.
  • \n
  • For implementations claiming materialized-occurrences, skipped_values MUST NOT overlap completed_values.
  • \n
  • Implementations claiming materialized-occurrences MUST provide at least one skipped value or fail skip of materialized occurrence notes deterministically (§5.20.3).
  • \n
  • Non-recurring completion MUST use this list, not hardcoded literals.
  • \n
  • When a complete operation does not provide an explicit target status, writers MUST use the first entry of completed_values.
  • \n
  • When a materialized occurrence skip operation does not provide an explicit skipped status, writers MUST use default_skipped when present, otherwise the first entry of skipped_values.
  • \n
\n

9.10 validation schema#

\n

Example:

\n
validation:\n  mode: strict\n  reject_unknown_fields: false\n

Rules:

\n
    \n
  • mode MUST be strict or permissive when present.
  • \n
  • If mode is absent, effective mode MUST default to strict.
  • \n
  • Conforming implementations MUST support strict.
  • \n
  • Implementations MAY support permissive.
  • \n
  • If mode=permissive is configured but not implemented, configuration MUST fail in strict mode and SHOULD emit warning/fallback in permissive mode.
  • \n
  • reject_unknown_fields=true enforces closed-schema behavior for mapped roles.
  • \n
\n

9.11 dependencies schema#

\n

Example:

\n
dependencies:\n  default_reltype: FINISHTOSTART\n  treat_missing_target_as_blocked: true\n  enforce_unique_uid: true\n  unresolved_target_severity: warning\n  require_resolved_uid_on_write: false\n

Rules:

\n
    \n
  • default_reltype MUST be one of the allowed reltype values in §10.2.
  • \n
  • treat_missing_target_as_blocked controls whether missing/unresolvable dependency targets contribute to blocked-state evaluation (§10.2.5).
  • \n
  • If treat_missing_target_as_blocked is absent, effective value MUST default to true.
  • \n
  • enforce_unique_uid=true enforces uniqueness at validation/write time.
  • \n
  • If enforce_unique_uid is absent, effective value MUST default to true.
  • \n
  • unresolved_target_severity MUST be warning or error.
  • \n
  • require_resolved_uid_on_write=true requires dependency UID resolution success for add/update operations.
  • \n
\n\n

Example:

\n
links:\n  extensions: [".md"]\n  unresolved_default_severity: warning\n  update_references_on_rename: true\n

Rules:

\n
    \n
  • extensions defines extension trial order for extensionless targets.
  • \n
  • unresolved_default_severity MUST be warning or error.
  • \n
  • update_references_on_rename=true enables rename-time link rewrite behavior when supported.
  • \n
\n

9.13 title schema#

\n

Example (storage=frontmatter):

\n
title:\n  storage: frontmatter\n  filename_format: custom\n  custom_filename_template: "{{date}} {{title}}"\n

Example (storage=filename):

\n
title:\n  storage: filename\n

Rules:

\n
    \n
  • storage MUST be frontmatter or filename.
  • \n
  • when storage=frontmatter, filename_format MUST be title, zettel, timestamp, or custom.
  • \n
  • when storage=frontmatter and filename_format=custom, custom_filename_template MUST be provided and non-empty.
  • \n
  • when storage=filename, filename_format and custom_filename_template MAY be present for compatibility input but MUST be ignored for canonical write behavior.
  • \n
  • Read precedence MUST be storage-mode-aware:
      \n
    1. when storage=frontmatter, use mapped title key when present and non-empty, then file basename fallback;
    2. \n
    3. when storage=filename, use file basename first, then mapped title fallback when basename is unavailable.
    4. \n
    \n
  • \n
  • If frontmatter and basename titles both exist and differ, the source authoritative for active storage MUST win.
  • \n
  • If storage=filename, canonical writes MUST treat filename as title source, MUST rename on title change, and MUST ignore filename_format and custom_filename_template.
  • \n
  • If storage=frontmatter, canonical writes MUST persist mapped title key; filename_format and custom_filename_template govern create-time filename generation.
  • \n
\n

Informative mapping to TaskNotes settings:

\n
    \n
  • title.storage=filename corresponds to storeTitleInFilename=true.
  • \n
  • title.filename_format corresponds to taskFilenameFormat.
  • \n
  • title.custom_filename_template corresponds to customFilenameTemplate.
  • \n
\n

9.14 templating schema#

\n

templating defines optional create-time template behavior.\nThis schema is required only for implementations claiming profile templating (§7.3.3).

\n

Example:

\n
templating:\n  enabled: true\n  template_path: Templates/Task.md\n  failure_mode: warning_fallback\n  unknown_variable_policy: preserve\n

Rules:

\n
    \n
  • enabled MUST be boolean.
  • \n
  • If enabled=true, template_path MUST be provided and non-empty.
  • \n
  • failure_mode MUST be error or warning_fallback when present.
  • \n
  • unknown_variable_policy MUST be preserve or empty when present.
  • \n
  • If failure_mode is absent, effective value MUST default to warning_fallback.
  • \n
  • If unknown_variable_policy is absent, effective value MUST default to preserve.
  • \n
  • Implementations claiming templating MUST support portable double-brace variables from §5.3.5.
  • \n
  • Implementations not claiming templating MAY ignore templating settings.
  • \n
\n

9.15 reminders schema#

\n

Example:

\n
reminders:\n  date_only_anchor_time: "00:00"\n  apply_defaults_when_explicit: false\n

Rules:

\n
    \n
  • date_only_anchor_time MUST be HH:MM 24-hour local time format.
  • \n
  • date_only_anchor_time is used by §10.3.4 for relative reminders against date-only bases.
  • \n
  • apply_defaults_when_explicit MUST be boolean when present.
  • \n
  • if apply_defaults_when_explicit is absent, effective value MUST default to false.
  • \n
  • apply_defaults_when_explicit=false means explicit input reminders replace default-reminder application at create time.
  • \n
  • apply_defaults_when_explicit=true means explicit create-time reminders are merged with defaults using §10.3.9 deterministic merge rules.
  • \n
\n

9.16 time_tracking schema#

\n

Example:

\n
time_tracking:\n  auto_stop_on_complete: true\n  auto_stop_notification: false\n

Rules:

\n
    \n
  • auto_stop_on_complete MUST be boolean when present.
  • \n
  • auto_stop_notification MUST be boolean when present.
  • \n
  • if auto_stop_on_complete=true, completion-triggered stop behavior MUST follow §5.19.5.
  • \n
  • if auto_stop_notification is absent, effective value MUST default to false.
  • \n
\n

9.17 occurrences schema#

\n

occurrences defines collection-level defaults for recurrence materialization.\nThis schema is required only for implementations claiming profile materialized-occurrences (§7.3.4).

\n

Example:

\n
occurrences:\n  default_materialization: manual\n  default_next_trigger: completion\n  past_horizon: P0D\n  future_horizon: P14D\n

Rules:

\n
    \n
  • default_materialization MUST be one of manual, on_completion, or rolling.
  • \n
  • If default_materialization is absent, effective value MUST default to manual.
  • \n
  • default_next_trigger MUST be completion or completion_or_skip.
  • \n
  • If default_next_trigger is absent, effective value MUST default to completion.
  • \n
  • past_horizon and future_horizon, when present, MUST be ISO 8601 duration strings.
  • \n
  • If default_materialization=rolling, implementations MUST use finite rolling bounds. If bounds are absent, documented finite defaults MUST be used.
  • \n
  • Parent task fields override collection defaults: occurrence_materialization overrides occurrences.default_materialization; occurrence_next_trigger overrides occurrences.default_next_trigger; occurrence_past_horizon and occurrence_future_horizon override occurrences.past_horizon and occurrences.future_horizon.
  • \n
  • If occurrences is absent, the effective behavior is manual materialization and completion next trigger.
  • \n
\n

9.17.1 nlp schema#

\n

nlp advertises optional natural-language capture triggers. These settings\nallow another TaskNotes client to preserve the same capture vocabulary without\nmaking natural-language parsing a requirement of the core profile.

\n

Example:

\n
nlp:\n  triggers:\n    - property_id: tags\n      trigger: "#"\n      enabled: true\n    - property_id: contexts\n      trigger: "@"\n      enabled: true\n    - property_id: priority\n      trigger: "!"\n      enabled: false\n

Rules:

\n
    \n
  • triggers MUST be a list when present.
  • \n
  • Every trigger entry MUST contain non-empty property_id and trigger\nstrings.
  • \n
  • property_id SHOULD use a stable TaskNotes role (tags, contexts,\nprojects, status, or priority) or the stable identifier of a configured\nuser field.
  • \n
  • enabled MUST be boolean when present and MUST default to true.
  • \n
  • Trigger strings MAY contain more than one character.
  • \n
  • Trigger entries with unknown property_id values MUST be preserved by\nconfiguration round-trips and MAY be ignored by clients that cannot resolve\nthe property.
  • \n
  • If nlp is absent, clients MAY use documented local defaults.
  • \n
  • This block controls capture parsing and suggestions only. It MUST NOT change\npersisted task field names or values.
  • \n
\n

Informative mapping to TaskNotes settings:

\n
    \n
  • nlp.triggers corresponds to nlpTriggers.triggers.
  • \n
  • property_id, trigger, and enabled correspond to the plugin fields\npropertyId, trigger, and enabled.
  • \n
\n

9.18 compatibility schema#

\n

Example:

\n
compatibility:\n  read_aliases: true\n  legacy_duration_field: true\n  legacy_local_datetime_input: false\n

Rules:

\n
    \n
  • Compatibility flags MUST default to conservative behavior in new collections.
  • \n
  • legacy_local_datetime_input=true MAY relax strict parsing for offset-less datetimes only in permissive mode; strict mode parsing rules in §3.4.2 still apply.
  • \n
  • Enabled compatibility flags SHOULD be disclosed in conformance output (§7).
  • \n
\n

9.19 Complete configuration example (yaml_file provider)#

\n
spec_version: 0.3.0-rc.3\n\nmapping:\n  title: title\n  status: status\n  priority: priority\n  due: due\n  scheduled: scheduled\n  attachments: attachments\n  completed_date: completedDate\n  date_created: dateCreated\n  date_modified: dateModified\n  recurrence: recurrence\n  recurrence_anchor: recurrenceAnchor\n  complete_instances: completeInstances\n  skipped_instances: skippedInstances\n  recurrence_parent: recurrence_parent\n  occurrence_date: occurrence_date\n  occurrence_materialization: occurrence_materialization\n  occurrence_next_trigger: occurrence_next_trigger\n  occurrence_template: occurrence_template\n  occurrence_past_horizon: occurrence_past_horizon\n  occurrence_future_horizon: occurrence_future_horizon\n  time_entries: timeEntries\n  blocked_by: blockedBy\n  reminders: reminders\n\ntask_detection:\n  method: tag\n  tag: task\n  default_folder: TaskNotes/Tasks\n\ndefaults:\n  status: open\n  priority: normal\n  recurrence_anchor: scheduled\n  reminders:\n    - id: due_minus_1d\n      type: relative\n      relatedTo: due\n      offset: -P1D\n\nstatus:\n  values: [open, in-progress, done, cancelled]\n  default: open\n  completed_values: [done]\n  skipped_values: [cancelled]\n  default_skipped: cancelled\n\nvalidation:\n  mode: strict\n  reject_unknown_fields: false\n\ndependencies:\n  default_reltype: FINISHTOSTART\n  treat_missing_target_as_blocked: true\n  enforce_unique_uid: true\n  unresolved_target_severity: warning\n  require_resolved_uid_on_write: false\n\nlinks:\n  extensions: [".md"]\n  unresolved_default_severity: warning\n  update_references_on_rename: true\n\ntitle:\n  storage: filename\n\ntemplating:\n  enabled: false\n  failure_mode: warning_fallback\n  unknown_variable_policy: preserve\n\nreminders:\n  date_only_anchor_time: "00:00"\n  apply_defaults_when_explicit: false\n\ntime_tracking:\n  auto_stop_on_complete: true\n  auto_stop_notification: false\n\noccurrences:\n  default_materialization: manual\n  default_next_trigger: completion\n  past_horizon: P0D\n  future_horizon: P14D\n\nnlp:\n  triggers:\n    - property_id: tags\n      trigger: "#"\n      enabled: true\n    - property_id: contexts\n      trigger: "@"\n      enabled: true\n    - property_id: projects\n      trigger: "+"\n      enabled: true\n    - property_id: status\n      trigger: "*"\n      enabled: true\n    - property_id: priority\n      trigger: "!"\n      enabled: false\n\ncompatibility:\n  read_aliases: true\n  legacy_duration_field: true\n

9.20 Configuration errors#

\n

Configuration validation MUST report structured errors with key path context.

\n

Examples:

\n
    \n
  • no readable configuration provider available in strict mode
  • \n
  • required effective key unresolved after provider resolution (spec_version or mapping)
  • \n
  • missing mapping.title
  • \n
  • status.default not present in status.values
  • \n
  • status.completed_values contains a value not present in status.values
  • \n
  • status.skipped_values contains a value not present in status.values
  • \n
  • status.default_skipped not present in status.skipped_values
  • \n
  • status.skipped_values overlaps status.completed_values when materialized-occurrences is claimed
  • \n
  • unsupported validation.mode
  • \n
  • validation.mode=permissive but permissive mode is not implemented
  • \n
  • invalid task_detection.method
  • \n
  • invalid task_detection.methods entry
  • \n
  • empty task_detection.tag when tag method is enabled
  • \n
  • missing task_detection.property_name when property method is enabled
  • \n
  • invalid task_detection.combine
  • \n
  • invalid dependencies.default_reltype
  • \n
  • invalid dependencies.unresolved_target_severity
  • \n
  • invalid links.unresolved_default_severity
  • \n
  • invalid title.storage
  • \n
  • invalid title.filename_format
  • \n
  • missing title.filename_format when title.storage=frontmatter
  • \n
  • missing title.custom_filename_template when title.storage=frontmatter and title.filename_format=custom
  • \n
  • missing templating.template_path when templating.enabled=true
  • \n
  • invalid templating.failure_mode
  • \n
  • invalid templating.unknown_variable_policy
  • \n
  • invalid reminders.date_only_anchor_time
  • \n
  • invalid reminders.apply_defaults_when_explicit
  • \n
  • invalid time_tracking.auto_stop_on_complete
  • \n
  • invalid time_tracking.auto_stop_notification
  • \n
  • invalid occurrences.default_materialization
  • \n
  • invalid occurrences.default_next_trigger
  • \n
  • invalid occurrences.past_horizon
  • \n
  • invalid occurrences.future_horizon
  • \n
  • invalid nlp.triggers
  • \n
  • empty nlp.triggers[].property_id
  • \n
  • empty nlp.triggers[].trigger
  • \n
  • invalid nlp.triggers[].enabled
  • \n
\n

9.21 Default collection state#

\n

This section describes what a fresh tasknotes vault looks like before any user customization. Implementations that read an existing tasknotes vault without a tasknotes.yaml SHOULD apply these defaults when data.json is absent or fields are missing.

\n

Folder layout#

\n
MyVault/\n├── TaskNotes/\n│   ├── Tasks/          ← new tasks created here by default\n│   └── Archive/        ← archived tasks moved here (if moveArchivedTasks=true)\n└── .obsidian/\n    └── plugins/\n        └── tasknotes/\n            └── data.json\n

Task detection#

\n

Default method: tag. A file is a task if it contains the tag #task in its frontmatter tags array or inline in the body.

\n

Default field mapping#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Semantic roleDefault storage key
titletitle
statusstatus
prioritypriority
duedue
scheduledscheduled
contextscontexts
projectsprojects
time_estimatetimeEstimate
completed_datecompletedDate
date_createddateCreated
date_modifieddateModified
recurrencerecurrence
recurrence_anchorrecurrence_anchor
complete_instancescomplete_instances
skipped_instancesskipped_instances
recurrence_parentrecurrence_parent
occurrence_dateoccurrence_date
occurrence_materializationoccurrence_materialization
occurrence_next_triggeroccurrence_next_trigger
occurrence_templateoccurrence_template
occurrence_past_horizonoccurrence_past_horizon
occurrence_future_horizonoccurrence_future_horizon
time_entriestimeEntries
blocked_byblockedBy
remindersreminders
\n

Note: recurrenceAnchor, completeInstances, and skippedInstances are accepted as aliases on read (§2.5). The mixed camelCase/snake_case defaults are intentional for compatibility with historical TaskNotes frontmatter.

\n

Default statuses#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
ValueLabelisCompletedOrder
noneNonefalse0
openOpenfalse1
in-progressIn progressfalse2
doneDonetrue3
\n

Default status on create: open. Default completed status (first isCompleted=true): done.\nNo skipped status is configured by default; implementations that support materialized occurrence skips MUST require configuration or expose a documented default before writing skipped occurrence state.

\n

Default priorities#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
ValueLabelWeight
noneNone0
lowLow1
normalNormal2
highHigh3
\n

Default priority on create: normal.

\n

Title and filename defaults#

\n
    \n
  • title.storage: filename (filename/path is the authoritative title source)
  • \n
  • default basename generation under title.storage=filename derives from semantic title using filename-safe sanitization
  • \n
  • implementations MAY also keep mapped title in frontmatter as a synchronized compatibility mirror
  • \n
  • TaskNotes data.json may still contain legacy taskFilenameFormat values such as zettel, but these are compatibility inputs rather than the forward default when title.storage=filename
  • \n
  • title is read from filename first; frontmatter title is compatibility fallback when filename-derived title is unavailable (§2.2.2)
  • \n
\n

Time tracking defaults#

\n
    \n
  • auto_stop_on_complete: true
  • \n
  • auto_stop_notification: false
  • \n
\n\n
    \n
  • useFrontmatterMarkdownLinks: false — wikilinks used by default (e.g. [[task-name]])
  • \n
  • To use markdown link format, the obsidian-frontmatter-markdown-links plugin must also be installed
  • \n
\n

Effective configuration for a minimal fresh vault#

\n

When neither data.json nor tasknotes.yaml is present, implementations MUST use the following effective configuration:

\n
spec_version: 0.3.0-rc.3   # synthesized\nmapping:\n  title: title\n  status: status\n  priority: priority\n  due: due\n  scheduled: scheduled\n  contexts: contexts\n  projects: projects\n  attachments: attachments\n  time_estimate: timeEstimate\n  completed_date: completedDate\n  date_created: dateCreated\n  date_modified: dateModified\n  recurrence: recurrence\n  recurrence_anchor: recurrence_anchor\n  complete_instances: complete_instances\n  skipped_instances: skipped_instances\n  recurrence_parent: recurrence_parent\n  occurrence_date: occurrence_date\n  occurrence_materialization: occurrence_materialization\n  occurrence_next_trigger: occurrence_next_trigger\n  occurrence_template: occurrence_template\n  occurrence_past_horizon: occurrence_past_horizon\n  occurrence_future_horizon: occurrence_future_horizon\n  time_entries: timeEntries\n  blocked_by: blockedBy\n  reminders: reminders\ntask_detection:\n  method: tag\n  tag: task\n  default_folder: TaskNotes/Tasks\nstatus:\n  values: [none, open, in-progress, done]\n  default: open\n  completed_values: [done]\ntitle:\n  storage: filename\ntime_tracking:\n  auto_stop_on_complete: true\n  auto_stop_notification: false\nlinks:\n  use_markdown_format: false\n  extensions: [".md"]\n  unresolved_default_severity: warning\n  update_references_on_rename: true\n
","text":"9.1 Purpose# This section defines the normative configuration model for collections using tasknotes-spec. 9.2 Configuration provider model# Implementations MUST derive an effective configuration from one or more configuration providers. A provider is a source adapter that returns a partial configuration normalized to this section's schema. Implementations MUST: support at least one provider, document supported providers, document provider precedence order, disclose active providers and fallback behavior in conformance output (§7). 9.2.1 Common provider types# Common providers include: yaml_file: a tasknotes.yaml document at collection root, tasknotes_plugin_data_json: .obsidian/plugins/tasknotes/data.json, built_in_defaults: implementation defaults, optional runtime/CLI/env overrides. This list is not exhaustive. 9.2.2 Deterministic precedence and merge# Provider precedence MUST be deterministic. Unless explicitly documented otherwise, implementations MUST resolve configuration per top-level key: for each key in §9.3/§9.4, the highest-precedence provider that supplies that key wins, winning object values replace lower-precedence object values as whole objects (no implicit deep merge), after top-level selection, implementations MUST apply documented schema defaults for missing nested keys before exposing effective configuration. If an implementation supports deep-merge behavior, it MUST be explicitly documented and deterministic. 9.2.3 Strict vs permissive provider behavior# In strict mode: failure to resolve required effective keys (spec_version, mapping) MUST be a configuration error. If permissive mode is implemented, then in permissive mode: implementations MAY continue with defaults when providers are missing/unreadable, implementations MUST emit configuration warnings, implementations MUST disclose that effective configuration is partial/default-derived. 9.2.4 TaskNotes plugin provider (data.json)# The TaskNotes plugin stores settings in .obsidian/plugins/tasknotes/data.json within the vault root. When using this file as a configuration provider, normalization MUST apply the field mapping in the table below. Key mapping table (data.json key → spec effective config): data.json key Spec key Notes fieldMapping mapping Normalize role names: dateCreated→date_created, completedDate→completed_date, recurrenceAnchor→recurrence_anchor, completeInstances→complete_instances, skippedInstances→skipped_instances, recurrenceParent→recurrence_parent, occurrenceDate→occurrence_date, occurrenceMaterialization→occurrence_materialization, occurrenceNextTrigger→occurrence_next_trigger, occurrenceTemplate→occurrence_template, occurrencePastHorizon→occurrence_past_horizon, occurrenceFutureHorizon→occurrence_future_horizon, blockedBy→blocked_by, timeEntries→time_entries, timeEstimate→time_estimate storeTitleInFilename title.storage true → \"filename\", false → \"frontmatter\" taskFilenameFormat title.filename_format Values: \"title\", \"zettel\", \"timestamp\", \"custom\"; used only when title.storage=frontmatter for canonical writes, but preserved as compatibility input when present customFilenameTemplate title.custom_filename_template Template string, e.g. \"{title}\"; used only when title.storage=frontmatter and filename_format=custom taskCreationDefaults.useBodyTemplate templating.enabled boolean taskCreationDefaults.bodyTemplate templating.template_path Path to template file customStatuses[*].value status.values Ordered array of status value strings defaultTaskStatus status.default Default status string customStatuses[isCompleted=true][*].value status.completed_values Statuses where isCompleted: true defaultTaskPriority defaults.priority Default priority string autoStopTimeTrackingOnComplete time_tracking.auto_stop_on_complete boolean autoStopTimeTrackingNotification time_tracking.auto_stop_notification boolean taskIdentificationMethod task_detection.method \"tag\" or \"property\" taskTag task_detection.tag Tag string used when method=\"tag\" taskPropertyName task_detection.property_name Frontmatter key used when method=\"property\" taskPropertyValue task_detection.property_value Expected value; empty means key must exist tasksFolder task_detection.default_folder Default folder for new tasks excludedFolders task_detection.excluded_folders Comma-separated folder paths to exclude moveArchivedTasks archive.move_on_archive boolean archiveFolder archive.folder Archive destination folder useFrontmatterMarkdownLinks links.use_markdown_format boolean; see §11 Key data.json fields with defaults (for cold-start reading of a vault with no tasknotes.yaml): Field Type Default Meaning tasksFolder string \"TaskNotes/Tasks\" Default folder for new task files taskIdentificationMethod \"tag\" | \"property\" \"tag\" How task files are identified taskTag string \"task\" Tag that identifies task files (when method=\"tag\") taskPropertyName string \"\" Frontmatter key for property-based identification taskPropertyValue string \"\" Expected value for property-based identification (empty = key presence) storeTitleInFilename boolean true Title storage mode taskFilenameFormat \"title\" | \"zettel\" | \"timestamp\" | \"custom\" \"title\" Filename generation format customFilenameTemplate string \"{title}\" Template for \"custom\" filename format defaultTaskStatus string \"open\" Default status on create defaultTaskPriority string \"normal\" Default priority on create customStatuses StatusConfig[] see object shape below Ordered status definitions autoStopTimeTrackingOnComplete boolean true Auto-stop active session on completion autoStopTimeTrackingNotification boolean false Show notification when auto-stopping useFrontmatterMarkdownLinks boolean false Use markdown links in frontmatter (requires obsidian-frontmatter-markdown-links plugin) moveArchivedTasks boolean false Move task file to archive folder on archive archiveFolder string \"TaskNotes/Archive\" Archive destination folder excludedFolders string \"\" Comma-separated folders to exclude from task indexing StatusConfig object shape: { \"id\": \"done\", \"value\": \"done\", \"label\": \"Done\", \"color\": \"#00aa00\", \"isCompleted\": true, \"order\": 3, \"autoArchive\": false, \"autoArchiveDelay\": 5 } spec_version is not present in data.json. Implementations MUST synthesize an effective spec_version as described in §9.5. Provider keys not listed above MAY be ignored by tasknotes-spec consumers. 9.3 Required top-level keys# Required keys apply to the effective configuration after provider resolution. Key Type Required Description spec_version string yes target spec version (provider-supplied or synthesized per §9.5) mapping object yes semantic role to storage key mapping 9.4 Recommended top-level keys# Key Type Description task_detection object task file identification rules defaults object role defaults used during create status object status set and completed-value semantics validation object validation behavior (strict required, permissive optional) links object link parsing/resolution behavior title object title source and filename behavior policy templating object optional create-time templating behavior policy dependencies object dependency behavior policy reminders object reminder behavior policy time_tracking object time-tracking management behavior policy occurrences object recurrence materialization defaults and bounds compatibility object legacy alias/behavior switches 9.5 spec_version behavior# spec_version MUST be a semantic version string. Pre-release identifiers are valid (for example 0.3.0-rc.3). Implementations in strict mode MUST reject unsupported major versions. If permissive mode is implemented, permissive mode MAY proceed with warning when major version differs. If a provider does not supply spec_version (for example TaskNotes data.json), implementations MUST synthesize an effective spec_version matching their target tasknotes-spec version and SHOULD disclose that it was synthesized. 9.6 mapping schema# mapping MUST map semantic roles (from §2) to string storage keys. Minimum required roles in mapping: title status completed_date date_created date_modified If semantic role id is supported (§2.6.5), mapping SHOULD include id. If profile materialized-occurrences is claimed, mapping MUST include recurrence_parent and occurrence_date, and SHOULD include parent policy roles (occurrence_materialization, occurrence_next_trigger, occurrence_template, occurrence_past_horizon, occurrence_future_horizon). Example: mapping: title: title status: status date_created: dateCreated date_modified: dateModified completed_date: completedDate recurrence: recurrence recurrence_anchor: recurrenceAnchor complete_instances: completeInstances skipped_instances: skippedInstances recurrence_parent: recurrence_parent occurrence_date: occurrence_date occurrence_materialization: occurrence_materialization occurrence_next_trigger: occurrence_next_trigger occurrence_template: occurrence_template occurrence_past_horizon: occurrence_past_horizon occurrence_future_horizon: occurrence_future_horizon time_entries: timeEntries blocked_by: blockedBy reminders: reminders attachments: attachments 9.7 task_detection schema# task_detection controls how task files are identified within the vault. Detection methods# The tasknotes plugin natively supports two identification methods, controlled by taskIdentificationMethod in data.json (mapped to task_detection.method): tag (default) — A markdown file is a task if it contains the configured tag (default #task) in its frontmatter tags array or inline in the body. Configured by task_detection.tag. property — A markdown file is a task if a specified frontmatter property has a specified value (or exists, if value is empty). Configured by task_detection.property_name and task_detection.property_value. Schema and selection rules: task_detection MAY specify either: method (single-method form), or methods (multi-method form; non-empty list). If both are present, methods MUST take precedence and implementations SHOULD emit a configuration warning. If neither is present, effective detection method MUST default to tag. method MUST be tag or property. methods entries MUST be unique and MUST be from: tag property field_presence field_match Method-specific required keys: when tag is enabled, effective task_detection.tag MUST be non-empty (default task when absent); when property is enabled, task_detection.property_name MUST be provided and non-empty; task_detection.property_value MAY be empty (empty means key-exists semantics). If methods has more than one entry, task_detection.combine controls combination semantics (§9.7.3). If omitted, it MUST default to or. 9.7.1 Tag matching semantics# When task_detection.method=tag, matching MUST follow these rules: Normalize configured task_detection.tag by stripping one leading # when present. Compare tag names case-insensitively after normalization. Frontmatter matching: tags MAY be a list of strings or a single string. each tag value is normalized by trimming surrounding whitespace and stripping one leading #. match requires exact normalized equality (for example task matches #task; task does not match tasking). Body matching: only markdown text outside fenced code blocks and inline code spans is considered, a match requires a hashtag token with exact normalized name (for example #task), partial-word matches MUST NOT count (for example #tasking does not match configured task). If either frontmatter or body matches, the file is identified as a task. 9.7.2 Property matching semantics# When property detection is enabled (method=property or methods includes property): task_detection.property_name MUST name the frontmatter key to inspect. If task_detection.property_value is non-empty, match requires semantic equality with the configured value. If task_detection.property_value is empty or absent, match requires key presence only. 9.7.3 Multi-method extension semantics# tasknotes.yaml-level providers MAY additionally support: field_presence (example: required key status) field_match (example: type == \"task\") Extension-key shape: field_presence: string or list of required frontmatter keys. field_match: object map of key -> expected scalar value for exact semantic equality checks. If multiple methods are configured in tasknotes.yaml, task_detection.combine MUST define combinator semantics: or (default): file is a task if any enabled method matches. and: file is a task only if all enabled methods match. If task_detection.combine is absent, implementations MUST default to or. Implementations MUST exclude folders listed in task_detection.excluded_folders from task indexing. Executable conformance: adapters participating in the fixture suite SHOULD expose config.detect_task_file to evaluate these detection semantics against fixture inputs. Example (tasknotes.yaml, equivalent to tag-based default): task_detection: method: tag tag: task default_folder: TaskNotes/Tasks Example (property-based): task_detection: method: property property_name: type property_value: task 9.8 defaults schema# defaults defines values used at create time when caller input omits a role. Defaults MUST NOT override explicit user input. Example: defaults: status: open priority: normal recurrence_anchor: scheduled reminders: - id: due_minus_1d type: relative relatedTo: due offset: -P1D defaults.reminders behavior is defined in §10.3.9. 9.9 status schema# status defines known status values and completion semantics. Example: status: values: [open, in-progress, done, cancelled] default: open completed_values: [done] skipped_values: [cancelled] default_skipped: cancelled Rules: default MUST be one of values. completed_values MUST be a non-empty list. Each completed_values entry MUST be in values. skipped_values, when present, MUST be a list whose entries are in values. default_skipped, when present, MUST be in skipped_values. For implementations claiming materialized-occurrences, skipped_values MUST NOT overlap completed_values. Implementations claiming materialized-occurrences MUST provide at least one skipped value or fail skip of materialized occurrence notes deterministically (§5.20.3). Non-recurring completion MUST use this list, not hardcoded literals. When a complete operation does not provide an explicit target status, writers MUST use the first entry of completed_values. When a materialized occurrence skip operation does not provide an explicit skipped status, writers MUST use default_skipped when present, otherwise the first entry of skipped_values. 9.10 validation schema# Example: validation: mode: strict reject_unknown_fields: false Rules: mode MUST be strict or permissive when present. If mode is absent, effective mode MUST default to strict. Conforming implementations MUST support strict. Implementations MAY support permissive. If mode=permissive is configured but not implemented, configuration MUST fail in strict mode and SHOULD emit warning/fallback in permissive mode. reject_unknown_fields=true enforces closed-schema behavior for mapped roles. 9.11 dependencies schema# Example: dependencies: default_reltype: FINISHTOSTART treat_missing_target_as_blocked: true enforce_unique_uid: true unresolved_target_severity: warning require_resolved_uid_on_write: false Rules: default_reltype MUST be one of the allowed reltype values in §10.2. treat_missing_target_as_blocked controls whether missing/unresolvable dependency targets contribute to blocked-state evaluation (§10.2.5). If treat_missing_target_as_blocked is absent, effective value MUST default to true. enforce_unique_uid=true enforces uniqueness at validation/write time. If enforce_unique_uid is absent, effective value MUST default to true. unresolved_target_severity MUST be warning or error. require_resolved_uid_on_write=true requires dependency UID resolution success for add/update operations. 9.12 links schema# Example: links: extensions: [\".md\"] unresolved_default_severity: warning update_references_on_rename: true Rules: extensions defines extension trial order for extensionless targets"},{"route":"/developers/specification/10-dependencies-and-reminders/","title":"10. Dependencies and Reminders","description":"This section defines canonical semantics for task dependencies (blocked_by) and task reminders (reminders).","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:10-dependencies-and-reminders.md","namespace":"specification","relativePath":"10-dependencies-and-reminders.md","raw":"# 10. Dependencies and Reminders\n\n## 10.1 Purpose\n\nThis section defines canonical semantics for task dependencies (`blocked_by`) and task reminders (`reminders`).\n\n## 10.2 Dependencies (`blocked_by`)\n\n### 10.2.1 Data shape\n\n`blocked_by` MUST be a list of dependency entries.\n\nEach entry MUST be an object with:\n\n- `uid` (required): reference to a blocking task (link or string)\n- `reltype` (required): one of\n - `FINISHTOSTART`\n - `STARTTOSTART`\n - `FINISHTOFINISH`\n - `STARTTOFINISH`\n- `gap` (optional): ISO 8601 duration string\n\nIf `reltype` is omitted on read in compatibility mode, implementations MAY treat it as `FINISHTOSTART` and SHOULD emit a warning.\n\n### 10.2.2 UID normalization\n\nImplementations SHOULD normalize `uid` values to a canonical reference representation on write.\n\nIf link formats are supported, both wikilink and markdown-link forms MAY be read. Canonical write form MUST be documented.\nLink parsing and resolution MUST follow §11.\n\n### 10.2.3 Dependency uniqueness\n\nWithin a task, dependency entries are keyed by normalized `uid`.\n\nPolicy is configuration-driven and MUST be deterministic:\n\n- when `dependencies.enforce_unique_uid=true` (default), duplicate normalized `uid` values MUST NOT be accepted as canonical persisted state:\n - strict mode: duplicates MUST fail validation/write with `duplicate_dependency_uid`;\n - permissive mode: implementations MAY either fail or normalize to one entry, but MUST emit `duplicate_dependency_uid`.\n- when `dependencies.enforce_unique_uid=false`, duplicates MAY be preserved as compatibility behavior.\n\nThe active policy MUST be documented in conformance claims.\n\n### 10.2.4 Self-dependency\n\nA task MUST NOT depend on itself.\n\nSelf-dependency is a validation error.\n\n### 10.2.5 Blocking semantics (v0.1)\n\nFor v0.1, blocking evaluation MUST be status-presence based:\n\n1. A task is blocked if it has at least one unresolved dependency.\n2. A dependency on a resolvable task is unresolved when the referenced task is not in a completed status.\n3. Completed status MUST be determined from configured `status.completed_values`.\n4. For recurring referenced tasks in v0.1, unresolved/resolved evaluation MUST use base `status` only; `complete_instances`/`skipped_instances` are not consulted.\n5. When a referenced task is missing/unresolvable, whether that missing target contributes to blocked-state evaluation MUST follow `dependencies.treat_missing_target_as_blocked` (§9.11, default `true`).\n\nFor v0.1, `reltype` and `gap` are preserved and validated but MUST NOT change the unresolved/resolved decision.\n\n### 10.2.6 Missing referenced task\n\nWhen `uid` cannot be resolved:\n\n- implementations SHOULD emit `unresolved_dependency_target`.\n- blocked-state contribution for this missing target MUST follow `dependencies.treat_missing_target_as_blocked` (§9.11).\n- issue severity SHOULD follow `dependencies.unresolved_target_severity` (default: `warning`).\n- for `blocked_by.uid`, this dependency-specific severity policy MUST take precedence over `links.unresolved_default_severity`.\n- parse failures that produce `invalid_link_format` and containment violations that produce `path_traversal` remain error-severity conditions from §11.\n- if `dependencies.require_resolved_uid_on_write=true`, add/update MUST fail with error.\n\n### 10.2.7 Cycles\n\nImplementations MUST reject direct self-cycles.\n\nDetection of multi-hop dependency cycles is RECOMMENDED but not required for `core-lite` or `recurrence` profiles.\n\n### 10.2.8 Reverse relation field\n\nSome implementations maintain reverse relationships (for example `blocking`). Such fields are derived and non-canonical in this spec unless explicitly mapped.\n\nIf maintained, reverse updates SHOULD remain consistent with `blocked_by` edits.\n\n### 10.2.9 Dependency operation semantics\n\n#### Add dependency\n\nAdd dependency MUST:\n\n- validate entry shape,\n- handle duplicates by policy (preserve, normalize, or reject),\n- preserve unrelated dependency entries,\n- update `date_modified` on change.\n\n#### Remove dependency\n\nRemove dependency MUST remove by normalized `uid` and be idempotent.\n\n#### Replace dependencies\n\nReplace behavior MUST be explicit operation mode (not default for patch update).\n\n### 10.2.10 Dependency examples\n\nExample entry:\n\n```yaml\nblockedBy:\n - uid: \"[[prepare-metrics]]\"\n reltype: FINISHTOSTART\n gap: PT4H\n```\n\nExample unresolved dependency (target missing):\n\n```yaml\nblockedBy:\n - uid: \"[[non-existent-task]]\"\n reltype: FINISHTOSTART\n```\n\n## 10.3 Reminders (`reminders`)\n\n### 10.3.1 Data shape\n\n`reminders` MUST be a list of reminder entries.\n\nEach reminder MUST include:\n\n- `id` (required): unique string within the task\n- `type` (required): `absolute` or `relative`\n\nOptional field:\n\n- `description` string\n\nType-specific fields:\n\n- `absolute`: requires `absoluteTime` datetime\n- `relative`: requires `relatedTo` (`due` or `scheduled`) and `offset` (ISO 8601 duration)\n\n### 10.3.2 Reminder uniqueness\n\nReminder `id` values MUST be unique within the task.\n\nIf duplicates occur:\n\n- strict mode: MUST raise `duplicate_reminder_id`.\n- permissive mode: MAY normalize deterministically and emit warning.\n\n### 10.3.3 Relative reminder base\n\n`relatedTo` MUST reference semantic role `due` or `scheduled`.\n\nIf the referenced role is absent, the reminder is unresolved.\n\n### 10.3.4 Trigger instant computation\n\nTrigger instant MUST be computed as follows:\n\n1. If `type=absolute`, trigger = `absoluteTime` instant.\n2. If `type=relative`,\n - resolve base field from `relatedTo`,\n - if base is datetime: use that instant,\n - if base is date: convert to local datetime at configured `reminders.date_only_anchor_time`,\n - trigger = base + `offset`.\n\nIf `reminders.date_only_anchor_time` is not configured, implementations MUST use `00:00` local time.\n\n### 10.3.5 Offset semantics\n\n`offset` MUST be a valid ISO 8601 duration with optional sign.\n\n- negative offset = before base\n- positive offset = after base\n- zero offset = at base instant\n\n### 10.3.6 Invalid mixed fields\n\nEntries with incompatible field combinations MUST fail validation in strict mode.\n\nExamples:\n\n- `type=absolute` with `relatedTo` and no `absoluteTime`\n- `type=relative` with `absoluteTime` and missing `offset`\n\n### 10.3.7 Reminder ordering\n\nWhen computing reminder schedules, implementations MUST sort by trigger instant ascending.\n\nFor identical trigger instants, implementations MUST use stable tie-break ordering by `id` ascending.\n\n### 10.3.8 Reminder operation semantics\n\n#### Add reminder\n\nAdd reminder MUST validate shape and unique `id`, then update `date_modified`.\n\nIf `id` is omitted by caller and implementation supports auto-ID generation, generated IDs MUST be unique within the task.\n\n#### Update reminder\n\nUpdate reminder MUST address reminders by `id` and be patch-by-default.\n\n#### Remove reminder\n\nRemove reminder by `id` MUST be idempotent.\n\n### 10.3.9 Default reminders\n\nIf `defaults.reminders` is configured (see §9):\n\n- create without explicit reminders MUST apply defaults.\n- create with explicit reminders MUST follow `reminders.apply_defaults_when_explicit` (§9.15):\n - `false` (default): explicit reminders replace defaults.\n - `true`: explicit reminders are merged with defaults.\n\nDeterministic merge rules when `apply_defaults_when_explicit=true`:\n\n1. Start with explicit reminders in caller order.\n2. Append each default reminder whose `id` is not already present.\n3. If explicit and default reminders share an `id`, explicit reminder MUST win.\n\n### 10.3.10 Reminder examples\n\nRelative reminder:\n\n```yaml\nreminders:\n - id: due_minus_15m\n type: relative\n relatedTo: due\n offset: -PT15M\n```\n\nAbsolute reminder:\n\n```yaml\nreminders:\n - id: call_now\n type: absolute\n absoluteTime: 2026-02-20T09:00:00Z\n```\n\n### 10.3.11 Reminder resolution error handling\n\nIf relative reminder base is unavailable (`relatedTo=due` but no `due` field):\n\n- strict mode: validation error `unresolvable_reminder_base`.\n- permissive mode: warning and reminder excluded from trigger computation.\n\n## 10.4 Interactions\n\n### 10.4.1 Rename interaction\n\nIf implementation supports rename/reference updates, dependency `uid` references SHOULD be updated consistently with other link references.\n\n### 10.4.2 Completion interaction\n\nChanging task completion state does not automatically remove dependencies or reminders unless explicitly configured.\n\n### 10.4.3 Archive interaction\n\nArchive operations MAY suppress reminder delivery in runtime systems, but archive MUST NOT silently delete reminder records from persisted frontmatter unless explicitly requested.\n","aliases":["/spec/10-dependencies-and-reminders/"],"toc":[{"level":2,"id":"101-purpose","text":"10.1 Purpose"},{"level":2,"id":"102-dependencies-blockedby","text":"10.2 Dependencies (blocked_by)"},{"level":3,"id":"1021-data-shape","text":"10.2.1 Data shape"},{"level":3,"id":"1022-uid-normalization","text":"10.2.2 UID normalization"},{"level":3,"id":"1023-dependency-uniqueness","text":"10.2.3 Dependency uniqueness"},{"level":3,"id":"1024-self-dependency","text":"10.2.4 Self-dependency"},{"level":3,"id":"1025-blocking-semantics-v01","text":"10.2.5 Blocking semantics (v0.1)"},{"level":3,"id":"1026-missing-referenced-task","text":"10.2.6 Missing referenced task"},{"level":3,"id":"1027-cycles","text":"10.2.7 Cycles"},{"level":3,"id":"1028-reverse-relation-field","text":"10.2.8 Reverse relation field"},{"level":3,"id":"1029-dependency-operation-semantics","text":"10.2.9 Dependency operation semantics"},{"level":3,"id":"10210-dependency-examples","text":"10.2.10 Dependency examples"},{"level":2,"id":"103-reminders-reminders","text":"10.3 Reminders (reminders)"},{"level":3,"id":"1031-data-shape","text":"10.3.1 Data shape"},{"level":3,"id":"1032-reminder-uniqueness","text":"10.3.2 Reminder uniqueness"},{"level":3,"id":"1033-relative-reminder-base","text":"10.3.3 Relative reminder base"},{"level":3,"id":"1034-trigger-instant-computation","text":"10.3.4 Trigger instant computation"},{"level":3,"id":"1035-offset-semantics","text":"10.3.5 Offset semantics"},{"level":3,"id":"1036-invalid-mixed-fields","text":"10.3.6 Invalid mixed fields"},{"level":3,"id":"1037-reminder-ordering","text":"10.3.7 Reminder ordering"},{"level":3,"id":"1038-reminder-operation-semantics","text":"10.3.8 Reminder operation semantics"},{"level":3,"id":"1039-default-reminders","text":"10.3.9 Default reminders"},{"level":3,"id":"10310-reminder-examples","text":"10.3.10 Reminder examples"},{"level":3,"id":"10311-reminder-resolution-error-handling","text":"10.3.11 Reminder resolution error handling"},{"level":2,"id":"104-interactions","text":"10.4 Interactions"},{"level":3,"id":"1041-rename-interaction","text":"10.4.1 Rename interaction"},{"level":3,"id":"1042-completion-interaction","text":"10.4.2 Completion interaction"},{"level":3,"id":"1043-archive-interaction","text":"10.4.3 Archive interaction"}],"html":"

10.1 Purpose#

\n

This section defines canonical semantics for task dependencies (blocked_by) and task reminders (reminders).

\n

10.2 Dependencies (blocked_by)#

\n

10.2.1 Data shape#

\n

blocked_by MUST be a list of dependency entries.

\n

Each entry MUST be an object with:

\n
    \n
  • uid (required): reference to a blocking task (link or string)
  • \n
  • reltype (required): one of
      \n
    • FINISHTOSTART
    • \n
    • STARTTOSTART
    • \n
    • FINISHTOFINISH
    • \n
    • STARTTOFINISH
    • \n
    \n
  • \n
  • gap (optional): ISO 8601 duration string
  • \n
\n

If reltype is omitted on read in compatibility mode, implementations MAY treat it as FINISHTOSTART and SHOULD emit a warning.

\n

10.2.2 UID normalization#

\n

Implementations SHOULD normalize uid values to a canonical reference representation on write.

\n

If link formats are supported, both wikilink and markdown-link forms MAY be read. Canonical write form MUST be documented.\nLink parsing and resolution MUST follow §11.

\n

10.2.3 Dependency uniqueness#

\n

Within a task, dependency entries are keyed by normalized uid.

\n

Policy is configuration-driven and MUST be deterministic:

\n
    \n
  • when dependencies.enforce_unique_uid=true (default), duplicate normalized uid values MUST NOT be accepted as canonical persisted state:
      \n
    • strict mode: duplicates MUST fail validation/write with duplicate_dependency_uid;
    • \n
    • permissive mode: implementations MAY either fail or normalize to one entry, but MUST emit duplicate_dependency_uid.
    • \n
    \n
  • \n
  • when dependencies.enforce_unique_uid=false, duplicates MAY be preserved as compatibility behavior.
  • \n
\n

The active policy MUST be documented in conformance claims.

\n

10.2.4 Self-dependency#

\n

A task MUST NOT depend on itself.

\n

Self-dependency is a validation error.

\n

10.2.5 Blocking semantics (v0.1)#

\n

For v0.1, blocking evaluation MUST be status-presence based:

\n
    \n
  1. A task is blocked if it has at least one unresolved dependency.
  2. \n
  3. A dependency on a resolvable task is unresolved when the referenced task is not in a completed status.
  4. \n
  5. Completed status MUST be determined from configured status.completed_values.
  6. \n
  7. For recurring referenced tasks in v0.1, unresolved/resolved evaluation MUST use base status only; complete_instances/skipped_instances are not consulted.
  8. \n
  9. When a referenced task is missing/unresolvable, whether that missing target contributes to blocked-state evaluation MUST follow dependencies.treat_missing_target_as_blocked (§9.11, default true).
  10. \n
\n

For v0.1, reltype and gap are preserved and validated but MUST NOT change the unresolved/resolved decision.

\n

10.2.6 Missing referenced task#

\n

When uid cannot be resolved:

\n
    \n
  • implementations SHOULD emit unresolved_dependency_target.
  • \n
  • blocked-state contribution for this missing target MUST follow dependencies.treat_missing_target_as_blocked (§9.11).
  • \n
  • issue severity SHOULD follow dependencies.unresolved_target_severity (default: warning).
  • \n
  • for blocked_by.uid, this dependency-specific severity policy MUST take precedence over links.unresolved_default_severity.
  • \n
  • parse failures that produce invalid_link_format and containment violations that produce path_traversal remain error-severity conditions from §11.
  • \n
  • if dependencies.require_resolved_uid_on_write=true, add/update MUST fail with error.
  • \n
\n

10.2.7 Cycles#

\n

Implementations MUST reject direct self-cycles.

\n

Detection of multi-hop dependency cycles is RECOMMENDED but not required for core-lite or recurrence profiles.

\n

10.2.8 Reverse relation field#

\n

Some implementations maintain reverse relationships (for example blocking). Such fields are derived and non-canonical in this spec unless explicitly mapped.

\n

If maintained, reverse updates SHOULD remain consistent with blocked_by edits.

\n

10.2.9 Dependency operation semantics#

\n

Add dependency#

\n

Add dependency MUST:

\n
    \n
  • validate entry shape,
  • \n
  • handle duplicates by policy (preserve, normalize, or reject),
  • \n
  • preserve unrelated dependency entries,
  • \n
  • update date_modified on change.
  • \n
\n

Remove dependency#

\n

Remove dependency MUST remove by normalized uid and be idempotent.

\n

Replace dependencies#

\n

Replace behavior MUST be explicit operation mode (not default for patch update).

\n

10.2.10 Dependency examples#

\n

Example entry:

\n
blockedBy:\n  - uid: "[[prepare-metrics]]"\n    reltype: FINISHTOSTART\n    gap: PT4H\n

Example unresolved dependency (target missing):

\n
blockedBy:\n  - uid: "[[non-existent-task]]"\n    reltype: FINISHTOSTART\n

10.3 Reminders (reminders)#

\n

10.3.1 Data shape#

\n

reminders MUST be a list of reminder entries.

\n

Each reminder MUST include:

\n
    \n
  • id (required): unique string within the task
  • \n
  • type (required): absolute or relative
  • \n
\n

Optional field:

\n
    \n
  • description string
  • \n
\n

Type-specific fields:

\n
    \n
  • absolute: requires absoluteTime datetime
  • \n
  • relative: requires relatedTo (due or scheduled) and offset (ISO 8601 duration)
  • \n
\n

10.3.2 Reminder uniqueness#

\n

Reminder id values MUST be unique within the task.

\n

If duplicates occur:

\n
    \n
  • strict mode: MUST raise duplicate_reminder_id.
  • \n
  • permissive mode: MAY normalize deterministically and emit warning.
  • \n
\n

10.3.3 Relative reminder base#

\n

relatedTo MUST reference semantic role due or scheduled.

\n

If the referenced role is absent, the reminder is unresolved.

\n

10.3.4 Trigger instant computation#

\n

Trigger instant MUST be computed as follows:

\n
    \n
  1. If type=absolute, trigger = absoluteTime instant.
  2. \n
  3. If type=relative,
      \n
    • resolve base field from relatedTo,
    • \n
    • if base is datetime: use that instant,
    • \n
    • if base is date: convert to local datetime at configured reminders.date_only_anchor_time,
    • \n
    • trigger = base + offset.
    • \n
    \n
  4. \n
\n

If reminders.date_only_anchor_time is not configured, implementations MUST use 00:00 local time.

\n

10.3.5 Offset semantics#

\n

offset MUST be a valid ISO 8601 duration with optional sign.

\n
    \n
  • negative offset = before base
  • \n
  • positive offset = after base
  • \n
  • zero offset = at base instant
  • \n
\n

10.3.6 Invalid mixed fields#

\n

Entries with incompatible field combinations MUST fail validation in strict mode.

\n

Examples:

\n
    \n
  • type=absolute with relatedTo and no absoluteTime
  • \n
  • type=relative with absoluteTime and missing offset
  • \n
\n

10.3.7 Reminder ordering#

\n

When computing reminder schedules, implementations MUST sort by trigger instant ascending.

\n

For identical trigger instants, implementations MUST use stable tie-break ordering by id ascending.

\n

10.3.8 Reminder operation semantics#

\n

Add reminder#

\n

Add reminder MUST validate shape and unique id, then update date_modified.

\n

If id is omitted by caller and implementation supports auto-ID generation, generated IDs MUST be unique within the task.

\n

Update reminder#

\n

Update reminder MUST address reminders by id and be patch-by-default.

\n

Remove reminder#

\n

Remove reminder by id MUST be idempotent.

\n

10.3.9 Default reminders#

\n

If defaults.reminders is configured (see §9):

\n
    \n
  • create without explicit reminders MUST apply defaults.
  • \n
  • create with explicit reminders MUST follow reminders.apply_defaults_when_explicit (§9.15):
      \n
    • false (default): explicit reminders replace defaults.
    • \n
    • true: explicit reminders are merged with defaults.
    • \n
    \n
  • \n
\n

Deterministic merge rules when apply_defaults_when_explicit=true:

\n
    \n
  1. Start with explicit reminders in caller order.
  2. \n
  3. Append each default reminder whose id is not already present.
  4. \n
  5. If explicit and default reminders share an id, explicit reminder MUST win.
  6. \n
\n

10.3.10 Reminder examples#

\n

Relative reminder:

\n
reminders:\n  - id: due_minus_15m\n    type: relative\n    relatedTo: due\n    offset: -PT15M\n

Absolute reminder:

\n
reminders:\n  - id: call_now\n    type: absolute\n    absoluteTime: 2026-02-20T09:00:00Z\n

10.3.11 Reminder resolution error handling#

\n

If relative reminder base is unavailable (relatedTo=due but no due field):

\n
    \n
  • strict mode: validation error unresolvable_reminder_base.
  • \n
  • permissive mode: warning and reminder excluded from trigger computation.
  • \n
\n

10.4 Interactions#

\n

10.4.1 Rename interaction#

\n

If implementation supports rename/reference updates, dependency uid references SHOULD be updated consistently with other link references.

\n

10.4.2 Completion interaction#

\n

Changing task completion state does not automatically remove dependencies or reminders unless explicitly configured.

\n

10.4.3 Archive interaction#

\n

Archive operations MAY suppress reminder delivery in runtime systems, but archive MUST NOT silently delete reminder records from persisted frontmatter unless explicitly requested.

\n","text":"10.1 Purpose# This section defines canonical semantics for task dependencies (blocked_by) and task reminders (reminders). 10.2 Dependencies (blocked_by)# 10.2.1 Data shape# blocked_by MUST be a list of dependency entries. Each entry MUST be an object with: uid (required): reference to a blocking task (link or string) reltype (required): one of FINISHTOSTART STARTTOSTART FINISHTOFINISH STARTTOFINISH gap (optional): ISO 8601 duration string If reltype is omitted on read in compatibility mode, implementations MAY treat it as FINISHTOSTART and SHOULD emit a warning. 10.2.2 UID normalization# Implementations SHOULD normalize uid values to a canonical reference representation on write. If link formats are supported, both wikilink and markdown-link forms MAY be read. Canonical write form MUST be documented. Link parsing and resolution MUST follow §11. 10.2.3 Dependency uniqueness# Within a task, dependency entries are keyed by normalized uid. Policy is configuration-driven and MUST be deterministic: when dependencies.enforce_unique_uid=true (default), duplicate normalized uid values MUST NOT be accepted as canonical persisted state: strict mode: duplicates MUST fail validation/write with duplicate_dependency_uid; permissive mode: implementations MAY either fail or normalize to one entry, but MUST emit duplicate_dependency_uid. when dependencies.enforce_unique_uid=false, duplicates MAY be preserved as compatibility behavior. The active policy MUST be documented in conformance claims. 10.2.4 Self-dependency# A task MUST NOT depend on itself. Self-dependency is a validation error. 10.2.5 Blocking semantics (v0.1)# For v0.1, blocking evaluation MUST be status-presence based: A task is blocked if it has at least one unresolved dependency. A dependency on a resolvable task is unresolved when the referenced task is not in a completed status. Completed status MUST be determined from configured status.completed_values. For recurring referenced tasks in v0.1, unresolved/resolved evaluation MUST use base status only; complete_instances/skipped_instances are not consulted. When a referenced task is missing/unresolvable, whether that missing target contributes to blocked-state evaluation MUST follow dependencies.treat_missing_target_as_blocked (§9.11, default true). For v0.1, reltype and gap are preserved and validated but MUST NOT change the unresolved/resolved decision. 10.2.6 Missing referenced task# When uid cannot be resolved: implementations SHOULD emit unresolved_dependency_target. blocked-state contribution for this missing target MUST follow dependencies.treat_missing_target_as_blocked (§9.11). issue severity SHOULD follow dependencies.unresolved_target_severity (default: warning). for blocked_by.uid, this dependency-specific severity policy MUST take precedence over links.unresolved_default_severity. parse failures that produce invalid_link_format and containment violations that produce path_traversal remain error-severity conditions from §11. if dependencies.require_resolved_uid_on_write=true, add/update MUST fail with error. 10.2.7 Cycles# Implementations MUST reject direct self-cycles. Detection of multi-hop dependency cycles is RECOMMENDED but not required for core-lite or recurrence profiles. 10.2.8 Reverse relation field# Some implementations maintain reverse relationships (for example blocking). Such fields are derived and non-canonical in this spec unless explicitly mapped. If maintained, reverse updates SHOULD remain consistent with blocked_by edits. 10.2.9 Dependency operation semantics# Add dependency# Add dependency MUST: validate entry shape, handle duplicates by policy (preserve, normalize, or reject), preserve unrelated dependency entries, update date_modified on change. Remove dependency# Remove dependency MUST remove by normalized uid and be idempotent. Replace dependencies# Replace behavior MUST be explicit operation mode (not default for patch update). 10.2.10 Dependency examples# Example entry: blockedBy: - uid: \"[[prepare-metrics]]\" reltype: FINISHTOSTART gap: PT4H Example unresolved dependency (target missing): blockedBy: - uid: \"[[non-existent-task]]\" reltype: FINISHTOSTART 10.3 Reminders (reminders)# 10.3.1 Data shape# reminders MUST be a list of reminder entries. Each reminder MUST include: id (required): unique string within the task type (required): absolute or relative Optional field: description string Type-specific fields: absolute: requires absoluteTime datetime relative: requires relatedTo (due or scheduled) and offset (ISO 8601 duration) 10.3.2 Reminder uniqueness# Reminder id values MUST be unique within the task. If duplicates occur: strict mode: MUST raise duplicate_reminder_id. permissive mode: MAY normalize deterministically and emit warning. 10.3.3 Relative reminder base# relatedTo MUST reference semantic role due or scheduled. If the referenced role is absent, the reminder is unresolved. 10.3.4 Trigger instant computation# Trigger instant MUST be computed as follows: If type=absolute, trigger = absoluteTime instant. If type=relative, resolve base field from relatedTo, if base is datetime: use that instant, if base is date: convert to local datetime at configured reminders.date_only_anchor_time, trigger = base + offset. If reminders.date_only_anchor_time is not configured, implementations MUST use 00:00 local time. 10.3.5 Offset semantics# offset MUST be a valid ISO 8601 duration with optional sign. negative offset = before base positive offset = after base zero offset = at base instant 10.3.6 Invalid mixed fields# Entries with incompatible field combinations MUST fail validation in strict mode. Examples: type=absolute with relatedTo and no absoluteTime type=relative with absoluteTime and missing offset 10.3.7 Reminder ordering# When computing reminder schedules, implementations MUST sort by trigger instant ascending. For identical trigger instants, implementations MUST use stable tie-break ordering by id ascending. 10.3.8 Reminder operation semantics# Add reminder# Add reminder MUST validate shape and unique id, then update date_modified. If id is omitted by caller and implementation supports auto-ID generation, generated IDs MUST be unique within the task. Update reminder# Update reminder MUST address reminders by id and be patch-by-default. Remove reminder# Remove reminder by id MUST be idempotent. 10.3.9 Default reminders# If defaults.reminders is configured (see §9): create without explicit reminders MUST apply defaults. create with explicit reminders MUST follow reminders.apply_defaults_when_explicit (§9.15): false (default): explicit reminders replace defaults. true: explicit reminders are merged with defaults. Deterministic merge rules when apply_defaults_when_explicit=true: Start with explicit reminders in caller order. Append each default reminder whose id is not already present. If explicit and default reminders share an id, explicit reminder MUST win. 10.3.10 Reminder examples# Relative reminder: reminders: - id: due_minus_15m type: relative relatedTo: due offset: -PT15M Absolute reminder: reminders: - id: call_now type: absolute absoluteTime: 2026-02-20T09:00:00Z 10.3.11 Reminder resolution error handling# If relative reminder base is unavailable (relatedTo=due but no due field): strict mode: validation error unresolvable_reminder_base. permissive mode: warning and reminder excluded from trigger computation. 10.4 Interactions# 10.4.1 Rename interaction# If implementation supports rename/reference updates, dependency uid references SHOULD be updated consistently with other link references. 10.4.2 Completion interaction# Changing task completion state does not automatically remove dependencies or reminders unless explicitly configured. 10.4.3 Archive interaction# Archive operations MAY suppress reminder delivery in runtime systems, but archive MUST NOT silently delete reminder records from persisted frontmatter unless explicitly requested."},{"route":"/developers/specification/11-links/","title":"11. Links","description":"This section defines link syntax, parsing, resolution, and write-format semantics for link-bearing task fields — primarily projects, blocked_by.uid, and attachments. Alignment w...","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:11-links.md","namespace":"specification","relativePath":"11-links.md","raw":"# 11. Links\n\n## 11.1 Purpose\n\nThis section defines link syntax, parsing, resolution, and write-format semantics for link-bearing task fields — primarily `projects`, `blocked_by.uid`, and `attachments`.\nAlignment with Obsidian and other ecosystems is informative context only; normative conformance is defined entirely by this section.\n\nApplicability:\n\n- Implementations claiming profile `extended` (§7.3.5) MUST conform to this section for supported link-bearing roles.\n- Implementations claiming profile `materialized-occurrences` (§7.3.4) MUST conform to this section for `recurrence_parent` links, but are not required to support unrelated extended link-bearing roles solely because of that profile.\n- Implementations supporting the `attachments` role MUST conform to this section for attachment references regardless of profile.\n- Implementations that claim neither `extended` nor `materialized-occurrences` MAY treat link-shaped strings as opaque data and are not required to implement §11 behavior.\n\n---\n\n## 11.2 Link formats\n\nImplementations that conform to §11 (see §11.1 applicability) MUST support three link formats.\n\n### 11.2.1 Wikilinks\n\n```\n[[target]]\n[[target|alias]]\n[[target#anchor]]\n[[target#anchor|alias]]\n[[folder/target]]\n[[./relative]]\n[[../parent/target]]\n```\n\n**Components:**\n- **target**: The file being linked to (without extension by default)\n- **alias**: Display text; does not affect resolution\n- **anchor**: A heading or block reference within the target\n- **path**: May be absolute (from collection root) or relative (from current file)\n\nExamples in frontmatter:\n\n```yaml\nprojects:\n - \"[[home-project]]\"\n - \"[[projects/alpha|Alpha Project]]\"\nblockedBy:\n - uid: \"[[prepare-metrics]]\"\n reltype: FINISHTOSTART\n```\n\n### 11.2.2 Markdown links\n\n```\n[text](path.md)\n[text](./relative.md)\n[text](../other/file.md)\n[text](path.md#anchor)\n```\n\nThe text portion is treated as an alias and does not affect resolution.\n\nMarkdown links in frontmatter require the `obsidian-frontmatter-markdown-links` Obsidian plugin. Implementations MUST NOT write markdown-format links by default unless `links.use_markdown_format=true` is configured (§11.7).\n\n### 11.2.3 Bare paths\n\n```\n./sibling.md\n../other/file.md\nfolder/file.md\n```\n\nBare paths follow the same resolution rules as markdown links (relative to containing file's directory unless starting with `/`).\n\n---\n\n## 11.3 Link parsing\n\nWhen a link value is read, implementations MUST parse it into a structured representation:\n\n| Component | Type | Description |\n|---|---|---|\n| `raw` | string | Original string value exactly as written |\n| `target` | string | File path or identifier (without anchor or alias) |\n| `alias` | string? | Display text if provided, otherwise null |\n| `anchor` | string? | Heading or block reference if provided, otherwise null |\n| `format` | enum | One of: `wikilink`, `markdown`, `path` |\n| `is_relative` | boolean | Whether target begins with `./` or `../` |\n\nParsing examples:\n\n| Input | target | alias | anchor | format | is_relative |\n|---|---|---|---|---|---|\n| `[[task-001]]` | `task-001` | null | null | wikilink | false |\n| `[[task-001\\|My Task]]` | `task-001` | `My Task` | null | wikilink | false |\n| `[[docs/api#auth]]` | `docs/api` | null | `auth` | wikilink | false |\n| `[[./sibling]]` | `./sibling` | null | null | wikilink | true |\n| `[Link](file.md)` | `file.md` | `Link` | null | markdown | false |\n| `./other.md` | `./other.md` | null | null | path | true |\n\n---\n\n## 11.4 Resolution algorithm\n\nResolution transforms a parsed link into an absolute path (relative to collection root) pointing to the target file.\n\nGiven a parsed link and the path of the source file containing it:\n\n### Step 1: Parse the link into components (target, format, is_relative)\n\n### Step 2: Route by format\n\n**If format is `markdown` or `path`:**\n- If target starts with `/`, resolve from collection root (strip the leading `/`)\n- Otherwise, resolve relative to the source file's directory (standard markdown behavior)\n- Example: link `[Docs](docs/api.md)` in `notes/meeting.md` resolves to `notes/docs/api.md`\n\n**If format is `wikilink`:**\n- If target starts with `./` or `../`, resolve relative to the source file's directory\n- If target starts with `/`, resolve from collection root (strip the leading `/`)\n- If target contains `/` (and is not relative), resolve from collection root\n - Example: `[[docs/api]]` resolves to `docs/api`\n- If simple name (no `/`, no `./` or `../`): proceed to Step 3\n\n### Step 3: Simple-name resolution (wikilinks only)\n\nFor simple wikilink names (no path separator):\n\n1. **Define the search scope:**\n - For `blocked_by.uid`: scope to files matching `task_detection` (task files only)\n - For `projects`: scope to all markdown files in the collection unless narrowed by explicit configuration\n - For `attachments`: scope to all non-directory files in the collection\n\n2. **ID match pass:** search scoped files for semantic role `id` (§2.6.5) equal to the name.\n - Implementations MAY treat literal frontmatter key `id` as compatibility input when semantic mapping for `id` is unavailable.\n - Equality MUST be exact string equality.\n - If exactly one match: resolve to that file\n - If multiple matches: fail with `ambiguous_link`\n\n3. **Filename match pass:** if no ID match, search scoped markdown files by filename (without extension).\n4. Implementations MUST deduplicate normalized candidate paths before final selection.\n5. If exactly one filename candidate remains after normalization and extension handling, resolve to that file.\n6. If multiple filename candidates remain, resolve to `null` and emit `ambiguous_link`. Callers SHOULD use a path-qualified or relative target to disambiguate.\n\n### Step 4: Extension handling\n\nIf the target has no extension, implementations SHOULD try configured extensions in order.\n\nDefault extension order: `[\".md\"]`.\n\nExample: `[[readme]]` tries `readme.md`, `readme.mdx`, etc.\n\n### Step 5: Path traversal check\n\nAfter resolution and normalization, if the resolved path would escape the collection root, abort with `path_traversal`. See §11.5.\n\n### Step 6: Return result\n\n- The normalized collection-relative path if found\n- `null` if no matching file exists\n\n### Resolution examples\n\nGiven collection structure:\n```\n/\n├── TaskNotes/\n│ ├── Tasks/\n│ │ ├── task-001.md\n│ │ └── subtasks/\n│ │ └── task-002.md\n├── notes/\n│ └── meeting.md\n└── projects/\n └── alpha.md\n```\n\nResolution from `TaskNotes/Tasks/subtasks/task-002.md`:\n\n| Link value | Resolved path | Notes |\n|---|---|---|\n| `[[task-001]]` | `TaskNotes/Tasks/task-001.md` | Simple-name search |\n| `[[../task-001]]` | `TaskNotes/Tasks/task-001.md` | Relative wikilink |\n| `[[./task-003]]` | `TaskNotes/Tasks/subtasks/task-003.md` | Relative (may not exist) |\n| `[[notes/meeting]]` | `notes/meeting.md` | Absolute from root |\n| `[[alpha]]` | `projects/alpha.md` | Simple-name search (projects scope) |\n| `[link](../task-001.md)` | `TaskNotes/Tasks/task-001.md` | Markdown, relative |\n| `../task-001.md` | `TaskNotes/Tasks/task-001.md` | Bare path, relative |\n\n---\n\n## 11.5 Path sandboxing\n\nLink resolution MUST NOT produce paths outside the collection root.\n\n**Rules:**\n- After resolving relative paths (applying `../` segments), the resulting path MUST be within the collection root directory\n- If resolution would escape the collection root, the link MUST resolve to `null` and implementations MUST emit a `path_traversal` error\n- This applies to all link formats: wikilinks, markdown links, and bare paths\n- Implementations MUST normalize paths (resolve `.` and `..` segments) before checking containment\n\n**Examples** (collection rooted at `/home/user/MyVault/`):\n\n| Link | From file | Result |\n|---|---|---|\n| `[[../../../etc/passwd]]` | `TaskNotes/Tasks/task.md` | `null` + `path_traversal` |\n| `[[../../secrets/key]]` | `deep/nested/file.md` | `null` + `path_traversal` |\n| `[[../task-001]]` | `TaskNotes/Tasks/subtasks/t.md` | Resolves normally |\n\n---\n\n## 11.6 Canonical write format\n\nWhen creating new link values or changing a link target, implementations MUST use a deterministic canonical form.\n\n### Default (wikilink format)\n\nBy default (`links.use_markdown_format=false`), the canonical write format is a **simple wikilink**:\n\n```yaml\nblockedBy:\n - uid: \"[[task-001]]\"\n reltype: FINISHTOSTART\nprojects:\n - \"[[projects/alpha]]\"\n```\n\nRules:\n- Use the filename without extension as the target when the file can be identified by simple-name resolution within the appropriate scope.\n- Use a path-qualified target (`folder/name`) when the simple name would be ambiguous.\n- Do NOT include the alias component in dependency `uid` writes.\n- Do NOT include the anchor component in dependency `uid` writes.\n- Preserve the alias component in `projects` entries when the alias was provided by the user.\n- For `attachments`, always write a path-qualified collection-relative target\n with its file extension, for example `[[Attachments/01K1-photo.jpg]]`.\n Attachment writes MUST NOT include an alias or anchor.\n\n### Markdown link format (`links.use_markdown_format=true`)\n\nWhen `links.use_markdown_format=true` is configured (requires the `obsidian-frontmatter-markdown-links` Obsidian plugin), the canonical write format for link-bearing fields is a **markdown link** using the collection-relative path:\n\n```yaml\nblockedBy:\n - uid: \"[task-001](TaskNotes/Tasks/task-001.md)\"\n reltype: FINISHTOSTART\n```\n\n### Round-trip preservation\n\nWhen writing an existing link field and the resolved target is unchanged, implementations MUST preserve the original format when possible:\n- If the user wrote `[[task-001|My Task]]`, preserve alias for `projects` entries.\n- If the user wrote a relative path, preserve relativity when possible.\n- For `blocked_by.uid`, alias and anchor components MUST still be removed on canonical writes.\n- If preservation is not possible (for example unresolved/ambiguous reconstruction), implementations MUST fall back to canonical write rules in this section.\n\n---\n\n## 11.7 Configuration\n\n`links` configuration keys (see §9.12):\n\n```yaml\nlinks:\n extensions: [\".md\"] # Extension trial order for extensionless targets\n use_markdown_format: false # Write markdown links instead of wikilinks\n unresolved_default_severity: warning # \"warning\" or \"error\"\n update_references_on_rename: true # Update link targets when files are renamed\n```\n\nRules:\n- `extensions` MUST be a non-empty list when present\n- `unresolved_default_severity` MUST be `\"warning\"` or `\"error\"`\n- `update_references_on_rename=true` enables rename-time link rewrite behavior (§11.9)\n- `use_markdown_format=true` requires the `obsidian-frontmatter-markdown-links` plugin in Obsidian deployments\n\n---\n\n## 11.8 Role-specific rules\n\n### 11.8.1 `projects`\n\n`projects` entries SHOULD be interpreted with this section's parsing/resolution rules.\n\nIf a `projects` entry is a plain string (not a wikilink or markdown link), implementations SHOULD treat it as a bare filename or path and attempt resolution.\n\nIf unresolved:\n- `links.unresolved_default_severity=error`: validation error\n- otherwise: SHOULD emit `unresolved_link_target` warning\n\n### 11.8.2 `blocked_by.uid`\n\n`blocked_by.uid` values MUST use this section's parsing/resolution rules.\n\nFor dependency semantics, unresolved `uid` handling follows §10.2.6.\nFor unresolved-target severity, `dependencies.unresolved_target_severity` controls and takes precedence over `links.unresolved_default_severity`.\n\nThe canonical write form for `uid` values is specified in §11.6.\n\n### 11.8.3 `attachments`\n\nAttachment references MUST resolve to files, not directories. Canonical\nattachment targets MUST be collection-relative, path-qualified, and retain an\nexplicit file extension. This avoids ambiguous simple-name lookup, makes the\nfrontmatter portable without a media-specific extension search policy, and\npreserves the actual filename.\n\nReaders MUST accept wikilinks, Markdown links, and bare paths. They MAY accept\nsimple-name or extensionless values as non-canonical compatibility input, but\ncanonical writes MUST resolve and replace them with an explicit path and\nextension. Aliases and anchors are not part of attachment identity and MUST be\nremoved on canonical writes.\n\nThe normalized resolved collection path defines attachment identity for\nduplicate detection. Implementations MUST preserve list order and MUST reject\nduplicates after path normalization. Unresolved attachment targets use the\nconfigured `unresolved_link_target` severity; offline-capable clients SHOULD\ndistinguish a known-but-not-locally-cached file from a genuinely unresolved\ntarget.\n\n---\n\n## 11.9 Rename and reference updates\n\nIf an implementation supports reference updates on rename (i.e. claims the `rename` capability):\n\n1. It MUST update resolvable references in `blocked_by.uid`, `projects`, and `attachments` link fields.\n2. It SHOULD update links in body content.\n3. It SHOULD preserve the original link format when possible.\n4. It MUST preserve alias and anchor components where valid for the target field. For `blocked_by.uid`, alias and anchor are non-canonical and MUST be removed on write (§11.6).\n5. It MUST report unresolved or ambiguous rewrite cases.\n\nIf reference updates are not supported, this limitation MUST be disclosed in conformance claims.\n\n---\n\n## 11.10 Validation\n\nLink validation issues:\n\n| Code | Severity | Trigger |\n|---|---|---|\n| `invalid_link_format` | error | Link value cannot be parsed as any supported format |\n| `ambiguous_link` | warning | Simple-name resolution found multiple candidates after normalization |\n| `unresolved_link_target` | warning | Link target cannot be resolved to an existing file |\n| `path_traversal` | error | Resolved path escapes collection root |\n\n`unresolved_link_target` severity may be promoted to error via `links.unresolved_default_severity=error`.\nFor `blocked_by.uid`, use `unresolved_dependency_target` severity policy from §10.2.6 instead of `unresolved_link_target`.\n\n---\n\n## 11.11 Examples\n\n### Dependency with wikilink (default)\n\n```yaml\n---\ntitle: Implement API\nstatus: open\ntags: [task]\nblockedBy:\n - uid: \"[[design-api]]\"\n reltype: FINISHTOSTART\n - uid: \"[[projects/infra/setup-server]]\"\n reltype: FINISHTOSTART\n gap: P1D\nprojects:\n - \"[[projects/alpha]]\"\ndateCreated: 2026-02-20T10:00:00Z\ndateModified: 2026-02-20T10:00:00Z\n---\n```\n\n### Dependency with markdown links (`links.use_markdown_format=true`)\n\n```yaml\n---\ntitle: Implement API\nstatus: open\ntags: [task]\nblockedBy:\n - uid: \"[design-api](TaskNotes/Tasks/design-api.md)\"\n reltype: FINISHTOSTART\n---\n```\n\n### Relative links from nested task\n\n```yaml\n# TaskNotes/Tasks/subtasks/task-002.md\n---\ntitle: Sub-task\nstatus: open\ntags: [task]\nblockedBy:\n - uid: \"[[../task-001]]\" # resolves to TaskNotes/Tasks/task-001.md\n reltype: FINISHTOSTART\nprojects:\n - \"[[projects/alpha]]\" # resolves from collection root\n---\n```\n","aliases":["/spec/11-links/"],"toc":[{"level":2,"id":"111-purpose","text":"11.1 Purpose"},{"level":2,"id":"112-link-formats","text":"11.2 Link formats"},{"level":3,"id":"1121-wikilinks","text":"11.2.1 Wikilinks"},{"level":3,"id":"1122-markdown-links","text":"11.2.2 Markdown links"},{"level":3,"id":"1123-bare-paths","text":"11.2.3 Bare paths"},{"level":2,"id":"113-link-parsing","text":"11.3 Link parsing"},{"level":2,"id":"114-resolution-algorithm","text":"11.4 Resolution algorithm"},{"level":3,"id":"step-1-parse-the-link-into-components-target-format-isrelative","text":"Step 1: Parse the link into components (target, format, is_relative)"},{"level":3,"id":"step-2-route-by-format","text":"Step 2: Route by format"},{"level":3,"id":"step-3-simple-name-resolution-wikilinks-only","text":"Step 3: Simple-name resolution (wikilinks only)"},{"level":3,"id":"step-4-extension-handling","text":"Step 4: Extension handling"},{"level":3,"id":"step-5-path-traversal-check","text":"Step 5: Path traversal check"},{"level":3,"id":"step-6-return-result","text":"Step 6: Return result"},{"level":3,"id":"resolution-examples","text":"Resolution examples"},{"level":2,"id":"115-path-sandboxing","text":"11.5 Path sandboxing"},{"level":2,"id":"116-canonical-write-format","text":"11.6 Canonical write format"},{"level":3,"id":"default-wikilink-format","text":"Default (wikilink format)"},{"level":3,"id":"markdown-link-format-linksusemarkdownformattrue","text":"Markdown link format (links.use_markdown_format=true)"},{"level":3,"id":"round-trip-preservation","text":"Round-trip preservation"},{"level":2,"id":"117-configuration","text":"11.7 Configuration"},{"level":2,"id":"118-role-specific-rules","text":"11.8 Role-specific rules"},{"level":3,"id":"1181-projects","text":"11.8.1 projects"},{"level":3,"id":"1182-blockedbyuid","text":"11.8.2 blocked_by.uid"},{"level":3,"id":"1183-attachments","text":"11.8.3 attachments"},{"level":2,"id":"119-rename-and-reference-updates","text":"11.9 Rename and reference updates"},{"level":2,"id":"1110-validation","text":"11.10 Validation"},{"level":2,"id":"1111-examples","text":"11.11 Examples"},{"level":3,"id":"dependency-with-wikilink-default","text":"Dependency with wikilink (default)"},{"level":3,"id":"dependency-with-markdown-links-linksusemarkdownformattrue","text":"Dependency with markdown links (links.use_markdown_format=true)"},{"level":3,"id":"relative-links-from-nested-task","text":"Relative links from nested task"}],"html":"

11.1 Purpose#

\n

This section defines link syntax, parsing, resolution, and write-format semantics for link-bearing task fields — primarily projects, blocked_by.uid, and attachments.\nAlignment with Obsidian and other ecosystems is informative context only; normative conformance is defined entirely by this section.

\n

Applicability:

\n
    \n
  • Implementations claiming profile extended (§7.3.5) MUST conform to this section for supported link-bearing roles.
  • \n
  • Implementations claiming profile materialized-occurrences (§7.3.4) MUST conform to this section for recurrence_parent links, but are not required to support unrelated extended link-bearing roles solely because of that profile.
  • \n
  • Implementations supporting the attachments role MUST conform to this section for attachment references regardless of profile.
  • \n
  • Implementations that claim neither extended nor materialized-occurrences MAY treat link-shaped strings as opaque data and are not required to implement §11 behavior.
  • \n
\n
\n\n

Implementations that conform to §11 (see §11.1 applicability) MUST support three link formats.

\n

11.2.1 Wikilinks#

\n
[[target]]\n[[target|alias]]\n[[target#anchor]]\n[[target#anchor|alias]]\n[[folder/target]]\n[[./relative]]\n[[../parent/target]]\n

Components:

\n
    \n
  • target: The file being linked to (without extension by default)
  • \n
  • alias: Display text; does not affect resolution
  • \n
  • anchor: A heading or block reference within the target
  • \n
  • path: May be absolute (from collection root) or relative (from current file)
  • \n
\n

Examples in frontmatter:

\n
projects:\n  - "[[home-project]]"\n  - "[[projects/alpha|Alpha Project]]"\nblockedBy:\n  - uid: "[[prepare-metrics]]"\n    reltype: FINISHTOSTART\n

11.2.2 Markdown links#

\n
[text](path.md)\n[text](./relative.md)\n[text](../other/file.md)\n[text](path.md#anchor)\n

The text portion is treated as an alias and does not affect resolution.

\n

Markdown links in frontmatter require the obsidian-frontmatter-markdown-links Obsidian plugin. Implementations MUST NOT write markdown-format links by default unless links.use_markdown_format=true is configured (§11.7).

\n

11.2.3 Bare paths#

\n
./sibling.md\n../other/file.md\nfolder/file.md\n

Bare paths follow the same resolution rules as markdown links (relative to containing file's directory unless starting with /).

\n
\n\n

When a link value is read, implementations MUST parse it into a structured representation:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
ComponentTypeDescription
rawstringOriginal string value exactly as written
targetstringFile path or identifier (without anchor or alias)
aliasstring?Display text if provided, otherwise null
anchorstring?Heading or block reference if provided, otherwise null
formatenumOne of: wikilink, markdown, path
is_relativebooleanWhether target begins with ./ or ../
\n

Parsing examples:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Inputtargetaliasanchorformatis_relative
[[task-001]]task-001nullnullwikilinkfalse
[[task-001|My Task]]task-001My Tasknullwikilinkfalse
[[docs/api#auth]]docs/apinullauthwikilinkfalse
[[./sibling]]./siblingnullnullwikilinktrue
[Link](file.md)file.mdLinknullmarkdownfalse
./other.md./other.mdnullnullpathtrue
\n
\n

11.4 Resolution algorithm#

\n

Resolution transforms a parsed link into an absolute path (relative to collection root) pointing to the target file.

\n

Given a parsed link and the path of the source file containing it:

\n\n

Step 2: Route by format#

\n

If format is markdown or path:

\n
    \n
  • If target starts with /, resolve from collection root (strip the leading /)
  • \n
  • Otherwise, resolve relative to the source file's directory (standard markdown behavior)
  • \n
  • Example: link [Docs](docs/api.md) in notes/meeting.md resolves to notes/docs/api.md
  • \n
\n

If format is wikilink:

\n
    \n
  • If target starts with ./ or ../, resolve relative to the source file's directory
  • \n
  • If target starts with /, resolve from collection root (strip the leading /)
  • \n
  • If target contains / (and is not relative), resolve from collection root
      \n
    • Example: [[docs/api]] resolves to docs/api
    • \n
    \n
  • \n
  • If simple name (no /, no ./ or ../): proceed to Step 3
  • \n
\n\n

For simple wikilink names (no path separator):

\n
    \n
  1. Define the search scope:

    \n
      \n
    • For blocked_by.uid: scope to files matching task_detection (task files only)
    • \n
    • For projects: scope to all markdown files in the collection unless narrowed by explicit configuration
    • \n
    • For attachments: scope to all non-directory files in the collection
    • \n
    \n
  2. \n
  3. ID match pass: search scoped files for semantic role id (§2.6.5) equal to the name.

    \n
      \n
    • Implementations MAY treat literal frontmatter key id as compatibility input when semantic mapping for id is unavailable.
    • \n
    • Equality MUST be exact string equality.
    • \n
    • If exactly one match: resolve to that file
    • \n
    • If multiple matches: fail with ambiguous_link
    • \n
    \n
  4. \n
  5. Filename match pass: if no ID match, search scoped markdown files by filename (without extension).

    \n
  6. \n
  7. Implementations MUST deduplicate normalized candidate paths before final selection.

    \n
  8. \n
  9. If exactly one filename candidate remains after normalization and extension handling, resolve to that file.

    \n
  10. \n
  11. If multiple filename candidates remain, resolve to null and emit ambiguous_link. Callers SHOULD use a path-qualified or relative target to disambiguate.

    \n
  12. \n
\n

Step 4: Extension handling#

\n

If the target has no extension, implementations SHOULD try configured extensions in order.

\n

Default extension order: [".md"].

\n

Example: [[readme]] tries readme.md, readme.mdx, etc.

\n

Step 5: Path traversal check#

\n

After resolution and normalization, if the resolved path would escape the collection root, abort with path_traversal. See §11.5.

\n

Step 6: Return result#

\n
    \n
  • The normalized collection-relative path if found
  • \n
  • null if no matching file exists
  • \n
\n

Resolution examples#

\n

Given collection structure:

\n
/\n├── TaskNotes/\n│   ├── Tasks/\n│   │   ├── task-001.md\n│   │   └── subtasks/\n│   │       └── task-002.md\n├── notes/\n│   └── meeting.md\n└── projects/\n    └── alpha.md\n

Resolution from TaskNotes/Tasks/subtasks/task-002.md:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Link valueResolved pathNotes
[[task-001]]TaskNotes/Tasks/task-001.mdSimple-name search
[[../task-001]]TaskNotes/Tasks/task-001.mdRelative wikilink
[[./task-003]]TaskNotes/Tasks/subtasks/task-003.mdRelative (may not exist)
[[notes/meeting]]notes/meeting.mdAbsolute from root
[[alpha]]projects/alpha.mdSimple-name search (projects scope)
[link](../task-001.md)TaskNotes/Tasks/task-001.mdMarkdown, relative
../task-001.mdTaskNotes/Tasks/task-001.mdBare path, relative
\n
\n

11.5 Path sandboxing#

\n

Link resolution MUST NOT produce paths outside the collection root.

\n

Rules:

\n
    \n
  • After resolving relative paths (applying ../ segments), the resulting path MUST be within the collection root directory
  • \n
  • If resolution would escape the collection root, the link MUST resolve to null and implementations MUST emit a path_traversal error
  • \n
  • This applies to all link formats: wikilinks, markdown links, and bare paths
  • \n
  • Implementations MUST normalize paths (resolve . and .. segments) before checking containment
  • \n
\n

Examples (collection rooted at /home/user/MyVault/):

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
LinkFrom fileResult
[[../../../etc/passwd]]TaskNotes/Tasks/task.mdnull + path_traversal
[[../../secrets/key]]deep/nested/file.mdnull + path_traversal
[[../task-001]]TaskNotes/Tasks/subtasks/t.mdResolves normally
\n
\n

11.6 Canonical write format#

\n

When creating new link values or changing a link target, implementations MUST use a deterministic canonical form.

\n\n

By default (links.use_markdown_format=false), the canonical write format is a simple wikilink:

\n
blockedBy:\n  - uid: "[[task-001]]"\n    reltype: FINISHTOSTART\nprojects:\n  - "[[projects/alpha]]"\n

Rules:

\n
    \n
  • Use the filename without extension as the target when the file can be identified by simple-name resolution within the appropriate scope.
  • \n
  • Use a path-qualified target (folder/name) when the simple name would be ambiguous.
  • \n
  • Do NOT include the alias component in dependency uid writes.
  • \n
  • Do NOT include the anchor component in dependency uid writes.
  • \n
  • Preserve the alias component in projects entries when the alias was provided by the user.
  • \n
  • For attachments, always write a path-qualified collection-relative target\nwith its file extension, for example [[Attachments/01K1-photo.jpg]].\nAttachment writes MUST NOT include an alias or anchor.
  • \n
\n\n

When links.use_markdown_format=true is configured (requires the obsidian-frontmatter-markdown-links Obsidian plugin), the canonical write format for link-bearing fields is a markdown link using the collection-relative path:

\n
blockedBy:\n  - uid: "[task-001](TaskNotes/Tasks/task-001.md)"\n    reltype: FINISHTOSTART\n

Round-trip preservation#

\n

When writing an existing link field and the resolved target is unchanged, implementations MUST preserve the original format when possible:

\n
    \n
  • If the user wrote [[task-001|My Task]], preserve alias for projects entries.
  • \n
  • If the user wrote a relative path, preserve relativity when possible.
  • \n
  • For blocked_by.uid, alias and anchor components MUST still be removed on canonical writes.
  • \n
  • If preservation is not possible (for example unresolved/ambiguous reconstruction), implementations MUST fall back to canonical write rules in this section.
  • \n
\n
\n

11.7 Configuration#

\n

links configuration keys (see §9.12):

\n
links:\n  extensions: [".md"]                  # Extension trial order for extensionless targets\n  use_markdown_format: false           # Write markdown links instead of wikilinks\n  unresolved_default_severity: warning # "warning" or "error"\n  update_references_on_rename: true    # Update link targets when files are renamed\n

Rules:

\n
    \n
  • extensions MUST be a non-empty list when present
  • \n
  • unresolved_default_severity MUST be "warning" or "error"
  • \n
  • update_references_on_rename=true enables rename-time link rewrite behavior (§11.9)
  • \n
  • use_markdown_format=true requires the obsidian-frontmatter-markdown-links plugin in Obsidian deployments
  • \n
\n
\n

11.8 Role-specific rules#

\n

11.8.1 projects#

\n

projects entries SHOULD be interpreted with this section's parsing/resolution rules.

\n

If a projects entry is a plain string (not a wikilink or markdown link), implementations SHOULD treat it as a bare filename or path and attempt resolution.

\n

If unresolved:

\n
    \n
  • links.unresolved_default_severity=error: validation error
  • \n
  • otherwise: SHOULD emit unresolved_link_target warning
  • \n
\n

11.8.2 blocked_by.uid#

\n

blocked_by.uid values MUST use this section's parsing/resolution rules.

\n

For dependency semantics, unresolved uid handling follows §10.2.6.\nFor unresolved-target severity, dependencies.unresolved_target_severity controls and takes precedence over links.unresolved_default_severity.

\n

The canonical write form for uid values is specified in §11.6.

\n

11.8.3 attachments#

\n

Attachment references MUST resolve to files, not directories. Canonical\nattachment targets MUST be collection-relative, path-qualified, and retain an\nexplicit file extension. This avoids ambiguous simple-name lookup, makes the\nfrontmatter portable without a media-specific extension search policy, and\npreserves the actual filename.

\n

Readers MUST accept wikilinks, Markdown links, and bare paths. They MAY accept\nsimple-name or extensionless values as non-canonical compatibility input, but\ncanonical writes MUST resolve and replace them with an explicit path and\nextension. Aliases and anchors are not part of attachment identity and MUST be\nremoved on canonical writes.

\n

The normalized resolved collection path defines attachment identity for\nduplicate detection. Implementations MUST preserve list order and MUST reject\nduplicates after path normalization. Unresolved attachment targets use the\nconfigured unresolved_link_target severity; offline-capable clients SHOULD\ndistinguish a known-but-not-locally-cached file from a genuinely unresolved\ntarget.

\n
\n

11.9 Rename and reference updates#

\n

If an implementation supports reference updates on rename (i.e. claims the rename capability):

\n
    \n
  1. It MUST update resolvable references in blocked_by.uid, projects, and attachments link fields.
  2. \n
  3. It SHOULD update links in body content.
  4. \n
  5. It SHOULD preserve the original link format when possible.
  6. \n
  7. It MUST preserve alias and anchor components where valid for the target field. For blocked_by.uid, alias and anchor are non-canonical and MUST be removed on write (§11.6).
  8. \n
  9. It MUST report unresolved or ambiguous rewrite cases.
  10. \n
\n

If reference updates are not supported, this limitation MUST be disclosed in conformance claims.

\n
\n

11.10 Validation#

\n

Link validation issues:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
CodeSeverityTrigger
invalid_link_formaterrorLink value cannot be parsed as any supported format
ambiguous_linkwarningSimple-name resolution found multiple candidates after normalization
unresolved_link_targetwarningLink target cannot be resolved to an existing file
path_traversalerrorResolved path escapes collection root
\n

unresolved_link_target severity may be promoted to error via links.unresolved_default_severity=error.\nFor blocked_by.uid, use unresolved_dependency_target severity policy from §10.2.6 instead of unresolved_link_target.

\n
\n

11.11 Examples#

\n\n
---\ntitle: Implement API\nstatus: open\ntags: [task]\nblockedBy:\n  - uid: "[[design-api]]"\n    reltype: FINISHTOSTART\n  - uid: "[[projects/infra/setup-server]]"\n    reltype: FINISHTOSTART\n    gap: P1D\nprojects:\n  - "[[projects/alpha]]"\ndateCreated: 2026-02-20T10:00:00Z\ndateModified: 2026-02-20T10:00:00Z\n---\n
\n
---\ntitle: Implement API\nstatus: open\ntags: [task]\nblockedBy:\n  - uid: "[design-api](TaskNotes/Tasks/design-api.md)"\n    reltype: FINISHTOSTART\n---\n
\n
# TaskNotes/Tasks/subtasks/task-002.md\n---\ntitle: Sub-task\nstatus: open\ntags: [task]\nblockedBy:\n  - uid: "[[../task-001]]"    # resolves to TaskNotes/Tasks/task-001.md\n    reltype: FINISHTOSTART\nprojects:\n  - "[[projects/alpha]]"      # resolves from collection root\n---\n
","text":"11.1 Purpose# This section defines link syntax, parsing, resolution, and write-format semantics for link-bearing task fields — primarily projects, blocked_by.uid, and attachments. Alignment with Obsidian and other ecosystems is informative context only; normative conformance is defined entirely by this section. Applicability: Implementations claiming profile extended (§7.3.5) MUST conform to this section for supported link-bearing roles. Implementations claiming profile materialized-occurrences (§7.3.4) MUST conform to this section for recurrence_parent links, but are not required to support unrelated extended link-bearing roles solely because of that profile. Implementations supporting the attachments role MUST conform to this section for attachment references regardless of profile. Implementations that claim neither extended nor materialized-occurrences MAY treat link-shaped strings as opaque data and are not required to implement §11 behavior. 11.2 Link formats# Implementations that conform to §11 (see §11.1 applicability) MUST support three link formats. 11.2.1 Wikilinks# [[target]] [[target|alias]] [[target#anchor]] [[target#anchor|alias]] [[folder/target]] [[./relative]] [[../parent/target]] Components: target: The file being linked to (without extension by default) alias: Display text; does not affect resolution anchor: A heading or block reference within the target path: May be absolute (from collection root) or relative (from current file) Examples in frontmatter: projects: - \"[[home-project]]\" - \"[[projects/alpha|Alpha Project]]\" blockedBy: - uid: \"[[prepare-metrics]]\" reltype: FINISHTOSTART 11.2.2 Markdown links# [text](path.md) [text](./relative.md) [text](../other/file.md) [text](path.md#anchor) The text portion is treated as an alias and does not affect resolution. Markdown links in frontmatter require the obsidian-frontmatter-markdown-links Obsidian plugin. Implementations MUST NOT write markdown-format links by default unless links.use_markdown_format=true is configured (§11.7). 11.2.3 Bare paths# ./sibling.md ../other/file.md folder/file.md Bare paths follow the same resolution rules as markdown links (relative to containing file's directory unless starting with /). 11.3 Link parsing# When a link value is read, implementations MUST parse it into a structured representation: Component Type Description raw string Original string value exactly as written target string File path or identifier (without anchor or alias) alias string? Display text if provided, otherwise null anchor string? Heading or block reference if provided, otherwise null format enum One of: wikilink, markdown, path is_relative boolean Whether target begins with ./ or ../ Parsing examples: Input target alias anchor format is_relative [[task-001]] task-001 null null wikilink false [[task-001|My Task]] task-001 My Task null wikilink false [[docs/api#auth]] docs/api null auth wikilink false [[./sibling]] ./sibling null null wikilink true [Link](file.md) file.md Link null markdown false ./other.md ./other.md null null path true 11.4 Resolution algorithm# Resolution transforms a parsed link into an absolute path (relative to collection root) pointing to the target file. Given a parsed link and the path of the source file containing it: Step 1: Parse the link into components (target, format, is_relative)# Step 2: Route by format# If format is markdown or path: If target starts with /, resolve from collection root (strip the leading /) Otherwise, resolve relative to the source file's directory (standard markdown behavior) Example: link [Docs](docs/api.md) in notes/meeting.md resolves to notes/docs/api.md If format is wikilink: If target starts with ./ or ../, resolve relative to the source file's directory If target starts with /, resolve from collection root (strip the leading /) If target contains / (and is not relative), resolve from collection root Example: [[docs/api]] resolves to docs/api If simple name (no /, no ./ or ../): proceed to Step 3 Step 3: Simple-name resolution (wikilinks only)# For simple wikilink names (no path separator): Define the search scope: For blocked_by.uid: scope to files matching task_detection (task files only) For projects: scope to all markdown files in the collection unless narrowed by explicit configuration For attachments: scope to all non-directory files in the collection ID match pass: search scoped files for semantic role id (§2.6.5) equal to the name. Implementations MAY treat literal frontmatter key id as compatibility input when semantic mapping for id is unavailable. Equality MUST be exact string equality. If exactly one match: resolve to that file If multiple matches: fail with ambiguous_link Filename match pass: if no ID match, search scoped markdown files by filename (without extension). Implementations MUST deduplicate normalized candidate paths before final selection. If exactly one filename candidate remains after normalization and extension handling, resolve to that file. If multiple filename candidates remain, resolve to null and emit ambiguous_link. Callers SHOULD use a path-qualified or relative target to disambiguate. Step 4: Extension handling# If the target has no extension, implementations SHOULD try configured extensions in order. Default extension order: [\".md\"]. Example: [[readme]] tries readme.md, readme.mdx, etc. Step 5: Path traversal check# After resolution and normalization, if the resolved path would escape the collection root, abort with path_traversal. See §11.5. Step 6: Return result# The normalized collection-relative path if found null if no matching file exists Resolution examples# Given collection structure: / ├── TaskNotes/ │ ├── Tasks/ │ │ ├── task-001.md │ │ └── subtasks/ │ │ └── task-002.md ├── notes/ │ └── meeting.md └── projects/ └── alpha.md Resolution from TaskNotes/Tasks/subtasks/task-002.md: Link value Resolved path Notes [[task-001]] TaskNotes/Tasks/task-001.md Simple-name search [[../task-001]] TaskNotes/Tasks/task-001.md Relative wikilink [[./task-003]] TaskNotes/Tasks/subtasks/task-003.md Relative (may not exist) [[notes/meeting]] notes/meeting.md Absolute from root [[alpha]] projects/alpha.md Simple-name search (projects scope) [link](../task-001.md) TaskNotes/Tasks/task-001.md Markdown, relative ../task-001.md TaskNotes/Tasks/task-001.md Bare path, relative 11.5 Path sandboxing# Link resolution MUST NOT produce paths outside the collection root. Rules: After resolving relative paths (applying ../ segments), the resulting path MUST be within the collection root directory If resolution would escape the collection root, the link MUST resolve to null and implementations MUST emit a path_traversal error This applies to all link formats: wikilinks, markdown links, and bare paths Implementations MUST normalize paths (resolve . and .. segments) before checking containment Examples (collection rooted at /home/user/MyVault/): Link From file Result [[../../../etc/passwd]] TaskNotes/Tasks/task.md null + path_traversal [[../../secrets/key]] deep/nested/file.md null + path_traversal [[../task-001]] TaskNotes/Tasks/subtasks/t.md Resolves normally 11.6 Canonical write format# When creating new link values or changing a link target, implementations MUST use a deterministic canonical form. Default (wikilink format)# By default (links.use_markdown_format=false), the canonical write format is a simple wikilink: blockedBy: - uid: \"[[task-001]]\" reltype: FINISHTOSTART projects: - \"[[projects/alpha]]\" Rules: Use the filename without extension as the target when the file can be identified by simple-name resolution within the appropriate scope. Use a path-qualified target (folder/name) when the simple name would be ambiguous. Do NOT include the alias component in dependency uid writes. Do NOT include the anchor component in dependency uid writes. Preserve the alias component in projects entries when the alias was provided by the user. For attachments, always write a path-qualified collection-relative target with its file extension, for example [[Attachments/01K1-photo.jpg]]. Attachment writes MUST NOT include an alias or anchor. Markdown link format (links.use_markdown_format=true)# When links.use_markdown_format=true is configured (requires the obsidian-frontmatter-markdown-links Obsidian plugin), the canonical write format for link-bearing fields is a markdown link using the collection-relative path: blockedBy: - uid: \"[task-001](TaskNotes/Tasks/task-001.md)\" reltype: FINISHTOSTART Round-trip preservation# When writing an existing link field and the resolved target is unchanged, implementations MUST preserve the original format when possible: If the user wrote [[task-001|My Task]], preserve alias for projects entries. If the user wrote a relative path, preserve relativity when possible. For blocked_by.uid, alias and anchor components MUST still be removed on canonical writes. If preservation is not possible (for example unresolved/ambiguous reconstruction), implementations MUST fall back to canonical write rules in this section. 11.7 Configuration# links configuration keys (see §9.12): links: extensions: [\".md\"] # Extension trial order for extensionless targets use_markdown_format: false # Write markdown links instead of wikilinks unresolved_default_severity: warning # \"warning\" or \"error\" update_references_on_rename: true # Update link targets when files are renamed Rules: extensions MUST be a non-empty list when present unresolved_default_severity MUST be \"warning\" or \"error\" update_references_on_rename=true enables rename-time link rewrite behavior (§11.9) use_markdown_format=true requires the obsidian-frontmatter-markdown-links plugin in Obsidian deployments 11.8 Role-specific rules# 11.8.1 projects# projects entries SHOULD be interpreted with this section's parsing/resolution rules. If a projects entry is a plain string (not a wikilink or markdown link), implementations SHOULD treat it as a bare filename or path and attempt resolution. If unresolved: links.unresolved_default_severity=error: validation error otherwise: SHOULD emit unresolved_link_target warning 11.8.2 blocked_by.uid# blocked_by.uid values MUST use this section's parsing/resolution rules. For dependency semantics, unresolved uid handling follows §10.2.6. For unresolved-target severity, dependencies.unresolved_target_severity controls and takes precedence over links.unresolved_default_severity. The canonical write form for uid values is specified in §11.6. 11.8.3 attachments# Attachment references MUST resolve to files, not directories. Canonical attachment targets MUST be collection-relative, path-qualified, and retain an explicit file extension. This avoids ambiguous simple-name lookup, makes the frontmatter portable without a media-specific extension search policy, and preserves the actual filename. Readers MUST accept wikilinks, Markdown links, and bare paths. They MAY accept simple-name or extensionless values as non-canonical compatibility input, but canonical writes MUST resolve and replace them with an explicit path and extension. Aliases and anchors are not part of attachment identity and MUST be removed on canonical writes. The normalized resolved collection path defines attachment identity for duplicate detection. Implementations MUST preserve list order and MUST reject duplicates after path normalization. Unresolved attachment targets use the configured unresolved_link_target severity; offline-capable clients SHOULD distinguish a known-but-not-locally-cached file from a genuinely unresolved target. 11.9 Rename and reference updates# If an implementation supports reference updates on rename (i.e. claims the rename capability): It MUST update resolvable references in blocked_by.uid, projects, and attachments link fields. It SHOULD update links in body content. It SHOULD preserve the original link format when possible. It MUST preserve alias and anchor components where valid for the target field. For blocked_by.uid, alias and anchor are non-canonical and MUST be removed on write (§11.6). It MUST report unresolved or ambiguous rewrite cases. If reference updates are not supported, this limitation MUST be disclosed in conformance claims. 11.10 Validation# Link validation issues: Code Severity Trigger invalid_link_format error Link value cannot be parsed as any supported format ambiguous_link warning Simple-name resolution found multiple candidates after normalization unresolved_link_target warning Link target cannot be resolved to an existing file path_traversal error Resolved path escapes collection root unresolved_link_target severity may be promoted to error via links.unresolved_default_severity=error. For blocked_by.uid, use unresolved_dependency_target severity policy from §10.2.6 instead of unresolved_link_target. 11.11 Examples# Dependency with wikilink (default)# --- title: Implement API status: open tags: [task] blockedBy: - uid: \"[[design-api]]\" reltype: FINISHTOSTART - uid: \"[[projects/infra/setup-server]]\" reltype: FINISHTOSTART gap: P1D projects: - \"[[projects/alpha]]\" dateCreated: 2026-02-20T10:00:00Z dateModified: 2026-02-20T10:00:00Z --- Dependency with markdown links (links.use_markdown_format=true)# --- title: Implement API status: open tags: [task] blockedBy: - uid: \"[design-api](TaskNotes/Tasks/design-api.md)\" reltype: FINISHTOSTART --- Relative links from nested task# # TaskNotes/Tasks/subtasks/task-002.md --- title: Sub-task status: open tags: [task] blockedBy: - uid: \"[[../task-001]]\" # resolves to TaskNotes/Tasks/task-001.md reltype: FINISHTOSTART projects: - \"[[projects/alpha]]\" # resolves from collection root ---"},{"route":"/developers/specification/12-mdbase-v0.3-binding/","title":"12. mdbase v0.3 Data-Contract Binding","description":"Status: Draft","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:12-mdbase-v0.3-binding.md","namespace":"specification","relativePath":"12-mdbase-v0.3-binding.md","raw":"# 12. mdbase v0.3 Data-Contract Binding\n\n**Status:** Draft\n\n**Record contract:** `tasknotes.task` `0.3.0-rc.3`\n\n**Event contract:** `tasknotes.task.completed` `1.0.0`\n\n**Target:** mdbase `0.3.x`\n\n## 12.1 Purpose\n\nThis chapter defines how a TaskNotes task model is exposed through mdbase\nwithout coupling TaskNotes to one record type or one application's private\nextension.\n\nThe binding has three deliberately separate parts:\n\n1. the `tasknotes.task` data contract defines the portable task view;\n2. an mdbase type's `implements` entry maps that view to its own frontmatter\n fields and supplies TaskNotes behavior; and\n3. the rest of the type file continues to define that type's storage,\n matching, defaults, lifecycle, links, and paths.\n\nThe normative artifacts are:\n\n- [`mdbase/tasknotes.task.md`](mdbase/tasknotes.task.md), the record contract;\n- [`schemas/tasknotes-task.schema.json`](schemas/tasknotes-task.schema.json),\n the projected task-view schema; and\n- [`schemas/tasknotes-task-binding.schema.json`](schemas/tasknotes-task-binding.schema.json),\n the implementation binding schema.\n\nThe optional event-interoperability artifacts are:\n\n- [`mdbase/tasknotes.task.completed.md`](mdbase/tasknotes.task.completed.md),\n the event contract; and\n- [`schemas/tasknotes-task-completed.schema.json`](schemas/tasknotes-task-completed.schema.json),\n its event-data schema.\n\n## 12.2 The mental model\n\nA contract is not another record type. It is a view that several record types\ncan implement and several applications can consume.\n\n```text\npersonal_task ─┐\nwork_task ─────┼─ implements tasknotes.task 0.3.0-rc.3 ── TaskNotes\nissue_task ────┘ ├─ automation\n └─ another task app\n```\n\nReading or listing through the contract uses the union of all implementing\ntypes. Creating a task is different: the caller MUST choose one exact target\ntype because the contract does not choose storage, paths, or lifecycle policy.\n\nThe contract version is an exact semantic version. For this draft it is also\nthe tasknotes-spec version whose task semantics the contract exposes. There is\nno independent `x-tasknotes.version` or `spec_version` mirror.\n\nRecord types use `implements` because they adapt persisted fields and semantic\nbindings to the `tasknotes.task` record contract. Event sources do not use a\ntype file. A TaskNotes application instead registers an event-source\ndeclaration for `tasknotes.task.completed` with an active mdbase\ninteroperability bridge.\n\n## 12.3 Layering\n\nAn implementing type MUST keep these responsibilities in their canonical\nlocations:\n\n| Information | mdbase v0.3 location |\n|---|---|\n| Persisted frontmatter shape, required fields, enum values, formats | `schema` |\n| Type identification | `match` |\n| Display field, defaults, links, uniqueness, and path generation | `collection` |\n| Managed create/update values | `lifecycle` |\n| Contract identity and custom field names | `implements[].contract`, `version`, and `fields` |\n| TaskNotes semantic behavior | `implements[].binding` |\n\nTaskNotes metadata MUST NOT be encoded as custom JSON Schema keywords.\n`x-tasknotes` MUST NOT be used for contract discovery, field mapping,\nconformance, or authorization.\n\n## 12.4 Declaring an implementation\n\nAn mdbase TaskNotes type declares one implementation:\n\n```yaml\nimplements:\n - contract: tasknotes.task\n version: 0.3.0-rc.3\n fields:\n title: summary\n status: state\n priority: importance\n dateCreated: created_at\n binding:\n # TaskNotes behavior; abbreviated here\n profiles: [core-lite]\n capabilities: []\n title:\n storage: frontmatter\n filename_format: title\n status:\n values: [todo, doing, done]\n default: todo\n completed_values: [done]\n definitions: []\n priority:\n values: [normal]\n default: normal\n definitions: []\n```\n\nThe contract file identified by the exact `contract` and `version` MUST exist\nin the collection contract registry. The `binding` MUST validate against that\ncontract's `binding_schema`.\n\nEach type MUST declare at most one implementation of one exact contract\nidentity. A type may implement several different contracts.\n\n## 12.5 Portable fields\n\n`fields` maps contract field paths to record field paths. Consumers access\ncontract fields and MUST NOT assume that their names are also frontmatter\nproperty names.\n\n```yaml\nfields:\n title: summary\n status: state\n blockedBy: dependencies\n attachments: files\n```\n\nEvery unconditionally required contract field MUST be mapped. Every mapped\ncontract field and record field MUST exist in its respective JSON Schema.\n\nThe contract view contains only mapped fields. It does not expose unmapped\nfrontmatter or the Markdown body. A consumer that requires either needs\nseparate, explicit whole-record access.\n\n`title` is optional in the portable schema because TaskNotes permits filename\ntitle storage. When `binding.title.storage` is `filename`, consumers derive\nthe effective title from the record identity/path rules in §9.13 instead of\nexpecting a projected frontmatter value.\n\nThe camel-case contract field names are stable portable identifiers. Their\nsnake-case tasknotes-spec counterparts include:\n\n| Contract field | tasknotes-spec role |\n|---|---|\n| `timeEstimate` | `time_estimate` |\n| `completedDate` | `completed_date` |\n| `dateCreated` | `date_created` |\n| `dateModified` | `date_modified` |\n| `recurrenceAnchor` | `recurrence_anchor` |\n| `completeInstances` | `complete_instances` |\n| `skippedInstances` | `skipped_instances` |\n| `recurrenceParent` | `recurrence_parent` |\n| `occurrenceDate` | `occurrence_date` |\n| `occurrenceMaterialization` | `occurrence_materialization` |\n| `occurrenceNextTrigger` | `occurrence_next_trigger` |\n| `occurrenceTemplate` | `occurrence_template` |\n| `occurrencePastHorizon` | `occurrence_past_horizon` |\n| `occurrenceFutureHorizon` | `occurrence_future_horizon` |\n| `timeEntries` | `time_entries` |\n| `blockedBy` | `blocked_by` |\n| `attachments` | `attachments` |\n\n## 12.6 Semantic profiles and capabilities\n\n`binding.profiles` and `binding.capabilities` describe semantics that records\nof this implementation may use:\n\n```yaml\nbinding:\n profiles: [core-lite, recurrence, materialized-occurrences]\n capabilities:\n - dependencies\n - reminders\n - attachments\n - links\n - time-tracking\n - materialized-occurrences\n - archive\n```\n\nThese are properties of the implementation, not claims that every consuming\napplication supports them. Before mutating a governed field, a consumer SHOULD\nverify its own corresponding capability. It may still perform unrelated\noperations when it preserves unsupported fields and invariants.\n\n## 12.7 Status and priority semantics\n\nThe implementing type schema defines the legal persisted values of the mapped\nfields. The binding gives those values TaskNotes meaning:\n\n```yaml\nbinding:\n status:\n values: [todo, doing, done, cancelled]\n default: todo\n completed_values: [done]\n skipped_values: [cancelled]\n default_skipped: cancelled\n definitions: []\n priority:\n values: [low, normal, high]\n default: normal\n definitions: []\n```\n\nThe following consistency rules apply:\n\n- binding values MUST equal the mapped type-schema enum values;\n- defaults MUST equal mapped `collection.read_defaults` values when present;\n- completed and skipped values MUST be members of `status.values`;\n- `default_skipped` MUST be a skipped value;\n- completed and skipped values MUST NOT overlap for materialized occurrences;\n and\n- definition semantics MUST agree with completed/skipped membership.\n\nStatus and priority labels, colors, and icons are presentation hints. Status\ncycle, completion, skipping, auto-archive, and priority weight are semantic.\n\n## 12.8 Title, recurrence, links, and operations\n\nThe remaining binding sections project the effective TaskNotes behavior\ndefined elsewhere in this specification:\n\n- `title` follows §9.13 and MUST agree with `collection.display` and\n `collection.path`;\n- `recurrence` follows §4;\n- `occurrences` follows §2.6.6, §4.18, §5.20, and §9.17;\n- `links` follows §11;\n- attachment membership is the portable `attachments` contract field; binary\n MIME type, digest, byte size, revision, and timestamps remain authoritative\n in mdbase file descriptors and are not projected into task frontmatter;\n- `archive` follows §5.12;\n- `time_tracking` follows §5.19 and §9.16;\n- `templating` follows §5.3.5 and §9.14; and\n- optional `nlp` triggers follow §9.18.\n\nArchive always operates on the portable `tags` contract field, so the binding\ndoes not repeat a record-specific `tags_field`. The implementation's `fields`\nmap determines the actual frontmatter property.\n\nApplication-local notification preferences and generator bookkeeping MUST NOT\nbe placed in the binding.\n\n## 12.9 Multiple implementations\n\nA collection may contain any number of types implementing\n`tasknotes.task 0.3.0-rc.3`. TaskNotes-aware readers MUST:\n\n1. resolve the exact local contract;\n2. enumerate every implementation in canonical type-name order;\n3. read each matching record through that implementation's projected view;\n4. validate the projected view; and\n5. retain the concrete type identity for updates.\n\nImplementations MUST NOT merge type schemas into one synthetic schema. A record\nis validated by its concrete type and then by its projected contract view.\n\nWhen an approval, cache, or external protocol pins an implementation set, it\nMUST pin the exact contract digest and sorted implementation descriptors,\nincluding each implementation digest. A newly installed type is therefore not\nsilently added to an existing approval.\n\nCreation MUST name one concrete implementing type. If no type is selected,\ncreation fails as ambiguous.\n\n## 12.10 Task-completed event\n\nAn event source that claims `tasknotes.task.completed 1.0.0` MUST emit one\nCloudEvents structured event for each observed transition from a\nnon-completed status to a completed status. Its `data` contains only:\n\n- `task_id`, using the stable TaskNotes ID when present and otherwise the\n normalized path;\n- `task_path`;\n- the current `title` and completed `status`; and\n- `completed_at`, the instant when TaskNotes observed the transition.\n\nThe event source MUST use the mdbase event/action interoperability profile\n`0.1`, pin the exact event-contract digest, and preserve any correlation and\ncausation identifiers supplied by the mutation context. It MUST NOT include a\ncomplete task record merely because one is locally available. An authorized\nconsumer can retrieve current state separately, avoiding stale snapshots and\nunnecessary disclosure.\n\nContract compatibility and bridge authorization are independent. Installing\nTaskNotes or resolving this contract does not grant permission to publish or\nconsume the event.\n\n## 12.11 Precedence and consistency\n\nThe complete implementation is self-describing:\n\n1. the contract schema is authoritative for the portable projected view;\n2. the type schema is authoritative for persisted value shapes;\n3. `collection` is authoritative for generic mdbase behavior;\n4. `lifecycle` is authoritative for generic managed writes; and\n5. `implements[].binding` is authoritative for TaskNotes semantics.\n\nWhere values intentionally mirror each other, producers MUST keep them equal.\nA TaskNotes-aware consumer MUST report a configuration error instead of\nsilently choosing between contradictory values.\n\n## 12.12 Safe writes\n\nTaskNotes-aware consumers MUST preserve:\n\n- unknown frontmatter properties unless explicit replacement or migration was\n requested;\n- Markdown body content unless an operation explicitly replaces it;\n- fields governed by unsupported capabilities; and\n- unrelated type metadata and implementations.\n\nGeneric mdbase operations are safe only when they preserve the same data.\nCompletion, recurrence mutation, occurrence materialization, dependency\nupdates, time tracking, archive, and other domain operations MUST follow the\nTaskNotes semantics referenced by the binding.\n\n## 12.13 Complete custom-field example\n\n```yaml\n---\nkind: mdbase.type\nname: work_task\nversion: 1\nschema:\n dialect: json-schema-2020-12\n value:\n type: object\n additionalProperties: true\n required: [summary, state, created_at]\n properties:\n summary: { type: string, minLength: 1 }\n state: { enum: [todo, doing, done, cancelled] }\n importance: { enum: [low, normal, high] }\n created_at: { type: string, format: date-time }\n tags:\n type: array\n items: { type: string }\ncollection:\n display:\n name_field: summary\n read_defaults:\n state: todo\n importance: normal\nlifecycle:\n on_create:\n set:\n created_at: { now: true }\nimplements:\n - contract: tasknotes.task\n version: 0.3.0-rc.3\n fields:\n title: summary\n status: state\n priority: importance\n dateCreated: created_at\n tags: tags\n binding:\n profiles: [core-lite]\n capabilities: [archive]\n title:\n storage: frontmatter\n filename_format: title\n status:\n values: [todo, doing, done, cancelled]\n default: todo\n completed_values: [done]\n skipped_values: [cancelled]\n default_skipped: cancelled\n definitions: []\n priority:\n values: [low, normal, high]\n default: normal\n definitions: []\n recurrence:\n syntax: tasknotes\n maintain_due_date_offset: false\n reset_body_checkboxes: false\n occurrences:\n identity_roles: [recurrenceParent, occurrenceDate]\n default_materialization: manual\n default_next_trigger: completion\n links:\n accepted_formats: [wikilink, markdown]\n write_format: wikilink\n archive:\n archived_tag: archived\n move_on_archive: false\n time_tracking:\n auto_stop_on_complete: true\n templating:\n enabled: false\n occurrence_enabled: false\n---\n```\n","aliases":["/spec/12-mdbase-v0.3-binding/"],"toc":[{"level":2,"id":"121-purpose","text":"12.1 Purpose"},{"level":2,"id":"122-the-mental-model","text":"12.2 The mental model"},{"level":2,"id":"123-layering","text":"12.3 Layering"},{"level":2,"id":"124-declaring-an-implementation","text":"12.4 Declaring an implementation"},{"level":2,"id":"125-portable-fields","text":"12.5 Portable fields"},{"level":2,"id":"126-semantic-profiles-and-capabilities","text":"12.6 Semantic profiles and capabilities"},{"level":2,"id":"127-status-and-priority-semantics","text":"12.7 Status and priority semantics"},{"level":2,"id":"128-title-recurrence-links-and-operations","text":"12.8 Title, recurrence, links, and operations"},{"level":2,"id":"129-multiple-implementations","text":"12.9 Multiple implementations"},{"level":2,"id":"1210-task-completed-event","text":"12.10 Task-completed event"},{"level":2,"id":"1211-precedence-and-consistency","text":"12.11 Precedence and consistency"},{"level":2,"id":"1212-safe-writes","text":"12.12 Safe writes"},{"level":2,"id":"1213-complete-custom-field-example","text":"12.13 Complete custom-field example"}],"html":"

Status: Draft

\n

Record contract: tasknotes.task 0.3.0-rc.3

\n

Event contract: tasknotes.task.completed 1.0.0

\n

Target: mdbase 0.3.x

\n

12.1 Purpose#

\n

This chapter defines how a TaskNotes task model is exposed through mdbase\nwithout coupling TaskNotes to one record type or one application's private\nextension.

\n

The binding has three deliberately separate parts:

\n
    \n
  1. the tasknotes.task data contract defines the portable task view;
  2. \n
  3. an mdbase type's implements entry maps that view to its own frontmatter\nfields and supplies TaskNotes behavior; and
  4. \n
  5. the rest of the type file continues to define that type's storage,\nmatching, defaults, lifecycle, links, and paths.
  6. \n
\n

The normative artifacts are:

\n\n

The optional event-interoperability artifacts are:

\n\n

12.2 The mental model#

\n

A contract is not another record type. It is a view that several record types\ncan implement and several applications can consume.

\n
personal_task ─┐\nwork_task ─────┼─ implements tasknotes.task 0.3.0-rc.3 ── TaskNotes\nissue_task ────┘                                  ├─ automation\n                                                  └─ another task app\n

Reading or listing through the contract uses the union of all implementing\ntypes. Creating a task is different: the caller MUST choose one exact target\ntype because the contract does not choose storage, paths, or lifecycle policy.

\n

The contract version is an exact semantic version. For this draft it is also\nthe tasknotes-spec version whose task semantics the contract exposes. There is\nno independent x-tasknotes.version or spec_version mirror.

\n

Record types use implements because they adapt persisted fields and semantic\nbindings to the tasknotes.task record contract. Event sources do not use a\ntype file. A TaskNotes application instead registers an event-source\ndeclaration for tasknotes.task.completed with an active mdbase\ninteroperability bridge.

\n

12.3 Layering#

\n

An implementing type MUST keep these responsibilities in their canonical\nlocations:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Informationmdbase v0.3 location
Persisted frontmatter shape, required fields, enum values, formatsschema
Type identificationmatch
Display field, defaults, links, uniqueness, and path generationcollection
Managed create/update valueslifecycle
Contract identity and custom field namesimplements[].contract, version, and fields
TaskNotes semantic behaviorimplements[].binding
\n

TaskNotes metadata MUST NOT be encoded as custom JSON Schema keywords.\nx-tasknotes MUST NOT be used for contract discovery, field mapping,\nconformance, or authorization.

\n

12.4 Declaring an implementation#

\n

An mdbase TaskNotes type declares one implementation:

\n
implements:\n  - contract: tasknotes.task\n    version: 0.3.0-rc.3\n    fields:\n      title: summary\n      status: state\n      priority: importance\n      dateCreated: created_at\n    binding:\n      # TaskNotes behavior; abbreviated here\n      profiles: [core-lite]\n      capabilities: []\n      title:\n        storage: frontmatter\n        filename_format: title\n      status:\n        values: [todo, doing, done]\n        default: todo\n        completed_values: [done]\n        definitions: []\n      priority:\n        values: [normal]\n        default: normal\n        definitions: []\n

The contract file identified by the exact contract and version MUST exist\nin the collection contract registry. The binding MUST validate against that\ncontract's binding_schema.

\n

Each type MUST declare at most one implementation of one exact contract\nidentity. A type may implement several different contracts.

\n

12.5 Portable fields#

\n

fields maps contract field paths to record field paths. Consumers access\ncontract fields and MUST NOT assume that their names are also frontmatter\nproperty names.

\n
fields:\n  title: summary\n  status: state\n  blockedBy: dependencies\n  attachments: files\n

Every unconditionally required contract field MUST be mapped. Every mapped\ncontract field and record field MUST exist in its respective JSON Schema.

\n

The contract view contains only mapped fields. It does not expose unmapped\nfrontmatter or the Markdown body. A consumer that requires either needs\nseparate, explicit whole-record access.

\n

title is optional in the portable schema because TaskNotes permits filename\ntitle storage. When binding.title.storage is filename, consumers derive\nthe effective title from the record identity/path rules in §9.13 instead of\nexpecting a projected frontmatter value.

\n

The camel-case contract field names are stable portable identifiers. Their\nsnake-case tasknotes-spec counterparts include:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Contract fieldtasknotes-spec role
timeEstimatetime_estimate
completedDatecompleted_date
dateCreateddate_created
dateModifieddate_modified
recurrenceAnchorrecurrence_anchor
completeInstancescomplete_instances
skippedInstancesskipped_instances
recurrenceParentrecurrence_parent
occurrenceDateoccurrence_date
occurrenceMaterializationoccurrence_materialization
occurrenceNextTriggeroccurrence_next_trigger
occurrenceTemplateoccurrence_template
occurrencePastHorizonoccurrence_past_horizon
occurrenceFutureHorizonoccurrence_future_horizon
timeEntriestime_entries
blockedByblocked_by
attachmentsattachments
\n

12.6 Semantic profiles and capabilities#

\n

binding.profiles and binding.capabilities describe semantics that records\nof this implementation may use:

\n
binding:\n  profiles: [core-lite, recurrence, materialized-occurrences]\n  capabilities:\n    - dependencies\n    - reminders\n    - attachments\n    - links\n    - time-tracking\n    - materialized-occurrences\n    - archive\n

These are properties of the implementation, not claims that every consuming\napplication supports them. Before mutating a governed field, a consumer SHOULD\nverify its own corresponding capability. It may still perform unrelated\noperations when it preserves unsupported fields and invariants.

\n

12.7 Status and priority semantics#

\n

The implementing type schema defines the legal persisted values of the mapped\nfields. The binding gives those values TaskNotes meaning:

\n
binding:\n  status:\n    values: [todo, doing, done, cancelled]\n    default: todo\n    completed_values: [done]\n    skipped_values: [cancelled]\n    default_skipped: cancelled\n    definitions: []\n  priority:\n    values: [low, normal, high]\n    default: normal\n    definitions: []\n

The following consistency rules apply:

\n
    \n
  • binding values MUST equal the mapped type-schema enum values;
  • \n
  • defaults MUST equal mapped collection.read_defaults values when present;
  • \n
  • completed and skipped values MUST be members of status.values;
  • \n
  • default_skipped MUST be a skipped value;
  • \n
  • completed and skipped values MUST NOT overlap for materialized occurrences;\nand
  • \n
  • definition semantics MUST agree with completed/skipped membership.
  • \n
\n

Status and priority labels, colors, and icons are presentation hints. Status\ncycle, completion, skipping, auto-archive, and priority weight are semantic.

\n\n

The remaining binding sections project the effective TaskNotes behavior\ndefined elsewhere in this specification:

\n
    \n
  • title follows §9.13 and MUST agree with collection.display and\ncollection.path;
  • \n
  • recurrence follows §4;
  • \n
  • occurrences follows §2.6.6, §4.18, §5.20, and §9.17;
  • \n
  • links follows §11;
  • \n
  • attachment membership is the portable attachments contract field; binary\nMIME type, digest, byte size, revision, and timestamps remain authoritative\nin mdbase file descriptors and are not projected into task frontmatter;
  • \n
  • archive follows §5.12;
  • \n
  • time_tracking follows §5.19 and §9.16;
  • \n
  • templating follows §5.3.5 and §9.14; and
  • \n
  • optional nlp triggers follow §9.18.
  • \n
\n

Archive always operates on the portable tags contract field, so the binding\ndoes not repeat a record-specific tags_field. The implementation's fields\nmap determines the actual frontmatter property.

\n

Application-local notification preferences and generator bookkeeping MUST NOT\nbe placed in the binding.

\n

12.9 Multiple implementations#

\n

A collection may contain any number of types implementing\ntasknotes.task 0.3.0-rc.3. TaskNotes-aware readers MUST:

\n
    \n
  1. resolve the exact local contract;
  2. \n
  3. enumerate every implementation in canonical type-name order;
  4. \n
  5. read each matching record through that implementation's projected view;
  6. \n
  7. validate the projected view; and
  8. \n
  9. retain the concrete type identity for updates.
  10. \n
\n

Implementations MUST NOT merge type schemas into one synthetic schema. A record\nis validated by its concrete type and then by its projected contract view.

\n

When an approval, cache, or external protocol pins an implementation set, it\nMUST pin the exact contract digest and sorted implementation descriptors,\nincluding each implementation digest. A newly installed type is therefore not\nsilently added to an existing approval.

\n

Creation MUST name one concrete implementing type. If no type is selected,\ncreation fails as ambiguous.

\n

12.10 Task-completed event#

\n

An event source that claims tasknotes.task.completed 1.0.0 MUST emit one\nCloudEvents structured event for each observed transition from a\nnon-completed status to a completed status. Its data contains only:

\n
    \n
  • task_id, using the stable TaskNotes ID when present and otherwise the\nnormalized path;
  • \n
  • task_path;
  • \n
  • the current title and completed status; and
  • \n
  • completed_at, the instant when TaskNotes observed the transition.
  • \n
\n

The event source MUST use the mdbase event/action interoperability profile\n0.1, pin the exact event-contract digest, and preserve any correlation and\ncausation identifiers supplied by the mutation context. It MUST NOT include a\ncomplete task record merely because one is locally available. An authorized\nconsumer can retrieve current state separately, avoiding stale snapshots and\nunnecessary disclosure.

\n

Contract compatibility and bridge authorization are independent. Installing\nTaskNotes or resolving this contract does not grant permission to publish or\nconsume the event.

\n

12.11 Precedence and consistency#

\n

The complete implementation is self-describing:

\n
    \n
  1. the contract schema is authoritative for the portable projected view;
  2. \n
  3. the type schema is authoritative for persisted value shapes;
  4. \n
  5. collection is authoritative for generic mdbase behavior;
  6. \n
  7. lifecycle is authoritative for generic managed writes; and
  8. \n
  9. implements[].binding is authoritative for TaskNotes semantics.
  10. \n
\n

Where values intentionally mirror each other, producers MUST keep them equal.\nA TaskNotes-aware consumer MUST report a configuration error instead of\nsilently choosing between contradictory values.

\n

12.12 Safe writes#

\n

TaskNotes-aware consumers MUST preserve:

\n
    \n
  • unknown frontmatter properties unless explicit replacement or migration was\nrequested;
  • \n
  • Markdown body content unless an operation explicitly replaces it;
  • \n
  • fields governed by unsupported capabilities; and
  • \n
  • unrelated type metadata and implementations.
  • \n
\n

Generic mdbase operations are safe only when they preserve the same data.\nCompletion, recurrence mutation, occurrence materialization, dependency\nupdates, time tracking, archive, and other domain operations MUST follow the\nTaskNotes semantics referenced by the binding.

\n

12.13 Complete custom-field example#

\n
---\nkind: mdbase.type\nname: work_task\nversion: 1\nschema:\n  dialect: json-schema-2020-12\n  value:\n    type: object\n    additionalProperties: true\n    required: [summary, state, created_at]\n    properties:\n      summary: { type: string, minLength: 1 }\n      state: { enum: [todo, doing, done, cancelled] }\n      importance: { enum: [low, normal, high] }\n      created_at: { type: string, format: date-time }\n      tags:\n        type: array\n        items: { type: string }\ncollection:\n  display:\n    name_field: summary\n  read_defaults:\n    state: todo\n    importance: normal\nlifecycle:\n  on_create:\n    set:\n      created_at: { now: true }\nimplements:\n  - contract: tasknotes.task\n    version: 0.3.0-rc.3\n    fields:\n      title: summary\n      status: state\n      priority: importance\n      dateCreated: created_at\n      tags: tags\n    binding:\n      profiles: [core-lite]\n      capabilities: [archive]\n      title:\n        storage: frontmatter\n        filename_format: title\n      status:\n        values: [todo, doing, done, cancelled]\n        default: todo\n        completed_values: [done]\n        skipped_values: [cancelled]\n        default_skipped: cancelled\n        definitions: []\n      priority:\n        values: [low, normal, high]\n        default: normal\n        definitions: []\n      recurrence:\n        syntax: tasknotes\n        maintain_due_date_offset: false\n        reset_body_checkboxes: false\n      occurrences:\n        identity_roles: [recurrenceParent, occurrenceDate]\n        default_materialization: manual\n        default_next_trigger: completion\n      links:\n        accepted_formats: [wikilink, markdown]\n        write_format: wikilink\n      archive:\n        archived_tag: archived\n        move_on_archive: false\n      time_tracking:\n        auto_stop_on_complete: true\n      templating:\n        enabled: false\n        occurrence_enabled: false\n---\n
","text":"Status: Draft Record contract: tasknotes.task 0.3.0-rc.3 Event contract: tasknotes.task.completed 1.0.0 Target: mdbase 0.3.x 12.1 Purpose# This chapter defines how a TaskNotes task model is exposed through mdbase without coupling TaskNotes to one record type or one application's private extension. The binding has three deliberately separate parts: the tasknotes.task data contract defines the portable task view; an mdbase type's implements entry maps that view to its own frontmatter fields and supplies TaskNotes behavior; and the rest of the type file continues to define that type's storage, matching, defaults, lifecycle, links, and paths. The normative artifacts are: mdbase/tasknotes.task.md, the record contract; schemas/tasknotes-task.schema.json, the projected task-view schema; and schemas/tasknotes-task-binding.schema.json, the implementation binding schema. The optional event-interoperability artifacts are: mdbase/tasknotes.task.completed.md, the event contract; and schemas/tasknotes-task-completed.schema.json, its event-data schema. 12.2 The mental model# A contract is not another record type. It is a view that several record types can implement and several applications can consume. personal_task ─┐ work_task ─────┼─ implements tasknotes.task 0.3.0-rc.3 ── TaskNotes issue_task ────┘ ├─ automation └─ another task app Reading or listing through the contract uses the union of all implementing types. Creating a task is different: the caller MUST choose one exact target type because the contract does not choose storage, paths, or lifecycle policy. The contract version is an exact semantic version. For this draft it is also the tasknotes-spec version whose task semantics the contract exposes. There is no independent x-tasknotes.version or spec_version mirror. Record types use implements because they adapt persisted fields and semantic bindings to the tasknotes.task record contract. Event sources do not use a type file. A TaskNotes application instead registers an event-source declaration for tasknotes.task.completed with an active mdbase interoperability bridge. 12.3 Layering# An implementing type MUST keep these responsibilities in their canonical locations: Information mdbase v0.3 location Persisted frontmatter shape, required fields, enum values, formats schema Type identification match Display field, defaults, links, uniqueness, and path generation collection Managed create/update values lifecycle Contract identity and custom field names implements[].contract, version, and fields TaskNotes semantic behavior implements[].binding TaskNotes metadata MUST NOT be encoded as custom JSON Schema keywords. x-tasknotes MUST NOT be used for contract discovery, field mapping, conformance, or authorization. 12.4 Declaring an implementation# An mdbase TaskNotes type declares one implementation: implements: - contract: tasknotes.task version: 0.3.0-rc.3 fields: title: summary status: state priority: importance dateCreated: created_at binding: # TaskNotes behavior; abbreviated here profiles: [core-lite] capabilities: [] title: storage: frontmatter filename_format: title status: values: [todo, doing, done] default: todo completed_values: [done] definitions: [] priority: values: [normal] default: normal definitions: [] The contract file identified by the exact contract and version MUST exist in the collection contract registry. The binding MUST validate against that contract's binding_schema. Each type MUST declare at most one implementation of one exact contract identity. A type may implement several different contracts. 12.5 Portable fields# fields maps contract field paths to record field paths. Consumers access contract fields and MUST NOT assume that their names are also frontmatter property names. fields: title: summary status: state blockedBy: dependencies attachments: files Every unconditionally required contract field MUST be mapped. Every mapped contract field and record field MUST exist in its respective JSON Schema. The contract view contains only mapped fields. It does not expose unmapped frontmatter or the Markdown body. A consumer that requires either needs separate, explicit whole-record access. title is optional in the portable schema because TaskNotes permits filename title storage. When binding.title.storage is filename, consumers derive the effective title from the record identity/path rules in §9.13 instead of expecting a projected frontmatter value. The camel-case contract field names are stable portable identifiers. Their snake-case tasknotes-spec counterparts include: Contract field tasknotes-spec role timeEstimate time_estimate completedDate completed_date dateCreated date_created dateModified date_modified recurrenceAnchor recurrence_anchor completeInstances complete_instances skippedInstances skipped_instances recurrenceParent recurrence_parent occurrenceDate occurrence_date occurrenceMaterialization occurrence_materialization occurrenceNextTrigger occurrence_next_trigger occurrenceTemplate occurrence_template occurrencePastHorizon occurrence_past_horizon occurrenceFutureHorizon occurrence_future_horizon timeEntries time_entries blockedBy blocked_by attachments attachments 12.6 Semantic profiles and capabilities# binding.profiles and binding.capabilities describe semantics that records of this implementation may use: binding: profiles: [core-lite, recurrence, materialized-occurrences] capabilities: - dependencies - reminders - attachments - links - time-tracking - materialized-occurrences - archive These are properties of the implementation, not claims that every consuming application supports them. Before mutating a governed field, a consumer SHOULD verify its own corresponding capability. It may still perform unrelated operations when it preserves unsupported fields and invariants. 12.7 Status and priority semantics# The implementing type schema defines the legal persisted values of the mapped fields. The binding gives those values TaskNotes meaning: binding: status: values: [todo, doing, done, cancelled] default: todo completed_values: [done] skipped_values: [cancelled] default_skipped: cancelled definitions: [] priority: values: [low, normal, high] default: normal definitions: [] The following consistency rules apply: binding values MUST equal the mapped type-schema enum values; defaults MUST equal mapped collection.read_defaults values when present; completed and skipped values MUST be members of status.values; default_skipped MUST be a skipped value; completed and skipped values MUST NOT overlap for materialized occurrences; and definition semantics MUST agree with completed/skipped membership. Status and priority labels, colors, and icons are presentation hints. Status cycle, completion, skipping, auto-archive, and priority weight are semantic. 12.8 Title, recurrence, links, and operations# The remaining binding sections project the effective TaskNotes behavior defined elsewhere in this specification: title follows §9.13 and MUST agree with collection.display and collection.path; recurrence follows §4; occurrences follows §2.6.6, §4.18, §5.20, and §9.17; links follows §11; attachment membership is the portable attachments contract field; binary MIME type, digest, byte size, revision, and timestamps remain authoritative in mdbase file descriptors and are not projected into task frontmatter; archive follows §5.12; time_tracking follows §5.19 and §9.16; templating follows §5.3.5 and §9.14; and optional nlp triggers follow §9.18. Archive always operates on the portable tags contract field, so the binding does not repeat a record-specific tags_field. The implementation's fields map determines the actual frontmatter property. Application-local notification preferences and generator bookkeeping MUST NOT be placed in the binding. 12.9 Multiple implementations# A collection may contain any number of types implementing tasknotes.task 0.3.0-rc.3. TaskNotes-aware readers MUST: resolve the exact local contract; enumerate every implementation in canonical type-name order; read each matching record through that implementation's projected view; validate the projected view; and retain the concrete type identity for updates. Implementations MUST NOT merge type schemas into one synthetic schema. A record is validated by its concrete type and then by its projected contract view. When an approval, cache, or external protocol pins an implementation set, it MUST pin the exact contract digest and sorted implementation descriptors, including each implementation digest. A newly installed type is therefore not silently added to an existing approval. Creation MUST name one concrete implementing type. If no type is selected, creation fails as ambiguous. 12.10 Task-completed event# An event source that claims tasknotes.task.completed 1.0.0 MUST emit one CloudEvents structured event for each observed transition from a non-completed status to a completed status. Its data contains only: task_id, using the stable TaskNotes ID when present and otherwise the normalized path; task_path; the current title and completed status; and completed_at, the instant when TaskNotes observed the transition. The event source MUST use the mdbase event/action interoperability profile 0.1, pin the exact event-contract digest, and preserve any correlation and causation identifiers supplied by the mutation context. It MUST NOT include a complete task record merely because one is locally available. An authorized consumer can retrieve current state separately, avoiding stale snapshots and unnecessary disclosure. Contract compatibility and bridge authorization are independent. Installing TaskNotes or resolving this contract does not grant permission to publish or consume the event. 12.11 Precedence and consistency# The complete implementation is self-describing: the contract schema is authoritative for the portable projected view; the type schema is authoritative for persisted value shapes; collection is authoritative for generic mdbase behavior; lifecycle is authoritative for generic managed writes; and implements[].binding is authoritative for TaskNotes semantics. Where values intentionally mirror each other, producers MUST keep them equal. A TaskNotes-aware consumer MUST report a configuration error instead of silently choosing between contradictory values. 12.12 Safe writes# TaskNotes-aware consumers MUST preserve: unknown frontmatter properties unless explicit replacement or migration was requested; Markdown body content unless an operation explicitly replaces it; fields governed by unsupported capabilities; and unrelated type metadata and implementations. Generic mdbase operations are safe only when they preserve the same data. Completion, recurrence mutation, occurrence materialization, dependency updates, time tracking, archive, and other domain operations MUST follow the TaskNotes semantics referenced by the binding. 12.13 Complete custom-field example# --- kind: mdbase.type name: work_task version: 1 schema: dialect: json-schema-2020-12 value: type: object additionalProperties: true required: [summary, state, created_at] properties: summary: { type: string, minLength: 1 } state: { enum: [todo, doing, done, cancelled] } importance: { enum: [low, normal, high] } created_at: { type: string, format: date-time } tags: type: array items: { type: string } collection: display: name_field: summary read_defaults: state: todo importance: normal lifecycle: on_create: set: created_at: { now: true } implements: - contract: tasknotes.task version: 0.3.0-rc.3 fields: title: summary status: state priority: importance dateCreated: created_at tags: tags binding: profiles: [core-lite] capabilities: [archive] title: storage: frontmatter filename_format: title status: values: [todo, doing, done, cancelled] default: todo completed_values: [done] skipped_values: [cancelled] default_skipped: cancelled definitions: [] priority: values: [low, normal, high] default: normal definitions: [] recurrence: syntax: tasknotes maintain_due_date_offset: false reset_body_checkboxes: false occurrences: identity_roles: [recurrenceParent, occurrenceDate] default_materialization: manual default_next_trigger: completion links: accepted_formats: [wikilink, markdown] write_format: wikilink archive: archived_tag: archived move_on_archive: false time_tracking: auto_stop_on_complete: true templating: enabled: false occurrence_enabled: false ---"},{"route":"/developers/specification/CHANGELOG/","title":"Changelog","description":"Initial standalone draft of tasknotes-spec including:","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:CHANGELOG.md","namespace":"specification","relativePath":"CHANGELOG.md","raw":"# Changelog\n\n## 0.3.0-rc.3 - 2026-08-02\n\n- define manual ordering as an opaque string rank so clients can insert and\n reorder tasks without renumbering an entire view\n\n## 0.3.0-rc.2 - 2026-08-02\n\n- add first-class `attachments` as an ordered frontmatter list of portable file\n links, with explicit membership, canonical-path, reference-safety, and\n materialized-occurrence semantics\n- expose attachment references in the `tasknotes.task` mdbase contract while\n leaving binary metadata authoritative in the file store\n\n## 0.3.0-rc.1 - 2026-07-28\n\n- adopt the discriminated first-class mdbase contract shape for\n `tasknotes.task`, including explicit `contract_type: record`\n- add the `tasknotes.task.completed 1.0.0` event contract and minimal\n privacy-preserving event-data schema for the mdbase interoperability profile\n- separate type-file record implementation bindings from application-level\n event-source declarations\n\n## 0.2.0-draft - 2026-05-31\n\n- add optional `materialized-occurrences` profile for recurrence occurrence notes, on-completion materialization, and occurrence-state reconciliation\n- add optional NLP trigger configuration so TaskNotes clients can share capture\n suggestion vocabulary\n- replace the private `x-tasknotes` discovery envelope with the first-class\n `tasknotes.task 0.2.0` mdbase data contract, portable task-view schema, and\n implementation binding schema\n- document the precedence and consistency rules between JSON Schema,\n `collection`, `lifecycle`, contract field mappings, and TaskNotes behavior\n\n## 0.1.0-draft - 2026-02-20\n\nInitial standalone draft of `tasknotes-spec` including:\n\n- motivation, scope, and normative conventions\n- terminology\n- task model and field mapping\n- temporal semantics\n- recurrence semantics\n- operation semantics\n- validation model\n- conformance profiles\n- compatibility and migration policy\n- collection configuration schema and provider model (`tasknotes.yaml`, TaskNotes `data.json`)\n- full dependency (`blocked_by`) semantics\n- full reminder (`reminders`) semantics\n- explicit time-tracking management semantics (`time_entries` lifecycle, start/stop/edit/remove, and completion-triggered auto-stop configuration)\n- explicit links chapter and link-resolution rules for projects/dependencies\n- optional `templating` conformance profile with create-time template expansion/merge semantics\n","aliases":["/spec/CHANGELOG/"],"toc":[{"level":2,"id":"030-rc3-2026-08-02","text":"0.3.0-rc.3 - 2026-08-02"},{"level":2,"id":"030-rc2-2026-08-02","text":"0.3.0-rc.2 - 2026-08-02"},{"level":2,"id":"030-rc1-2026-07-28","text":"0.3.0-rc.1 - 2026-07-28"},{"level":2,"id":"020-draft-2026-05-31","text":"0.2.0-draft - 2026-05-31"},{"level":2,"id":"010-draft-2026-02-20","text":"0.1.0-draft - 2026-02-20"}],"html":"

0.3.0-rc.3 - 2026-08-02#

\n
    \n
  • define manual ordering as an opaque string rank so clients can insert and\nreorder tasks without renumbering an entire view
  • \n
\n

0.3.0-rc.2 - 2026-08-02#

\n
    \n
  • add first-class attachments as an ordered frontmatter list of portable file\nlinks, with explicit membership, canonical-path, reference-safety, and\nmaterialized-occurrence semantics
  • \n
  • expose attachment references in the tasknotes.task mdbase contract while\nleaving binary metadata authoritative in the file store
  • \n
\n

0.3.0-rc.1 - 2026-07-28#

\n
    \n
  • adopt the discriminated first-class mdbase contract shape for\ntasknotes.task, including explicit contract_type: record
  • \n
  • add the tasknotes.task.completed 1.0.0 event contract and minimal\nprivacy-preserving event-data schema for the mdbase interoperability profile
  • \n
  • separate type-file record implementation bindings from application-level\nevent-source declarations
  • \n
\n

0.2.0-draft - 2026-05-31#

\n
    \n
  • add optional materialized-occurrences profile for recurrence occurrence notes, on-completion materialization, and occurrence-state reconciliation
  • \n
  • add optional NLP trigger configuration so TaskNotes clients can share capture\nsuggestion vocabulary
  • \n
  • replace the private x-tasknotes discovery envelope with the first-class\ntasknotes.task 0.2.0 mdbase data contract, portable task-view schema, and\nimplementation binding schema
  • \n
  • document the precedence and consistency rules between JSON Schema,\ncollection, lifecycle, contract field mappings, and TaskNotes behavior
  • \n
\n

0.1.0-draft - 2026-02-20#

\n

Initial standalone draft of tasknotes-spec including:

\n
    \n
  • motivation, scope, and normative conventions
  • \n
  • terminology
  • \n
  • task model and field mapping
  • \n
  • temporal semantics
  • \n
  • recurrence semantics
  • \n
  • operation semantics
  • \n
  • validation model
  • \n
  • conformance profiles
  • \n
  • compatibility and migration policy
  • \n
  • collection configuration schema and provider model (tasknotes.yaml, TaskNotes data.json)
  • \n
  • full dependency (blocked_by) semantics
  • \n
  • full reminder (reminders) semantics
  • \n
  • explicit time-tracking management semantics (time_entries lifecycle, start/stop/edit/remove, and completion-triggered auto-stop configuration)
  • \n
  • explicit links chapter and link-resolution rules for projects/dependencies
  • \n
  • optional templating conformance profile with create-time template expansion/merge semantics
  • \n
\n","text":"0.3.0-rc.3 - 2026-08-02# define manual ordering as an opaque string rank so clients can insert and reorder tasks without renumbering an entire view 0.3.0-rc.2 - 2026-08-02# add first-class attachments as an ordered frontmatter list of portable file links, with explicit membership, canonical-path, reference-safety, and materialized-occurrence semantics expose attachment references in the tasknotes.task mdbase contract while leaving binary metadata authoritative in the file store 0.3.0-rc.1 - 2026-07-28# adopt the discriminated first-class mdbase contract shape for tasknotes.task, including explicit contract_type: record add the tasknotes.task.completed 1.0.0 event contract and minimal privacy-preserving event-data schema for the mdbase interoperability profile separate type-file record implementation bindings from application-level event-source declarations 0.2.0-draft - 2026-05-31# add optional materialized-occurrences profile for recurrence occurrence notes, on-completion materialization, and occurrence-state reconciliation add optional NLP trigger configuration so TaskNotes clients can share capture suggestion vocabulary replace the private x-tasknotes discovery envelope with the first-class tasknotes.task 0.2.0 mdbase data contract, portable task-view schema, and implementation binding schema document the precedence and consistency rules between JSON Schema, collection, lifecycle, contract field mappings, and TaskNotes behavior 0.1.0-draft - 2026-02-20# Initial standalone draft of tasknotes-spec including: motivation, scope, and normative conventions terminology task model and field mapping temporal semantics recurrence semantics operation semantics validation model conformance profiles compatibility and migration policy collection configuration schema and provider model (tasknotes.yaml, TaskNotes data.json) full dependency (blocked_by) semantics full reminder (reminders) semantics explicit time-tracking management semantics (time_entries lifecycle, start/stop/edit/remove, and completion-triggered auto-stop configuration) explicit links chapter and link-resolution rules for projects/dependencies optional templating conformance profile with create-time template expansion/merge semantics"},{"route":"/obsidian/","title":"TaskNotes for Obsidian","description":"Install TaskNotes, create a first task, and open the default Obsidian Base views.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/index.md","namespace":"obsidian","relativePath":"index.md","raw":"---\ndescription: Install TaskNotes, create a first task, and open the default Obsidian Base views.\nhide:\n - toc\n---\n\n# TaskNotes for Obsidian\n\nThis guide covers the TaskNotes plugin for Obsidian. It follows the \"one note per task\" principle: each task is a Markdown file with structured metadata in YAML frontmatter.\n\n![Task List view](assets/views-tasks-list.png)\n\n## Requirements\n\nTaskNotes 4.12.3 requires **Obsidian 1.12.2** or later and depends on the **Bases** core plugin. Before you begin, open Obsidian Settings and confirm Bases is enabled under Core Plugins.\n\n## Getting Started\n\n### 1. Install and Enable\n\nInstall TaskNotes from Community Plugins in Obsidian settings, then enable it. If Bases is still disabled, enable it right away so TaskNotes views can open correctly.\n\n### 2. Create Your First Task\n\nPress Ctrl+P (or Cmd+P on macOS), run **TaskNotes: Create new task**, fill in the modal, and save. If you prefer inline workflows, start with a checkbox like `- [ ] Buy groceries` and convert it using the inline task command.\n\n![Create task modal](assets/modal-task-create.png)\n\n### 3. Open the Task List\n\nOpen your first view from the TaskNotes ribbon icon or by running **TaskNotes: Open tasks view** from the command palette. This opens the default Task List `.base` file inside `TaskNotes/Views`.\n\n### 4. Explore\n\nUse [Core Concepts](core-concepts.md) to understand the data model, [Features](features.md) for workflow capabilities, [Views](views.md) for interface behaviour, and [Settings](settings.md) to tune TaskNotes for your vault. If you already have task-like notes, start with [Adopt TaskNotes in an existing vault](getting-started/existing-vault.md).\n\n## Quick Links\n\n\n","aliases":[],"toc":[{"level":2,"id":"requirements","text":"Requirements"},{"level":2,"id":"getting-started","text":"Getting Started"},{"level":3,"id":"1-install-and-enable","text":"1. Install and Enable"},{"level":3,"id":"2-create-your-first-task","text":"2. Create Your First Task"},{"level":3,"id":"3-open-the-task-list","text":"3. Open the Task List"},{"level":3,"id":"4-explore","text":"4. Explore"},{"level":2,"id":"quick-links","text":"Quick Links"}],"html":"

This guide covers the TaskNotes plugin for Obsidian. It follows the "one note per task" principle: each task is a Markdown file with structured metadata in YAML frontmatter.

\n

\"Task

\n

Requirements#

\n

TaskNotes 4.12.3 requires Obsidian 1.12.2 or later and depends on the Bases core plugin. Before you begin, open Obsidian Settings and confirm Bases is enabled under Core Plugins.

\n

Getting Started#

\n

1. Install and Enable#

\n

Install TaskNotes from Community Plugins in Obsidian settings, then enable it. If Bases is still disabled, enable it right away so TaskNotes views can open correctly.

\n

2. Create Your First Task#

\n

Press Ctrl+P (or Cmd+P on macOS), run TaskNotes: Create new task, fill in the modal, and save. If you prefer inline workflows, start with a checkbox like - [ ] Buy groceries and convert it using the inline task command.

\n

\"Create

\n

3. Open the Task List#

\n

Open your first view from the TaskNotes ribbon icon or by running TaskNotes: Open tasks view from the command palette. This opens the default Task List .base file inside TaskNotes/Views.

\n

4. Explore#

\n

Use Core Concepts to understand the data model, Features for workflow capabilities, Views for interface behaviour, and Settings to tune TaskNotes for your vault. If you already have task-like notes, start with Adopt TaskNotes in an existing vault.

\n

Quick Links#

\n\n","text":"This guide covers the TaskNotes plugin for Obsidian. It follows the \"one note per task\" principle: each task is a Markdown file with structured metadata in YAML frontmatter. Requirements# TaskNotes 4.12.3 requires Obsidian 1.12.2 or later and depends on the Bases core plugin. Before you begin, open Obsidian Settings and confirm Bases is enabled under Core Plugins. Getting Started# 1. Install and Enable# Install TaskNotes from Community Plugins in Obsidian settings, then enable it. If Bases is still disabled, enable it right away so TaskNotes views can open correctly. 2. Create Your First Task# Press Ctrl+P (or Cmd+P on macOS), run TaskNotes: Create new task, fill in the modal, and save. If you prefer inline workflows, start with a checkbox like - [ ] Buy groceries and convert it using the inline task command. 3. Open the Task List# Open your first view from the TaskNotes ribbon icon or by running TaskNotes: Open tasks view from the command palette. This opens the default Task List .base file inside TaskNotes/Views. 4. Explore# Use Core Concepts to understand the data model, Features for workflow capabilities, Views for interface behaviour, and Settings to tune TaskNotes for your vault. If you already have task-like notes, start with Adopt TaskNotes in an existing vault. Quick Links# GitHub Repository Source code, issues, releases, and contribution discussions Task Management Status, priority, dates, reminders, and recurring tasks Inline Tasks Widgets, natural language parsing, and checkbox conversion Calendar Integration Google Calendar, Outlook, and ICS subscriptions HTTP API REST API for automation and external integrations JavaScript API In-process API for companion plugins and in-vault scripts Companion Plugins Optional plugins such as Canvas Bases and TaskNotes Workflows that build on TaskNotes Migration Guide Upgrading from TaskNotes v3 to v4 Troubleshooting Common issues and how to resolve them Command Reference Every registered command, generated from the plugin source Backup & Recovery Protect task notes, Base files, settings, and integration data Specification The formal spec behind TaskNotes: data model, operations, recurrence, and conformance"},{"route":"/obsidian/calendar-setup/","title":"Calendar Integration Setup","description":"TaskNotes supports Google Calendar and Microsoft Calendar integration via OAuth 2.0.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/calendar-setup.md","namespace":"obsidian","relativePath":"calendar-setup.md","raw":"# Calendar Integration Setup\n\nTaskNotes supports Google Calendar and Microsoft Calendar integration via OAuth 2.0.\n\n## Setup (Your Own OAuth Credentials)\n\nTo connect calendars, create OAuth credentials with Google and/or Microsoft, then paste them into TaskNotes Integrations settings. The sections below walk through each provider.\n\n![Integrations calendar settings](assets/settings-integrations-calendar.png)\n\n### Google Calendar\n\n\n\n*Video by [@antoneheyward](https://www.youtube.com/@antoneheyward)*\n\nIn [Google Cloud Console](https://console.cloud.google.com), create or select a project, enable the Google Calendar API, and create OAuth 2.0 credentials using the Desktop application type. Then copy the Client ID and Client Secret into TaskNotes (`Settings -> TaskNotes -> Integrations`) and click **Connect Google Calendar**.\n\nIf your Google OAuth app is still in testing mode, add the Google account you will connect with under **Google Auth Platform -> Audience -> Test users**. Otherwise Google may block sign-in with a 403 `access_denied` error saying the app has not completed verification.\n\n### Microsoft Calendar\n\nIn [Azure Portal](https://portal.azure.com), create an App Registration for your Microsoft account type. TaskNotes currently uses Microsoft's `common` OAuth authority, so the app registration must allow the account type you plan to connect through that authority. Tenant-specific single-tenant authorities are not configurable yet.\n\nUnder **Authentication**, add the **Mobile and desktop applications** platform and add this redirect URI:\n\n```text\nhttp://localhost\n```\n\nAlso turn on **Allow public client flows**. TaskNotes uses a local loopback callback with a dynamic port, which Microsoft matches against the registered loopback URI.\n\nIf Azure does not accept the loopback redirect URI through the normal UI, configure loopback redirect support in the manifest by adding:\n\n```json\n{\n \"url\": \"http://127.0.0.1\",\n \"type\": \"Web\"\n}\n```\n\nNext, add delegated Microsoft Graph API permissions (`Calendars.Read`, `Calendars.ReadWrite`, and `offline_access`) and grant consent when required by your organization. Copy the Application (client) ID into TaskNotes, then click **Connect Microsoft Calendar**. The client secret field can be left blank for public-client desktop setup.\n\n## Security Notes\n\nOAuth client IDs, client secrets, and account tokens are stored locally in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system. They are not written to TaskNotes' `data.json`. Tokens refresh automatically, calendar data syncs directly between your vault and provider, and you can disconnect at any time to revoke account access.\n\nSecret Storage is local to the Obsidian installation and vault. When setting up TaskNotes on another device, enter the OAuth app credentials and connect the calendar again. After disconnecting, use **Forget saved credentials** if you also want to remove the client ID and client secret.\n\n## Troubleshooting\n\n**\"Failed to connect\"**\n\nVerify credentials first, then confirm loopback redirect configuration. TaskNotes uses a local callback on `127.0.0.1` with a dynamically selected port. For Microsoft, ensure loopback redirect support is configured in the app registration. Also confirm required permissions/scopes are granted.\n\nFor Google 403 `access_denied` errors during sign-in, confirm the account is listed as a test user in the Google Auth Platform audience settings while your OAuth app is in testing mode.\n\n**\"Failed to fetch events\"**\n\nDisconnect and reconnect to refresh OAuth tokens, then re-check provider-side calendar permissions.\n\n**Connection lost after Obsidian restart**\n\nTokens should persist between sessions. If reconnection is required each restart, check whether Obsidian Secret Storage is available and retaining secrets for the vault.\n","aliases":["/calendar-setup/"],"toc":[{"level":2,"id":"setup-your-own-oauth-credentials","text":"Setup (Your Own OAuth Credentials)"},{"level":3,"id":"google-calendar","text":"Google Calendar"},{"level":3,"id":"microsoft-calendar","text":"Microsoft Calendar"},{"level":2,"id":"security-notes","text":"Security Notes"},{"level":2,"id":"troubleshooting","text":"Troubleshooting"}],"html":"

TaskNotes supports Google Calendar and Microsoft Calendar integration via OAuth 2.0.

\n

Setup (Your Own OAuth Credentials)#

\n

To connect calendars, create OAuth credentials with Google and/or Microsoft, then paste them into TaskNotes Integrations settings. The sections below walk through each provider.

\n

\"Integrations

\n

Google Calendar#

\n\n\n

Video by @antoneheyward

\n

In Google Cloud Console, create or select a project, enable the Google Calendar API, and create OAuth 2.0 credentials using the Desktop application type. Then copy the Client ID and Client Secret into TaskNotes (Settings -> TaskNotes -> Integrations) and click Connect Google Calendar.

\n

If your Google OAuth app is still in testing mode, add the Google account you will connect with under Google Auth Platform -> Audience -> Test users. Otherwise Google may block sign-in with a 403 access_denied error saying the app has not completed verification.

\n

Microsoft Calendar#

\n

In Azure Portal, create an App Registration for your Microsoft account type. TaskNotes currently uses Microsoft's common OAuth authority, so the app registration must allow the account type you plan to connect through that authority. Tenant-specific single-tenant authorities are not configurable yet.

\n

Under Authentication, add the Mobile and desktop applications platform and add this redirect URI:

\n
http://localhost\n

Also turn on Allow public client flows. TaskNotes uses a local loopback callback with a dynamic port, which Microsoft matches against the registered loopback URI.

\n

If Azure does not accept the loopback redirect URI through the normal UI, configure loopback redirect support in the manifest by adding:

\n
{\n  "url": "http://127.0.0.1",\n  "type": "Web"\n}\n

Next, add delegated Microsoft Graph API permissions (Calendars.Read, Calendars.ReadWrite, and offline_access) and grant consent when required by your organization. Copy the Application (client) ID into TaskNotes, then click Connect Microsoft Calendar. The client secret field can be left blank for public-client desktop setup.

\n

Security Notes#

\n

OAuth client IDs, client secrets, and account tokens are stored locally in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system. They are not written to TaskNotes' data.json. Tokens refresh automatically, calendar data syncs directly between your vault and provider, and you can disconnect at any time to revoke account access.

\n

Secret Storage is local to the Obsidian installation and vault. When setting up TaskNotes on another device, enter the OAuth app credentials and connect the calendar again. After disconnecting, use Forget saved credentials if you also want to remove the client ID and client secret.

\n

Troubleshooting#

\n

"Failed to connect"

\n

Verify credentials first, then confirm loopback redirect configuration. TaskNotes uses a local callback on 127.0.0.1 with a dynamically selected port. For Microsoft, ensure loopback redirect support is configured in the app registration. Also confirm required permissions/scopes are granted.

\n

For Google 403 access_denied errors during sign-in, confirm the account is listed as a test user in the Google Auth Platform audience settings while your OAuth app is in testing mode.

\n

"Failed to fetch events"

\n

Disconnect and reconnect to refresh OAuth tokens, then re-check provider-side calendar permissions.

\n

Connection lost after Obsidian restart

\n

Tokens should persist between sessions. If reconnection is required each restart, check whether Obsidian Secret Storage is available and retaining secrets for the vault.

\n","text":"TaskNotes supports Google Calendar and Microsoft Calendar integration via OAuth 2.0. Setup (Your Own OAuth Credentials)# To connect calendars, create OAuth credentials with Google and/or Microsoft, then paste them into TaskNotes Integrations settings. The sections below walk through each provider. Google Calendar# Video by @antoneheyward In Google Cloud Console, create or select a project, enable the Google Calendar API, and create OAuth 2.0 credentials using the Desktop application type. Then copy the Client ID and Client Secret into TaskNotes (Settings -> TaskNotes -> Integrations) and click Connect Google Calendar. If your Google OAuth app is still in testing mode, add the Google account you will connect with under Google Auth Platform -> Audience -> Test users. Otherwise Google may block sign-in with a 403 access_denied error saying the app has not completed verification. Microsoft Calendar# In Azure Portal, create an App Registration for your Microsoft account type. TaskNotes currently uses Microsoft's common OAuth authority, so the app registration must allow the account type you plan to connect through that authority. Tenant-specific single-tenant authorities are not configurable yet. Under Authentication, add the Mobile and desktop applications platform and add this redirect URI: http://localhost Also turn on Allow public client flows. TaskNotes uses a local loopback callback with a dynamic port, which Microsoft matches against the registered loopback URI. If Azure does not accept the loopback redirect URI through the normal UI, configure loopback redirect support in the manifest by adding: { \"url\": \"http://127.0.0.1\", \"type\": \"Web\" } Next, add delegated Microsoft Graph API permissions (Calendars.Read, Calendars.ReadWrite, and offline_access) and grant consent when required by your organization. Copy the Application (client) ID into TaskNotes, then click Connect Microsoft Calendar. The client secret field can be left blank for public-client desktop setup. Security Notes# OAuth client IDs, client secrets, and account tokens are stored locally in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system. They are not written to TaskNotes' data.json. Tokens refresh automatically, calendar data syncs directly between your vault and provider, and you can disconnect at any time to revoke account access. Secret Storage is local to the Obsidian installation and vault. When setting up TaskNotes on another device, enter the OAuth app credentials and connect the calendar again. After disconnecting, use Forget saved credentials if you also want to remove the client ID and client secret. Troubleshooting# \"Failed to connect\" Verify credentials first, then confirm loopback redirect configuration. TaskNotes uses a local callback on 127.0.0.1 with a dynamically selected port. For Microsoft, ensure loopback redirect support is configured in the app registration. Also confirm required permissions/scopes are granted. For Google 403 access_denied errors during sign-in, confirm the account is listed as a test user in the Google Auth Platform audience settings while your OAuth app is in testing mode. \"Failed to fetch events\" Disconnect and reconnect to refresh OAuth tokens, then re-check provider-side calendar permissions. Connection lost after Obsidian restart Tokens should persist between sessions. If reconnection is required each restart, check whether Obsidian Secret Storage is available and retaining secrets for the vault."},{"route":"/obsidian/companion-plugins/","title":"Companion Plugins","description":"Companion plugins are optional Obsidian plugins that build on TaskNotes without adding every workflow to the core plugin. They run inside the same Obsidian app, use TaskNotes...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/companion-plugins.md","namespace":"obsidian","relativePath":"companion-plugins.md","raw":"# Companion Plugins\n\nCompanion plugins are optional Obsidian plugins that build on TaskNotes without adding every workflow to the core plugin. They run inside the same Obsidian app, use TaskNotes' runtime API for live task reads and writes, and keep task data in ordinary Markdown files.\n\nUse companion plugins when you want a deeper product surface than a script or webhook, but you still want TaskNotes itself to stay focused on task storage, editing, views, time tracking, and calendar behavior.\n\n## Available Companion Plugins\n\n| Plugin | Purpose | Documentation |\n| --- | --- | --- |\n| Canvas Bases | TaskNotes canvas companion for Obsidian Bases views, with canvas-style boards, JSON Canvas snapshots, optional TaskNotes badges, actions, and relationship edges. | [Canvas Bases](companion-plugins/canvas-bases.md) |\n| TaskNotes Workflows | Markdown-defined automation for TaskNotes tasks, schedules, events, and manual command-palette workflows. | [TaskNotes Workflows](companion-plugins/tasknotes-workflows.md) |\n\nMore companion plugins may be documented here over time.\n\n## How Companion Plugins Relate to TaskNotes\n\nTaskNotes remains the source of truth for task behavior. Companion plugins should use the [TaskNotes JavaScript Runtime API](javascript-api.md) for live vault operations instead of rewriting TaskNotes frontmatter directly. This keeps task updates consistent with TaskNotes settings, task cache, events, calendar behavior, time tracking, and future data-model changes.\n\nCompanion plugins can also publish their own runtime surface through `api.extensions`. Other plugins and scripts can discover those extension APIs from TaskNotes:\n\n```js\nconst tasknotes = app.plugins.getPlugin(\"tasknotes\");\nconst workflows = tasknotes?.api?.extensions.get(\"tasknotes-workflows\");\n```\n\nThe extension registry is useful when companion plugins need to expose commands, validation helpers, catalogs, or run APIs to other in-vault tools.\n\n## Choosing an Integration Surface\n\n| Use case | Prefer |\n| --- | --- |\n| A user-facing Obsidian UI that works with TaskNotes tasks | Companion plugin |\n| In-vault scripting with Templater, QuickAdd, MetaBind, or another plugin | [JavaScript Runtime API](javascript-api.md) |\n| Local tools outside Obsidian | [HTTP API](HTTP_API.md) or [TaskNotes Obsidian CLI](obsidian-cli.md) |\n| Notifications to external services when tasks change | [Webhooks](webhooks.md) |\n| Direct file analysis without Obsidian running | [mdbase-tasknotes CLI](mdbase-tasknotes-cli.md) |\n\n## Compatibility Expectations\n\nCompanion plugins should:\n\n- Check `api.apiVersion` and `api.hasCapability(...)` before using runtime features.\n- Use `api.catalog` and canonical runtime query DTOs from `api.query` instead of reaching into TaskNotes filter/view internals.\n- Include a `source` value when mutating tasks so TaskNotes events are debuggable.\n- Avoid reacting to their own mutations unless the behavior is explicit.\n- Keep user data in the vault where possible, using readable Markdown or JSON files.\n- Treat TaskNotes task notes and Bases files as user-owned documents.\n\nTaskNotes does not need every companion plugin installed. If a companion plugin is disabled, TaskNotes task notes remain normal Markdown files and TaskNotes core views continue to work.\n","aliases":["/companion-plugins/"],"toc":[{"level":2,"id":"available-companion-plugins","text":"Available Companion Plugins"},{"level":2,"id":"how-companion-plugins-relate-to-tasknotes","text":"How Companion Plugins Relate to TaskNotes"},{"level":2,"id":"choosing-an-integration-surface","text":"Choosing an Integration Surface"},{"level":2,"id":"compatibility-expectations","text":"Compatibility Expectations"}],"html":"

Companion plugins are optional Obsidian plugins that build on TaskNotes without adding every workflow to the core plugin. They run inside the same Obsidian app, use TaskNotes' runtime API for live task reads and writes, and keep task data in ordinary Markdown files.

\n

Use companion plugins when you want a deeper product surface than a script or webhook, but you still want TaskNotes itself to stay focused on task storage, editing, views, time tracking, and calendar behavior.

\n

Available Companion Plugins#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
PluginPurposeDocumentation
Canvas BasesTaskNotes canvas companion for Obsidian Bases views, with canvas-style boards, JSON Canvas snapshots, optional TaskNotes badges, actions, and relationship edges.Canvas Bases
TaskNotes WorkflowsMarkdown-defined automation for TaskNotes tasks, schedules, events, and manual command-palette workflows.TaskNotes Workflows
\n

More companion plugins may be documented here over time.

\n

How Companion Plugins Relate to TaskNotes#

\n

TaskNotes remains the source of truth for task behavior. Companion plugins should use the TaskNotes JavaScript Runtime API for live vault operations instead of rewriting TaskNotes frontmatter directly. This keeps task updates consistent with TaskNotes settings, task cache, events, calendar behavior, time tracking, and future data-model changes.

\n

Companion plugins can also publish their own runtime surface through api.extensions. Other plugins and scripts can discover those extension APIs from TaskNotes:

\n
const tasknotes = app.plugins.getPlugin("tasknotes");\nconst workflows = tasknotes?.api?.extensions.get("tasknotes-workflows");\n

The extension registry is useful when companion plugins need to expose commands, validation helpers, catalogs, or run APIs to other in-vault tools.

\n

Choosing an Integration Surface#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Use casePrefer
A user-facing Obsidian UI that works with TaskNotes tasksCompanion plugin
In-vault scripting with Templater, QuickAdd, MetaBind, or another pluginJavaScript Runtime API
Local tools outside ObsidianHTTP API or TaskNotes Obsidian CLI
Notifications to external services when tasks changeWebhooks
Direct file analysis without Obsidian runningmdbase-tasknotes CLI
\n

Compatibility Expectations#

\n

Companion plugins should:

\n
    \n
  • Check api.apiVersion and api.hasCapability(...) before using runtime features.
  • \n
  • Use api.catalog and canonical runtime query DTOs from api.query instead of reaching into TaskNotes filter/view internals.
  • \n
  • Include a source value when mutating tasks so TaskNotes events are debuggable.
  • \n
  • Avoid reacting to their own mutations unless the behavior is explicit.
  • \n
  • Keep user data in the vault where possible, using readable Markdown or JSON files.
  • \n
  • Treat TaskNotes task notes and Bases files as user-owned documents.
  • \n
\n

TaskNotes does not need every companion plugin installed. If a companion plugin is disabled, TaskNotes task notes remain normal Markdown files and TaskNotes core views continue to work.

\n","text":"Companion plugins are optional Obsidian plugins that build on TaskNotes without adding every workflow to the core plugin. They run inside the same Obsidian app, use TaskNotes' runtime API for live task reads and writes, and keep task data in ordinary Markdown files. Use companion plugins when you want a deeper product surface than a script or webhook, but you still want TaskNotes itself to stay focused on task storage, editing, views, time tracking, and calendar behavior. Available Companion Plugins# Plugin Purpose Documentation Canvas Bases TaskNotes canvas companion for Obsidian Bases views, with canvas-style boards, JSON Canvas snapshots, optional TaskNotes badges, actions, and relationship edges. Canvas Bases TaskNotes Workflows Markdown-defined automation for TaskNotes tasks, schedules, events, and manual command-palette workflows. TaskNotes Workflows More companion plugins may be documented here over time. How Companion Plugins Relate to TaskNotes# TaskNotes remains the source of truth for task behavior. Companion plugins should use the TaskNotes JavaScript Runtime API for live vault operations instead of rewriting TaskNotes frontmatter directly. This keeps task updates consistent with TaskNotes settings, task cache, events, calendar behavior, time tracking, and future data-model changes. Companion plugins can also publish their own runtime surface through api.extensions. Other plugins and scripts can discover those extension APIs from TaskNotes: const tasknotes = app.plugins.getPlugin(\"tasknotes\"); const workflows = tasknotes?.api?.extensions.get(\"tasknotes-workflows\"); The extension registry is useful when companion plugins need to expose commands, validation helpers, catalogs, or run APIs to other in-vault tools. Choosing an Integration Surface# Use case Prefer A user-facing Obsidian UI that works with TaskNotes tasks Companion plugin In-vault scripting with Templater, QuickAdd, MetaBind, or another plugin JavaScript Runtime API Local tools outside Obsidian HTTP API or TaskNotes Obsidian CLI Notifications to external services when tasks change Webhooks Direct file analysis without Obsidian running mdbase-tasknotes CLI Compatibility Expectations# Companion plugins should: Check api.apiVersion and api.hasCapability(...) before using runtime features. Use api.catalog and canonical runtime query DTOs from api.query instead of reaching into TaskNotes filter/view internals. Include a source value when mutating tasks so TaskNotes events are debuggable. Avoid reacting to their own mutations unless the behavior is explicit. Keep user data in the vault where possible, using readable Markdown or JSON files. Treat TaskNotes task notes and Bases files as user-owned documents. TaskNotes does not need every companion plugin installed. If a companion plugin is disabled, TaskNotes task notes remain normal Markdown files and TaskNotes core views continue to work."},{"route":"/obsidian/companion-plugins/canvas-bases/","title":"Canvas Bases","description":"Canvas Bases is the TaskNotes canvas companion plugin for Obsidian Bases and Canvas. It turns the current Bases result set into a canvas-style board, either as a live Bases layo...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/companion-plugins/canvas-bases.md","namespace":"obsidian","relativePath":"companion-plugins/canvas-bases.md","raw":"# Canvas Bases\n\nCanvas Bases is the TaskNotes canvas companion plugin for Obsidian Bases and Canvas. It turns the current Bases result set into a canvas-style board, either as a live Bases layout named **Canvas Bases** or as a generated JSON Canvas snapshot.\n\nCanvas Bases works with normal notes and with TaskNotes task notes. Bases remains the source for which notes appear: filters, sorting, grouping, formulas, and visible properties all come from the `.base` file. Canvas Bases handles spatial layout, cards, edges, zones, pinned notes, text cards, and linked canvas updates.\n\n## Requirements\n\n- Obsidian 1.10.1 or newer.\n- The Obsidian Bases core plugin.\n- The Obsidian Canvas core plugin when opening or editing generated `.canvas` files.\n- TaskNotes is optional, but must be installed and enabled for TaskNotes-specific badges, task menus, dependency edges, subtasks, time tracking, Pomodoro actions, and recurring-task zone actions.\n\nIf TaskNotes is disabled, Canvas Bases still works as a Bases and Canvas plugin. TaskNotes-specific actions are skipped when TaskNotes is absent or does not expose the required runtime API capability.\n\n## When to Use Canvas Bases\n\nUse Canvas Bases when a task view benefits from spatial arrangement instead of a list, table, calendar, or Kanban column set.\n\nCommon uses include:\n\n- Planning project tasks on a visual board.\n- Seeing dependencies or related notes as edges between cards.\n- Embedding a board in a daily note, project note, or meeting note.\n- Turning a filtered Base view into a reusable `.canvas` snapshot.\n- Grouping notes with Bases, then manually arranging the result.\n- Dropping cards into assignment zones to update a note property or run a supported TaskNotes action.\n\nIf the question is only \"which tasks should appear?\", keep that in Bases filters, formulas, sorting, and grouping. Canvas Bases is for visualizing and arranging the current Bases result set.\n\n## Canvas Bases Layout\n\nAfter Canvas Bases is installed, open or create a `.base` file and add a view using the **Canvas Bases** layout.\n\nIn the live layout:\n\n- Each Base result row becomes a file card.\n- Displayed Base properties appear on each card in the same order as the Base properties menu.\n- Base groups become group frames.\n- Cards and group frames can be dragged and resized.\n- Ungrouped views place cards directly on the board.\n- The initial card order follows the Base sort order.\n- Inline note-body editing is available when **Show body editor** is enabled.\n- Board controls support panning, zooming, fit view, reset view, and opening cards.\n- Manual notes, manual groups, and text cards can be added without changing the Base query.\n\nCanvas Bases stores layout and board state in Canvas Bases-owned keys in the `.base` view config. It does not need to rewrite the core query just to remember card positions, sizes, colors, pinned notes, text cards, zones, or the linked canvas path.\n\n## Materialize a Canvas\n\nCanvas Bases can also create or update a JSON Canvas file from any active Bases view, including native and third-party Bases layouts.\n\nRun these commands from the command palette:\n\n```text\nCanvas Bases: Create canvas from current bases view\nCanvas Bases: Update linked canvas\nCanvas Bases: Open linked canvas\n```\n\nThe create command asks for the canvas path, layout, edge options, node size, and update behavior. Canvas Bases-owned node and edge IDs are stable, so updating a linked canvas can preserve existing Canvas Bases node positions and keep unrelated manual Canvas nodes and edges.\n\nThe generated `.canvas` file is a snapshot, not a live query. Re-run **Canvas Bases: Update linked canvas** after changing the Base result set or board layout.\n\n## TaskNotes Integration\n\nCanvas Bases reads TaskNotes through the [TaskNotes JavaScript Runtime API](../javascript-api.md). It feature-detects API capabilities before using them, so the board can degrade cleanly when TaskNotes is unavailable or a capability is missing.\n\nWhen TaskNotes integration is enabled, Canvas Bases can:\n\n- Show TaskNotes status, priority, planning, recurrence, blocked, blocking, subtask, time estimate, tracked time, and active tracking badges on task cards.\n- Add TaskNotes task actions to card context menus through the TaskNotes task menu API.\n- Draw dependency edges between visible tasks.\n- Draw dependency and parent-subtask edges when the TaskNotes relationship mode is set to `all`.\n- Add or remove dependency and subtask relationships by dragging from one card's link handle to another.\n- Update mapped TaskNotes task properties when a card is dropped into a property zone.\n- Run supported zone actions such as complete, uncomplete, archive, unarchive, start or stop time tracking, start or assign a Pomodoro, complete an occurrence, or skip an occurrence.\n\nTaskNotes remains responsible for task semantics. Canvas Bases asks TaskNotes to read and mutate tasks instead of editing task frontmatter directly.\n\n## Edges and Relationships\n\nCanvas Bases can draw edges when both endpoint notes are present on the board.\n\nSupported edge sources include:\n\n| Source | What it uses |\n| --- | --- |\n| `wikilinks` | Links found in the note body. |\n| `properties` | Links stored in configured note properties. |\n| `all` | Wikilinks and configured property links. |\n| TaskNotes dependencies | Blocking relationships from TaskNotes. |\n| TaskNotes subtasks | Parent-child task relationships from TaskNotes when enabled. |\n\nFor property edges, configure a comma-separated list of property names, such as:\n\n```text\ndepends_on, related\n```\n\nEdges can be opened from their context menu. Removable TaskNotes and property relationships can also be removed from that menu.\n\n## Assignment Zones\n\nAssignment zones are board regions that do something when a card is dropped into them.\n\nThe default zone action updates a note property. A grouped Canvas Bases view can turn Bases groups into zones, so dragging a card into another status, priority, or custom-property group writes that property value back to the note.\n\nCustom zones can update another note property or run supported TaskNotes actions. This lets a board mix automatic Bases-derived groups with manual workflow areas such as review queues, time-tracking lanes, or Pomodoro focus zones.\n\n## Files and Data\n\nCanvas Bases keeps user data in normal vault files:\n\n| Data | Where it lives |\n| --- | --- |\n| Task and note content | Markdown files. |\n| Query, visible properties, sorting, and grouping | `.base` files. |\n| Live board geometry and Canvas Bases options | Canvas Bases-owned keys in the `.base` view config. |\n| Generated board snapshots | `.canvas` files. |\n| Options for non-Canvas Bases active views | Canvas Bases plugin data. |\n\nManual non-Canvas Bases nodes in a generated `.canvas` file are preserved when Canvas Bases updates that canvas.\n\n## First Board\n\nA practical first Canvas Bases setup is:\n\n1. Create or duplicate a TaskNotes `.base` view.\n2. Filter it to the tasks or notes you want on the board.\n3. Add a Canvas Bases layout view to that `.base` file.\n4. Choose which properties to show on cards.\n5. Enable TaskNotes badges, actions, or relationships if the board is task-focused.\n6. Arrange the cards and groups.\n7. Use the toolbar to create a linked `.canvas` snapshot when you want a Canvas file.\n\nCanvas Bases can also create starter files under `Canvas Bases/` with a demo Base, sample notes, and a linked Canvas path. Run **Canvas Bases: Create starter files** from the command palette if you want a small example board to inspect before adapting your own TaskNotes views.\n","aliases":["/companion-plugins/canvas-bases/"],"toc":[{"level":2,"id":"requirements","text":"Requirements"},{"level":2,"id":"when-to-use-canvas-bases","text":"When to Use Canvas Bases"},{"level":2,"id":"canvas-bases-layout","text":"Canvas Bases Layout"},{"level":2,"id":"materialize-a-canvas","text":"Materialize a Canvas"},{"level":2,"id":"tasknotes-integration","text":"TaskNotes Integration"},{"level":2,"id":"edges-and-relationships","text":"Edges and Relationships"},{"level":2,"id":"assignment-zones","text":"Assignment Zones"},{"level":2,"id":"files-and-data","text":"Files and Data"},{"level":2,"id":"first-board","text":"First Board"}],"html":"

Canvas Bases is the TaskNotes canvas companion plugin for Obsidian Bases and Canvas. It turns the current Bases result set into a canvas-style board, either as a live Bases layout named Canvas Bases or as a generated JSON Canvas snapshot.

\n

Canvas Bases works with normal notes and with TaskNotes task notes. Bases remains the source for which notes appear: filters, sorting, grouping, formulas, and visible properties all come from the .base file. Canvas Bases handles spatial layout, cards, edges, zones, pinned notes, text cards, and linked canvas updates.

\n

Requirements#

\n
    \n
  • Obsidian 1.10.1 or newer.
  • \n
  • The Obsidian Bases core plugin.
  • \n
  • The Obsidian Canvas core plugin when opening or editing generated .canvas files.
  • \n
  • TaskNotes is optional, but must be installed and enabled for TaskNotes-specific badges, task menus, dependency edges, subtasks, time tracking, Pomodoro actions, and recurring-task zone actions.
  • \n
\n

If TaskNotes is disabled, Canvas Bases still works as a Bases and Canvas plugin. TaskNotes-specific actions are skipped when TaskNotes is absent or does not expose the required runtime API capability.

\n

When to Use Canvas Bases#

\n

Use Canvas Bases when a task view benefits from spatial arrangement instead of a list, table, calendar, or Kanban column set.

\n

Common uses include:

\n
    \n
  • Planning project tasks on a visual board.
  • \n
  • Seeing dependencies or related notes as edges between cards.
  • \n
  • Embedding a board in a daily note, project note, or meeting note.
  • \n
  • Turning a filtered Base view into a reusable .canvas snapshot.
  • \n
  • Grouping notes with Bases, then manually arranging the result.
  • \n
  • Dropping cards into assignment zones to update a note property or run a supported TaskNotes action.
  • \n
\n

If the question is only "which tasks should appear?", keep that in Bases filters, formulas, sorting, and grouping. Canvas Bases is for visualizing and arranging the current Bases result set.

\n

Canvas Bases Layout#

\n

After Canvas Bases is installed, open or create a .base file and add a view using the Canvas Bases layout.

\n

In the live layout:

\n
    \n
  • Each Base result row becomes a file card.
  • \n
  • Displayed Base properties appear on each card in the same order as the Base properties menu.
  • \n
  • Base groups become group frames.
  • \n
  • Cards and group frames can be dragged and resized.
  • \n
  • Ungrouped views place cards directly on the board.
  • \n
  • The initial card order follows the Base sort order.
  • \n
  • Inline note-body editing is available when Show body editor is enabled.
  • \n
  • Board controls support panning, zooming, fit view, reset view, and opening cards.
  • \n
  • Manual notes, manual groups, and text cards can be added without changing the Base query.
  • \n
\n

Canvas Bases stores layout and board state in Canvas Bases-owned keys in the .base view config. It does not need to rewrite the core query just to remember card positions, sizes, colors, pinned notes, text cards, zones, or the linked canvas path.

\n

Materialize a Canvas#

\n

Canvas Bases can also create or update a JSON Canvas file from any active Bases view, including native and third-party Bases layouts.

\n

Run these commands from the command palette:

\n
Canvas Bases: Create canvas from current bases view\nCanvas Bases: Update linked canvas\nCanvas Bases: Open linked canvas\n

The create command asks for the canvas path, layout, edge options, node size, and update behavior. Canvas Bases-owned node and edge IDs are stable, so updating a linked canvas can preserve existing Canvas Bases node positions and keep unrelated manual Canvas nodes and edges.

\n

The generated .canvas file is a snapshot, not a live query. Re-run Canvas Bases: Update linked canvas after changing the Base result set or board layout.

\n

TaskNotes Integration#

\n

Canvas Bases reads TaskNotes through the TaskNotes JavaScript Runtime API. It feature-detects API capabilities before using them, so the board can degrade cleanly when TaskNotes is unavailable or a capability is missing.

\n

When TaskNotes integration is enabled, Canvas Bases can:

\n
    \n
  • Show TaskNotes status, priority, planning, recurrence, blocked, blocking, subtask, time estimate, tracked time, and active tracking badges on task cards.
  • \n
  • Add TaskNotes task actions to card context menus through the TaskNotes task menu API.
  • \n
  • Draw dependency edges between visible tasks.
  • \n
  • Draw dependency and parent-subtask edges when the TaskNotes relationship mode is set to all.
  • \n
  • Add or remove dependency and subtask relationships by dragging from one card's link handle to another.
  • \n
  • Update mapped TaskNotes task properties when a card is dropped into a property zone.
  • \n
  • Run supported zone actions such as complete, uncomplete, archive, unarchive, start or stop time tracking, start or assign a Pomodoro, complete an occurrence, or skip an occurrence.
  • \n
\n

TaskNotes remains responsible for task semantics. Canvas Bases asks TaskNotes to read and mutate tasks instead of editing task frontmatter directly.

\n

Edges and Relationships#

\n

Canvas Bases can draw edges when both endpoint notes are present on the board.

\n

Supported edge sources include:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
SourceWhat it uses
wikilinksLinks found in the note body.
propertiesLinks stored in configured note properties.
allWikilinks and configured property links.
TaskNotes dependenciesBlocking relationships from TaskNotes.
TaskNotes subtasksParent-child task relationships from TaskNotes when enabled.
\n

For property edges, configure a comma-separated list of property names, such as:

\n
depends_on, related\n

Edges can be opened from their context menu. Removable TaskNotes and property relationships can also be removed from that menu.

\n

Assignment Zones#

\n

Assignment zones are board regions that do something when a card is dropped into them.

\n

The default zone action updates a note property. A grouped Canvas Bases view can turn Bases groups into zones, so dragging a card into another status, priority, or custom-property group writes that property value back to the note.

\n

Custom zones can update another note property or run supported TaskNotes actions. This lets a board mix automatic Bases-derived groups with manual workflow areas such as review queues, time-tracking lanes, or Pomodoro focus zones.

\n

Files and Data#

\n

Canvas Bases keeps user data in normal vault files:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
DataWhere it lives
Task and note contentMarkdown files.
Query, visible properties, sorting, and grouping.base files.
Live board geometry and Canvas Bases optionsCanvas Bases-owned keys in the .base view config.
Generated board snapshots.canvas files.
Options for non-Canvas Bases active viewsCanvas Bases plugin data.
\n

Manual non-Canvas Bases nodes in a generated .canvas file are preserved when Canvas Bases updates that canvas.

\n

First Board#

\n

A practical first Canvas Bases setup is:

\n
    \n
  1. Create or duplicate a TaskNotes .base view.
  2. \n
  3. Filter it to the tasks or notes you want on the board.
  4. \n
  5. Add a Canvas Bases layout view to that .base file.
  6. \n
  7. Choose which properties to show on cards.
  8. \n
  9. Enable TaskNotes badges, actions, or relationships if the board is task-focused.
  10. \n
  11. Arrange the cards and groups.
  12. \n
  13. Use the toolbar to create a linked .canvas snapshot when you want a Canvas file.
  14. \n
\n

Canvas Bases can also create starter files under Canvas Bases/ with a demo Base, sample notes, and a linked Canvas path. Run Canvas Bases: Create starter files from the command palette if you want a small example board to inspect before adapting your own TaskNotes views.

\n","text":"Canvas Bases is the TaskNotes canvas companion plugin for Obsidian Bases and Canvas. It turns the current Bases result set into a canvas-style board, either as a live Bases layout named Canvas Bases or as a generated JSON Canvas snapshot. Canvas Bases works with normal notes and with TaskNotes task notes. Bases remains the source for which notes appear: filters, sorting, grouping, formulas, and visible properties all come from the .base file. Canvas Bases handles spatial layout, cards, edges, zones, pinned notes, text cards, and linked canvas updates. Requirements# Obsidian 1.10.1 or newer. The Obsidian Bases core plugin. The Obsidian Canvas core plugin when opening or editing generated .canvas files. TaskNotes is optional, but must be installed and enabled for TaskNotes-specific badges, task menus, dependency edges, subtasks, time tracking, Pomodoro actions, and recurring-task zone actions. If TaskNotes is disabled, Canvas Bases still works as a Bases and Canvas plugin. TaskNotes-specific actions are skipped when TaskNotes is absent or does not expose the required runtime API capability. When to Use Canvas Bases# Use Canvas Bases when a task view benefits from spatial arrangement instead of a list, table, calendar, or Kanban column set. Common uses include: Planning project tasks on a visual board. Seeing dependencies or related notes as edges between cards. Embedding a board in a daily note, project note, or meeting note. Turning a filtered Base view into a reusable .canvas snapshot. Grouping notes with Bases, then manually arranging the result. Dropping cards into assignment zones to update a note property or run a supported TaskNotes action. If the question is only \"which tasks should appear?\", keep that in Bases filters, formulas, sorting, and grouping. Canvas Bases is for visualizing and arranging the current Bases result set. Canvas Bases Layout# After Canvas Bases is installed, open or create a .base file and add a view using the Canvas Bases layout. In the live layout: Each Base result row becomes a file card. Displayed Base properties appear on each card in the same order as the Base properties menu. Base groups become group frames. Cards and group frames can be dragged and resized. Ungrouped views place cards directly on the board. The initial card order follows the Base sort order. Inline note-body editing is available when Show body editor is enabled. Board controls support panning, zooming, fit view, reset view, and opening cards. Manual notes, manual groups, and text cards can be added without changing the Base query. Canvas Bases stores layout and board state in Canvas Bases-owned keys in the .base view config. It does not need to rewrite the core query just to remember card positions, sizes, colors, pinned notes, text cards, zones, or the linked canvas path. Materialize a Canvas# Canvas Bases can also create or update a JSON Canvas file from any active Bases view, including native and third-party Bases layouts. Run these commands from the command palette: Canvas Bases: Create canvas from current bases view Canvas Bases: Update linked canvas Canvas Bases: Open linked canvas The create command asks for the canvas path, layout, edge options, node size, and update behavior. Canvas Bases-owned node and edge IDs are stable, so updating a linked canvas can preserve existing Canvas Bases node positions and keep unrelated manual Canvas nodes and edges. The generated .canvas file is a snapshot, not a live query. Re-run Canvas Bases: Update linked canvas after changing the Base result set or board layout. TaskNotes Integration# Canvas Bases reads TaskNotes through the TaskNotes JavaScript Runtime API. It feature-detects API capabilities before using them, so the board can degrade cleanly when TaskNotes is unavailable or a capability is missing. When TaskNotes integration is enabled, Canvas Bases can: Show TaskNotes status, priority, planning, recurrence, blocked, blocking, subtask, time estimate, tracked time, and active tracking badges on task cards. Add TaskNotes task actions to card context menus through the TaskNotes task menu API. Draw dependency edges between visible tasks. Draw dependency and parent-subtask edges when the TaskNotes relationship mode is set to all. Add or remove dependency and subtask relationships by dragging from one card's link handle to another. Update mapped TaskNotes task properties when a card is dropped into a property zone. Run supported zone actions such as complete, uncomplete, archive, unarchive, start or stop time tracking, start or assign a Pomodoro, complete an occurrence, or skip an occurrence. TaskNotes remains responsible for task semantics. Canvas Bases asks TaskNotes to read and mutate tasks instead of editing task frontmatter directly. Edges and Relationships# Canvas Bases can draw edges when both endpoint notes are present on the board. Supported edge sources include: Source What it uses wikilinks Links found in the note body. properties Links stored in configured note properties. all Wikilinks and configured property links. TaskNotes dependencies Blocking relationships from TaskNotes. TaskNotes subtasks Parent-child task relationships from TaskNotes when enabled. For property edges, configure a comma-separated list of property names, such as: depends_on, related Edges can be opened from their context menu. Removable TaskNotes and property relationships can also be removed from that menu. Assignment Zones# Assignment zones are board regions that do something when a card is dropped into them. The default zone action updates a note property. A grouped Canvas Bases view can turn Bases groups into zones, so dragging a card into another status, priority, or custom-property group writes that property value back to the note. Custom zones can update another note property or run supported TaskNotes actions. This lets a board mix automatic Bases-derived groups with manual workflow areas such as review queues, time-tracking lanes, or Pomodoro focus zones. Files and Data# Canvas Bases keeps user data in normal vault files: Data Where it lives Task and note content Markdown files. Query, visible properties, sorting, and grouping .base files. Live board geometry and Canvas Bases options Canvas Bases-owned keys in the .base view config. Generated board snapshots .canvas files. Options for non-Canvas Bases active views Canvas Bases plugin data. Manual non-Canvas Bases nodes in a generated .canvas file are preserved when Canvas Bases updates that canvas. First Board# A practical first Canvas Bases setup is: Create or duplicate a TaskNotes .base view. Filter it to the tasks or notes you want on the board. Add a Canvas Bases layout view to that .base file. Choose which properties to show on cards. Enable TaskNotes badges, actions, or relationships if the board is task-focused. Arrange the cards and groups. Use the toolbar to create a linked .canvas snapshot when you want a Canvas file. Canvas Bases can also create starter files under Canvas Bases/ with a demo Base, sample notes, and a linked Canvas path. Run Canvas Bases: Create starter files from the command palette if you want a small example board to inspect before adapting your own TaskNotes views."},{"route":"/obsidian/companion-plugins/tasknotes-workflows/","title":"TaskNotes Workflows","description":"TaskNotes Workflows is a companion plugin for Markdown-defined automation. It lets you create workflow notes that respond to TaskNotes events, schedules, manual commands, and se...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/companion-plugins/tasknotes-workflows.md","namespace":"obsidian","relativePath":"companion-plugins/tasknotes-workflows.md","raw":"# TaskNotes Workflows\n\nTaskNotes Workflows is a companion plugin for Markdown-defined automation. It lets you create workflow notes that respond to TaskNotes events, schedules, manual commands, and selected Obsidian events, then run typed actions against TaskNotes tasks.\n\n## Install TaskNotes Workflows\n\n\n\nYou can also install it from Obsidian: open Settings > Community plugins > Browse, then search for `TaskNotes Workflows`.\n\nThe plugin is designed for workflows users often ask TaskNotes core to handle, such as:\n\n- Start time tracking when a task becomes active.\n- Stop time tracking when a task is completed.\n- Move completed tasks into a review folder.\n- Copy parent task context, tags, priority, dates, or dependencies to subtasks.\n- Warn when a blocked task is moved to active.\n- Run a daily review query.\n\nTaskNotes Workflows keeps this behavior outside TaskNotes core while still using the [TaskNotes JavaScript Runtime API](../javascript-api.md) for safe task reads, writes, canonical queries, events, and relationship resolution.\n\n## Requirements\n\n- TaskNotes must be installed and enabled.\n- TaskNotes must expose the JavaScript runtime API.\n- Obsidian must be open for workflows to run.\n- Scheduled workflows run while Obsidian is running. They are not a background service when Obsidian is closed.\n- The plugin runtime uses Obsidian APIs only. Node is used for development and build scripts, not for workflow execution, so Markdown workflow definitions can work on Obsidian mobile while the plugin is loaded.\n\nIf TaskNotes is disabled or unavailable, the workflow Base can still validate and display workflow files, but TaskNotes read/write steps cannot run.\n\n## Files Created by the Plugin\n\nBy default, TaskNotes Workflows uses:\n\n| Path | Purpose |\n| --- | --- |\n| `TaskNotes/Workflows/` | Workflow Markdown files. |\n| `TaskNotes/Views/workflows.base` | Generated Obsidian Base that renders workflow cards through the custom workflow view. |\n| Plugin config folder | Run history and detail logs, unless a run-log folder is configured. |\n\nWorkflow notes are ordinary Markdown files. The YAML frontmatter is executable configuration, and the note body is for human explanation, testing notes, and maintenance guidance.\n\n## First Run\n\nOn first load, the plugin can create a default workflow folder, a workflow Base, and a set of example workflow notes. The default workflow notes are disabled so they can be inspected, dry-run, edited, and enabled intentionally.\n\nThe generated Base is the main workbench. It shows workflow cards with status, trigger and step summaries, recent run state, and buttons for editing, dry-running, running, and opening the source note.\n\nWorkflow notes also show a compact workflow card in reading mode and live preview, so the note remains useful even when opened directly.\n\n## Default Workflows\n\nThe plugin can write these starter workflows:\n\n| Workflow | What it demonstrates |\n| --- | --- |\n| Auto-start time tracking | Starts a timer when a task status changes to active. |\n| Stop time tracking on complete | Stops the timer when a task is completed. |\n| Morning overdue review | Runs a daily cron query and marks overdue open tasks high priority. |\n| Move completed tasks to review | Moves completed task notes into a review folder. |\n| Inherit subtask contexts and tags | Copies contexts and tags from the first parent task when a task becomes a subtask. |\n| Inherit subtask priority | Copies priority from the first parent task when a task becomes a subtask. |\n| Inherit subtask planning dates | Copies scheduled and due dates from the first parent task when a task becomes a subtask. |\n| Inherit subtask dependencies | Adds the first parent task's blocking dependencies to new subtasks. |\n| Mirror parent priority to subtasks | Updates existing subtasks when a parent task priority changes. |\n| Mirror parent planning dates to subtasks | Updates existing subtasks when a parent scheduled or due date changes. |\n| Mirror parent dependencies to subtasks | Replaces each subtask's dependencies with the parent task's current dependencies. |\n| Warn when starting a blocked task | Shows a notice when a task becomes active while dependencies remain. |\n| Daily active task review | Shows a daily count of tasks still marked active. |\n\nTreat these as editable examples. Adjust folders, statuses, priorities, dates, and filters to match your vault before enabling mutating workflows.\n\n## Workflow Shape\n\nA workflow file looks like this:\n\n```markdown\n---\ntype: tasknotes-workflow\nschemaVersion: 1\nid: auto-start-time-tracking\nname: Auto-start time tracking\nenabled: false\ndescription: Start a timer when a task status changes to active.\ntriggers:\n - id: status-active\n type: tasknotes.event\n event: task.status.changed\n to: active\nconditions:\n - field: trigger.after.path\n operator: exists\nsteps:\n - id: start-time\n type: time.start\n input:\n task: \"{{trigger.after.path}}\"\n options:\n description: \"Started by {{workflow.name}}\"\nrun:\n mode: sequential\n noOverlap: true\n source: tasknotes-workflows\n maxTasks: 1\n onError: stop\n---\n\n# Auto-start time tracking\n\nEnable this workflow to start time tracking when a TaskNotes task moves to `active`.\n```\n\nRequired frontmatter fields:\n\n| Field | Type | Notes |\n| --- | --- | --- |\n| `type` | string | Must be `tasknotes-workflow`. |\n| `schemaVersion` | number | Must be `1`. |\n| `id` | string | Stable lowercase identifier. Use letters, numbers, dots, underscores, and dashes. |\n| `name` | string | Human-readable name shown in workflow cards and command-palette commands. |\n| `enabled` | boolean | Disabled workflows can be edited and dry-run but do not run automatically or from manual commands. |\n| `triggers` | array | One or more trigger definitions. |\n| `conditions` | array | Optional workflow-level guards. |\n| `steps` | array | Linear typed step pipeline. |\n| `run` | object | Run policy and safety limits. |\n\n## Triggers\n\nTriggers decide when a workflow should run.\n\n### TaskNotes Events\n\nUse `tasknotes.event` to react to TaskNotes runtime events:\n\n```yaml\ntriggers:\n - id: status-active\n type: tasknotes.event\n event: task.status.changed\n from: open\n to: active\n```\n\nCommon event names include:\n\n- `task.created`\n- `task.updated`\n- `task.deleted`\n- `task.moved`\n- `task.status.changed`\n- `task.completed`\n- `task.uncompleted`\n- `task.archived`\n- `task.unarchived`\n- `task.scheduled.changed`\n- `task.due.changed`\n- `task.priority.changed`\n- `task.tags.changed`\n- `task.contexts.changed`\n- `task.projects.changed`\n- `task.reminders.changed`\n- `task.dependencies.changed`\n- `task.recurrence.changed`\n- `time.started`\n- `time.stopped`\n- `pomodoro.started`\n- `pomodoro.completed`\n- `pomodoro.interrupted`\n- `recurring.instance.completed`\n- `recurring.instance.skipped`\n\nThe workflow editor loads available TaskNotes events dynamically from `api.events.list()`, so event pickers can follow the runtime API instead of relying on a hardcoded list.\n\nTaskNotes event triggers can use these filters:\n\n| Field | Purpose |\n| --- | --- |\n| `event` | Runtime event name. |\n| `from` | Previous status or value for status-change workflows. |\n| `to` | New status or value for status-change workflows. |\n| `path.glob` | Optional path glob limiting which task files can trigger the workflow. |\n| `allowSelfTrigger` | Allows this workflow to react to writes caused by `tasknotes-workflows`. Leave off unless you have a clear reason. |\n\nTaskNotes event output fields include values such as `trigger.after.path`, `trigger.after.status`, `trigger.before.status`, `trigger.changes`, `trigger.source`, and `trigger.correlationId`.\n\n### Cron\n\nCron triggers run on matching minutes while Obsidian is open:\n\n```yaml\ntriggers:\n - id: weekday-review\n type: cron\n schedule: \"0 17 * * 1-5\"\n timezone: local\n```\n\nThe schedule uses five fields: minute, hour, day of month, month, day of week. Keep cron workflows bounded with `run.maxTasks`, especially if they query many tasks.\n\n### Interval\n\nInterval triggers run repeatedly while Obsidian is open:\n\n```yaml\ntriggers:\n - id: half-hour-check\n type: interval\n every: 30m\n```\n\nThe plugin enforces a minimum interval to avoid excessive background work.\n\n### Manual\n\nManual triggers let a workflow run from a card button, another plugin, or the Obsidian command palette:\n\n```yaml\ntriggers:\n - id: manual\n type: manual\n```\n\nEnabled workflows with a manual trigger are registered as Obsidian commands named `Run: `. You can launch them from the command palette or assign hotkeys in Obsidian settings.\n\nThe generated command id is based on the workflow `id`. Changing a workflow id creates a different command, so any hotkey assigned to the old command id will need to be reassigned.\n\n### Obsidian Events\n\nAdvanced Obsidian triggers are opt-in from the plugin settings. They can listen to selected vault, metadata, and workspace events:\n\n```yaml\ntriggers:\n - id: project-note-opened\n type: obsidian.workspace\n event: file-open\n path:\n glob: \"Projects/**/*.md\"\n\n - id: task-note-modified\n type: obsidian.vault\n event: modify\n path:\n glob: \"Tasks/**/*.md\"\n\n - id: metadata-changed\n type: obsidian.metadata\n event: changed\n path:\n glob: \"Projects/**/*.md\"\n```\n\nKeep path filters narrow for Obsidian triggers. Vault and metadata events can be frequent.\n\n## Conditions\n\nConditions can appear at workflow level or on individual steps.\n\n```yaml\nconditions:\n - field: trigger.after.path\n operator: exists\n - field: trigger.after.status\n operator: is\n value: active\n```\n\nSupported operators:\n\n| Operator | Meaning |\n| --- | --- |\n| `is` / `isNot` | Exact comparison after scalar normalization. |\n| `in` / `notIn` | Check a value against an array. |\n| `exists` / `missing` | Check whether a field has a value. |\n| `contains` | Check whether a string contains text or an array contains a value. |\n| `startsWith` | String prefix check. |\n| `before` / `after` | Date comparison. |\n| `onOrBefore` / `onOrAfter` | Inclusive date comparison. |\n\nStep-level conditions use the same shape:\n\n```yaml\nsteps:\n - id: warn\n type: notice.show\n if:\n - field: steps.dependencies.tasks[0].path\n operator: exists\n input:\n message: \"This task still has dependencies.\"\n```\n\n## References\n\nReferences use constrained template expressions. Arbitrary JavaScript is not evaluated.\n\n```text\n{{workflow.id}}\n{{workflow.name}}\n{{trigger.after.path}}\n{{trigger.changes.status.after}}\n{{steps.query.tasks}}\n{{steps.parents.tasks[0].path}}\n{{item.path}}\n{{today}}\n{{now}}\n```\n\nIf a string is exactly one reference, the underlying value is preserved. If a reference is embedded in other text, the value is stringified.\n\nUse `forEach` when a step should run once per item:\n\n```yaml\nsteps:\n - id: overdue\n type: task.query\n input:\n query:\n where:\n all:\n - field: task.due\n op: lt\n value:\n fn: today\n - field: task.status\n op: notIn\n value:\n - done\n - cancelled\n sort:\n - field: task.due\n direction: asc\n limit: 50\n scope:\n includeArchived: false\n\n - id: mark-high\n type: task.patch\n forEach: \"{{steps.overdue.tasks}}\"\n input:\n task: \"{{item.path}}\"\n patch:\n priority: high\n```\n\nWhen a step uses `forEach`, `{{item}}` refers to the current item and the step output becomes an array of per-item outputs.\n\n`task.query` uses the canonical TaskNotes runtime query DTO. Its output includes `tasks`, `count`, `total`, `matched`, `returned`, `groups`, `groupPaths`, `query`, and `warnings`.\n\nRuntime query conditions use canonical field IDs and operators:\n\n```yaml\nquery:\n where:\n all:\n - field: task.status\n op: ne\n value: done\n - any:\n - field: task.due\n op: lte\n value:\n fn: today\n - field: task.priority\n op: eq\n value: high\n sort:\n - field: task.due\n direction: asc\n group:\n - field: task.status\n limit: 25\n scope:\n includeArchived: false\n```\n\nCommon fields include `task.status`, `task.priority`, `task.due`, `task.scheduled`, `task.projects`, `task.contexts`, `task.tags`, `task.isBlocked`, and `file.path`. Operators include `eq`, `ne`, `contains`, `notContains`, `in`, `notIn`, `exists`, `missing`, `lt`, `lte`, `gt`, `gte`, `isTrue`, and `isFalse`. Use `api.catalog.filterProperties()` and `api.catalog.filterOperators()` for the complete runtime catalog.\n\n## Steps\n\nSteps are typed actions. The editor reads a step catalog so it can show expected inputs, output fields, examples, and TaskNotes option pickers.\n\nTask read steps:\n\n| Step | Output |\n| --- | --- |\n| `task.get` | One task. |\n| `task.query` | Tasks matching a canonical TaskNotes runtime query. |\n| `task.parents` | Parent tasks linked from the task's projects. |\n| `task.subtasks` | Tasks that reference the current task as a project. |\n| `task.dependencies` | Dependencies stored in `blockedBy`, with resolved task data when available. |\n| `task.blocking` | Tasks blocked by the current task. |\n| `task.relationships` | The task plus parents, subtasks, dependencies, and blocking tasks. |\n\nTask write steps:\n\n| Step | Purpose |\n| --- | --- |\n| `task.create` | Create a new TaskNotes task. |\n| `task.patch` | Update one or more fields. |\n| `task.set` | Set one field. |\n| `task.move` | Move the task note to a target folder. |\n| `task.archive` / `task.unarchive` | Archive or unarchive a task. |\n| `task.complete` / `task.uncomplete` | Complete or reopen a task. |\n| `task.reschedule` | Update planning dates. |\n| `task.setDue` / `task.clearDue` | Set or clear due date. |\n| `task.setScheduled` / `task.clearScheduled` | Set or clear scheduled date. |\n| `task.addTag` / `task.removeTag` | Mutate tags. |\n| `task.addProject` / `task.removeProject` | Mutate project links. |\n| `task.addContext` / `task.removeContext` | Mutate contexts. |\n| `task.addDependency` / `task.removeDependency` | Mutate blocking dependencies. |\n\nTime and utility steps:\n\n| Step | Purpose |\n| --- | --- |\n| `time.start` | Start time tracking for a task. |\n| `time.stop` | Stop active time tracking for a task. |\n| `time.appendEntry` | Append a time entry. |\n| `notice.show` | Show an Obsidian notice. |\n| `workflow.stop` | Stop a workflow early. |\n\nCompanion plugins and scripts can inspect the same catalog through the TaskNotes runtime extension:\n\n```js\nconst tasknotes = app.plugins.getPlugin(\"tasknotes\")?.api;\nconst workflows = tasknotes?.extensions.get(\"tasknotes-workflows\");\nconst steps = workflows?.listStepDefinitions();\n```\n\n## Run Policy\n\nEvery workflow has a run policy:\n\n```yaml\nrun:\n mode: sequential\n noOverlap: true\n source: tasknotes-workflows\n maxTasks: 25\n onError: stop\n timeout: 30s\n```\n\n| Field | Notes |\n| --- | --- |\n| `mode` | Currently `sequential`. Steps run in order. |\n| `noOverlap` | Skips a new run if the same workflow is already running. |\n| `source` | Mutation source passed to TaskNotes runtime API calls. |\n| `maxTasks` | Safety limit for `forEach` batch steps. |\n| `onError` | `stop` or `continue`. |\n| `timeout` | Optional duration string. |\n\nTaskNotes attaches `source`, correlation, and reason metadata to events caused by runtime API writes. Workflows use this to make runs debuggable and to avoid accidental self-trigger loops.\n\n## Run Logs and Debugging\n\nWorkflow run logs are stored under the plugin's Obsidian config folder by default. You can configure a run-log folder and a log level in the plugin settings.\n\nRun records include:\n\n- Workflow id, name, and source path.\n- Trigger payload.\n- Step statuses.\n- Inputs and outputs, depending on the configured log level.\n- Error text when a run fails.\n\nUse dry runs before enabling workflows that mutate tasks. Dry runs still execute the workflow path, but mutating steps should report what they would do instead of changing task files.\n\n## Example: Manual Command Workflow\n\nThis workflow can be run from the command palette after it is enabled:\n\n```markdown\n---\ntype: tasknotes-workflow\nschemaVersion: 1\nid: show-active-count\nname: Show active task count\nenabled: true\ndescription: Show a notice with the number of active tasks.\ntriggers:\n - id: manual\n type: manual\nsteps:\n - id: active\n type: task.query\n input:\n query:\n where:\n field: task.status\n op: eq\n value: active\n limit: 25\n scope:\n includeArchived: false\n - id: notice\n type: notice.show\n input:\n message: \"Active tasks: {{steps.active.count}}\"\nrun:\n mode: sequential\n noOverlap: true\n source: tasknotes-workflows\n maxTasks: 25\n onError: stop\n---\n\n# Show active task count\n\nRun this from the Obsidian command palette with `TaskNotes Workflows: Run: Show active task count`.\n```\n\n## Example: Inherit Parent Priority\n\nThis workflow copies priority from the first parent task when a task becomes a subtask:\n\n```yaml\ntype: tasknotes-workflow\nschemaVersion: 1\nid: inherit-subtask-priority\nname: Inherit subtask priority\nenabled: false\ntriggers:\n - id: projects-changed\n type: tasknotes.event\n event: task.projects.changed\n - id: task-created\n type: tasknotes.event\n event: task.created\nconditions:\n - field: trigger.after.path\n operator: exists\n - field: trigger.after.projects\n operator: exists\nsteps:\n - id: parents\n type: task.parents\n input:\n task: \"{{trigger.after.path}}\"\n - id: inherit-priority\n type: task.patch\n if:\n - field: steps.parents.tasks[0].priority\n operator: exists\n input:\n task: \"{{trigger.after.path}}\"\n patch:\n priority: \"{{steps.parents.tasks[0].priority}}\"\nrun:\n mode: sequential\n noOverlap: true\n source: tasknotes-workflows\n maxTasks: 1\n onError: stop\n```\n\nThis pattern uses `task.parents` rather than trying to parse project links manually.\n\n## Authoring Guidelines\n\nWhen writing workflow notes:\n\n- Start with `enabled: false` for any workflow that mutates tasks.\n- Give every trigger and step a stable `id`.\n- Prefer typed TaskNotes steps over direct frontmatter editing.\n- Use relationship read steps such as `task.parents`, `task.subtasks`, and `task.dependencies` for parent/subtask/dependency logic.\n- Add workflow-level conditions for required trigger fields such as `trigger.after.path`.\n- Add `run.noOverlap: true` unless overlapping runs are intentional.\n- Set `run.maxTasks` for batch workflows.\n- Use `allowSelfTrigger: true` only when the workflow really should react to its own writes.\n- Keep the Markdown body useful for future maintenance: describe what the workflow changes, how to test it, and why it exists.\n\n## Troubleshooting\n\n### Task steps do not run\n\nConfirm TaskNotes is enabled and exposes the runtime API. The workflow Base can display definitions without TaskNotes, but steps such as `task.patch`, `time.start`, or `task.dependencies` need TaskNotes.\n\n### A manual workflow is missing from the command palette\n\nCheck that:\n\n- The workflow is valid.\n- `enabled` is `true`.\n- It has a `manual` trigger.\n- The workflow `id` is valid and stable.\n- Workflows have reloaded after editing the file.\n\nDisabled manual workflows can still be dry-run from the workflow card, but they are not registered as run commands.\n\n### A cron or interval workflow did not run\n\nScheduled workflows only run while Obsidian is open and the plugin is loaded. Check the schedule, timezone, enabled state, and `run.maxTasks` limit.\n\n### A workflow runs more than once\n\nCheck whether multiple triggers match the same update. Also check `allowSelfTrigger`; most workflows should leave it unset so they do not react to writes caused by `tasknotes-workflows`.\n\n### A workflow is invalid\n\nOpen the workflow Base or the workflow note card. Validation messages point to the field path, such as `triggers[0].type` or `steps[1].input`.\n\nCommon causes are missing required fields, unsupported trigger types, invalid YAML, or references to step outputs that do not exist.\n","aliases":["/companion-plugins/tasknotes-workflows/"],"toc":[{"level":2,"id":"install-tasknotes-workflows","text":"Install TaskNotes Workflows"},{"level":2,"id":"requirements","text":"Requirements"},{"level":2,"id":"files-created-by-the-plugin","text":"Files Created by the Plugin"},{"level":2,"id":"first-run","text":"First Run"},{"level":2,"id":"default-workflows","text":"Default Workflows"},{"level":2,"id":"workflow-shape","text":"Workflow Shape"},{"level":2,"id":"triggers","text":"Triggers"},{"level":3,"id":"tasknotes-events","text":"TaskNotes Events"},{"level":3,"id":"cron","text":"Cron"},{"level":3,"id":"interval","text":"Interval"},{"level":3,"id":"manual","text":"Manual"},{"level":3,"id":"obsidian-events","text":"Obsidian Events"},{"level":2,"id":"conditions","text":"Conditions"},{"level":2,"id":"references","text":"References"},{"level":2,"id":"steps","text":"Steps"},{"level":2,"id":"run-policy","text":"Run Policy"},{"level":2,"id":"run-logs-and-debugging","text":"Run Logs and Debugging"},{"level":2,"id":"example-manual-command-workflow","text":"Example: Manual Command Workflow"},{"level":2,"id":"example-inherit-parent-priority","text":"Example: Inherit Parent Priority"},{"level":2,"id":"authoring-guidelines","text":"Authoring Guidelines"},{"level":2,"id":"troubleshooting","text":"Troubleshooting"},{"level":3,"id":"task-steps-do-not-run","text":"Task steps do not run"},{"level":3,"id":"a-manual-workflow-is-missing-from-the-command-palette","text":"A manual workflow is missing from the command palette"},{"level":3,"id":"a-cron-or-interval-workflow-did-not-run","text":"A cron or interval workflow did not run"},{"level":3,"id":"a-workflow-runs-more-than-once","text":"A workflow runs more than once"},{"level":3,"id":"a-workflow-is-invalid","text":"A workflow is invalid"}],"html":"

TaskNotes Workflows is a companion plugin for Markdown-defined automation. It lets you create workflow notes that respond to TaskNotes events, schedules, manual commands, and selected Obsidian events, then run typed actions against TaskNotes tasks.

\n

Install TaskNotes Workflows#

\n\n\n

You can also install it from Obsidian: open Settings > Community plugins > Browse, then search for TaskNotes Workflows.

\n

The plugin is designed for workflows users often ask TaskNotes core to handle, such as:

\n
    \n
  • Start time tracking when a task becomes active.
  • \n
  • Stop time tracking when a task is completed.
  • \n
  • Move completed tasks into a review folder.
  • \n
  • Copy parent task context, tags, priority, dates, or dependencies to subtasks.
  • \n
  • Warn when a blocked task is moved to active.
  • \n
  • Run a daily review query.
  • \n
\n

TaskNotes Workflows keeps this behavior outside TaskNotes core while still using the TaskNotes JavaScript Runtime API for safe task reads, writes, canonical queries, events, and relationship resolution.

\n

Requirements#

\n
    \n
  • TaskNotes must be installed and enabled.
  • \n
  • TaskNotes must expose the JavaScript runtime API.
  • \n
  • Obsidian must be open for workflows to run.
  • \n
  • Scheduled workflows run while Obsidian is running. They are not a background service when Obsidian is closed.
  • \n
  • The plugin runtime uses Obsidian APIs only. Node is used for development and build scripts, not for workflow execution, so Markdown workflow definitions can work on Obsidian mobile while the plugin is loaded.
  • \n
\n

If TaskNotes is disabled or unavailable, the workflow Base can still validate and display workflow files, but TaskNotes read/write steps cannot run.

\n

Files Created by the Plugin#

\n

By default, TaskNotes Workflows uses:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
PathPurpose
TaskNotes/Workflows/Workflow Markdown files.
TaskNotes/Views/workflows.baseGenerated Obsidian Base that renders workflow cards through the custom workflow view.
Plugin config folderRun history and detail logs, unless a run-log folder is configured.
\n

Workflow notes are ordinary Markdown files. The YAML frontmatter is executable configuration, and the note body is for human explanation, testing notes, and maintenance guidance.

\n

First Run#

\n

On first load, the plugin can create a default workflow folder, a workflow Base, and a set of example workflow notes. The default workflow notes are disabled so they can be inspected, dry-run, edited, and enabled intentionally.

\n

The generated Base is the main workbench. It shows workflow cards with status, trigger and step summaries, recent run state, and buttons for editing, dry-running, running, and opening the source note.

\n

Workflow notes also show a compact workflow card in reading mode and live preview, so the note remains useful even when opened directly.

\n

Default Workflows#

\n

The plugin can write these starter workflows:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
WorkflowWhat it demonstrates
Auto-start time trackingStarts a timer when a task status changes to active.
Stop time tracking on completeStops the timer when a task is completed.
Morning overdue reviewRuns a daily cron query and marks overdue open tasks high priority.
Move completed tasks to reviewMoves completed task notes into a review folder.
Inherit subtask contexts and tagsCopies contexts and tags from the first parent task when a task becomes a subtask.
Inherit subtask priorityCopies priority from the first parent task when a task becomes a subtask.
Inherit subtask planning datesCopies scheduled and due dates from the first parent task when a task becomes a subtask.
Inherit subtask dependenciesAdds the first parent task's blocking dependencies to new subtasks.
Mirror parent priority to subtasksUpdates existing subtasks when a parent task priority changes.
Mirror parent planning dates to subtasksUpdates existing subtasks when a parent scheduled or due date changes.
Mirror parent dependencies to subtasksReplaces each subtask's dependencies with the parent task's current dependencies.
Warn when starting a blocked taskShows a notice when a task becomes active while dependencies remain.
Daily active task reviewShows a daily count of tasks still marked active.
\n

Treat these as editable examples. Adjust folders, statuses, priorities, dates, and filters to match your vault before enabling mutating workflows.

\n

Workflow Shape#

\n

A workflow file looks like this:

\n
---\ntype: tasknotes-workflow\nschemaVersion: 1\nid: auto-start-time-tracking\nname: Auto-start time tracking\nenabled: false\ndescription: Start a timer when a task status changes to active.\ntriggers:\n  - id: status-active\n    type: tasknotes.event\n    event: task.status.changed\n    to: active\nconditions:\n  - field: trigger.after.path\n    operator: exists\nsteps:\n  - id: start-time\n    type: time.start\n    input:\n      task: "{{trigger.after.path}}"\n      options:\n        description: "Started by {{workflow.name}}"\nrun:\n  mode: sequential\n  noOverlap: true\n  source: tasknotes-workflows\n  maxTasks: 1\n  onError: stop\n---\n\n# Auto-start time tracking\n\nEnable this workflow to start time tracking when a TaskNotes task moves to `active`.\n

Required frontmatter fields:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
FieldTypeNotes
typestringMust be tasknotes-workflow.
schemaVersionnumberMust be 1.
idstringStable lowercase identifier. Use letters, numbers, dots, underscores, and dashes.
namestringHuman-readable name shown in workflow cards and command-palette commands.
enabledbooleanDisabled workflows can be edited and dry-run but do not run automatically or from manual commands.
triggersarrayOne or more trigger definitions.
conditionsarrayOptional workflow-level guards.
stepsarrayLinear typed step pipeline.
runobjectRun policy and safety limits.
\n

Triggers#

\n

Triggers decide when a workflow should run.

\n

TaskNotes Events#

\n

Use tasknotes.event to react to TaskNotes runtime events:

\n
triggers:\n  - id: status-active\n    type: tasknotes.event\n    event: task.status.changed\n    from: open\n    to: active\n

Common event names include:

\n
    \n
  • task.created
  • \n
  • task.updated
  • \n
  • task.deleted
  • \n
  • task.moved
  • \n
  • task.status.changed
  • \n
  • task.completed
  • \n
  • task.uncompleted
  • \n
  • task.archived
  • \n
  • task.unarchived
  • \n
  • task.scheduled.changed
  • \n
  • task.due.changed
  • \n
  • task.priority.changed
  • \n
  • task.tags.changed
  • \n
  • task.contexts.changed
  • \n
  • task.projects.changed
  • \n
  • task.reminders.changed
  • \n
  • task.dependencies.changed
  • \n
  • task.recurrence.changed
  • \n
  • time.started
  • \n
  • time.stopped
  • \n
  • pomodoro.started
  • \n
  • pomodoro.completed
  • \n
  • pomodoro.interrupted
  • \n
  • recurring.instance.completed
  • \n
  • recurring.instance.skipped
  • \n
\n

The workflow editor loads available TaskNotes events dynamically from api.events.list(), so event pickers can follow the runtime API instead of relying on a hardcoded list.

\n

TaskNotes event triggers can use these filters:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
FieldPurpose
eventRuntime event name.
fromPrevious status or value for status-change workflows.
toNew status or value for status-change workflows.
path.globOptional path glob limiting which task files can trigger the workflow.
allowSelfTriggerAllows this workflow to react to writes caused by tasknotes-workflows. Leave off unless you have a clear reason.
\n

TaskNotes event output fields include values such as trigger.after.path, trigger.after.status, trigger.before.status, trigger.changes, trigger.source, and trigger.correlationId.

\n

Cron#

\n

Cron triggers run on matching minutes while Obsidian is open:

\n
triggers:\n  - id: weekday-review\n    type: cron\n    schedule: "0 17 * * 1-5"\n    timezone: local\n

The schedule uses five fields: minute, hour, day of month, month, day of week. Keep cron workflows bounded with run.maxTasks, especially if they query many tasks.

\n

Interval#

\n

Interval triggers run repeatedly while Obsidian is open:

\n
triggers:\n  - id: half-hour-check\n    type: interval\n    every: 30m\n

The plugin enforces a minimum interval to avoid excessive background work.

\n

Manual#

\n

Manual triggers let a workflow run from a card button, another plugin, or the Obsidian command palette:

\n
triggers:\n  - id: manual\n    type: manual\n

Enabled workflows with a manual trigger are registered as Obsidian commands named Run: <workflow name>. You can launch them from the command palette or assign hotkeys in Obsidian settings.

\n

The generated command id is based on the workflow id. Changing a workflow id creates a different command, so any hotkey assigned to the old command id will need to be reassigned.

\n

Obsidian Events#

\n

Advanced Obsidian triggers are opt-in from the plugin settings. They can listen to selected vault, metadata, and workspace events:

\n
triggers:\n  - id: project-note-opened\n    type: obsidian.workspace\n    event: file-open\n    path:\n      glob: "Projects/**/*.md"\n\n  - id: task-note-modified\n    type: obsidian.vault\n    event: modify\n    path:\n      glob: "Tasks/**/*.md"\n\n  - id: metadata-changed\n    type: obsidian.metadata\n    event: changed\n    path:\n      glob: "Projects/**/*.md"\n

Keep path filters narrow for Obsidian triggers. Vault and metadata events can be frequent.

\n

Conditions#

\n

Conditions can appear at workflow level or on individual steps.

\n
conditions:\n  - field: trigger.after.path\n    operator: exists\n  - field: trigger.after.status\n    operator: is\n    value: active\n

Supported operators:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
OperatorMeaning
is / isNotExact comparison after scalar normalization.
in / notInCheck a value against an array.
exists / missingCheck whether a field has a value.
containsCheck whether a string contains text or an array contains a value.
startsWithString prefix check.
before / afterDate comparison.
onOrBefore / onOrAfterInclusive date comparison.
\n

Step-level conditions use the same shape:

\n
steps:\n  - id: warn\n    type: notice.show\n    if:\n      - field: steps.dependencies.tasks[0].path\n        operator: exists\n    input:\n      message: "This task still has dependencies."\n

References#

\n

References use constrained template expressions. Arbitrary JavaScript is not evaluated.

\n
{{workflow.id}}\n{{workflow.name}}\n{{trigger.after.path}}\n{{trigger.changes.status.after}}\n{{steps.query.tasks}}\n{{steps.parents.tasks[0].path}}\n{{item.path}}\n{{today}}\n{{now}}\n

If a string is exactly one reference, the underlying value is preserved. If a reference is embedded in other text, the value is stringified.

\n

Use forEach when a step should run once per item:

\n
steps:\n  - id: overdue\n    type: task.query\n    input:\n      query:\n        where:\n          all:\n            - field: task.due\n              op: lt\n              value:\n                fn: today\n            - field: task.status\n              op: notIn\n              value:\n                - done\n                - cancelled\n        sort:\n          - field: task.due\n            direction: asc\n        limit: 50\n        scope:\n          includeArchived: false\n\n  - id: mark-high\n    type: task.patch\n    forEach: "{{steps.overdue.tasks}}"\n    input:\n      task: "{{item.path}}"\n      patch:\n        priority: high\n

When a step uses forEach, {{item}} refers to the current item and the step output becomes an array of per-item outputs.

\n

task.query uses the canonical TaskNotes runtime query DTO. Its output includes tasks, count, total, matched, returned, groups, groupPaths, query, and warnings.

\n

Runtime query conditions use canonical field IDs and operators:

\n
query:\n  where:\n    all:\n      - field: task.status\n        op: ne\n        value: done\n      - any:\n          - field: task.due\n            op: lte\n            value:\n              fn: today\n          - field: task.priority\n            op: eq\n            value: high\n  sort:\n    - field: task.due\n      direction: asc\n  group:\n    - field: task.status\n  limit: 25\n  scope:\n    includeArchived: false\n

Common fields include task.status, task.priority, task.due, task.scheduled, task.projects, task.contexts, task.tags, task.isBlocked, and file.path. Operators include eq, ne, contains, notContains, in, notIn, exists, missing, lt, lte, gt, gte, isTrue, and isFalse. Use api.catalog.filterProperties() and api.catalog.filterOperators() for the complete runtime catalog.

\n

Steps#

\n

Steps are typed actions. The editor reads a step catalog so it can show expected inputs, output fields, examples, and TaskNotes option pickers.

\n

Task read steps:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StepOutput
task.getOne task.
task.queryTasks matching a canonical TaskNotes runtime query.
task.parentsParent tasks linked from the task's projects.
task.subtasksTasks that reference the current task as a project.
task.dependenciesDependencies stored in blockedBy, with resolved task data when available.
task.blockingTasks blocked by the current task.
task.relationshipsThe task plus parents, subtasks, dependencies, and blocking tasks.
\n

Task write steps:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StepPurpose
task.createCreate a new TaskNotes task.
task.patchUpdate one or more fields.
task.setSet one field.
task.moveMove the task note to a target folder.
task.archive / task.unarchiveArchive or unarchive a task.
task.complete / task.uncompleteComplete or reopen a task.
task.rescheduleUpdate planning dates.
task.setDue / task.clearDueSet or clear due date.
task.setScheduled / task.clearScheduledSet or clear scheduled date.
task.addTag / task.removeTagMutate tags.
task.addProject / task.removeProjectMutate project links.
task.addContext / task.removeContextMutate contexts.
task.addDependency / task.removeDependencyMutate blocking dependencies.
\n

Time and utility steps:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StepPurpose
time.startStart time tracking for a task.
time.stopStop active time tracking for a task.
time.appendEntryAppend a time entry.
notice.showShow an Obsidian notice.
workflow.stopStop a workflow early.
\n

Companion plugins and scripts can inspect the same catalog through the TaskNotes runtime extension:

\n
const tasknotes = app.plugins.getPlugin("tasknotes")?.api;\nconst workflows = tasknotes?.extensions.get("tasknotes-workflows");\nconst steps = workflows?.listStepDefinitions();\n

Run Policy#

\n

Every workflow has a run policy:

\n
run:\n  mode: sequential\n  noOverlap: true\n  source: tasknotes-workflows\n  maxTasks: 25\n  onError: stop\n  timeout: 30s\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
FieldNotes
modeCurrently sequential. Steps run in order.
noOverlapSkips a new run if the same workflow is already running.
sourceMutation source passed to TaskNotes runtime API calls.
maxTasksSafety limit for forEach batch steps.
onErrorstop or continue.
timeoutOptional duration string.
\n

TaskNotes attaches source, correlation, and reason metadata to events caused by runtime API writes. Workflows use this to make runs debuggable and to avoid accidental self-trigger loops.

\n

Run Logs and Debugging#

\n

Workflow run logs are stored under the plugin's Obsidian config folder by default. You can configure a run-log folder and a log level in the plugin settings.

\n

Run records include:

\n
    \n
  • Workflow id, name, and source path.
  • \n
  • Trigger payload.
  • \n
  • Step statuses.
  • \n
  • Inputs and outputs, depending on the configured log level.
  • \n
  • Error text when a run fails.
  • \n
\n

Use dry runs before enabling workflows that mutate tasks. Dry runs still execute the workflow path, but mutating steps should report what they would do instead of changing task files.

\n

Example: Manual Command Workflow#

\n

This workflow can be run from the command palette after it is enabled:

\n
---\ntype: tasknotes-workflow\nschemaVersion: 1\nid: show-active-count\nname: Show active task count\nenabled: true\ndescription: Show a notice with the number of active tasks.\ntriggers:\n  - id: manual\n    type: manual\nsteps:\n  - id: active\n    type: task.query\n    input:\n      query:\n        where:\n          field: task.status\n          op: eq\n          value: active\n        limit: 25\n        scope:\n          includeArchived: false\n  - id: notice\n    type: notice.show\n    input:\n      message: "Active tasks: {{steps.active.count}}"\nrun:\n  mode: sequential\n  noOverlap: true\n  source: tasknotes-workflows\n  maxTasks: 25\n  onError: stop\n---\n\n# Show active task count\n\nRun this from the Obsidian command palette with `TaskNotes Workflows: Run: Show active task count`.\n

Example: Inherit Parent Priority#

\n

This workflow copies priority from the first parent task when a task becomes a subtask:

\n
type: tasknotes-workflow\nschemaVersion: 1\nid: inherit-subtask-priority\nname: Inherit subtask priority\nenabled: false\ntriggers:\n  - id: projects-changed\n    type: tasknotes.event\n    event: task.projects.changed\n  - id: task-created\n    type: tasknotes.event\n    event: task.created\nconditions:\n  - field: trigger.after.path\n    operator: exists\n  - field: trigger.after.projects\n    operator: exists\nsteps:\n  - id: parents\n    type: task.parents\n    input:\n      task: "{{trigger.after.path}}"\n  - id: inherit-priority\n    type: task.patch\n    if:\n      - field: steps.parents.tasks[0].priority\n        operator: exists\n    input:\n      task: "{{trigger.after.path}}"\n      patch:\n        priority: "{{steps.parents.tasks[0].priority}}"\nrun:\n  mode: sequential\n  noOverlap: true\n  source: tasknotes-workflows\n  maxTasks: 1\n  onError: stop\n

This pattern uses task.parents rather than trying to parse project links manually.

\n

Authoring Guidelines#

\n

When writing workflow notes:

\n
    \n
  • Start with enabled: false for any workflow that mutates tasks.
  • \n
  • Give every trigger and step a stable id.
  • \n
  • Prefer typed TaskNotes steps over direct frontmatter editing.
  • \n
  • Use relationship read steps such as task.parents, task.subtasks, and task.dependencies for parent/subtask/dependency logic.
  • \n
  • Add workflow-level conditions for required trigger fields such as trigger.after.path.
  • \n
  • Add run.noOverlap: true unless overlapping runs are intentional.
  • \n
  • Set run.maxTasks for batch workflows.
  • \n
  • Use allowSelfTrigger: true only when the workflow really should react to its own writes.
  • \n
  • Keep the Markdown body useful for future maintenance: describe what the workflow changes, how to test it, and why it exists.
  • \n
\n

Troubleshooting#

\n

Task steps do not run#

\n

Confirm TaskNotes is enabled and exposes the runtime API. The workflow Base can display definitions without TaskNotes, but steps such as task.patch, time.start, or task.dependencies need TaskNotes.

\n

A manual workflow is missing from the command palette#

\n

Check that:

\n
    \n
  • The workflow is valid.
  • \n
  • enabled is true.
  • \n
  • It has a manual trigger.
  • \n
  • The workflow id is valid and stable.
  • \n
  • Workflows have reloaded after editing the file.
  • \n
\n

Disabled manual workflows can still be dry-run from the workflow card, but they are not registered as run commands.

\n

A cron or interval workflow did not run#

\n

Scheduled workflows only run while Obsidian is open and the plugin is loaded. Check the schedule, timezone, enabled state, and run.maxTasks limit.

\n

A workflow runs more than once#

\n

Check whether multiple triggers match the same update. Also check allowSelfTrigger; most workflows should leave it unset so they do not react to writes caused by tasknotes-workflows.

\n

A workflow is invalid#

\n

Open the workflow Base or the workflow note card. Validation messages point to the field path, such as triggers[0].type or steps[1].input.

\n

Common causes are missing required fields, unsupported trigger types, invalid YAML, or references to step outputs that do not exist.

\n","text":"TaskNotes Workflows is a companion plugin for Markdown-defined automation. It lets you create workflow notes that respond to TaskNotes events, schedules, manual commands, and selected Obsidian events, then run typed actions against TaskNotes tasks. Install TaskNotes Workflows# Install from Obsidian Community Plugins Open the TaskNotes Workflows listing in the Obsidian plugin directory You can also install it from Obsidian: open Settings > Community plugins > Browse, then search for TaskNotes Workflows. The plugin is designed for workflows users often ask TaskNotes core to handle, such as: Start time tracking when a task becomes active. Stop time tracking when a task is completed. Move completed tasks into a review folder. Copy parent task context, tags, priority, dates, or dependencies to subtasks. Warn when a blocked task is moved to active. Run a daily review query. TaskNotes Workflows keeps this behavior outside TaskNotes core while still using the TaskNotes JavaScript Runtime API for safe task reads, writes, canonical queries, events, and relationship resolution. Requirements# TaskNotes must be installed and enabled. TaskNotes must expose the JavaScript runtime API. Obsidian must be open for workflows to run. Scheduled workflows run while Obsidian is running. They are not a background service when Obsidian is closed. The plugin runtime uses Obsidian APIs only. Node is used for development and build scripts, not for workflow execution, so Markdown workflow definitions can work on Obsidian mobile while the plugin is loaded. If TaskNotes is disabled or unavailable, the workflow Base can still validate and display workflow files, but TaskNotes read/write steps cannot run. Files Created by the Plugin# By default, TaskNotes Workflows uses: Path Purpose TaskNotes/Workflows/ Workflow Markdown files. TaskNotes/Views/workflows.base Generated Obsidian Base that renders workflow cards through the custom workflow view. Plugin config folder Run history and detail logs, unless a run-log folder is configured. Workflow notes are ordinary Markdown files. The YAML frontmatter is executable configuration, and the note body is for human explanation, testing notes, and maintenance guidance. First Run# On first load, the plugin can create a default workflow folder, a workflow Base, and a set of example workflow notes. The default workflow notes are disabled so they can be inspected, dry-run, edited, and enabled intentionally. The generated Base is the main workbench. It shows workflow cards with status, trigger and step summaries, recent run state, and buttons for editing, dry-running, running, and opening the source note. Workflow notes also show a compact workflow card in reading mode and live preview, so the note remains useful even when opened directly. Default Workflows# The plugin can write these starter workflows: Workflow What it demonstrates Auto-start time tracking Starts a timer when a task status changes to active. Stop time tracking on complete Stops the timer when a task is completed. Morning overdue review Runs a daily cron query and marks overdue open tasks high priority. Move completed tasks to review Moves completed task notes into a review folder. Inherit subtask contexts and tags Copies contexts and tags from the first parent task when a task becomes a subtask. Inherit subtask priority Copies priority from the first parent task when a task becomes a subtask. Inherit subtask planning dates Copies scheduled and due dates from the first parent task when a task becomes a subtask. Inherit subtask dependencies Adds the first parent task's blocking dependencies to new subtasks. Mirror parent priority to subtasks Updates existing subtasks when a parent task priority changes. Mirror parent planning dates to subtasks Updates existing subtasks when a parent scheduled or due date changes. Mirror parent dependencies to subtasks Replaces each subtask's dependencies with the parent task's current dependencies. Warn when starting a blocked task Shows a notice when a task becomes active while dependencies remain. Daily active task review Shows a daily count of tasks still marked active. Treat these as editable examples. Adjust folders, statuses, priorities, dates, and filters to match your vault before enabling mutating workflows. Workflow Shape# A workflow file looks like this: --- type: tasknotes-workflow schemaVersion: 1 id: auto-start-time-tracking name: Auto-start time tracking enabled: false description: Start a timer when a task status changes to active. triggers: - id: status-active type: tasknotes.event event: task.status.changed to: active conditions: - field: trigger.after.path operator: exists steps: - id: start-time type: time.start input: task: \"{{trigger.after.path}}\" options: description: \"Started by {{workflow.name}}\" run: mode: sequential noOverlap: true source: tasknotes-workflows maxTasks: 1 onError: stop --- # Auto-start time tracking Enable this workflow to start time tracking when a TaskNotes task moves to `active`. Required frontmatter fields: Field Type Notes type string Must be tasknotes-workflow. schemaVersion number Must be 1. id string Stable lowercase identifier. Use letters, numbers, dots, underscores, and dashes. name string Human-readable name shown in workflow cards and command-palette commands. enabled boolean Disabled workflows can be edited and dry-run but do not run automatically or from manual commands. triggers array One or more trigger definitions. conditions array Optional workflow-level guards. steps array Linear typed step pipeline. run object Run policy and safety limits. Triggers# Triggers decide when a workflow should run. TaskNotes Events# Use tasknotes.event to react to TaskNotes runtime events: triggers: - id: status-active type: tasknotes.event event: task.status.changed from: open to: active Common event names include: task.created task.updated task.deleted task.moved task.status.changed task.completed task.uncompleted task.archived task.unarchived task.scheduled.changed task.due.changed task.priority.changed task.tags.changed task.contexts.changed task.projects.changed task.reminders.changed task.dependencies.changed task.recurrence.changed time.started time.stopped pomodoro.started pomodoro.completed pomodoro.interrupted recurring.instance.completed recurring.instance.skipped The workflow editor loads available TaskNotes events dynamically from api.events.list(), so event pickers can follow the runtime API instead of relying on a hardcoded list. TaskNotes event triggers can use these filters: Field Purpose event Runtime event name. from Previous status or value for status-change workflows. to New status or value for status-change workflows. path.glob Optional path glob limiting which task files can trigger the workflow. allowSelfTrigger Allows this workflow to react to writes caused by tasknotes-workflows. Leave off unless you have a clear reason. TaskNotes event output fields include values such as trigger.after.path, trigger.after.status, trigger.before.status, trigger.changes, trigger.source, and trigger.correlationId. Cron# Cron triggers run on matching minutes while Obsidian is open: triggers: - id: weekday-review type: cron schedule: \"0 17 * * 1-5\" timezone: local The schedule uses five fields: minute, hour, day of month, month, day of week. Keep cron workflows bounded with run.maxTasks, especially if they query many tasks. Interval# Interval triggers run repeatedly while Obsidian is open: triggers: - id: half-hour-check type: interval every: 30m The plugin enforces a minimum interval to avoid excessive background work. Manual# Manual triggers let a workflow run from a card button, another plugin, or the Obsidian command palette: triggers: - id: manual type: manual Enabled workflows with a manual trigger are registered as Obsidian commands named Run: . You can launch them from the command palette or assign hotkeys in Obsidian settings. The generated command id is based on the workflow id. Changing a workflow id creates a different command, so any hotkey assigned to the old command id will need to be reassigned. Obsidian Events# Advanced Obsidian triggers are opt-in from the plugin settings. They can listen to selected vault, metadata, and workspace events: triggers: - id: project-note-opened type: obsidian.workspace event: file-open path: glob: \"Projects/**/*.md\" - id: task-note-modified type: obsidian.vault event: modify path: glob: \"Tasks/**/*.md\" - id: metadata-changed type: obsidian.metadata event: changed path: glob: \"Projects/**/*.md\" Keep path filters narrow for Obsidian triggers. Vault and metadata events can be frequent. Conditions# Conditions can appear at workflow level or on individual steps. conditions: - field: trigger.after.path operator: exists - field: trigger.after.status operator: is value: active Supported operators: Operator Meaning is / isNot Exact comparison after scalar normalization. in / notIn Check a value against an array. exists / missing Check whether a field has a value. contains Check whether a string contains text or an array contains a value. startsWith String prefix check. before / after Date comparison. onOrBefore / onOrAfter Inclusive date comparison. Step-level conditions use the same shape: steps: - id: warn type: notice.show if: - field: steps.dependencies.tasks[0].path operator: exists input: message: \"This task still has dependencies.\" References# References use constrained template expressions. Arbitrary JavaScript is not evaluated. {{workflow.id}} {{workflow.name}} {{trigger.after.path}} {{trigger.changes.status.after}} {{steps.query.tasks}} {{steps.parents.tasks[0].path}} {{item.path}} {{today}} {{now}} If a string is exactly one reference, the underlying value is preserved. If a reference is embedded in other text, the value is stringified. Use forEach when a step should run once per item: steps: - id: overdue type: task.query input: query: where: all: - field: task.due op: lt value: fn: today - field: task.status op: notIn value: - done - cancelled sort: - field: task.due direction: asc limit: 50 scope: includeArchived: false - id: mark-high type: task.patch forEach: \"{{steps.overdue.tasks}}\" input: task: \"{{item.path}}\" patch: priority: high When a step uses forEach, {{item}} refers to the current item and the step output becomes an array of per-item outputs. task.query uses the canonical TaskNotes runtime query DTO. Its output includes tasks, count, total, matched, returned, groups, groupPaths, query, and warnings. Runtime query conditions use canonical field IDs and operators: query: where: all: - field: task.status op: ne value: done - any: - field: task.due op: lte value: fn: today - field: task.priority op: eq value: high sort: - field: task.due direction: asc group: - field: task.status limit: 25 scope: includeArchived: false Common fields include task.status, task.priority, task.due, task.scheduled, task.projects, task.contexts, task.tags, task.isBlocked, and file.path. Operators include eq, ne, contains, notContains, in, notIn, exists, missing, lt, lte, gt, gte, isTrue, and isFalse. Use api.catalog.filterProperties() and api.catalog.filterOperators() for the complete runtime catalog. Steps# Steps are typed actions. The editor reads a step catalog so it can show expected inputs, output fields, examples, and TaskNotes option pickers. Task read steps: Step Output task.get One task. task.query Tasks matching a canonical TaskNotes runtime query. task.parents Parent tasks linked from the task's projects. task.subtasks Tasks that reference the current task as a project. task.dependencies Dependencies stored in blockedBy, with resolved task data when available. task.blocking Tasks blocked by the current task. task.relationships The task plus parents, subtasks, dependencies, and blocking tasks. Task write steps: Step Purpose task.create Create a new TaskNotes task. task.patch Update one or more fields. task.set Set one field. task.move Move the task note to a target folder. task.archive / task.unarchive Archive or unarchive a task. task.complete / task.uncomplete Complete or reopen a task. task.reschedule Update planning dates. task.setDue / task.clearDue Set or clear due date. task.setScheduled / task.clearScheduled Set or clear scheduled date. task.addTag / task.removeTag Mutate tags. task.addProject / task.removeProject Mutate project links. task.addContext / task.removeContext Mutate contexts. task.addDependency / task.removeDependency Mutate blocking dependencies. Time and utility steps: Step Purpose time.start Start time tracking for a task. time.stop Stop active time tracking for a task. time.appendEntry Append a time entry. notice.show Show an Obsidian notice. workflow.stop Stop a workflow early. Companion plugins and scripts can inspect the same catalog through the TaskNotes runtime extension: const tasknotes = app.plugins.getPlugin(\"tasknotes\")?.api; const workflows = tasknotes?.extensions.get(\"tasknotes-workflows\"); const steps = workflows?.listStepDefinitions(); Run Policy# Every workflow has a run policy: run: mode: sequential noOverlap: true source: tasknotes-workflows maxTasks: 25 onError: stop timeout: 30s Field Notes mode Currently sequential. Steps run in order. noOverlap Skips a new run if the same workflow is already running. source Mutation source passed to TaskNotes runtime API calls. maxTasks Safety limit for forEach batch steps. onError stop or continue. timeout Optional duration string. TaskNotes attaches source, correlation, and reason metadata to events caused by runtime API writes. Workflows use this to make runs debuggable and to avoid accidental self-trigger loops. Run Logs and Debugging# Workflow run logs are stored under the plugin's Obsidian config folder by default. You can configure a run-log folder and a log level in the plugin settings. Run records include: Workflow id, name, and source path. Trigger payload. Step statuses. Inputs and outputs, depending on the configured log level. Error text when a run fails. Use dry runs before enabling workflows that mutate tasks. Dry runs still execute the workflow path, but mutating steps should report what they would do instead of changing task files. Example: Manual Command Workflow# This workflow can be run from the command palette after it is enabled: --- type: tasknotes-workflow schemaVersion: 1 id: show-active-count name: Show active task count enabled: true description: Show a notice with the number of active tasks. triggers: - id: manual type: manual steps: - id: active type: task.query input: query: where: field: task.status op: eq value: active limit: 25 scope: includeArchived: false - id: notice type: notice.show input: message: \"Active tasks: {{steps.active.count}}\" run: mode: sequential noOverlap: true source: tasknotes-workflows maxTasks: 25 onError: stop --- # Show active task count Run this from the Obsidian command palette with `TaskNotes Workflows: Run: Show active task count`. Example: Inherit Parent Priority# This workflow copies priority from the first parent task when a task becomes a subtask: type: tasknotes-workflow schemaVersion: 1 id: inherit-subtask-priority name: Inherit subtask priority enabled: false triggers: - id: projects-changed type: tasknotes.event event: task.projects.changed - id: task-created type: tasknotes.event event: task.created conditions: - field: trigger.after.path operator: exists - field: trigger.after.projects operator: exists steps: - id: parents type: task.parents input: task: \"{{trigger.after.path}}\" - id: inherit-priority type: task.patch if: - field: steps.parents.tasks[0].priority operator: exists input: task: \"{{trigger.after.path}}\" patch: priority: \"{{steps.parents.tasks[0].priority}}\" run: mode: sequential noOverlap: true source: tasknotes-workflows maxTasks: 1 onError: stop This pattern uses task.parents rather than trying to parse project links manually. Authoring Guidelines# When writing workflow notes: Start with enabled: false fo"},{"route":"/obsidian/core-concepts/","title":"Core Concepts","description":"TaskNotes follows the \"one note per task\" principle, where each task lives as a separate Markdown note with structured metadata in YAML frontmatter.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/core-concepts.md","namespace":"obsidian","relativePath":"core-concepts.md","raw":"# Core Concepts\n\nTaskNotes follows the \"one note per task\" principle, where each task lives as a separate Markdown note with structured metadata in YAML frontmatter.\n\n## The Note-Per-Task Approach\n\nIndividual Markdown notes replace centralized databases or proprietary formats. Each task file can be read, edited, and backed up with any text editor or automation tool.\n\n### Task Structure\n\nA TaskNotes task is a standard Markdown file with YAML frontmatter:\n\n```markdown\n---\ntags:\n - task\ntitle: Review quarterly report\nstatus: in-progress\npriority: high\ndue: 2025-01-15\nscheduled: 2025-01-14\ncontexts:\n - office\nprojects:\n - \"[[Q1 Planning]]\"\n---\n\n## Notes\n\nKey points to review:\n- Revenue projections\n- Budget allocations\n\n## Meeting Notes\n\nDiscussion with finance team on 2025-01-10...\n```\n\nThe frontmatter contains structured, queryable properties. The note body holds freeform content—research findings, meeting notes, checklists, or links to related documents.\n\n### Obsidian Integration\n\nSince tasks are proper notes, they work with Obsidian's core features:\n\n- **Backlinks**: See which notes reference a task\n- **Graph View**: Visualize task relationships and project connections\n- **Tags**: Use Obsidian's tag system for additional categorization\n- **Search**: Find tasks using Obsidian's search\n- **Links**: Reference tasks from daily notes, meeting notes, or project documents\n\nThis approach creates many small files. TaskNotes stores tasks in a configurable folder (default: `TaskNotes/Tasks/`) to keep them organized.\nIn practice, this lets TaskNotes fit into existing vault habits instead of replacing them. You keep using normal note workflows, and TaskNotes adds structure, filtering, and commands on top.\n\n## YAML Frontmatter\n\nTask properties are stored in YAML frontmatter, a standard format with broad tool support.\nTreat frontmatter as the machine-readable layer and the note body as the human-readable layer. TaskNotes automations and Bases filters rely on frontmatter; your project notes and context stay in the body.\n\n### Property Types\n\nTaskNotes uses several property types:\n\n| Type | Example | Description |\n|------|---------|-------------|\n| Text | `title: Buy groceries` | Single text value |\n| List | `tags: [work, urgent]` | Multiple values |\n| Date | `due: 2025-01-15` | ISO 8601 date format |\n| DateTime | `scheduled: 2025-01-15T09:00` | Date with time |\n| Link | `projects: [\"[[Project A]]\"]` | Obsidian wikilinks |\n| Number | `timeEstimate: 60` | Numeric values (minutes) |\n\n### Field Mapping\n\nProperty keys are configurable. If your vault uses `deadline` instead of `due`, you can map TaskNotes to use your existing field names without modifying your files.\n\nThe exact rules for how fields map to semantic roles, how dates are interpreted, and how operations like completion and recurrence behave are defined in the [TaskNotes Specification](spec.md). The spec is the shared contract between the Obsidian plugin, the terminal UI, and any other tool that reads or writes TaskNotes data.\n\n### Custom Fields\n\nAdd any frontmatter property to your tasks. User-defined fields work in filtering, sorting, and templates. Define custom fields in `Settings -> TaskNotes -> Task Properties` to include them in task modals and views.\n\n## Bases Integration\n\nTaskNotes v4 uses Obsidian's Bases core plugin for its main views. Bases provides:\n\n- **Filtering**: Query tasks using AND/OR conditions\n- **Sorting**: Order tasks by any property\n- **Grouping**: Organize tasks by status, priority, project, or custom fields\n- **Views**: Task List, Kanban, Calendar, and Agenda are all Bases views\n\nViews are stored as `.base` files in `TaskNotes/Views/`. These files contain YAML configuration that defines the view's query and display settings. You can duplicate, modify, or create new views by editing these files.\nThis makes view behavior inspectable and predictable. If a task appears in the wrong place, you can open the `.base` file and see exactly which filter or grouping rule produced that result.\n\n### Enabling Bases\n\nBases is a core plugin included with Obsidian 1.10.1+:\n\n1. Open `Settings -> Core Plugins`\n2. Enable \"Bases\"\n3. TaskNotes views will now function\n","aliases":["/core-concepts/"],"toc":[{"level":2,"id":"the-note-per-task-approach","text":"The Note-Per-Task Approach"},{"level":3,"id":"task-structure","text":"Task Structure"},{"level":3,"id":"obsidian-integration","text":"Obsidian Integration"},{"level":2,"id":"yaml-frontmatter","text":"YAML Frontmatter"},{"level":3,"id":"property-types","text":"Property Types"},{"level":3,"id":"field-mapping","text":"Field Mapping"},{"level":3,"id":"custom-fields","text":"Custom Fields"},{"level":2,"id":"bases-integration","text":"Bases Integration"},{"level":3,"id":"enabling-bases","text":"Enabling Bases"}],"html":"

TaskNotes follows the "one note per task" principle, where each task lives as a separate Markdown note with structured metadata in YAML frontmatter.

\n

The Note-Per-Task Approach#

\n

Individual Markdown notes replace centralized databases or proprietary formats. Each task file can be read, edited, and backed up with any text editor or automation tool.

\n

Task Structure#

\n

A TaskNotes task is a standard Markdown file with YAML frontmatter:

\n
---\ntags:\n  - task\ntitle: Review quarterly report\nstatus: in-progress\npriority: high\ndue: 2025-01-15\nscheduled: 2025-01-14\ncontexts:\n  - office\nprojects:\n  - "[[Q1 Planning]]"\n---\n\n## Notes\n\nKey points to review:\n- Revenue projections\n- Budget allocations\n\n## Meeting Notes\n\nDiscussion with finance team on 2025-01-10...\n

The frontmatter contains structured, queryable properties. The note body holds freeform content—research findings, meeting notes, checklists, or links to related documents.

\n

Obsidian Integration#

\n

Since tasks are proper notes, they work with Obsidian's core features:

\n
    \n
  • Backlinks: See which notes reference a task
  • \n
  • Graph View: Visualize task relationships and project connections
  • \n
  • Tags: Use Obsidian's tag system for additional categorization
  • \n
  • Search: Find tasks using Obsidian's search
  • \n
  • Links: Reference tasks from daily notes, meeting notes, or project documents
  • \n
\n

This approach creates many small files. TaskNotes stores tasks in a configurable folder (default: TaskNotes/Tasks/) to keep them organized.\nIn practice, this lets TaskNotes fit into existing vault habits instead of replacing them. You keep using normal note workflows, and TaskNotes adds structure, filtering, and commands on top.

\n

YAML Frontmatter#

\n

Task properties are stored in YAML frontmatter, a standard format with broad tool support.\nTreat frontmatter as the machine-readable layer and the note body as the human-readable layer. TaskNotes automations and Bases filters rely on frontmatter; your project notes and context stay in the body.

\n

Property Types#

\n

TaskNotes uses several property types:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
TypeExampleDescription
Texttitle: Buy groceriesSingle text value
Listtags: [work, urgent]Multiple values
Datedue: 2025-01-15ISO 8601 date format
DateTimescheduled: 2025-01-15T09:00Date with time
Linkprojects: ["[[Project A]]"]Obsidian wikilinks
NumbertimeEstimate: 60Numeric values (minutes)
\n

Field Mapping#

\n

Property keys are configurable. If your vault uses deadline instead of due, you can map TaskNotes to use your existing field names without modifying your files.

\n

The exact rules for how fields map to semantic roles, how dates are interpreted, and how operations like completion and recurrence behave are defined in the TaskNotes Specification. The spec is the shared contract between the Obsidian plugin, the terminal UI, and any other tool that reads or writes TaskNotes data.

\n

Custom Fields#

\n

Add any frontmatter property to your tasks. User-defined fields work in filtering, sorting, and templates. Define custom fields in Settings -> TaskNotes -> Task Properties to include them in task modals and views.

\n

Bases Integration#

\n

TaskNotes v4 uses Obsidian's Bases core plugin for its main views. Bases provides:

\n
    \n
  • Filtering: Query tasks using AND/OR conditions
  • \n
  • Sorting: Order tasks by any property
  • \n
  • Grouping: Organize tasks by status, priority, project, or custom fields
  • \n
  • Views: Task List, Kanban, Calendar, and Agenda are all Bases views
  • \n
\n

Views are stored as .base files in TaskNotes/Views/. These files contain YAML configuration that defines the view's query and display settings. You can duplicate, modify, or create new views by editing these files.\nThis makes view behavior inspectable and predictable. If a task appears in the wrong place, you can open the .base file and see exactly which filter or grouping rule produced that result.

\n

Enabling Bases#

\n

Bases is a core plugin included with Obsidian 1.10.1+:

\n
    \n
  1. Open Settings -> Core Plugins
  2. \n
  3. Enable "Bases"
  4. \n
  5. TaskNotes views will now function
  6. \n
\n","text":"TaskNotes follows the \"one note per task\" principle, where each task lives as a separate Markdown note with structured metadata in YAML frontmatter. The Note-Per-Task Approach# Individual Markdown notes replace centralized databases or proprietary formats. Each task file can be read, edited, and backed up with any text editor or automation tool. Task Structure# A TaskNotes task is a standard Markdown file with YAML frontmatter: --- tags: - task title: Review quarterly report status: in-progress priority: high due: 2025-01-15 scheduled: 2025-01-14 contexts: - office projects: - \"[[Q1 Planning]]\" --- ## Notes Key points to review: - Revenue projections - Budget allocations ## Meeting Notes Discussion with finance team on 2025-01-10... The frontmatter contains structured, queryable properties. The note body holds freeform content—research findings, meeting notes, checklists, or links to related documents. Obsidian Integration# Since tasks are proper notes, they work with Obsidian's core features: Backlinks: See which notes reference a task Graph View: Visualize task relationships and project connections Tags: Use Obsidian's tag system for additional categorization Search: Find tasks using Obsidian's search Links: Reference tasks from daily notes, meeting notes, or project documents This approach creates many small files. TaskNotes stores tasks in a configurable folder (default: TaskNotes/Tasks/) to keep them organized. In practice, this lets TaskNotes fit into existing vault habits instead of replacing them. You keep using normal note workflows, and TaskNotes adds structure, filtering, and commands on top. YAML Frontmatter# Task properties are stored in YAML frontmatter, a standard format with broad tool support. Treat frontmatter as the machine-readable layer and the note body as the human-readable layer. TaskNotes automations and Bases filters rely on frontmatter; your project notes and context stay in the body. Property Types# TaskNotes uses several property types: Type Example Description Text title: Buy groceries Single text value List tags: [work, urgent] Multiple values Date due: 2025-01-15 ISO 8601 date format DateTime scheduled: 2025-01-15T09:00 Date with time Link projects: [\"[[Project A]]\"] Obsidian wikilinks Number timeEstimate: 60 Numeric values (minutes) Field Mapping# Property keys are configurable. If your vault uses deadline instead of due, you can map TaskNotes to use your existing field names without modifying your files. The exact rules for how fields map to semantic roles, how dates are interpreted, and how operations like completion and recurrence behave are defined in the TaskNotes Specification. The spec is the shared contract between the Obsidian plugin, the terminal UI, and any other tool that reads or writes TaskNotes data. Custom Fields# Add any frontmatter property to your tasks. User-defined fields work in filtering, sorting, and templates. Define custom fields in Settings -> TaskNotes -> Task Properties to include them in task modals and views. Bases Integration# TaskNotes v4 uses Obsidian's Bases core plugin for its main views. Bases provides: Filtering: Query tasks using AND/OR conditions Sorting: Order tasks by any property Grouping: Organize tasks by status, priority, project, or custom fields Views: Task List, Kanban, Calendar, and Agenda are all Bases views Views are stored as .base files in TaskNotes/Views/. These files contain YAML configuration that defines the view's query and display settings. You can duplicate, modify, or create new views by editing these files. This makes view behavior inspectable and predictable. If a task appears in the wrong place, you can open the .base file and see exactly which filter or grouping rule produced that result. Enabling Bases# Bases is a core plugin included with Obsidian 1.10.1+: Open Settings -> Core Plugins Enable \"Bases\" TaskNotes views will now function"},{"route":"/obsidian/features/","title":"Features","description":"TaskNotes includes task organization, time tracking, and calendar integration features.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/features.md","namespace":"obsidian","relativePath":"features.md","raw":"# Features\n\nTaskNotes includes task organization, time tracking, and calendar integration features.\n\n## Task Management\n\nTaskNotes gives each task a structured set of properties, including status, priority, due and scheduled dates, tags, contexts, and optional estimates. Because these values live in frontmatter, they stay readable and portable while still powering advanced filtering and grouping in Bases.\n\nReminders can be relative (for example, \"3 days before due\") or absolute, and completed tasks can be archived automatically to keep active work surfaces focused. Recurring tasks can stay virtual for lightweight checkoff workflows, or you can materialize individual occurrences into normal task notes when a specific instance needs its own checklist, comments, time tracking, or attachments. Occurrence notes inherit useful planning metadata from the parent while keeping their own completion state and time entries, and calendar views coalesce them with the matching virtual recurrence instance.\n\nSee [Task Management](features/task-management.md) for details.\nFor recurrence behavior, see [Recurring Tasks](features/recurring-tasks.md).\nFor reminder setup and data format, see [Task Reminders](features/reminders.md).\n\n## Filtering and Views\n\nTaskNotes uses Obsidian's Bases engine for filtering, sorting, and grouping. Each view is a `.base` file, so you can inspect or edit its query logic directly instead of relying on hidden plugin state.\n\nThis design also makes view customization practical: you can duplicate a default view, tweak grouping or formulas, and keep both versions side by side in your vault.\n\n![Kanban view](assets/views-kanban.png)\n\nFor details on how Bases integration works, see [Core Concepts](core-concepts.md#bases-integration). For Bases syntax documentation, see the [official Obsidian Bases documentation](https://help.obsidian.md/Bases/Introduction+to+Bases).\n\n## Inline Task Integration\n\nInline task features let you work from normal notes without context switching. Task links can display interactive cards, checkboxes can be converted into full task notes, and project notes can surface subtasks and dependency relationships in place.\n\nNatural language parsing supports date, priority, and context extraction across multiple languages, which helps keep fast capture while preserving structured data.\n\nSee [Inline Task Integration](features/inline-tasks.md) for details.\n\n## Time Management\n\nTime tracking records work sessions per task, and Pomodoro mode supports focused intervals with break handling. Over time, the statistics views help you compare estimated versus actual effort and spot trends in workload distribution.\n\n![Pomodoro timer](assets/feature-pomodoro-timer.png)\n\nSee [Time Management](features/time-management.md) for details.\n\n## Calendar Integration\n\nTaskNotes supports bidirectional OAuth sync with Google Calendar and Microsoft Outlook, plus read-only ICS subscriptions for external feeds. Calendar views include month, week, day, year, and list modes, and drag-and-drop scheduling can update tasks directly.\n\nFor planning workflows, time-blocking and calendar-linked task updates connect backlog management with schedule execution in the same workspace.\n\n![Calendar month view](assets/views-calendar-month.png)\n\nSee [Calendar Integration](features/calendar-integration.md) for details.\n\n## User Fields\n\nUser fields let you extend the core model with vault-specific metadata like client, energy level, billing code, or review state. Once added, these fields become available in filters, sorting, templates, and formulas.\n\nSee [User Fields](features/user-fields.md) for details.\n\n## Integrations\n\nBeyond calendar sync, TaskNotes includes an HTTP API and webhook support for automation workflows, external dashboards, or custom tooling.\n\nSee [Integrations](settings/integrations.md) for details.\n\n## Companion Plugins\n\nTaskNotes can be extended by optional companion plugins that use the JavaScript runtime API while keeping task data in Markdown files. [Canvas Bases](companion-plugins/canvas-bases.md) is the TaskNotes canvas companion, adding canvas-style boards and JSON Canvas snapshots for Bases views, with optional TaskNotes badges, actions, and relationship edges. [TaskNotes Workflows](companion-plugins/tasknotes-workflows.md) adds Markdown-defined automation for TaskNotes events, schedules, manual commands, and typed task actions.\n\nSee [Companion Plugins](companion-plugins.md) for details.\n\n## REST API\n\nExternal applications can interact with TaskNotes through its REST API for automation, reporting, and integration with other tools.\n\nSee [HTTP API](HTTP_API.md) for details.\n","aliases":["/features/"],"toc":[{"level":2,"id":"task-management","text":"Task Management"},{"level":2,"id":"filtering-and-views","text":"Filtering and Views"},{"level":2,"id":"inline-task-integration","text":"Inline Task Integration"},{"level":2,"id":"time-management","text":"Time Management"},{"level":2,"id":"calendar-integration","text":"Calendar Integration"},{"level":2,"id":"user-fields","text":"User Fields"},{"level":2,"id":"integrations","text":"Integrations"},{"level":2,"id":"companion-plugins","text":"Companion Plugins"},{"level":2,"id":"rest-api","text":"REST API"}],"html":"

TaskNotes includes task organization, time tracking, and calendar integration features.

\n

Task Management#

\n

TaskNotes gives each task a structured set of properties, including status, priority, due and scheduled dates, tags, contexts, and optional estimates. Because these values live in frontmatter, they stay readable and portable while still powering advanced filtering and grouping in Bases.

\n

Reminders can be relative (for example, "3 days before due") or absolute, and completed tasks can be archived automatically to keep active work surfaces focused. Recurring tasks can stay virtual for lightweight checkoff workflows, or you can materialize individual occurrences into normal task notes when a specific instance needs its own checklist, comments, time tracking, or attachments. Occurrence notes inherit useful planning metadata from the parent while keeping their own completion state and time entries, and calendar views coalesce them with the matching virtual recurrence instance.

\n

See Task Management for details.\nFor recurrence behavior, see Recurring Tasks.\nFor reminder setup and data format, see Task Reminders.

\n

Filtering and Views#

\n

TaskNotes uses Obsidian's Bases engine for filtering, sorting, and grouping. Each view is a .base file, so you can inspect or edit its query logic directly instead of relying on hidden plugin state.

\n

This design also makes view customization practical: you can duplicate a default view, tweak grouping or formulas, and keep both versions side by side in your vault.

\n

\"Kanban

\n

For details on how Bases integration works, see Core Concepts. For Bases syntax documentation, see the official Obsidian Bases documentation.

\n

Inline Task Integration#

\n

Inline task features let you work from normal notes without context switching. Task links can display interactive cards, checkboxes can be converted into full task notes, and project notes can surface subtasks and dependency relationships in place.

\n

Natural language parsing supports date, priority, and context extraction across multiple languages, which helps keep fast capture while preserving structured data.

\n

See Inline Task Integration for details.

\n

Time Management#

\n

Time tracking records work sessions per task, and Pomodoro mode supports focused intervals with break handling. Over time, the statistics views help you compare estimated versus actual effort and spot trends in workload distribution.

\n

\"Pomodoro

\n

See Time Management for details.

\n

Calendar Integration#

\n

TaskNotes supports bidirectional OAuth sync with Google Calendar and Microsoft Outlook, plus read-only ICS subscriptions for external feeds. Calendar views include month, week, day, year, and list modes, and drag-and-drop scheduling can update tasks directly.

\n

For planning workflows, time-blocking and calendar-linked task updates connect backlog management with schedule execution in the same workspace.

\n

\"Calendar

\n

See Calendar Integration for details.

\n

User Fields#

\n

User fields let you extend the core model with vault-specific metadata like client, energy level, billing code, or review state. Once added, these fields become available in filters, sorting, templates, and formulas.

\n

See User Fields for details.

\n

Integrations#

\n

Beyond calendar sync, TaskNotes includes an HTTP API and webhook support for automation workflows, external dashboards, or custom tooling.

\n

See Integrations for details.

\n

Companion Plugins#

\n

TaskNotes can be extended by optional companion plugins that use the JavaScript runtime API while keeping task data in Markdown files. Canvas Bases is the TaskNotes canvas companion, adding canvas-style boards and JSON Canvas snapshots for Bases views, with optional TaskNotes badges, actions, and relationship edges. TaskNotes Workflows adds Markdown-defined automation for TaskNotes events, schedules, manual commands, and typed task actions.

\n

See Companion Plugins for details.

\n

REST API#

\n

External applications can interact with TaskNotes through its REST API for automation, reporting, and integration with other tools.

\n

See HTTP API for details.

\n","text":"TaskNotes includes task organization, time tracking, and calendar integration features. Task Management# TaskNotes gives each task a structured set of properties, including status, priority, due and scheduled dates, tags, contexts, and optional estimates. Because these values live in frontmatter, they stay readable and portable while still powering advanced filtering and grouping in Bases. Reminders can be relative (for example, \"3 days before due\") or absolute, and completed tasks can be archived automatically to keep active work surfaces focused. Recurring tasks can stay virtual for lightweight checkoff workflows, or you can materialize individual occurrences into normal task notes when a specific instance needs its own checklist, comments, time tracking, or attachments. Occurrence notes inherit useful planning metadata from the parent while keeping their own completion state and time entries, and calendar views coalesce them with the matching virtual recurrence instance. See Task Management for details. For recurrence behavior, see Recurring Tasks. For reminder setup and data format, see Task Reminders. Filtering and Views# TaskNotes uses Obsidian's Bases engine for filtering, sorting, and grouping. Each view is a .base file, so you can inspect or edit its query logic directly instead of relying on hidden plugin state. This design also makes view customization practical: you can duplicate a default view, tweak grouping or formulas, and keep both versions side by side in your vault. For details on how Bases integration works, see Core Concepts. For Bases syntax documentation, see the official Obsidian Bases documentation. Inline Task Integration# Inline task features let you work from normal notes without context switching. Task links can display interactive cards, checkboxes can be converted into full task notes, and project notes can surface subtasks and dependency relationships in place. Natural language parsing supports date, priority, and context extraction across multiple languages, which helps keep fast capture while preserving structured data. See Inline Task Integration for details. Time Management# Time tracking records work sessions per task, and Pomodoro mode supports focused intervals with break handling. Over time, the statistics views help you compare estimated versus actual effort and spot trends in workload distribution. See Time Management for details. Calendar Integration# TaskNotes supports bidirectional OAuth sync with Google Calendar and Microsoft Outlook, plus read-only ICS subscriptions for external feeds. Calendar views include month, week, day, year, and list modes, and drag-and-drop scheduling can update tasks directly. For planning workflows, time-blocking and calendar-linked task updates connect backlog management with schedule execution in the same workspace. See Calendar Integration for details. User Fields# User fields let you extend the core model with vault-specific metadata like client, energy level, billing code, or review state. Once added, these fields become available in filters, sorting, templates, and formulas. See User Fields for details. Integrations# Beyond calendar sync, TaskNotes includes an HTTP API and webhook support for automation workflows, external dashboards, or custom tooling. See Integrations for details. Companion Plugins# TaskNotes can be extended by optional companion plugins that use the JavaScript runtime API while keeping task data in Markdown files. Canvas Bases is the TaskNotes canvas companion, adding canvas-style boards and JSON Canvas snapshots for Bases views, with optional TaskNotes badges, actions, and relationship edges. TaskNotes Workflows adds Markdown-defined automation for TaskNotes events, schedules, manual commands, and typed task actions. See Companion Plugins for details. REST API# External applications can interact with TaskNotes through its REST API for automation, reporting, and integration with other tools. See HTTP API for details."},{"route":"/obsidian/features/calendar-integration/","title":"Calendar Integration","description":"TaskNotes provides calendar integration through OAuth-connected calendar services, two Bases-powered calendar views, and read-only ICS calendar subscriptions.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/features/calendar-integration.md","namespace":"obsidian","relativePath":"features/calendar-integration.md","raw":"# Calendar Integration\n\nTaskNotes provides calendar integration through OAuth-connected calendar services, two Bases-powered calendar views, and read-only ICS calendar subscriptions.\n\n## OAuth Calendar Integration\n\nTaskNotes supports bidirectional synchronization with Google Calendar and Microsoft Outlook using OAuth authentication. This integration allows you to view external calendar events alongside your tasks and sync changes back to the calendar provider.\n\n### Supported Providers\n\n- **Google Calendar** - OAuth 2.0 authentication with access to all calendars in your Google account\n- **Microsoft Outlook** - OAuth 2.0 authentication with access to calendars in your Microsoft 365 or Outlook.com account\n\n### Setup Requirements\n\nOAuth calendar integration requires creating an OAuth application with your calendar provider. This process takes approximately 15 minutes per provider. You will need to:\n\n1. Create an OAuth application in Google Cloud Console or Microsoft Azure Portal\n2. Configure redirect URIs and scopes\n3. Obtain client ID and client secret\n4. Enter credentials in TaskNotes settings (`Settings -> TaskNotes -> Integrations`, OAuth calendar section)\n\n### Synchronization Behavior\n\n- Events are fetched automatically every 15 minutes\n- Events are also fetched when local changes occur (task creation, updates, rescheduling)\n- Dragging calendar events to new dates/times updates the event in the calendar provider\n- Per-calendar visibility toggles allow selective display of calendars\n- Access tokens are automatically refreshed when expired\n\n### Token Management\n\nTaskNotes stores OAuth client credentials, access tokens, and refresh tokens in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system and kept separate from TaskNotes' `data.json`. Tokens are refreshed automatically before expiration. You can revoke account access or forget the saved OAuth app credentials through the integrations settings.\n\n## Calendar Views\n\nTaskNotes provides Calendar and Mini Calendar views that display tasks alongside OAuth calendar events and ICS subscriptions. Both views support drag-and-drop scheduling.\n\nFor detailed view documentation, see [Calendar Views](../views/calendar-views.md).\n\nNotes linked from recurring external calendar events can be matched either across the loaded event series or only to the selected recurrence instance. Configure this in [Integrations settings](../settings/integrations.md#calendar-subscriptions-ics).\n\n## Time Entry Editor\n\nTaskNotes includes a time entry editor for tracking time spent on tasks. Time entries are created and managed through the Calendar View.\n\n### Creating Time Entries\n\nTo create a time entry on the Calendar View:\n\n1. Click and drag on a time slot in the calendar to select a time range\n2. When the selection menu appears, choose **Create time entry** (timeblock appears only if the feature is enabled)\n3. Choose a task in the task selector modal\n4. A time entry is created for that task with the selected start/end range\n\nTime entries are always associated with a specific task and stored in that task's frontmatter. Multiple time entries can exist for one task.\n\n### Managing Time Entries\n\nThe time entry editor modal provides functions to:\n\n- View all time entries for a task\n- Edit the start time, end time, and duration of time entries\n- Delete time entries\n- See the total time tracked across all entries for a task\n\nAccess the time entry editor by clicking an existing time entry in the calendar.\n\n## ICS Calendar Subscriptions\n\nTaskNotes can subscribe to external calendar feeds using the iCalendar (ICS) format. This provides read-only access to events from calendar services. ICS subscriptions differ from OAuth calendar integration in that they are read-only—dragging ICS events to new dates does not update the source calendar.\n\nAdd and manage ICS subscriptions from `Settings -> TaskNotes -> Integrations` (Calendar Subscriptions section).\n\nFor details on creating notes and tasks from calendar events, see [ICS Integration](ics-integration.md).\n\n## Time Blocking\n\nThe Calendar View supports time blocking for scheduling dedicated work periods. To create a time block:\n\n1. Click and drag on a time slot in the calendar to select a time range\n2. A context menu will appear with available options\n3. Select \"Create timeblock\" from the menu (this option only appears if timeblocking is enabled in settings)\n\nTime blocks are stored in the frontmatter of daily notes and can be linked to specific tasks. This differs from time entries, which track actual time spent and are stored in task frontmatter rather than daily notes.\n\nEnable time blocking under `Settings -> TaskNotes -> Features` (Timeblocking section).\n","aliases":["/features/calendar-integration/"],"toc":[{"level":2,"id":"oauth-calendar-integration","text":"OAuth Calendar Integration"},{"level":3,"id":"supported-providers","text":"Supported Providers"},{"level":3,"id":"setup-requirements","text":"Setup Requirements"},{"level":3,"id":"synchronization-behavior","text":"Synchronization Behavior"},{"level":3,"id":"token-management","text":"Token Management"},{"level":2,"id":"calendar-views","text":"Calendar Views"},{"level":2,"id":"time-entry-editor","text":"Time Entry Editor"},{"level":3,"id":"creating-time-entries","text":"Creating Time Entries"},{"level":3,"id":"managing-time-entries","text":"Managing Time Entries"},{"level":2,"id":"ics-calendar-subscriptions","text":"ICS Calendar Subscriptions"},{"level":2,"id":"time-blocking","text":"Time Blocking"}],"html":"

TaskNotes provides calendar integration through OAuth-connected calendar services, two Bases-powered calendar views, and read-only ICS calendar subscriptions.

\n

OAuth Calendar Integration#

\n

TaskNotes supports bidirectional synchronization with Google Calendar and Microsoft Outlook using OAuth authentication. This integration allows you to view external calendar events alongside your tasks and sync changes back to the calendar provider.

\n

Supported Providers#

\n
    \n
  • Google Calendar - OAuth 2.0 authentication with access to all calendars in your Google account
  • \n
  • Microsoft Outlook - OAuth 2.0 authentication with access to calendars in your Microsoft 365 or Outlook.com account
  • \n
\n

Setup Requirements#

\n

OAuth calendar integration requires creating an OAuth application with your calendar provider. This process takes approximately 15 minutes per provider. You will need to:

\n
    \n
  1. Create an OAuth application in Google Cloud Console or Microsoft Azure Portal
  2. \n
  3. Configure redirect URIs and scopes
  4. \n
  5. Obtain client ID and client secret
  6. \n
  7. Enter credentials in TaskNotes settings (Settings -> TaskNotes -> Integrations, OAuth calendar section)
  8. \n
\n

Synchronization Behavior#

\n
    \n
  • Events are fetched automatically every 15 minutes
  • \n
  • Events are also fetched when local changes occur (task creation, updates, rescheduling)
  • \n
  • Dragging calendar events to new dates/times updates the event in the calendar provider
  • \n
  • Per-calendar visibility toggles allow selective display of calendars
  • \n
  • Access tokens are automatically refreshed when expired
  • \n
\n

Token Management#

\n

TaskNotes stores OAuth client credentials, access tokens, and refresh tokens in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system and kept separate from TaskNotes' data.json. Tokens are refreshed automatically before expiration. You can revoke account access or forget the saved OAuth app credentials through the integrations settings.

\n

Calendar Views#

\n

TaskNotes provides Calendar and Mini Calendar views that display tasks alongside OAuth calendar events and ICS subscriptions. Both views support drag-and-drop scheduling.

\n

For detailed view documentation, see Calendar Views.

\n

Notes linked from recurring external calendar events can be matched either across the loaded event series or only to the selected recurrence instance. Configure this in Integrations settings.

\n

Time Entry Editor#

\n

TaskNotes includes a time entry editor for tracking time spent on tasks. Time entries are created and managed through the Calendar View.

\n

Creating Time Entries#

\n

To create a time entry on the Calendar View:

\n
    \n
  1. Click and drag on a time slot in the calendar to select a time range
  2. \n
  3. When the selection menu appears, choose Create time entry (timeblock appears only if the feature is enabled)
  4. \n
  5. Choose a task in the task selector modal
  6. \n
  7. A time entry is created for that task with the selected start/end range
  8. \n
\n

Time entries are always associated with a specific task and stored in that task's frontmatter. Multiple time entries can exist for one task.

\n

Managing Time Entries#

\n

The time entry editor modal provides functions to:

\n
    \n
  • View all time entries for a task
  • \n
  • Edit the start time, end time, and duration of time entries
  • \n
  • Delete time entries
  • \n
  • See the total time tracked across all entries for a task
  • \n
\n

Access the time entry editor by clicking an existing time entry in the calendar.

\n

ICS Calendar Subscriptions#

\n

TaskNotes can subscribe to external calendar feeds using the iCalendar (ICS) format. This provides read-only access to events from calendar services. ICS subscriptions differ from OAuth calendar integration in that they are read-only—dragging ICS events to new dates does not update the source calendar.

\n

Add and manage ICS subscriptions from Settings -> TaskNotes -> Integrations (Calendar Subscriptions section).

\n

For details on creating notes and tasks from calendar events, see ICS Integration.

\n

Time Blocking#

\n

The Calendar View supports time blocking for scheduling dedicated work periods. To create a time block:

\n
    \n
  1. Click and drag on a time slot in the calendar to select a time range
  2. \n
  3. A context menu will appear with available options
  4. \n
  5. Select "Create timeblock" from the menu (this option only appears if timeblocking is enabled in settings)
  6. \n
\n

Time blocks are stored in the frontmatter of daily notes and can be linked to specific tasks. This differs from time entries, which track actual time spent and are stored in task frontmatter rather than daily notes.

\n

Enable time blocking under Settings -> TaskNotes -> Features (Timeblocking section).

\n","text":"TaskNotes provides calendar integration through OAuth-connected calendar services, two Bases-powered calendar views, and read-only ICS calendar subscriptions. OAuth Calendar Integration# TaskNotes supports bidirectional synchronization with Google Calendar and Microsoft Outlook using OAuth authentication. This integration allows you to view external calendar events alongside your tasks and sync changes back to the calendar provider. Supported Providers# Google Calendar - OAuth 2.0 authentication with access to all calendars in your Google account Microsoft Outlook - OAuth 2.0 authentication with access to calendars in your Microsoft 365 or Outlook.com account Setup Requirements# OAuth calendar integration requires creating an OAuth application with your calendar provider. This process takes approximately 15 minutes per provider. You will need to: Create an OAuth application in Google Cloud Console or Microsoft Azure Portal Configure redirect URIs and scopes Obtain client ID and client secret Enter credentials in TaskNotes settings (Settings -> TaskNotes -> Integrations, OAuth calendar section) Synchronization Behavior# Events are fetched automatically every 15 minutes Events are also fetched when local changes occur (task creation, updates, rescheduling) Dragging calendar events to new dates/times updates the event in the calendar provider Per-calendar visibility toggles allow selective display of calendars Access tokens are automatically refreshed when expired Token Management# TaskNotes stores OAuth client credentials, access tokens, and refresh tokens in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system and kept separate from TaskNotes' data.json. Tokens are refreshed automatically before expiration. You can revoke account access or forget the saved OAuth app credentials through the integrations settings. Calendar Views# TaskNotes provides Calendar and Mini Calendar views that display tasks alongside OAuth calendar events and ICS subscriptions. Both views support drag-and-drop scheduling. For detailed view documentation, see Calendar Views. Notes linked from recurring external calendar events can be matched either across the loaded event series or only to the selected recurrence instance. Configure this in Integrations settings. Time Entry Editor# TaskNotes includes a time entry editor for tracking time spent on tasks. Time entries are created and managed through the Calendar View. Creating Time Entries# To create a time entry on the Calendar View: Click and drag on a time slot in the calendar to select a time range When the selection menu appears, choose Create time entry (timeblock appears only if the feature is enabled) Choose a task in the task selector modal A time entry is created for that task with the selected start/end range Time entries are always associated with a specific task and stored in that task's frontmatter. Multiple time entries can exist for one task. Managing Time Entries# The time entry editor modal provides functions to: View all time entries for a task Edit the start time, end time, and duration of time entries Delete time entries See the total time tracked across all entries for a task Access the time entry editor by clicking an existing time entry in the calendar. ICS Calendar Subscriptions# TaskNotes can subscribe to external calendar feeds using the iCalendar (ICS) format. This provides read-only access to events from calendar services. ICS subscriptions differ from OAuth calendar integration in that they are read-only—dragging ICS events to new dates does not update the source calendar. Add and manage ICS subscriptions from Settings -> TaskNotes -> Integrations (Calendar Subscriptions section). For details on creating notes and tasks from calendar events, see ICS Integration. Time Blocking# The Calendar View supports time blocking for scheduling dedicated work periods. To create a time block: Click and drag on a time slot in the calendar to select a time range A context menu will appear with available options Select \"Create timeblock\" from the menu (this option only appears if timeblocking is enabled in settings) Time blocks are stored in the frontmatter of daily notes and can be linked to specific tasks. This differs from time entries, which track actual time spent and are stored in task frontmatter rather than daily notes. Enable time blocking under Settings -> TaskNotes -> Features (Timeblocking section)."},{"route":"/obsidian/features/ics-integration/","title":"ICS Calendar Event Integration","description":"TaskNotes can use ICS calendar events to create notes and tasks directly from calendar entries. ICS integration creates linked notes and tasks from event data without manual re-...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/features/ics-integration.md","namespace":"obsidian","relativePath":"features/ics-integration.md","raw":"# ICS Calendar Event Integration\n\nTaskNotes can use ICS calendar events to create notes and tasks directly from calendar entries.\nICS integration creates linked notes and tasks from event data without manual re-entry.\n\n## Overview\n\nThe ICS integration allows you to:\n\n- View detailed information about calendar events\n- Create notes from calendar events with customizable templates\n- Generate tasks from events with proper scheduling and context\n- Link existing vault content to calendar events\n- Maintain relationships between events and created content\nEvent context, notes, and follow-up tasks remain connected through frontmatter links.\n\n## Event Information Modal\n\nWhen you interact with a calendar event in TaskNotes, an information modal displays event details and available actions. The modal provides:\n\n### Event Details\n\n- Event title and description\n- Start and end times (formatted according to your locale)\n- Location information\n- Source calendar name\n- Event URL (if available)\n\n### Related Content\n\nThe modal shows a list of existing notes and tasks that are linked to the calendar event. Content is automatically categorized as:\n\n- **Task** - Files containing the configured task tag\n- **Note** - Files without the task tag\n\nThe relationship is maintained through the ICS Event ID field in the content's frontmatter.\n\n### Available Actions\n\n**Create Note** - Opens a creation dialog for generating a new note from the event data.\n\n**Create Task** - Creates a task immediately using the event information with default settings.\n\n**Link Note** - Opens a file selection dialog to link an existing note to the calendar event.\n\n**Refresh** - Reloads the list of related content to reflect recent changes.\n\n## Note Creation from Events\n\nThe note creation process allows customization of the generated content:\n\n### Basic Settings\n\n- **Title** - Default combines event title and date, but can be modified\n- **Folder** - Destination for the new note (uses default ICS note folder if configured)\n- **Template** - Optional template file to structure the note content\n\n### Template Usage\n\nWhen a template is specified:\n\n- The template file is processed with ICS-specific variables\n- Standard TaskNotes template variables are also available\n- Template content replaces the default event description format\n- Frontmatter from templates is merged with required ICS fields\nTemplates apply a consistent note structure across imported events.\n\n### Default Content\n\nWithout a template, notes include:\n\n- Event title as the main heading\n- Formatted start and end times\n- Location information\n- Source calendar name\n- Event description (if provided)\n- Event URL (if available)\n\n## Task Creation from Events\n\nTasks created from calendar events include relevant event data:\n\n### Scheduled Date and Time\n\nTasks are scheduled using the event's start time as an ISO timestamp, preserving both date and time information. This allows for accurate scheduling that reflects the original event timing.\n\n### Task Properties\n\n- **Title** - Uses the event title\n- **Status** - Set to the default task status configured in settings\n- **Priority** - Set to the default task priority\n- **Contexts** - Event location is added as a context (if provided)\n- **Time Estimate** - Calculated from event duration (if start and end times are available)\n- **Tags** - Includes the ICS event tag and any default task tags\nAfter creation, priority, status, and schedule can be edited if event data does not match the final task plan.\n\n### Content\n\nTask content includes formatted event details similar to note creation, providing context about the original calendar event.\n\n## Linking Existing Content\n\nYou can establish connections between existing vault content and calendar events:\n\n### Link Process\n\n1. Select an existing markdown file from your vault\n2. The file's frontmatter is updated to include the event ID\n3. The modification date is updated to reflect the change\n4. The connection appears in the related content list\n\n### Bidirectional References\n\n- Calendar events can display all linked content\n- Content files maintain references to their associated events\n- Multiple pieces of content can be linked to a single event\n- Content can be linked to multiple events (stored as an array)\n\n## Field Mapping Integration\n\nThe ICS integration extends the field mapping system with two new fields:\n\n### ICS Event ID Field\n\n- Stores the unique identifier connecting content to calendar events\n- Default field name is `icsEventId`\n- Values are stored as arrays to support multiple event associations\n- Field name can be customized through field mapping settings\n\n### ICS Event Tag Field\n\n- Tag automatically applied to content created from events\n- Default tag is `ics_event`\n- Used to identify ICS-related content throughout the system\n- Can be customized through field mapping settings\n\n## Template Variables\n\nTemplates used for ICS content creation have access to event-specific variables in addition to standard TaskNotes variables:\n\n### Event Information\n\n- `{{icsEventTitle}}` - Event title\n- `{{icsEventStart}}` - Start date and time (ISO format)\n- `{{icsEventEnd}}` - End date and time (ISO format)\n- `{{icsEventLocation}}` - Event location\n- `{{icsEventDescription}}` - Event description\n- `{{icsEventUrl}}` - Event URL\n- `{{icsEventSubscription}}` - Calendar subscription name\n- `{{icsEventId}}` - Unique event identifier\n\n### Standard Variables\n\nAll standard TaskNotes template variables remain available:\n- `{{title}}`, `{{date}}`, `{{time}}`\n- `{{priority}}`, `{{status}}`, `{{contexts}}`\n- And others as documented in the template system\n\n## Configuration\n\nICS integration settings are located under `Settings -> TaskNotes -> Integrations`:\n\n### Default Templates\n\nConfigure template files for consistent content creation from events. Templates are optional and the system provides sensible defaults when not specified.\n\n### Default Folders\n\nSet destination folders for content created from events. This helps organize ICS-generated content separately from other vault content if desired.\n\nFolder paths support template variables for dynamic organization:\n\n- Date variables: `{{year}}`, `{{month}}`, `{{day}}`, `{{monthName}}`, etc.\n- ICS event variables: `{{icsEventTitle}}`, `{{icsEventLocation}}`, `{{icsEventDescription}}`\n- Other variables: See template variables section below\n\nExample folder paths:\n\n- `Daily/{{year}}/{{month}}/{{day}}` creates date-based hierarchy\n- `Events/{{year}}/{{icsEventTitle}}` organizes by year and event title\n- `Meetings/{{monthName}}` groups by month name\n\n### Filename Formats\n\nThe system uses the standard TaskNotes filename generation with event-specific context, ensuring unique and descriptive filenames for created content.\n\n## Technical Implementation\n\n### Event Identification\n\nCalendar events are identified by their unique ICS event ID, which is maintained in the frontmatter of created content. This allows the system to track relationships even if event details change.\n\n### Content Type Detection\n\nThe system distinguishes between tasks and notes by checking for the presence of the configured task tag in the content's frontmatter tags array, rather than relying on file structure or naming conventions.\n\n### Error Handling\n\nThe integration includes error boundaries for network issues, file operations, and template processing. Failed operations provide user feedback without interrupting the overall workflow.\n","aliases":["/features/ics-integration/"],"toc":[{"level":2,"id":"overview","text":"Overview"},{"level":2,"id":"event-information-modal","text":"Event Information Modal"},{"level":3,"id":"event-details","text":"Event Details"},{"level":3,"id":"related-content","text":"Related Content"},{"level":3,"id":"available-actions","text":"Available Actions"},{"level":2,"id":"note-creation-from-events","text":"Note Creation from Events"},{"level":3,"id":"basic-settings","text":"Basic Settings"},{"level":3,"id":"template-usage","text":"Template Usage"},{"level":3,"id":"default-content","text":"Default Content"},{"level":2,"id":"task-creation-from-events","text":"Task Creation from Events"},{"level":3,"id":"scheduled-date-and-time","text":"Scheduled Date and Time"},{"level":3,"id":"task-properties","text":"Task Properties"},{"level":3,"id":"content","text":"Content"},{"level":2,"id":"linking-existing-content","text":"Linking Existing Content"},{"level":3,"id":"link-process","text":"Link Process"},{"level":3,"id":"bidirectional-references","text":"Bidirectional References"},{"level":2,"id":"field-mapping-integration","text":"Field Mapping Integration"},{"level":3,"id":"ics-event-id-field","text":"ICS Event ID Field"},{"level":3,"id":"ics-event-tag-field","text":"ICS Event Tag Field"},{"level":2,"id":"template-variables","text":"Template Variables"},{"level":3,"id":"event-information","text":"Event Information"},{"level":3,"id":"standard-variables","text":"Standard Variables"},{"level":2,"id":"configuration","text":"Configuration"},{"level":3,"id":"default-templates","text":"Default Templates"},{"level":3,"id":"default-folders","text":"Default Folders"},{"level":3,"id":"filename-formats","text":"Filename Formats"},{"level":2,"id":"technical-implementation","text":"Technical Implementation"},{"level":3,"id":"event-identification","text":"Event Identification"},{"level":3,"id":"content-type-detection","text":"Content Type Detection"},{"level":3,"id":"error-handling","text":"Error Handling"}],"html":"

TaskNotes can use ICS calendar events to create notes and tasks directly from calendar entries.\nICS integration creates linked notes and tasks from event data without manual re-entry.

\n

Overview#

\n

The ICS integration allows you to:

\n
    \n
  • View detailed information about calendar events
  • \n
  • Create notes from calendar events with customizable templates
  • \n
  • Generate tasks from events with proper scheduling and context
  • \n
  • Link existing vault content to calendar events
  • \n
  • Maintain relationships between events and created content\nEvent context, notes, and follow-up tasks remain connected through frontmatter links.
  • \n
\n

Event Information Modal#

\n

When you interact with a calendar event in TaskNotes, an information modal displays event details and available actions. The modal provides:

\n

Event Details#

\n
    \n
  • Event title and description
  • \n
  • Start and end times (formatted according to your locale)
  • \n
  • Location information
  • \n
  • Source calendar name
  • \n
  • Event URL (if available)
  • \n
\n

Related Content#

\n

The modal shows a list of existing notes and tasks that are linked to the calendar event. Content is automatically categorized as:

\n
    \n
  • Task - Files containing the configured task tag
  • \n
  • Note - Files without the task tag
  • \n
\n

The relationship is maintained through the ICS Event ID field in the content's frontmatter.

\n

Available Actions#

\n

Create Note - Opens a creation dialog for generating a new note from the event data.

\n

Create Task - Creates a task immediately using the event information with default settings.

\n

Link Note - Opens a file selection dialog to link an existing note to the calendar event.

\n

Refresh - Reloads the list of related content to reflect recent changes.

\n

Note Creation from Events#

\n

The note creation process allows customization of the generated content:

\n

Basic Settings#

\n
    \n
  • Title - Default combines event title and date, but can be modified
  • \n
  • Folder - Destination for the new note (uses default ICS note folder if configured)
  • \n
  • Template - Optional template file to structure the note content
  • \n
\n

Template Usage#

\n

When a template is specified:

\n
    \n
  • The template file is processed with ICS-specific variables
  • \n
  • Standard TaskNotes template variables are also available
  • \n
  • Template content replaces the default event description format
  • \n
  • Frontmatter from templates is merged with required ICS fields\nTemplates apply a consistent note structure across imported events.
  • \n
\n

Default Content#

\n

Without a template, notes include:

\n
    \n
  • Event title as the main heading
  • \n
  • Formatted start and end times
  • \n
  • Location information
  • \n
  • Source calendar name
  • \n
  • Event description (if provided)
  • \n
  • Event URL (if available)
  • \n
\n

Task Creation from Events#

\n

Tasks created from calendar events include relevant event data:

\n

Scheduled Date and Time#

\n

Tasks are scheduled using the event's start time as an ISO timestamp, preserving both date and time information. This allows for accurate scheduling that reflects the original event timing.

\n

Task Properties#

\n
    \n
  • Title - Uses the event title
  • \n
  • Status - Set to the default task status configured in settings
  • \n
  • Priority - Set to the default task priority
  • \n
  • Contexts - Event location is added as a context (if provided)
  • \n
  • Time Estimate - Calculated from event duration (if start and end times are available)
  • \n
  • Tags - Includes the ICS event tag and any default task tags\nAfter creation, priority, status, and schedule can be edited if event data does not match the final task plan.
  • \n
\n

Content#

\n

Task content includes formatted event details similar to note creation, providing context about the original calendar event.

\n

Linking Existing Content#

\n

You can establish connections between existing vault content and calendar events:

\n\n
    \n
  1. Select an existing markdown file from your vault
  2. \n
  3. The file's frontmatter is updated to include the event ID
  4. \n
  5. The modification date is updated to reflect the change
  6. \n
  7. The connection appears in the related content list
  8. \n
\n

Bidirectional References#

\n
    \n
  • Calendar events can display all linked content
  • \n
  • Content files maintain references to their associated events
  • \n
  • Multiple pieces of content can be linked to a single event
  • \n
  • Content can be linked to multiple events (stored as an array)
  • \n
\n

Field Mapping Integration#

\n

The ICS integration extends the field mapping system with two new fields:

\n

ICS Event ID Field#

\n
    \n
  • Stores the unique identifier connecting content to calendar events
  • \n
  • Default field name is icsEventId
  • \n
  • Values are stored as arrays to support multiple event associations
  • \n
  • Field name can be customized through field mapping settings
  • \n
\n

ICS Event Tag Field#

\n
    \n
  • Tag automatically applied to content created from events
  • \n
  • Default tag is ics_event
  • \n
  • Used to identify ICS-related content throughout the system
  • \n
  • Can be customized through field mapping settings
  • \n
\n

Template Variables#

\n

Templates used for ICS content creation have access to event-specific variables in addition to standard TaskNotes variables:

\n

Event Information#

\n
    \n
  • {{icsEventTitle}} - Event title
  • \n
  • {{icsEventStart}} - Start date and time (ISO format)
  • \n
  • {{icsEventEnd}} - End date and time (ISO format)
  • \n
  • {{icsEventLocation}} - Event location
  • \n
  • {{icsEventDescription}} - Event description
  • \n
  • {{icsEventUrl}} - Event URL
  • \n
  • {{icsEventSubscription}} - Calendar subscription name
  • \n
  • {{icsEventId}} - Unique event identifier
  • \n
\n

Standard Variables#

\n

All standard TaskNotes template variables remain available:

\n
    \n
  • {{title}}, {{date}}, {{time}}
  • \n
  • {{priority}}, {{status}}, {{contexts}}
  • \n
  • And others as documented in the template system
  • \n
\n

Configuration#

\n

ICS integration settings are located under Settings -> TaskNotes -> Integrations:

\n

Default Templates#

\n

Configure template files for consistent content creation from events. Templates are optional and the system provides sensible defaults when not specified.

\n

Default Folders#

\n

Set destination folders for content created from events. This helps organize ICS-generated content separately from other vault content if desired.

\n

Folder paths support template variables for dynamic organization:

\n
    \n
  • Date variables: {{year}}, {{month}}, {{day}}, {{monthName}}, etc.
  • \n
  • ICS event variables: {{icsEventTitle}}, {{icsEventLocation}}, {{icsEventDescription}}
  • \n
  • Other variables: See template variables section below
  • \n
\n

Example folder paths:

\n
    \n
  • Daily/{{year}}/{{month}}/{{day}} creates date-based hierarchy
  • \n
  • Events/{{year}}/{{icsEventTitle}} organizes by year and event title
  • \n
  • Meetings/{{monthName}} groups by month name
  • \n
\n

Filename Formats#

\n

The system uses the standard TaskNotes filename generation with event-specific context, ensuring unique and descriptive filenames for created content.

\n

Technical Implementation#

\n

Event Identification#

\n

Calendar events are identified by their unique ICS event ID, which is maintained in the frontmatter of created content. This allows the system to track relationships even if event details change.

\n

Content Type Detection#

\n

The system distinguishes between tasks and notes by checking for the presence of the configured task tag in the content's frontmatter tags array, rather than relying on file structure or naming conventions.

\n

Error Handling#

\n

The integration includes error boundaries for network issues, file operations, and template processing. Failed operations provide user feedback without interrupting the overall workflow.

\n","text":"TaskNotes can use ICS calendar events to create notes and tasks directly from calendar entries. ICS integration creates linked notes and tasks from event data without manual re-entry. Overview# The ICS integration allows you to: View detailed information about calendar events Create notes from calendar events with customizable templates Generate tasks from events with proper scheduling and context Link existing vault content to calendar events Maintain relationships between events and created content Event context, notes, and follow-up tasks remain connected through frontmatter links. Event Information Modal# When you interact with a calendar event in TaskNotes, an information modal displays event details and available actions. The modal provides: Event Details# Event title and description Start and end times (formatted according to your locale) Location information Source calendar name Event URL (if available) Related Content# The modal shows a list of existing notes and tasks that are linked to the calendar event. Content is automatically categorized as: Task - Files containing the configured task tag Note - Files without the task tag The relationship is maintained through the ICS Event ID field in the content's frontmatter. Available Actions# Create Note - Opens a creation dialog for generating a new note from the event data. Create Task - Creates a task immediately using the event information with default settings. Link Note - Opens a file selection dialog to link an existing note to the calendar event. Refresh - Reloads the list of related content to reflect recent changes. Note Creation from Events# The note creation process allows customization of the generated content: Basic Settings# Title - Default combines event title and date, but can be modified Folder - Destination for the new note (uses default ICS note folder if configured) Template - Optional template file to structure the note content Template Usage# When a template is specified: The template file is processed with ICS-specific variables Standard TaskNotes template variables are also available Template content replaces the default event description format Frontmatter from templates is merged with required ICS fields Templates apply a consistent note structure across imported events. Default Content# Without a template, notes include: Event title as the main heading Formatted start and end times Location information Source calendar name Event description (if provided) Event URL (if available) Task Creation from Events# Tasks created from calendar events include relevant event data: Scheduled Date and Time# Tasks are scheduled using the event's start time as an ISO timestamp, preserving both date and time information. This allows for accurate scheduling that reflects the original event timing. Task Properties# Title - Uses the event title Status - Set to the default task status configured in settings Priority - Set to the default task priority Contexts - Event location is added as a context (if provided) Time Estimate - Calculated from event duration (if start and end times are available) Tags - Includes the ICS event tag and any default task tags After creation, priority, status, and schedule can be edited if event data does not match the final task plan. Content# Task content includes formatted event details similar to note creation, providing context about the original calendar event. Linking Existing Content# You can establish connections between existing vault content and calendar events: Link Process# Select an existing markdown file from your vault The file's frontmatter is updated to include the event ID The modification date is updated to reflect the change The connection appears in the related content list Bidirectional References# Calendar events can display all linked content Content files maintain references to their associated events Multiple pieces of content can be linked to a single event Content can be linked to multiple events (stored as an array) Field Mapping Integration# The ICS integration extends the field mapping system with two new fields: ICS Event ID Field# Stores the unique identifier connecting content to calendar events Default field name is icsEventId Values are stored as arrays to support multiple event associations Field name can be customized through field mapping settings ICS Event Tag Field# Tag automatically applied to content created from events Default tag is ics_event Used to identify ICS-related content throughout the system Can be customized through field mapping settings Template Variables# Templates used for ICS content creation have access to event-specific variables in addition to standard TaskNotes variables: Event Information# {{icsEventTitle}} - Event title {{icsEventStart}} - Start date and time (ISO format) {{icsEventEnd}} - End date and time (ISO format) {{icsEventLocation}} - Event location {{icsEventDescription}} - Event description {{icsEventUrl}} - Event URL {{icsEventSubscription}} - Calendar subscription name {{icsEventId}} - Unique event identifier Standard Variables# All standard TaskNotes template variables remain available: {{title}}, {{date}}, {{time}} {{priority}}, {{status}}, {{contexts}} And others as documented in the template system Configuration# ICS integration settings are located under Settings -> TaskNotes -> Integrations: Default Templates# Configure template files for consistent content creation from events. Templates are optional and the system provides sensible defaults when not specified. Default Folders# Set destination folders for content created from events. This helps organize ICS-generated content separately from other vault content if desired. Folder paths support template variables for dynamic organization: Date variables: {{year}}, {{month}}, {{day}}, {{monthName}}, etc. ICS event variables: {{icsEventTitle}}, {{icsEventLocation}}, {{icsEventDescription}} Other variables: See template variables section below Example folder paths: Daily/{{year}}/{{month}}/{{day}} creates date-based hierarchy Events/{{year}}/{{icsEventTitle}} organizes by year and event title Meetings/{{monthName}} groups by month name Filename Formats# The system uses the standard TaskNotes filename generation with event-specific context, ensuring unique and descriptive filenames for created content. Technical Implementation# Event Identification# Calendar events are identified by their unique ICS event ID, which is maintained in the frontmatter of created content. This allows the system to track relationships even if event details change. Content Type Detection# The system distinguishes between tasks and notes by checking for the presence of the configured task tag in the content's frontmatter tags array, rather than relying on file structure or naming conventions. Error Handling# The integration includes error boundaries for network issues, file operations, and template processing. Failed operations provide user feedback without interrupting the overall workflow."},{"route":"/obsidian/features/inline-tasks/","title":"Inline Task Integration","description":"TaskNotes integrates with the Obsidian editor to allow task management directly within notes. This is achieved through interactive widgets, a conversion feature for checkboxes,...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/features/inline-tasks.md","namespace":"obsidian","relativePath":"features/inline-tasks.md","raw":"# Inline Task Integration\n\n\nTaskNotes integrates with the Obsidian editor to allow task management directly within notes. This is achieved through interactive widgets, a conversion feature for checkboxes, and natural language processing.\nInline features support capture and task updates without leaving the current note.\n\n## Task Link Overlays\n\nWhen a wikilink to a task note is created, TaskNotes can replace it with an interactive **Task Link Overlay**. Enable or disable overlays from `Settings -> TaskNotes -> Features` (`Task link overlay`). The widget displays information about the task, such as status, priority, and due date, and allows actions like status/priority changes or opening the edit modal.\n\n![Task Link Overlays in Live Preview mode](../assets/2025-07-17_21-03-55.png)\n\n*Task link overlays in Live Preview mode show interactive widgets with status, dates, and quick actions*\n\n![Task Link Overlays in Source mode](../assets/2025-07-17_21-04-24.png)\n\n*In Source mode, task links appear as standard wikilinks until rendered*\n\n### Widget Features\n\nThe task link overlay displays:\n\n- **Status Dot**: Clickable circular indicator showing current task status. Click to cycle through available statuses.\n- **Priority Dot**: Color-coded indicator for task priority (only shown when assigned).\n- **Task Title**: Displays the task name (truncated to 80 characters). Click to open the task edit modal.\n- **Date Information**: Shows due dates (calendar icon) and scheduled dates (clock icon) with clickable context menus.\n- **Recurrence Indicator**: Rotating arrow icon for recurring tasks with modification options.\n- **Action Menu**: Ellipsis icon (shown on hover) provides additional task actions.\nThe widget exposes common task actions at the link location, so status and metadata can be updated in-place.\n\n### Mode-Specific Behavior\n\nTask link overlays work in both Live Preview and Reading modes:\n\n- **Live Preview Mode**: Widgets hide when the cursor is within the wikilink range, allowing for easy editing.\n- **Reading Mode**: Widgets display with full functionality and integrate with the reading mode typography.\n\nThe overlays support drag-and-drop to calendar views and provide keyboard shortcuts for quick navigation (Ctrl/Cmd+Click to open the source file).\n\n## Create New Inline Task Command\n\nThe `Create new inline task` command opens the task creation modal from the editor and inserts a link to the new task when it is saved. This command is available in the command palette.\n\nWhen the cursor is on an empty line, the link is inserted at the cursor. When the cursor is on a line with content, TaskNotes inserts a new line below it and places the task link there. The command does not use the current line as the task title.\n\nTo turn the current line into a TaskNote, use `Convert to TaskNote` or the instant conversion button next to a supported line. That flow uses the current line as the task title and replaces the original line with a link to the new task file.\n\n## Instant Task Conversion\n\nThe **Instant Task Conversion** feature transforms lines in your notes into TaskNotes files. This works with both checkbox tasks and regular lines of text. Turn the feature on or off from `Settings -> TaskNotes -> Features` (`Show convert button next to checkboxes`). When enabled, a \"convert\" button appears next to content in edit mode. Clicking this button creates a new task note using the line text as the title and replaces the original line with a link to the new task file.\nThis supports progressive conversion from draft notes to dedicated task files.\n\n### Folder Configuration\n\nBy default, converted tasks are placed in the same folder as the current note (`{{currentNotePath}}`). You can change this behavior in `Settings -> TaskNotes -> General` (`Folder for converted tasks`):\n\n- **Leave empty**: Uses your default tasks folder (configured in the same section)\n- **`{{currentNotePath}}`**: Places tasks in the same folder as the note you're editing (default)\n- **`{{currentNoteTitle}}`**: Creates a subfolder named after the current note\n- **Custom path**: Specify any folder path (e.g., `TaskNotes/Converted`)\n\n### Supported Line Types\n\nThe conversion feature works with:\n\n- **Checkbox tasks**: `- [ ] Task description` becomes a TaskNote with task metadata\n- **Bullet points**: `- Some task idea` becomes a TaskNote with the text as title\n- **Numbered lists**: `1. Important item` becomes a TaskNote\n- **Blockquoted content**: `> Task in callout` becomes a TaskNote (preserves blockquote formatting)\n- **Plain text lines**: `Important thing to do` becomes a TaskNote\n- **Mixed formats**: `> - [ ] Task in blockquote` handles both blockquote and checkbox formatting\n\n### Content Processing\n\nWhen converting lines:\n\n- **Special characters** like `>`, `#`, `-` are automatically removed from the task title\n- **Original formatting** is preserved in the note (e.g., `> [[Task Title]]` for blockquoted content)\n- **Task metadata** is extracted from checkbox tasks (due dates, priorities, etc.)\n- **Natural language processing** can extract dates and metadata from plain text (if enabled)\nConversion preserves surrounding formatting, including callouts, outlines, and nested lists.\n\nThe feature handles edge cases like nested blockquotes and maintains proper indentation in the final link replacement.\n\n## Bulk Task Conversion\n\nThe **Bulk Task Conversion** command converts all checkbox tasks in the current note to TaskNotes in a single operation. This command is available in the command palette as \"Convert all tasks in note to TaskNotes\".\n\n### How It Works\n\nThe command:\n\n1. Scans the entire current note for checkbox tasks (`- [ ]`, `* [ ]`, `1. [ ]`, etc.)\n2. Includes tasks inside blockquotes (e.g., `> - [ ] task in callout`)\n3. Applies the same enhanced conversion logic as instant task conversion\n4. Creates individual TaskNote files for each task\n5. Replaces the original checkboxes with links to the new task files\n6. Preserves original indentation and formatting (including blockquote markers)\n\nThe bulk conversion uses the same content processing as instant conversion, automatically removing special characters from task titles while preserving original formatting in the note.\n\n### Usage\n\nTo use bulk conversion:\n\n1. Open a note containing checkbox tasks\n2. Access the command palette (`Ctrl+P` / `Cmd+P`)\n3. Search for \"Convert all tasks in note to TaskNotes\"\n4. Execute the command\n\nThe command displays progress and shows a summary when complete (for example, \"Successfully converted 5 tasks to TaskNotes.\").\n\n!!! warning \"Important Considerations\"\n\n **This command modifies note content permanently.** Before using:\n\n - **Create a backup** of your note if it contains important data\n - **Review the tasks** to ensure they should become individual TaskNotes\n - **Expect processing time** - notes with many tasks may take several seconds to process\n - **Avoid interruption** - do not edit the note while conversion is running\n\n!!! note \"Performance\"\n\n Processing time depends on the number of tasks:\n\n - Small notes (1-10 tasks): Near-instant\n - Medium notes (10-50 tasks): 2-5 seconds\n - Large notes (50+ tasks): 10+ seconds\n\n The operation creates multiple files and updates the note content, which requires disk I/O and editor updates.\n\n### Error Handling\n\nIf some tasks fail to convert, the command will:\n\n- Complete successfully converted tasks\n- Display a summary showing both successes and failures\n- Log detailed error information to the console for troubleshooting\n\nFailed conversions typically occur due to:\n\n- Tasks with titles containing invalid filename characters\n- Insufficient disk permissions\n- Very long task titles (over 200 characters)\nFor large notes, converting a small section first helps validate folder and filename settings.\n\n## Relationships Widget\n\n**New in v4**: The Relationships Widget consolidates what were previously three separate widgets (project subtasks, task dependencies, and blocking tasks) into a single dynamic interface.\n\nThe widget appears in task notes and automatically displays up to five tabs based on available relationship data:\n\n- **Subtasks Tab (Kanban)**: Shows tasks that reference the current note as a project. Uses Kanban layout for visual task management.\n- **Occurrences Tab (List)**: Shows materialized occurrence notes that reference the current recurring task as their parent. Uses list layout sorted by occurrence date.\n- **Projects Tab (List)**: Shows projects that the current task belongs to. Uses list layout.\n- **Blocked By Tab (List)**: Shows tasks that are blocking the current task. Uses list layout.\n- **Blocking Tab (Kanban)**: Shows tasks that the current task is blocking. Uses Kanban layout.\n\n### Automatic Tab Management\n\nTabs automatically show or hide based on the presence of relationship data. If a task has no subtasks, the Subtasks tab does not appear. If a recurring task has no materialized occurrence notes, the Occurrences tab does not appear. If there are no blocking relationships, those tabs remain hidden. This keeps the interface focused on relevant information.\nThe widget layout changes with available data, so simple tasks show fewer sections.\n\n### Features\n\nThe widget embeds the `TaskNotes/Views/relationships.base` view directly in the editor. Every filter, grouping rule, or property shown in that `.base` file is exactly what appears inside the widget, so you can customize the experience by editing the file just like any other Bases view.\n\nAdditional behavior:\n\n- **Collapsible Interface**: Click the widget title to expand or collapse. The state is remembered between sessions.\n- **Persistent Grouping**: Any grouping defined in the `.base` file is honoured, and collapsed groups retain their state per note.\n- **Task Details**: Each task shows its status, priority, due date, and other configured properties.\n- **Real-time Updates**: The widget updates automatically when tasks are added, modified, or deleted via Bases views.\n\n### Configuration\n\nEnable or disable the widget in `Settings -> TaskNotes -> Appearance` (`Show relationships widget`).\n\nPosition the widget at the top (after frontmatter) or bottom of the note using the **Relationships Position** setting.\n\n### Expandable Subtasks Chevron\n\nTasks with subtasks can display an expand/collapse chevron that toggles subtask visibility.\n\n- The chevron can be positioned on the Right (default, hover to show) or on the Left (always visible, matches group chevrons).\n- Configure this in `Settings -> TaskNotes -> Appearance` (`Subtask chevron position`).\n\n![Left subtask chevron](../assets/left-task-subtask-chevron.gif)\n\n### Migration from v3\n\nIn v3, TaskNotes provided three separate widgets controlled by individual settings:\n\n- `showProjectSubtasks` and `projectSubtasksPosition`\n- `showTaskDependencies` and `taskDependenciesPosition`\n- `showBlockingTasks` and `blockingTasksPosition`\n\nThese settings are replaced in v4 by:\n\n- `showRelationships` and `relationshipsPosition`\n\nIf you had project subtasks enabled in v3, the relationships widget is enabled automatically after upgrading to v4. The underlying Bases file changed from `TaskNotes/Views/project-subtasks.base` to `TaskNotes/Views/relationships.base`. Run the **Create files** action in `Settings -> TaskNotes -> General -> Views & base files` if `relationships.base` is missing.\n\n## Natural Language Processing\n\nTaskNotes includes a **Natural Language Processor (NLP)** that parses task descriptions to extract structured data. This allows for task creation from conversational language, such as \"Prepare quarterly report due Friday #work high priority,\" which would automatically set the due date, tag, and priority.\n\nThe NLP engine supports multiple languages, including English, Spanish, French, German, Italian, Japanese, Dutch, Portuguese, Russian, Swedish, Chinese, and Ukrainian.\n\n### Supported Syntax\n\nThe NLP engine recognizes:\n\n- **Tags and Contexts**: `#tag` and `@context` syntax (triggers are customizable).\n- **Projects**: `+project` for simple projects or `+[[Project Name]]` for projects with spaces.\n- **Priority Levels**: Keywords like \"high,\" \"normal,\" and \"low\". Also supports a trigger character (default: `!`).\n- **Status Assignment**: Keywords like \"open,\" \"in-progress,\" and \"done\". Also supports a trigger character (default: `*`).\n- **Dates and Times**: Phrases like \"tomorrow,\" \"next Friday,\" and \"January 15th at 3pm\".\n- **Time Estimates**: Formats like \"2h,\" \"30min,\" and \"1h30m\".\n- **Recurrence Patterns**: Phrases like \"daily,\" \"weekly,\" and \"every Monday\".\n- **User-Defined Fields**: Custom fields can be assigned using configured triggers (e.g., `effort: high`). Supports quoted values for multi-word entries.\nNLP parses common patterns during capture; fields can be refined in the modal afterward.\n\n### Rich Markdown Editor\n\n**New in v4**: The task creation modal uses a rich CodeMirror markdown editor instead of a plain textarea.\n\nFeatures include:\n\n- **Live Preview**: Rendered markdown preview as you type.\n- **Syntax Highlighting**: Code blocks, links, and formatting are highlighted.\n- **Wikilink Support**: Create links to other notes using `[[Note Name]]` syntax.\n- **Keyboard Shortcuts**:\n - `Ctrl/Cmd+Enter` saves the task\n - `Esc` or `Tab` to navigate out of the editor\n- **Placeholder Text**: Shows an example task (e.g., \"Buy groceries tomorrow at 3pm @home #errands\") when the editor is empty.\n\n### Customizable Triggers\n\n**New in v4**: Triggers for NLP properties can be customized in `Settings -> TaskNotes -> Features` (`NLP Triggers`).\n\nYou can configure trigger characters or strings for:\n\n- **Tags** (default: `#`) - When set to `#`, Obsidian's native tag suggester is used\n- **Contexts** (default: `@`)\n- **Projects** (default: `+`)\n- **Status** (default: `*`)\n- **Priority** (default: `!`, disabled by default)\n- **User-Defined Fields** (default: `fieldname:`) - Each custom field can have its own trigger\n\nTriggers support up to 10 characters and can include trailing spaces (e.g., `\"def: \"` for a custom field).\n\n### Autocomplete\n\n**New in v4**: When typing a trigger in the NLP editor, an autocomplete menu appears with available values.\n\n- Navigate suggestions with arrow keys\n- Select with `Enter` or `Tab`\n- Autocomplete works for tags, contexts, projects, status, priority, and user-defined fields\n- Tag autocomplete uses Obsidian's native tag suggester when using the `#` trigger\n- For user fields with multi-word values, wrap the value in quotes (e.g., `effort: \"very high\"`)\n\nThe NLP engine is integrated with the task creation modal and bulk conversion features. Typing a natural language description populates the corresponding task fields automatically.\n","aliases":["/features/inline-tasks/"],"toc":[{"level":2,"id":"task-link-overlays","text":"Task Link Overlays"},{"level":3,"id":"widget-features","text":"Widget Features"},{"level":3,"id":"mode-specific-behavior","text":"Mode-Specific Behavior"},{"level":2,"id":"create-new-inline-task-command","text":"Create New Inline Task Command"},{"level":2,"id":"instant-task-conversion","text":"Instant Task Conversion"},{"level":3,"id":"folder-configuration","text":"Folder Configuration"},{"level":3,"id":"supported-line-types","text":"Supported Line Types"},{"level":3,"id":"content-processing","text":"Content Processing"},{"level":2,"id":"bulk-task-conversion","text":"Bulk Task Conversion"},{"level":3,"id":"how-it-works","text":"How It Works"},{"level":3,"id":"usage","text":"Usage"},{"level":3,"id":"error-handling","text":"Error Handling"},{"level":2,"id":"relationships-widget","text":"Relationships Widget"},{"level":3,"id":"automatic-tab-management","text":"Automatic Tab Management"},{"level":3,"id":"features","text":"Features"},{"level":3,"id":"configuration","text":"Configuration"},{"level":3,"id":"expandable-subtasks-chevron","text":"Expandable Subtasks Chevron"},{"level":3,"id":"migration-from-v3","text":"Migration from v3"},{"level":2,"id":"natural-language-processing","text":"Natural Language Processing"},{"level":3,"id":"supported-syntax","text":"Supported Syntax"},{"level":3,"id":"rich-markdown-editor","text":"Rich Markdown Editor"},{"level":3,"id":"customizable-triggers","text":"Customizable Triggers"},{"level":3,"id":"autocomplete","text":"Autocomplete"}],"html":"

TaskNotes integrates with the Obsidian editor to allow task management directly within notes. This is achieved through interactive widgets, a conversion feature for checkboxes, and natural language processing.\nInline features support capture and task updates without leaving the current note.

\n\n

When a wikilink to a task note is created, TaskNotes can replace it with an interactive Task Link Overlay. Enable or disable overlays from Settings -> TaskNotes -> Features (Task link overlay). The widget displays information about the task, such as status, priority, and due date, and allows actions like status/priority changes or opening the edit modal.

\n

\"Task

\n

Task link overlays in Live Preview mode show interactive widgets with status, dates, and quick actions

\n

\"Task

\n

In Source mode, task links appear as standard wikilinks until rendered

\n

Widget Features#

\n

The task link overlay displays:

\n
    \n
  • Status Dot: Clickable circular indicator showing current task status. Click to cycle through available statuses.
  • \n
  • Priority Dot: Color-coded indicator for task priority (only shown when assigned).
  • \n
  • Task Title: Displays the task name (truncated to 80 characters). Click to open the task edit modal.
  • \n
  • Date Information: Shows due dates (calendar icon) and scheduled dates (clock icon) with clickable context menus.
  • \n
  • Recurrence Indicator: Rotating arrow icon for recurring tasks with modification options.
  • \n
  • Action Menu: Ellipsis icon (shown on hover) provides additional task actions.\nThe widget exposes common task actions at the link location, so status and metadata can be updated in-place.
  • \n
\n

Mode-Specific Behavior#

\n

Task link overlays work in both Live Preview and Reading modes:

\n
    \n
  • Live Preview Mode: Widgets hide when the cursor is within the wikilink range, allowing for easy editing.
  • \n
  • Reading Mode: Widgets display with full functionality and integrate with the reading mode typography.
  • \n
\n

The overlays support drag-and-drop to calendar views and provide keyboard shortcuts for quick navigation (Ctrl/Cmd+Click to open the source file).

\n

Create New Inline Task Command#

\n

The Create new inline task command opens the task creation modal from the editor and inserts a link to the new task when it is saved. This command is available in the command palette.

\n

When the cursor is on an empty line, the link is inserted at the cursor. When the cursor is on a line with content, TaskNotes inserts a new line below it and places the task link there. The command does not use the current line as the task title.

\n

To turn the current line into a TaskNote, use Convert to TaskNote or the instant conversion button next to a supported line. That flow uses the current line as the task title and replaces the original line with a link to the new task file.

\n

Instant Task Conversion#

\n

The Instant Task Conversion feature transforms lines in your notes into TaskNotes files. This works with both checkbox tasks and regular lines of text. Turn the feature on or off from Settings -> TaskNotes -> Features (Show convert button next to checkboxes). When enabled, a "convert" button appears next to content in edit mode. Clicking this button creates a new task note using the line text as the title and replaces the original line with a link to the new task file.\nThis supports progressive conversion from draft notes to dedicated task files.

\n

Folder Configuration#

\n

By default, converted tasks are placed in the same folder as the current note ({{currentNotePath}}). You can change this behavior in Settings -> TaskNotes -> General (Folder for converted tasks):

\n
    \n
  • Leave empty: Uses your default tasks folder (configured in the same section)
  • \n
  • {{currentNotePath}}: Places tasks in the same folder as the note you're editing (default)
  • \n
  • {{currentNoteTitle}}: Creates a subfolder named after the current note
  • \n
  • Custom path: Specify any folder path (e.g., TaskNotes/Converted)
  • \n
\n

Supported Line Types#

\n

The conversion feature works with:

\n
    \n
  • Checkbox tasks: - [ ] Task description becomes a TaskNote with task metadata
  • \n
  • Bullet points: - Some task idea becomes a TaskNote with the text as title
  • \n
  • Numbered lists: 1. Important item becomes a TaskNote
  • \n
  • Blockquoted content: > Task in callout becomes a TaskNote (preserves blockquote formatting)
  • \n
  • Plain text lines: Important thing to do becomes a TaskNote
  • \n
  • Mixed formats: > - [ ] Task in blockquote handles both blockquote and checkbox formatting
  • \n
\n

Content Processing#

\n

When converting lines:

\n
    \n
  • Special characters like >, #, - are automatically removed from the task title
  • \n
  • Original formatting is preserved in the note (e.g., > [[Task Title]] for blockquoted content)
  • \n
  • Task metadata is extracted from checkbox tasks (due dates, priorities, etc.)
  • \n
  • Natural language processing can extract dates and metadata from plain text (if enabled)\nConversion preserves surrounding formatting, including callouts, outlines, and nested lists.
  • \n
\n

The feature handles edge cases like nested blockquotes and maintains proper indentation in the final link replacement.

\n

Bulk Task Conversion#

\n

The Bulk Task Conversion command converts all checkbox tasks in the current note to TaskNotes in a single operation. This command is available in the command palette as "Convert all tasks in note to TaskNotes".

\n

How It Works#

\n

The command:

\n
    \n
  1. Scans the entire current note for checkbox tasks (- [ ], * [ ], 1. [ ], etc.)
  2. \n
  3. Includes tasks inside blockquotes (e.g., > - [ ] task in callout)
  4. \n
  5. Applies the same enhanced conversion logic as instant task conversion
  6. \n
  7. Creates individual TaskNote files for each task
  8. \n
  9. Replaces the original checkboxes with links to the new task files
  10. \n
  11. Preserves original indentation and formatting (including blockquote markers)
  12. \n
\n

The bulk conversion uses the same content processing as instant conversion, automatically removing special characters from task titles while preserving original formatting in the note.

\n

Usage#

\n

To use bulk conversion:

\n
    \n
  1. Open a note containing checkbox tasks
  2. \n
  3. Access the command palette (Ctrl+P / Cmd+P)
  4. \n
  5. Search for "Convert all tasks in note to TaskNotes"
  6. \n
  7. Execute the command
  8. \n
\n

The command displays progress and shows a summary when complete (for example, "Successfully converted 5 tasks to TaskNotes.").

\n\n
**This command modifies note content permanently.** Before using:\n\n- **Create a backup** of your note if it contains important data\n- **Review the tasks** to ensure they should become individual TaskNotes\n- **Expect processing time** - notes with many tasks may take several seconds to process\n- **Avoid interruption** - do not edit the note while conversion is running\n
\n
Processing time depends on the number of tasks:\n\n- Small notes (1-10 tasks): Near-instant\n- Medium notes (10-50 tasks): 2-5 seconds\n- Large notes (50+ tasks): 10+ seconds\n\nThe operation creates multiple files and updates the note content, which requires disk I/O and editor updates.\n

Error Handling#

\n

If some tasks fail to convert, the command will:

\n
    \n
  • Complete successfully converted tasks
  • \n
  • Display a summary showing both successes and failures
  • \n
  • Log detailed error information to the console for troubleshooting
  • \n
\n

Failed conversions typically occur due to:

\n
    \n
  • Tasks with titles containing invalid filename characters
  • \n
  • Insufficient disk permissions
  • \n
  • Very long task titles (over 200 characters)\nFor large notes, converting a small section first helps validate folder and filename settings.
  • \n
\n

Relationships Widget#

\n

New in v4: The Relationships Widget consolidates what were previously three separate widgets (project subtasks, task dependencies, and blocking tasks) into a single dynamic interface.

\n

The widget appears in task notes and automatically displays up to five tabs based on available relationship data:

\n
    \n
  • Subtasks Tab (Kanban): Shows tasks that reference the current note as a project. Uses Kanban layout for visual task management.
  • \n
  • Occurrences Tab (List): Shows materialized occurrence notes that reference the current recurring task as their parent. Uses list layout sorted by occurrence date.
  • \n
  • Projects Tab (List): Shows projects that the current task belongs to. Uses list layout.
  • \n
  • Blocked By Tab (List): Shows tasks that are blocking the current task. Uses list layout.
  • \n
  • Blocking Tab (Kanban): Shows tasks that the current task is blocking. Uses Kanban layout.
  • \n
\n

Automatic Tab Management#

\n

Tabs automatically show or hide based on the presence of relationship data. If a task has no subtasks, the Subtasks tab does not appear. If a recurring task has no materialized occurrence notes, the Occurrences tab does not appear. If there are no blocking relationships, those tabs remain hidden. This keeps the interface focused on relevant information.\nThe widget layout changes with available data, so simple tasks show fewer sections.

\n

Features#

\n

The widget embeds the TaskNotes/Views/relationships.base view directly in the editor. Every filter, grouping rule, or property shown in that .base file is exactly what appears inside the widget, so you can customize the experience by editing the file just like any other Bases view.

\n

Additional behavior:

\n
    \n
  • Collapsible Interface: Click the widget title to expand or collapse. The state is remembered between sessions.
  • \n
  • Persistent Grouping: Any grouping defined in the .base file is honoured, and collapsed groups retain their state per note.
  • \n
  • Task Details: Each task shows its status, priority, due date, and other configured properties.
  • \n
  • Real-time Updates: The widget updates automatically when tasks are added, modified, or deleted via Bases views.
  • \n
\n

Configuration#

\n

Enable or disable the widget in Settings -> TaskNotes -> Appearance (Show relationships widget).

\n

Position the widget at the top (after frontmatter) or bottom of the note using the Relationships Position setting.

\n

Expandable Subtasks Chevron#

\n

Tasks with subtasks can display an expand/collapse chevron that toggles subtask visibility.

\n
    \n
  • The chevron can be positioned on the Right (default, hover to show) or on the Left (always visible, matches group chevrons).
  • \n
  • Configure this in Settings -> TaskNotes -> Appearance (Subtask chevron position).
  • \n
\n

\"Left

\n

Migration from v3#

\n

In v3, TaskNotes provided three separate widgets controlled by individual settings:

\n
    \n
  • showProjectSubtasks and projectSubtasksPosition
  • \n
  • showTaskDependencies and taskDependenciesPosition
  • \n
  • showBlockingTasks and blockingTasksPosition
  • \n
\n

These settings are replaced in v4 by:

\n
    \n
  • showRelationships and relationshipsPosition
  • \n
\n

If you had project subtasks enabled in v3, the relationships widget is enabled automatically after upgrading to v4. The underlying Bases file changed from TaskNotes/Views/project-subtasks.base to TaskNotes/Views/relationships.base. Run the Create files action in Settings -> TaskNotes -> General -> Views & base files if relationships.base is missing.

\n

Natural Language Processing#

\n

TaskNotes includes a Natural Language Processor (NLP) that parses task descriptions to extract structured data. This allows for task creation from conversational language, such as "Prepare quarterly report due Friday #work high priority," which would automatically set the due date, tag, and priority.

\n

The NLP engine supports multiple languages, including English, Spanish, French, German, Italian, Japanese, Dutch, Portuguese, Russian, Swedish, Chinese, and Ukrainian.

\n

Supported Syntax#

\n

The NLP engine recognizes:

\n
    \n
  • Tags and Contexts: #tag and @context syntax (triggers are customizable).
  • \n
  • Projects: +project for simple projects or +[[Project Name]] for projects with spaces.
  • \n
  • Priority Levels: Keywords like "high," "normal," and "low". Also supports a trigger character (default: !).
  • \n
  • Status Assignment: Keywords like "open," "in-progress," and "done". Also supports a trigger character (default: *).
  • \n
  • Dates and Times: Phrases like "tomorrow," "next Friday," and "January 15th at 3pm".
  • \n
  • Time Estimates: Formats like "2h," "30min," and "1h30m".
  • \n
  • Recurrence Patterns: Phrases like "daily," "weekly," and "every Monday".
  • \n
  • User-Defined Fields: Custom fields can be assigned using configured triggers (e.g., effort: high). Supports quoted values for multi-word entries.\nNLP parses common patterns during capture; fields can be refined in the modal afterward.
  • \n
\n

Rich Markdown Editor#

\n

New in v4: The task creation modal uses a rich CodeMirror markdown editor instead of a plain textarea.

\n

Features include:

\n
    \n
  • Live Preview: Rendered markdown preview as you type.
  • \n
  • Syntax Highlighting: Code blocks, links, and formatting are highlighted.
  • \n
  • Wikilink Support: Create links to other notes using [[Note Name]] syntax.
  • \n
  • Keyboard Shortcuts:
      \n
    • Ctrl/Cmd+Enter saves the task
    • \n
    • Esc or Tab to navigate out of the editor
    • \n
    \n
  • \n
  • Placeholder Text: Shows an example task (e.g., "Buy groceries tomorrow at 3pm @home #errands") when the editor is empty.
  • \n
\n

Customizable Triggers#

\n

New in v4: Triggers for NLP properties can be customized in Settings -> TaskNotes -> Features (NLP Triggers).

\n

You can configure trigger characters or strings for:

\n
    \n
  • Tags (default: #) - When set to #, Obsidian's native tag suggester is used
  • \n
  • Contexts (default: @)
  • \n
  • Projects (default: +)
  • \n
  • Status (default: *)
  • \n
  • Priority (default: !, disabled by default)
  • \n
  • User-Defined Fields (default: fieldname:) - Each custom field can have its own trigger
  • \n
\n

Triggers support up to 10 characters and can include trailing spaces (e.g., "def: " for a custom field).

\n

Autocomplete#

\n

New in v4: When typing a trigger in the NLP editor, an autocomplete menu appears with available values.

\n
    \n
  • Navigate suggestions with arrow keys
  • \n
  • Select with Enter or Tab
  • \n
  • Autocomplete works for tags, contexts, projects, status, priority, and user-defined fields
  • \n
  • Tag autocomplete uses Obsidian's native tag suggester when using the # trigger
  • \n
  • For user fields with multi-word values, wrap the value in quotes (e.g., effort: "very high")
  • \n
\n

The NLP engine is integrated with the task creation modal and bulk conversion features. Typing a natural language description populates the corresponding task fields automatically.

\n","text":"TaskNotes integrates with the Obsidian editor to allow task management directly within notes. This is achieved through interactive widgets, a conversion feature for checkboxes, and natural language processing. Inline features support capture and task updates without leaving the current note. Task Link Overlays# When a wikilink to a task note is created, TaskNotes can replace it with an interactive Task Link Overlay. Enable or disable overlays from Settings -> TaskNotes -> Features (Task link overlay). The widget displays information about the task, such as status, priority, and due date, and allows actions like status/priority changes or opening the edit modal. Task link overlays in Live Preview mode show interactive widgets with status, dates, and quick actions In Source mode, task links appear as standard wikilinks until rendered Widget Features# The task link overlay displays: Status Dot: Clickable circular indicator showing current task status. Click to cycle through available statuses. Priority Dot: Color-coded indicator for task priority (only shown when assigned). Task Title: Displays the task name (truncated to 80 characters). Click to open the task edit modal. Date Information: Shows due dates (calendar icon) and scheduled dates (clock icon) with clickable context menus. Recurrence Indicator: Rotating arrow icon for recurring tasks with modification options. Action Menu: Ellipsis icon (shown on hover) provides additional task actions. The widget exposes common task actions at the link location, so status and metadata can be updated in-place. Mode-Specific Behavior# Task link overlays work in both Live Preview and Reading modes: Live Preview Mode: Widgets hide when the cursor is within the wikilink range, allowing for easy editing. Reading Mode: Widgets display with full functionality and integrate with the reading mode typography. The overlays support drag-and-drop to calendar views and provide keyboard shortcuts for quick navigation (Ctrl/Cmd+Click to open the source file). Create New Inline Task Command# The Create new inline task command opens the task creation modal from the editor and inserts a link to the new task when it is saved. This command is available in the command palette. When the cursor is on an empty line, the link is inserted at the cursor. When the cursor is on a line with content, TaskNotes inserts a new line below it and places the task link there. The command does not use the current line as the task title. To turn the current line into a TaskNote, use Convert to TaskNote or the instant conversion button next to a supported line. That flow uses the current line as the task title and replaces the original line with a link to the new task file. Instant Task Conversion# The Instant Task Conversion feature transforms lines in your notes into TaskNotes files. This works with both checkbox tasks and regular lines of text. Turn the feature on or off from Settings -> TaskNotes -> Features (Show convert button next to checkboxes). When enabled, a \"convert\" button appears next to content in edit mode. Clicking this button creates a new task note using the line text as the title and replaces the original line with a link to the new task file. This supports progressive conversion from draft notes to dedicated task files. Folder Configuration# By default, converted tasks are placed in the same folder as the current note ({{currentNotePath}}). You can change this behavior in Settings -> TaskNotes -> General (Folder for converted tasks): Leave empty: Uses your default tasks folder (configured in the same section) {{currentNotePath}}: Places tasks in the same folder as the note you're editing (default) {{currentNoteTitle}}: Creates a subfolder named after the current note Custom path: Specify any folder path (e.g., TaskNotes/Converted) Supported Line Types# The conversion feature works with: Checkbox tasks: - [ ] Task description becomes a TaskNote with task metadata Bullet points: - Some task idea becomes a TaskNote with the text as title Numbered lists: 1. Important item becomes a TaskNote Blockquoted content: > Task in callout becomes a TaskNote (preserves blockquote formatting) Plain text lines: Important thing to do becomes a TaskNote Mixed formats: > - [ ] Task in blockquote handles both blockquote and checkbox formatting Content Processing# When converting lines: Special characters like >, #, - are automatically removed from the task title Original formatting is preserved in the note (e.g., > [[Task Title]] for blockquoted content) Task metadata is extracted from checkbox tasks (due dates, priorities, etc.) Natural language processing can extract dates and metadata from plain text (if enabled) Conversion preserves surrounding formatting, including callouts, outlines, and nested lists. The feature handles edge cases like nested blockquotes and maintains proper indentation in the final link replacement. Bulk Task Conversion# The Bulk Task Conversion command converts all checkbox tasks in the current note to TaskNotes in a single operation. This command is available in the command palette as \"Convert all tasks in note to TaskNotes\". How It Works# The command: Scans the entire current note for checkbox tasks (- [ ], * [ ], 1. [ ], etc.) Includes tasks inside blockquotes (e.g., > - [ ] task in callout) Applies the same enhanced conversion logic as instant task conversion Creates individual TaskNote files for each task Replaces the original checkboxes with links to the new task files Preserves original indentation and formatting (including blockquote markers) The bulk conversion uses the same content processing as instant conversion, automatically removing special characters from task titles while preserving original formatting in the note. Usage# To use bulk conversion: Open a note containing checkbox tasks Access the command palette (Ctrl+P / Cmd+P) Search for \"Convert all tasks in note to TaskNotes\" Execute the command The command displays progress and shows a summary when complete (for example, \"Successfully converted 5 tasks to TaskNotes.\"). Important Considerations **This command modifies note content permanently.** Before using: - **Create a backup** of your note if it contains important data - **Review the tasks** to ensure they should become individual TaskNotes - **Expect processing time** - notes with many tasks may take several seconds to process - **Avoid interruption** - do not edit the note while conversion is running Performance Processing time depends on the number of tasks: - Small notes (1-10 tasks): Near-instant - Medium notes (10-50 tasks): 2-5 seconds - Large notes (50+ tasks): 10+ seconds The operation creates multiple files and updates the note content, which requires disk I/O and editor updates. Error Handling# If some tasks fail to convert, the command will: Complete successfully converted tasks Display a summary showing both successes and failures Log detailed error information to the console for troubleshooting Failed conversions typically occur due to: Tasks with titles containing invalid filename characters Insufficient disk permissions Very long task titles (over 200 characters) For large notes, converting a small section first helps validate folder and filename settings. Relationships Widget# New in v4: The Relationships Widget consolidates what were previously three separate widgets (project subtasks, task dependencies, and blocking tasks) into a single dynamic interface. The widget appears in task notes and automatically displays up to five tabs based on available relationship data: Subtasks Tab (Kanban): Shows tasks that reference the current note as a project. Uses Kanban layout for visual task management. Occurrences Tab (List): Shows materialized occurrence notes that reference the current recurring task as their parent. Uses list layout sorted by occurrence date. Projects Tab (List): Shows projects that the current task belongs to. Uses list layout. Blocked By Tab (List): Shows tasks that are blocking the current task. Uses list layout. Blocking Tab (Kanban): Shows tasks that the current task is blocking. Uses Kanban layout. Automatic Tab Management# Tabs automatically show or hide based on the presence of relationship data. If a task has no subtasks, the Subtasks tab does not appear. If a recurring task has no materialized occurrence notes, the Occurrences tab does not appear. If there are no blocking relationships, those tabs remain hidden. This keeps the interface focused on relevant information. The widget layout changes with available data, so simple tasks show fewer sections. Features# The widget embeds the TaskNotes/Views/relationships.base view directly in the editor. Every filter, grouping rule, or property shown in that .base file is exactly what appears inside the widget, so you can customize the experience by editing the file just like any other Bases view. Additional behavior: Collapsible Interface: Click the widget title to expand or collapse. The state is remembered between sessions. Persistent Grouping: Any grouping defined in the .base file is honoured, and collapsed groups retain their state per note. Task Details: Each task shows its status, priority, due date, and other configured properties. Real-time Updates: The widget updates automatically when tasks are added, modified, or deleted via Bases views. Configuration# Enable or disable the widget in Settings -> TaskNotes -> Appearance (Show relationships widget). Position the widget at the top (after frontmatter) or bottom of the note using the Relationships Position setting. Expandable Subtasks Chevron# Tasks with subtasks can display an expand/collapse chevron that toggles subtask visibility. The chevron can be positioned on the Right (default, hover to show) or on the Left (always visible, matches group chevrons). Configure this in Settings -> TaskNotes -> Appearance (Subtask chevron position). Migration from v3# In v3, TaskNotes provided three separate widgets controlled by individual settings: showProjectSubtasks and projectSubtasksPosition showTaskDependencies and taskDependenciesPosition showBlockingTasks and blockingTasksPosition These settings are replaced in v4 by: showRelationships and relationshipsPosition If you had project subtasks enabled in v3, the relationships widget is enabled automatically after upgrading to v4. The underlying Bases file changed from TaskNotes/Views/project-subtasks.base to TaskNotes/Views/relationships.base. Run the Create files action in Settings -> TaskNotes -> General -> Views & base files if relationships.base is missing. Natural Language Processing# TaskNotes includes a Natural Language Processor (NLP) that parses task descriptions to extract structured data. This allows for task creation from conversational language, such as \"Prepare quarterly report due Friday #work high priority,\" which would automatically set the due date, tag, and priority. The NLP engine supports multiple languages, including English, Spanish, French, German, Italian, Japanese, Dutch, Portuguese, Russian, Swedish, Chinese, and Ukrainian. Supported Syntax# The NLP engine recognizes: Tags and Contexts: #tag and @context syntax (triggers are customizable). Projects: +project for simple projects or +[[Project Name]] for projects with spaces. Priority Levels: Keywords like \"high,\" \"normal,\" and \"low\". Also supports a trigger character (default: !). Status Assignment: Keywords like \"open,\" \"in-progress,\" and \"done\". Also supports a trigger character (default: *). Dates and Times: Phrases like \"tomorrow,\" \"next Friday,\" and \"January 15th at 3pm\". Time Estimates: Formats like \"2h,\" \"30min,\" and \"1h30m\". Recurrence Patterns: Phrases like \"daily,\" \"weekly,\" and \"every Monday\". User-Defined Fields: Custom fields can be assigned using configured triggers (e.g., effort: high). Supports quoted values for multi-word entries. NLP parses common patterns during capture; fields can be refined in the modal afterward. Rich Markdown Editor# New in v4: The task creation modal uses a rich CodeMirror markdown editor instead of a plain textarea. Features include: Live Preview: Rendered markdown preview as you type. Syntax Highlighting: Code blocks, links, and formatting are highlighted. Wikilink Support: Create links to other notes using [[Note Name]] syntax. Keyboard Shortcuts: Ctrl/Cmd+Enter saves the task Esc or Tab to navigate out of the editor Placeholder Text: Shows an example task (e.g., \"Buy groceries tomorrow at 3pm @home #errands\") when the editor is empty. Customizable Triggers# New in v4: Triggers for NLP properties can be customized in Settings -> TaskNotes -> Features (NLP Triggers). You can configure trigger characters or strings for: Tags (default: #) - When set to #, Obsidian's native tag suggester is used Contexts (default: @) Projects (default: +) Status (default: *) Priority (default: !, disabled by default) User-Defined Fields (default: fieldname:) - Each custom field can have its own trigger Triggers support up to 10 characters and can include trailing spaces (e.g., \"def: \" for a custom field). Autocomplete# New in v4: When typing a trigger in the NLP editor, an autocomplete menu appears with available values. Navigate suggestions with arrow keys Select with Enter or Tab Autocomplete works for tags, contexts, projects, status, priority, and user-defined fields Tag autocomplete uses Obsidian's native tag suggester when using the # trigger For user fields with multi-word values, wrap the value in quotes (e.g., effort: \"very high\") The NLP engine is integrated with the task creation modal and bulk conversion features. Typing a natural language description populates the corresponding task fields automatically."},{"route":"/obsidian/features/integrations/","title":"Integrations","description":"TaskNotes integrates with external services and Obsidian's core plugins.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/features/integrations.md","namespace":"obsidian","relativePath":"features/integrations.md","raw":"# Integrations\n\nTaskNotes integrates with external services and Obsidian's core plugins.\n\n\n## Bases Core Plugin\n\nTaskNotes v4 uses Obsidian's Bases core plugin for its main views (Task List, Kanban, Calendar, Agenda). Bases must be enabled in `Settings -> Core Plugins`.\n\nFor details on Bases integration, see [Core Concepts](../core-concepts.md#bases-integration).\n\n## External Calendars\n\nTaskNotes supports bidirectional sync with Google Calendar and Microsoft Outlook via OAuth, plus read-only access to any calendar via ICS subscriptions.\n\nFor setup instructions, see [Calendar Integration](calendar-integration.md).\n\n## HTTP API\n\nA REST API enables external applications to create, update, and query tasks. Use it for automation, browser extensions, or custom integrations.\n\nFor API documentation, see [HTTP API](../HTTP_API.md).\n\n## Webhooks\n\nWebhooks send task event payloads to external services when subscribed events occur. Optional payload transformations support service-specific formats.\n\nFor configuration, see [Webhooks](../webhooks.md).\n\n## Companion Plugins\n\nCompanion plugins run inside Obsidian alongside TaskNotes and use the JavaScript runtime API for live task operations. They are useful when an integration needs a real Obsidian UI, command-palette commands, or vault-local configuration files.\n\nFor the companion-plugin model and guides for Canvas Bases and TaskNotes Workflows, see [Companion Plugins](../companion-plugins.md).\n","aliases":["/features/integrations/"],"toc":[{"level":2,"id":"bases-core-plugin","text":"Bases Core Plugin"},{"level":2,"id":"external-calendars","text":"External Calendars"},{"level":2,"id":"http-api","text":"HTTP API"},{"level":2,"id":"webhooks","text":"Webhooks"},{"level":2,"id":"companion-plugins","text":"Companion Plugins"}],"html":"

TaskNotes integrates with external services and Obsidian's core plugins.

\n

Bases Core Plugin#

\n

TaskNotes v4 uses Obsidian's Bases core plugin for its main views (Task List, Kanban, Calendar, Agenda). Bases must be enabled in Settings -> Core Plugins.

\n

For details on Bases integration, see Core Concepts.

\n

External Calendars#

\n

TaskNotes supports bidirectional sync with Google Calendar and Microsoft Outlook via OAuth, plus read-only access to any calendar via ICS subscriptions.

\n

For setup instructions, see Calendar Integration.

\n

HTTP API#

\n

A REST API enables external applications to create, update, and query tasks. Use it for automation, browser extensions, or custom integrations.

\n

For API documentation, see HTTP API.

\n

Webhooks#

\n

Webhooks send task event payloads to external services when subscribed events occur. Optional payload transformations support service-specific formats.

\n

For configuration, see Webhooks.

\n

Companion Plugins#

\n

Companion plugins run inside Obsidian alongside TaskNotes and use the JavaScript runtime API for live task operations. They are useful when an integration needs a real Obsidian UI, command-palette commands, or vault-local configuration files.

\n

For the companion-plugin model and guides for Canvas Bases and TaskNotes Workflows, see Companion Plugins.

\n","text":"TaskNotes integrates with external services and Obsidian's core plugins. Bases Core Plugin# TaskNotes v4 uses Obsidian's Bases core plugin for its main views (Task List, Kanban, Calendar, Agenda). Bases must be enabled in Settings -> Core Plugins. For details on Bases integration, see Core Concepts. External Calendars# TaskNotes supports bidirectional sync with Google Calendar and Microsoft Outlook via OAuth, plus read-only access to any calendar via ICS subscriptions. For setup instructions, see Calendar Integration. HTTP API# A REST API enables external applications to create, update, and query tasks. Use it for automation, browser extensions, or custom integrations. For API documentation, see HTTP API. Webhooks# Webhooks send task event payloads to external services when subscribed events occur. Optional payload transformations support service-specific formats. For configuration, see Webhooks. Companion Plugins# Companion plugins run inside Obsidian alongside TaskNotes and use the JavaScript runtime API for live task operations. They are useful when an integration needs a real Obsidian UI, command-palette commands, or vault-local configuration files. For the companion-plugin model and guides for Canvas Bases and TaskNotes Workflows, see Companion Plugins."},{"route":"/obsidian/features/recurring-tasks/","title":"Recurring Tasks","description":"TaskNotes recurring tasks use RFC 5545 RRule strings with DTSTART support and dynamic next-occurrence scheduling. The model separates recurrence patterns from the next planned i...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/features/recurring-tasks.md","namespace":"obsidian","relativePath":"features/recurring-tasks.md","raw":"# Recurring Tasks\n\n\nTaskNotes recurring tasks use RFC 5545 RRule strings with `DTSTART` support and dynamic next-occurrence scheduling. The model separates recurrence patterns from the next planned instance, and can also create normal task notes for individual occurrences when an instance needs its own content.\n\nIf you are new to recurring tasks in TaskNotes, think of the recurrence rule as the long-term plan and the `scheduled` field as the next concrete commitment. Most day-to-day editing affects `scheduled`, while recurrence editing changes the plan itself.\n\n## Core Concepts\n\nRecurring tasks operate on two independent levels:\n\n1. **Recurring Pattern**: Defines when pattern instances appear (controlled by `DTSTART` in the recurrence rule)\n2. **Next Occurrence**: The specific date/time when you plan to work on the next instance (controlled by the `scheduled` field)\n3. **Materialized Occurrence Notes**: Optional child task notes for specific occurrence dates, used when an occurrence needs its own checklist, status, time tracking, or body content\n\nThis separation lets you reschedule the next occurrence without changing the pattern.\n\n## Setting Up Recurring Tasks\n\nIn practice, setup is usually a two-step flow: choose a pattern, then check whether the next scheduled occurrence matches how you actually want to execute the next instance.\n\n### Creating Recurrence Patterns\n\nYou can create recurring tasks through:\n\n1. **Recurrence Context Menu** in task modals for presets or custom options\n2. **Preset Options** such as daily, weekly, or monthly\n3. **Custom Recurrence Modal** with date/time pickers and RRule configuration\n\n### Required Components\n\nRecurring tasks require:\n\n- **Recurrence Rule**: RRule string with `DTSTART`\n- **Scheduled Date**: Next occurrence date (independent from the pattern)\n\nMaterialized occurrence notes add two system fields to the occurrence note:\n\n- `recurrence_parent`: link/path back to the recurring parent task\n- `occurrence_date`: the occurrence date represented by the note\n\n### DTSTART Integration\n\n`DTSTART` is the anchor for pattern generation. It controls where the rule begins and, when time is included, the default time for future pattern instances.\n\n- **Date-only**: `DTSTART:20250804;FREQ=DAILY`\n- **Date and time**: `DTSTART:20250804T090000Z;FREQ=DAILY`\n\n## Recurring Task Due Date\n\nWhen a recurring task is completed, `scheduled` advances to the next occurrence. By default, `due` does not change.\n\nEnable `Maintain due date offset in recurring tasks` in **Settings → TaskNotes → Features → Recurring Tasks** to preserve due/scheduled spacing.\n\nExample:\n\n- Scheduled: `2025-01-01`\n- Due: `2025-01-03`\n- Recurrence: weekly\n\nIf the task advances to `scheduled: 2025-01-08`, the due date becomes `2025-01-10` when this setting is enabled.\n\nThis setting is most useful when due dates represent a fixed lead/lag relative to scheduled work (for example, \"due two days after execution\"). If due dates are independent deadlines, leaving the setting off is usually clearer.\n\n## Recurrence Pattern Examples\n\n```text\nDTSTART:20250804T090000Z;FREQ=DAILY\n→ Daily at 9:00 AM, starting August 4, 2025\n\nDTSTART:20250804T140000Z;FREQ=WEEKLY;BYDAY=MO,WE,FR\n→ Monday, Wednesday, Friday at 2:00 PM, starting August 4, 2025\n\nDTSTART:20250815;FREQ=MONTHLY;BYMONTHDAY=15\n→ 15th of each month (all-day), starting August 15, 2025\n\nDTSTART:20250831;FREQ=MONTHLY;BYMONTHDAY=-1\n→ Last day of each month (all-day), starting August 31, 2025\n\nDTSTART:20250801T100000Z;FREQ=MONTHLY;BYDAY=-1FR\n→ Last Friday of each month at 10:00 AM, starting August 1, 2025\n```\n\n## Dynamic Scheduled Dates\n\nThe `scheduled` field automatically tracks the next uncompleted occurrence:\n\n1. Initially set to the `DTSTART` date\n2. Advances when occurrences are completed\n3. Recalculates when the rule changes\n4. Can be manually rescheduled independently\n\nThis behavior keeps recurring tasks practical in real planning: you can preserve a stable weekly/monthly pattern while still adapting the immediate next occurrence to calendar realities.\n\n## Materialized Occurrence Notes\n\nMost recurring tasks can remain virtual: the parent task stores `complete_instances` and `skipped_instances`, and TaskNotes renders each calendar/list instance from that parent. Materialized occurrence notes are for heavier instances where the date-specific work needs its own note.\n\nGood uses include:\n\n- A weekly review where each week needs a separate agenda and notes\n- A maintenance task where each visit needs photos, links, or a checklist\n- A recurring meeting where every occurrence should have its own time entries and completion state\n\nTo create one manually, right-click a recurring task card or calendar occurrence and choose **Open or create occurrence note**. The Task Action Palette also exposes **Open or create occurrence note** for recurring tasks. If a matching note already exists for the same parent and date, TaskNotes opens it instead of creating a duplicate.\n\nAn occurrence note is an ordinary TaskNotes task. It appears in views, can be edited like any other task, and shows an occurrence pill that links back to the recurring parent. On the calendar, a materialized occurrence replaces the matching virtual parent occurrence for the same parent/date pair, so you do not see both the generated instance and the note-backed instance at the same time.\n\nIts frontmatter includes:\n\n```yaml\nrecurrence_parent: \"[[Tasks/Weekly review]]\"\noccurrence_date: \"2026-06-01\"\nscheduled: \"2026-06-01T09:30\"\ntimeEstimate: 45\n```\n\nWhen TaskNotes creates an occurrence note, it copies the parent fields that describe how that instance should be planned: title, priority, scheduled time, due offset, contexts, projects, tags, reminders, dependencies, details, custom properties, and time estimate. Date-like fields are rebased onto the occurrence date, so a parent scheduled at `09:30` creates an occurrence scheduled at `09:30` on the selected date, and a due date one day after the parent scheduled date stays one day after the occurrence scheduled date.\n\nOccurrence notes can use a separate template from regular new tasks. Set `occurrence_template` on the recurring parent to point at a template note, or configure **Settings → Features → Body template → Occurrence note template file** as a global fallback. Parent-level `occurrence_template` wins over the global fallback. If neither occurrence-specific template is configured, occurrence note creation keeps the normal body template behavior.\n\nThe parent task remains the source of the recurrence rule and series history. Occurrence notes do not copy the parent's `recurrence`, `complete_instances`, `skipped_instances`, `completedDate`, calendar provider IDs, or `timeEntries`. New time entries belong to the occurrence note once you track time there.\n\n### Occurrence Filenames\n\nBy default, materialized occurrence notes use the existing filename behavior: the parent title followed by a numeric suffix. To opt in to custom filenames, set **Occurrence filename template** under **Settings → Task Properties → Title**. For example, `{{title}} — {{occurrenceDate}}` produces `Weekly review — 2026-08-01.md`.\n\nOccurrence filename templates support all regular filename variables plus these occurrence-specific variables:\n\n- `{{occurrenceDate}}` - occurrence date, such as `2026-08-01`\n- `{{occurrenceWeek}}` - ISO week, such as `2026-W31`\n- `{{occurrenceMonth}}` - month, such as `2026-08`\n- `{{occurrenceYear}}` - year, such as `2026`\n- `{{occurrenceMonthName}}` - full month name, such as `August`\n\nChoose the date granularity explicitly in the template; TaskNotes does not infer it from the recurrence rule. A recurring parent can override the global template with the frontmatter property configured by **Occurrence template override property** (by default, `occurrenceFilenameTemplate`):\n\n```yaml\noccurrenceFilenameTemplate: \"{{title}} ({{occurrenceWeek}})\"\n```\n\nLeaving the global template empty preserves the existing filename behavior. TaskNotes never renames existing occurrence notes, and filename collisions continue to receive a numeric suffix.\n\n### Occurrence Note Policies\n\nEach recurring parent has an **Occurrence notes** submenu under its recurrence menu:\n\n- **Create manually**: occurrence notes are only created by explicit action.\n- **Create next after completion**: after you complete a materialized occurrence note, TaskNotes creates the next occurrence note.\n- **Rolling window**: defined by the TaskNotes spec, but not automated in the plugin yet.\n\nWhen **Create next after completion** is enabled, creating the first occurrence is still a deliberate action. After that, completing the occurrence note advances the parent recurrence state and materializes the next scheduled occurrence.\n\nHTTP API and MCP clients can create occurrence notes without using the desktop context menu. Use `POST /api/tasks/:id/materialize-occurrence` or the MCP `tasknotes_materialize_occurrence` tool with a parent task path and occurrence date. Completing a recurring instance through the API or MCP also respects existing occurrence notes and the **Create next after completion** policy.\n\nThe same submenu also controls the next-note trigger:\n\n- **Completion only**: create the next occurrence note only when the current occurrence is completed.\n- **Completion or skip**: create the next occurrence note when the current occurrence is completed or skipped.\n\nSkip/unskip controls appear on materialized occurrence notes when a skipped status is configured. Skipping an occurrence preserves the note, updates its status, and reconciles the parent `skipped_instances` list.\n\n### Completion Reconciliation\n\nWhen a materialized occurrence note is completed, TaskNotes updates both sides of the relationship:\n\n- The occurrence note is completed like a normal task.\n- The parent adds the occurrence date to `complete_instances`.\n- The parent removes that date from `skipped_instances` if needed.\n- The parent recalculates `scheduled` to the next uncompleted occurrence.\n- If the parent policy is **Create next after completion**, TaskNotes creates the next occurrence note idempotently.\n\nUncompleting an occurrence note removes the date from the parent's `complete_instances` list, but it does not delete later occurrence notes that were already created.\n\n### Example Behavior\n\n```yaml\n# Initial state\nrecurrence: \"DTSTART:20250804T090000Z;FREQ=DAILY\"\nscheduled: \"2025-08-04T09:00\"\ncomplete_instances: []\n\n# After completing Aug 4\nrecurrence: \"DTSTART:20250804T090000Z;FREQ=DAILY\"\nscheduled: \"2025-08-05T09:00\"\ncomplete_instances: [\"2025-08-04\"]\n\n# After manually rescheduling next occurrence\nrecurrence: \"DTSTART:20250804T090000Z;FREQ=DAILY\"\nscheduled: \"2025-08-05T14:30\"\ncomplete_instances: [\"2025-08-04\"]\n```\n\n## Calendar Drag and Drop\n\nCalendar interactions follow the same model distinction: drag the concrete next item to reschedule execution, or drag a pattern instance to redefine the recurrence anchor.\n\nRecurring tasks can show:\n\n- **Next occurrence** (solid border): dragging updates only `scheduled`\n- **Pattern instances** (dashed border): dragging updates `DTSTART` and future pattern instances\n- **Materialized occurrence notes**: dragging updates the occurrence note's own `scheduled` or `due` date like a normal task, without changing the parent's recurrence rule\n\n![Recurring tasks in calendar week view](../assets/views-calendar-week.png)\n\nMaterialized occurrence notes keep `occurrence_date` as their identity. If you drag the note for the June 1 occurrence to June 2, it is still the June 1 recurrence instance, now scheduled for June 2. TaskNotes suppresses the June 1 virtual parent event and leaves the June 2 virtual occurrence alone unless that date also has its own materialized note.\n\n## Completion Tracking\n\nEach occurrence can be completed or skipped independently (task cards, calendar menus, task edit modal completion calendar).\n\nCompleted instances are stored in:\n\n```yaml\ncomplete_instances: [\"2025-08-04\", \"2025-08-06\", \"2025-08-08\"]\n```\n\nSkipped instances are stored in:\n\n```yaml\nskipped_instances: [\"2025-08-05\"]\n```\n\nWhen completion changes, `scheduled` updates to the next uncompleted instance. If a materialized occurrence note exists for a date, that note's own status takes precedence for that occurrence, and TaskNotes reconciles the parent compatibility lists during completion, uncompletion, skip, and unskip actions.\n\nThis means completion history and next-action planning stay synchronized automatically, without manually advancing recurring tasks.\n\n## Flexible Scheduling\n\nTaskNotes intentionally allows off-pattern scheduling so recurring tasks can absorb real-world disruptions without rewriting the entire recurrence rule.\n\nThe next occurrence can be:\n\n- Before `DTSTART`\n- Outside the pattern day\n- At a different time than pattern instances\n- Far ahead while pattern continues unchanged\n\n### Examples\n\n```yaml\n# Early start before DTSTART\nrecurrence: \"DTSTART:20250810T090000Z;FREQ=WEEKLY;BYDAY=MO\"\nscheduled: \"2025-08-07T14:00\"\n```\n\n```yaml\n# Off-pattern next occurrence\nrecurrence: \"DTSTART:20250804T090000Z;FREQ=WEEKLY;BYDAY=MO\"\nscheduled: \"2025-08-06T15:30\"\n```\n\n## Timezone Handling\n\nRecurring task logic uses a UTC anchor approach:\n\n- Pattern generation uses UTC dates\n- `DTSTART` dates are interpreted as UTC anchors\n- Display adapts to local timezone\n- Prevents common off-by-one date issues\n\nIn other words, calculations stay stable internally while display remains local, which avoids drift when traveling or sharing vaults across timezones.\n\n## Backward Compatibility\n\nRecurring behavior remains compatible with older task data, so upgrades do not require manual note rewrites.\n\n- Legacy RRule strings without `DTSTART` continue to work using `scheduled` as anchor\n- Legacy recurrence objects are converted to RRule format\n- Existing tasks continue to function without migration steps\n- Mixed formats are handled transparently\n","aliases":["/features/recurring-tasks/"],"toc":[{"level":2,"id":"core-concepts","text":"Core Concepts"},{"level":2,"id":"setting-up-recurring-tasks","text":"Setting Up Recurring Tasks"},{"level":3,"id":"creating-recurrence-patterns","text":"Creating Recurrence Patterns"},{"level":3,"id":"required-components","text":"Required Components"},{"level":3,"id":"dtstart-integration","text":"DTSTART Integration"},{"level":2,"id":"recurring-task-due-date","text":"Recurring Task Due Date"},{"level":2,"id":"recurrence-pattern-examples","text":"Recurrence Pattern Examples"},{"level":2,"id":"dynamic-scheduled-dates","text":"Dynamic Scheduled Dates"},{"level":2,"id":"materialized-occurrence-notes","text":"Materialized Occurrence Notes"},{"level":3,"id":"occurrence-filenames","text":"Occurrence Filenames"},{"level":3,"id":"occurrence-note-policies","text":"Occurrence Note Policies"},{"level":3,"id":"completion-reconciliation","text":"Completion Reconciliation"},{"level":3,"id":"example-behavior","text":"Example Behavior"},{"level":2,"id":"calendar-drag-and-drop","text":"Calendar Drag and Drop"},{"level":2,"id":"completion-tracking","text":"Completion Tracking"},{"level":2,"id":"flexible-scheduling","text":"Flexible Scheduling"},{"level":3,"id":"examples","text":"Examples"},{"level":2,"id":"timezone-handling","text":"Timezone Handling"},{"level":2,"id":"backward-compatibility","text":"Backward Compatibility"}],"html":"

TaskNotes recurring tasks use RFC 5545 RRule strings with DTSTART support and dynamic next-occurrence scheduling. The model separates recurrence patterns from the next planned instance, and can also create normal task notes for individual occurrences when an instance needs its own content.

\n

If you are new to recurring tasks in TaskNotes, think of the recurrence rule as the long-term plan and the scheduled field as the next concrete commitment. Most day-to-day editing affects scheduled, while recurrence editing changes the plan itself.

\n

Core Concepts#

\n

Recurring tasks operate on two independent levels:

\n
    \n
  1. Recurring Pattern: Defines when pattern instances appear (controlled by DTSTART in the recurrence rule)
  2. \n
  3. Next Occurrence: The specific date/time when you plan to work on the next instance (controlled by the scheduled field)
  4. \n
  5. Materialized Occurrence Notes: Optional child task notes for specific occurrence dates, used when an occurrence needs its own checklist, status, time tracking, or body content
  6. \n
\n

This separation lets you reschedule the next occurrence without changing the pattern.

\n

Setting Up Recurring Tasks#

\n

In practice, setup is usually a two-step flow: choose a pattern, then check whether the next scheduled occurrence matches how you actually want to execute the next instance.

\n

Creating Recurrence Patterns#

\n

You can create recurring tasks through:

\n
    \n
  1. Recurrence Context Menu in task modals for presets or custom options
  2. \n
  3. Preset Options such as daily, weekly, or monthly
  4. \n
  5. Custom Recurrence Modal with date/time pickers and RRule configuration
  6. \n
\n

Required Components#

\n

Recurring tasks require:

\n
    \n
  • Recurrence Rule: RRule string with DTSTART
  • \n
  • Scheduled Date: Next occurrence date (independent from the pattern)
  • \n
\n

Materialized occurrence notes add two system fields to the occurrence note:

\n
    \n
  • recurrence_parent: link/path back to the recurring parent task
  • \n
  • occurrence_date: the occurrence date represented by the note
  • \n
\n

DTSTART Integration#

\n

DTSTART is the anchor for pattern generation. It controls where the rule begins and, when time is included, the default time for future pattern instances.

\n
    \n
  • Date-only: DTSTART:20250804;FREQ=DAILY
  • \n
  • Date and time: DTSTART:20250804T090000Z;FREQ=DAILY
  • \n
\n

Recurring Task Due Date#

\n

When a recurring task is completed, scheduled advances to the next occurrence. By default, due does not change.

\n

Enable Maintain due date offset in recurring tasks in Settings → TaskNotes → Features → Recurring Tasks to preserve due/scheduled spacing.

\n

Example:

\n
    \n
  • Scheduled: 2025-01-01
  • \n
  • Due: 2025-01-03
  • \n
  • Recurrence: weekly
  • \n
\n

If the task advances to scheduled: 2025-01-08, the due date becomes 2025-01-10 when this setting is enabled.

\n

This setting is most useful when due dates represent a fixed lead/lag relative to scheduled work (for example, "due two days after execution"). If due dates are independent deadlines, leaving the setting off is usually clearer.

\n

Recurrence Pattern Examples#

\n
DTSTART:20250804T090000Z;FREQ=DAILY\n→ Daily at 9:00 AM, starting August 4, 2025\n\nDTSTART:20250804T140000Z;FREQ=WEEKLY;BYDAY=MO,WE,FR\n→ Monday, Wednesday, Friday at 2:00 PM, starting August 4, 2025\n\nDTSTART:20250815;FREQ=MONTHLY;BYMONTHDAY=15\n→ 15th of each month (all-day), starting August 15, 2025\n\nDTSTART:20250831;FREQ=MONTHLY;BYMONTHDAY=-1\n→ Last day of each month (all-day), starting August 31, 2025\n\nDTSTART:20250801T100000Z;FREQ=MONTHLY;BYDAY=-1FR\n→ Last Friday of each month at 10:00 AM, starting August 1, 2025\n

Dynamic Scheduled Dates#

\n

The scheduled field automatically tracks the next uncompleted occurrence:

\n
    \n
  1. Initially set to the DTSTART date
  2. \n
  3. Advances when occurrences are completed
  4. \n
  5. Recalculates when the rule changes
  6. \n
  7. Can be manually rescheduled independently
  8. \n
\n

This behavior keeps recurring tasks practical in real planning: you can preserve a stable weekly/monthly pattern while still adapting the immediate next occurrence to calendar realities.

\n

Materialized Occurrence Notes#

\n

Most recurring tasks can remain virtual: the parent task stores complete_instances and skipped_instances, and TaskNotes renders each calendar/list instance from that parent. Materialized occurrence notes are for heavier instances where the date-specific work needs its own note.

\n

Good uses include:

\n
    \n
  • A weekly review where each week needs a separate agenda and notes
  • \n
  • A maintenance task where each visit needs photos, links, or a checklist
  • \n
  • A recurring meeting where every occurrence should have its own time entries and completion state
  • \n
\n

To create one manually, right-click a recurring task card or calendar occurrence and choose Open or create occurrence note. The Task Action Palette also exposes Open or create occurrence note for recurring tasks. If a matching note already exists for the same parent and date, TaskNotes opens it instead of creating a duplicate.

\n

An occurrence note is an ordinary TaskNotes task. It appears in views, can be edited like any other task, and shows an occurrence pill that links back to the recurring parent. On the calendar, a materialized occurrence replaces the matching virtual parent occurrence for the same parent/date pair, so you do not see both the generated instance and the note-backed instance at the same time.

\n

Its frontmatter includes:

\n
recurrence_parent: "[[Tasks/Weekly review]]"\noccurrence_date: "2026-06-01"\nscheduled: "2026-06-01T09:30"\ntimeEstimate: 45\n

When TaskNotes creates an occurrence note, it copies the parent fields that describe how that instance should be planned: title, priority, scheduled time, due offset, contexts, projects, tags, reminders, dependencies, details, custom properties, and time estimate. Date-like fields are rebased onto the occurrence date, so a parent scheduled at 09:30 creates an occurrence scheduled at 09:30 on the selected date, and a due date one day after the parent scheduled date stays one day after the occurrence scheduled date.

\n

Occurrence notes can use a separate template from regular new tasks. Set occurrence_template on the recurring parent to point at a template note, or configure Settings → Features → Body template → Occurrence note template file as a global fallback. Parent-level occurrence_template wins over the global fallback. If neither occurrence-specific template is configured, occurrence note creation keeps the normal body template behavior.

\n

The parent task remains the source of the recurrence rule and series history. Occurrence notes do not copy the parent's recurrence, complete_instances, skipped_instances, completedDate, calendar provider IDs, or timeEntries. New time entries belong to the occurrence note once you track time there.

\n

Occurrence Filenames#

\n

By default, materialized occurrence notes use the existing filename behavior: the parent title followed by a numeric suffix. To opt in to custom filenames, set Occurrence filename template under Settings → Task Properties → Title. For example, {{title}} — {{occurrenceDate}} produces Weekly review — 2026-08-01.md.

\n

Occurrence filename templates support all regular filename variables plus these occurrence-specific variables:

\n
    \n
  • {{occurrenceDate}} - occurrence date, such as 2026-08-01
  • \n
  • {{occurrenceWeek}} - ISO week, such as 2026-W31
  • \n
  • {{occurrenceMonth}} - month, such as 2026-08
  • \n
  • {{occurrenceYear}} - year, such as 2026
  • \n
  • {{occurrenceMonthName}} - full month name, such as August
  • \n
\n

Choose the date granularity explicitly in the template; TaskNotes does not infer it from the recurrence rule. A recurring parent can override the global template with the frontmatter property configured by Occurrence template override property (by default, occurrenceFilenameTemplate):

\n
occurrenceFilenameTemplate: "{{title}} ({{occurrenceWeek}})"\n

Leaving the global template empty preserves the existing filename behavior. TaskNotes never renames existing occurrence notes, and filename collisions continue to receive a numeric suffix.

\n

Occurrence Note Policies#

\n

Each recurring parent has an Occurrence notes submenu under its recurrence menu:

\n
    \n
  • Create manually: occurrence notes are only created by explicit action.
  • \n
  • Create next after completion: after you complete a materialized occurrence note, TaskNotes creates the next occurrence note.
  • \n
  • Rolling window: defined by the TaskNotes spec, but not automated in the plugin yet.
  • \n
\n

When Create next after completion is enabled, creating the first occurrence is still a deliberate action. After that, completing the occurrence note advances the parent recurrence state and materializes the next scheduled occurrence.

\n

HTTP API and MCP clients can create occurrence notes without using the desktop context menu. Use POST /api/tasks/:id/materialize-occurrence or the MCP tasknotes_materialize_occurrence tool with a parent task path and occurrence date. Completing a recurring instance through the API or MCP also respects existing occurrence notes and the Create next after completion policy.

\n

The same submenu also controls the next-note trigger:

\n
    \n
  • Completion only: create the next occurrence note only when the current occurrence is completed.
  • \n
  • Completion or skip: create the next occurrence note when the current occurrence is completed or skipped.
  • \n
\n

Skip/unskip controls appear on materialized occurrence notes when a skipped status is configured. Skipping an occurrence preserves the note, updates its status, and reconciles the parent skipped_instances list.

\n

Completion Reconciliation#

\n

When a materialized occurrence note is completed, TaskNotes updates both sides of the relationship:

\n
    \n
  • The occurrence note is completed like a normal task.
  • \n
  • The parent adds the occurrence date to complete_instances.
  • \n
  • The parent removes that date from skipped_instances if needed.
  • \n
  • The parent recalculates scheduled to the next uncompleted occurrence.
  • \n
  • If the parent policy is Create next after completion, TaskNotes creates the next occurrence note idempotently.
  • \n
\n

Uncompleting an occurrence note removes the date from the parent's complete_instances list, but it does not delete later occurrence notes that were already created.

\n

Example Behavior#

\n
# Initial state\nrecurrence: "DTSTART:20250804T090000Z;FREQ=DAILY"\nscheduled: "2025-08-04T09:00"\ncomplete_instances: []\n\n# After completing Aug 4\nrecurrence: "DTSTART:20250804T090000Z;FREQ=DAILY"\nscheduled: "2025-08-05T09:00"\ncomplete_instances: ["2025-08-04"]\n\n# After manually rescheduling next occurrence\nrecurrence: "DTSTART:20250804T090000Z;FREQ=DAILY"\nscheduled: "2025-08-05T14:30"\ncomplete_instances: ["2025-08-04"]\n

Calendar Drag and Drop#

\n

Calendar interactions follow the same model distinction: drag the concrete next item to reschedule execution, or drag a pattern instance to redefine the recurrence anchor.

\n

Recurring tasks can show:

\n
    \n
  • Next occurrence (solid border): dragging updates only scheduled
  • \n
  • Pattern instances (dashed border): dragging updates DTSTART and future pattern instances
  • \n
  • Materialized occurrence notes: dragging updates the occurrence note's own scheduled or due date like a normal task, without changing the parent's recurrence rule
  • \n
\n

\"Recurring

\n

Materialized occurrence notes keep occurrence_date as their identity. If you drag the note for the June 1 occurrence to June 2, it is still the June 1 recurrence instance, now scheduled for June 2. TaskNotes suppresses the June 1 virtual parent event and leaves the June 2 virtual occurrence alone unless that date also has its own materialized note.

\n

Completion Tracking#

\n

Each occurrence can be completed or skipped independently (task cards, calendar menus, task edit modal completion calendar).

\n

Completed instances are stored in:

\n
complete_instances: ["2025-08-04", "2025-08-06", "2025-08-08"]\n

Skipped instances are stored in:

\n
skipped_instances: ["2025-08-05"]\n

When completion changes, scheduled updates to the next uncompleted instance. If a materialized occurrence note exists for a date, that note's own status takes precedence for that occurrence, and TaskNotes reconciles the parent compatibility lists during completion, uncompletion, skip, and unskip actions.

\n

This means completion history and next-action planning stay synchronized automatically, without manually advancing recurring tasks.

\n

Flexible Scheduling#

\n

TaskNotes intentionally allows off-pattern scheduling so recurring tasks can absorb real-world disruptions without rewriting the entire recurrence rule.

\n

The next occurrence can be:

\n
    \n
  • Before DTSTART
  • \n
  • Outside the pattern day
  • \n
  • At a different time than pattern instances
  • \n
  • Far ahead while pattern continues unchanged
  • \n
\n

Examples#

\n
# Early start before DTSTART\nrecurrence: "DTSTART:20250810T090000Z;FREQ=WEEKLY;BYDAY=MO"\nscheduled: "2025-08-07T14:00"\n
# Off-pattern next occurrence\nrecurrence: "DTSTART:20250804T090000Z;FREQ=WEEKLY;BYDAY=MO"\nscheduled: "2025-08-06T15:30"\n

Timezone Handling#

\n

Recurring task logic uses a UTC anchor approach:

\n
    \n
  • Pattern generation uses UTC dates
  • \n
  • DTSTART dates are interpreted as UTC anchors
  • \n
  • Display adapts to local timezone
  • \n
  • Prevents common off-by-one date issues
  • \n
\n

In other words, calculations stay stable internally while display remains local, which avoids drift when traveling or sharing vaults across timezones.

\n

Backward Compatibility#

\n

Recurring behavior remains compatible with older task data, so upgrades do not require manual note rewrites.

\n
    \n
  • Legacy RRule strings without DTSTART continue to work using scheduled as anchor
  • \n
  • Legacy recurrence objects are converted to RRule format
  • \n
  • Existing tasks continue to function without migration steps
  • \n
  • Mixed formats are handled transparently
  • \n
\n","text":"TaskNotes recurring tasks use RFC 5545 RRule strings with DTSTART support and dynamic next-occurrence scheduling. The model separates recurrence patterns from the next planned instance, and can also create normal task notes for individual occurrences when an instance needs its own content. If you are new to recurring tasks in TaskNotes, think of the recurrence rule as the long-term plan and the scheduled field as the next concrete commitment. Most day-to-day editing affects scheduled, while recurrence editing changes the plan itself. Core Concepts# Recurring tasks operate on two independent levels: Recurring Pattern: Defines when pattern instances appear (controlled by DTSTART in the recurrence rule) Next Occurrence: The specific date/time when you plan to work on the next instance (controlled by the scheduled field) Materialized Occurrence Notes: Optional child task notes for specific occurrence dates, used when an occurrence needs its own checklist, status, time tracking, or body content This separation lets you reschedule the next occurrence without changing the pattern. Setting Up Recurring Tasks# In practice, setup is usually a two-step flow: choose a pattern, then check whether the next scheduled occurrence matches how you actually want to execute the next instance. Creating Recurrence Patterns# You can create recurring tasks through: Recurrence Context Menu in task modals for presets or custom options Preset Options such as daily, weekly, or monthly Custom Recurrence Modal with date/time pickers and RRule configuration Required Components# Recurring tasks require: Recurrence Rule: RRule string with DTSTART Scheduled Date: Next occurrence date (independent from the pattern) Materialized occurrence notes add two system fields to the occurrence note: recurrence_parent: link/path back to the recurring parent task occurrence_date: the occurrence date represented by the note DTSTART Integration# DTSTART is the anchor for pattern generation. It controls where the rule begins and, when time is included, the default time for future pattern instances. Date-only: DTSTART:20250804;FREQ=DAILY Date and time: DTSTART:20250804T090000Z;FREQ=DAILY Recurring Task Due Date# When a recurring task is completed, scheduled advances to the next occurrence. By default, due does not change. Enable Maintain due date offset in recurring tasks in Settings → TaskNotes → Features → Recurring Tasks to preserve due/scheduled spacing. Example: Scheduled: 2025-01-01 Due: 2025-01-03 Recurrence: weekly If the task advances to scheduled: 2025-01-08, the due date becomes 2025-01-10 when this setting is enabled. This setting is most useful when due dates represent a fixed lead/lag relative to scheduled work (for example, \"due two days after execution\"). If due dates are independent deadlines, leaving the setting off is usually clearer. Recurrence Pattern Examples# DTSTART:20250804T090000Z;FREQ=DAILY → Daily at 9:00 AM, starting August 4, 2025 DTSTART:20250804T140000Z;FREQ=WEEKLY;BYDAY=MO,WE,FR → Monday, Wednesday, Friday at 2:00 PM, starting August 4, 2025 DTSTART:20250815;FREQ=MONTHLY;BYMONTHDAY=15 → 15th of each month (all-day), starting August 15, 2025 DTSTART:20250831;FREQ=MONTHLY;BYMONTHDAY=-1 → Last day of each month (all-day), starting August 31, 2025 DTSTART:20250801T100000Z;FREQ=MONTHLY;BYDAY=-1FR → Last Friday of each month at 10:00 AM, starting August 1, 2025 Dynamic Scheduled Dates# The scheduled field automatically tracks the next uncompleted occurrence: Initially set to the DTSTART date Advances when occurrences are completed Recalculates when the rule changes Can be manually rescheduled independently This behavior keeps recurring tasks practical in real planning: you can preserve a stable weekly/monthly pattern while still adapting the immediate next occurrence to calendar realities. Materialized Occurrence Notes# Most recurring tasks can remain virtual: the parent task stores complete_instances and skipped_instances, and TaskNotes renders each calendar/list instance from that parent. Materialized occurrence notes are for heavier instances where the date-specific work needs its own note. Good uses include: A weekly review where each week needs a separate agenda and notes A maintenance task where each visit needs photos, links, or a checklist A recurring meeting where every occurrence should have its own time entries and completion state To create one manually, right-click a recurring task card or calendar occurrence and choose Open or create occurrence note. The Task Action Palette also exposes Open or create occurrence note for recurring tasks. If a matching note already exists for the same parent and date, TaskNotes opens it instead of creating a duplicate. An occurrence note is an ordinary TaskNotes task. It appears in views, can be edited like any other task, and shows an occurrence pill that links back to the recurring parent. On the calendar, a materialized occurrence replaces the matching virtual parent occurrence for the same parent/date pair, so you do not see both the generated instance and the note-backed instance at the same time. Its frontmatter includes: recurrence_parent: \"[[Tasks/Weekly review]]\" occurrence_date: \"2026-06-01\" scheduled: \"2026-06-01T09:30\" timeEstimate: 45 When TaskNotes creates an occurrence note, it copies the parent fields that describe how that instance should be planned: title, priority, scheduled time, due offset, contexts, projects, tags, reminders, dependencies, details, custom properties, and time estimate. Date-like fields are rebased onto the occurrence date, so a parent scheduled at 09:30 creates an occurrence scheduled at 09:30 on the selected date, and a due date one day after the parent scheduled date stays one day after the occurrence scheduled date. Occurrence notes can use a separate template from regular new tasks. Set occurrence_template on the recurring parent to point at a template note, or configure Settings → Features → Body template → Occurrence note template file as a global fallback. Parent-level occurrence_template wins over the global fallback. If neither occurrence-specific template is configured, occurrence note creation keeps the normal body template behavior. The parent task remains the source of the recurrence rule and series history. Occurrence notes do not copy the parent's recurrence, complete_instances, skipped_instances, completedDate, calendar provider IDs, or timeEntries. New time entries belong to the occurrence note once you track time there. Occurrence Filenames# By default, materialized occurrence notes use the existing filename behavior: the parent title followed by a numeric suffix. To opt in to custom filenames, set Occurrence filename template under Settings → Task Properties → Title. For example, {{title}} — {{occurrenceDate}} produces Weekly review — 2026-08-01.md. Occurrence filename templates support all regular filename variables plus these occurrence-specific variables: {{occurrenceDate}} - occurrence date, such as 2026-08-01 {{occurrenceWeek}} - ISO week, such as 2026-W31 {{occurrenceMonth}} - month, such as 2026-08 {{occurrenceYear}} - year, such as 2026 {{occurrenceMonthName}} - full month name, such as August Choose the date granularity explicitly in the template; TaskNotes does not infer it from the recurrence rule. A recurring parent can override the global template with the frontmatter property configured by Occurrence template override property (by default, occurrenceFilenameTemplate): occurrenceFilenameTemplate: \"{{title}} ({{occurrenceWeek}})\" Leaving the global template empty preserves the existing filename behavior. TaskNotes never renames existing occurrence notes, and filename collisions continue to receive a numeric suffix. Occurrence Note Policies# Each recurring parent has an Occurrence notes submenu under its recurrence menu: Create manually: occurrence notes are only created by explicit action. Create next after completion: after you complete a materialized occurrence note, TaskNotes creates the next occurrence note. Rolling window: defined by the TaskNotes spec, but not automated in the plugin yet. When Create next after completion is enabled, creating the first occurrence is still a deliberate action. After that, completing the occurrence note advances the parent recurrence state and materializes the next scheduled occurrence. HTTP API and MCP clients can create occurrence notes without using the desktop context menu. Use POST /api/tasks/:id/materialize-occurrence or the MCP tasknotes_materialize_occurrence tool with a parent task path and occurrence date. Completing a recurring instance through the API or MCP also respects existing occurrence notes and the Create next after completion policy. The same submenu also controls the next-note trigger: Completion only: create the next occurrence note only when the current occurrence is completed. Completion or skip: create the next occurrence note when the current occurrence is completed or skipped. Skip/unskip controls appear on materialized occurrence notes when a skipped status is configured. Skipping an occurrence preserves the note, updates its status, and reconciles the parent skipped_instances list. Completion Reconciliation# When a materialized occurrence note is completed, TaskNotes updates both sides of the relationship: The occurrence note is completed like a normal task. The parent adds the occurrence date to complete_instances. The parent removes that date from skipped_instances if needed. The parent recalculates scheduled to the next uncompleted occurrence. If the parent policy is Create next after completion, TaskNotes creates the next occurrence note idempotently. Uncompleting an occurrence note removes the date from the parent's complete_instances list, but it does not delete later occurrence notes that were already created. Example Behavior# # Initial state recurrence: \"DTSTART:20250804T090000Z;FREQ=DAILY\" scheduled: \"2025-08-04T09:00\" complete_instances: [] # After completing Aug 4 recurrence: \"DTSTART:20250804T090000Z;FREQ=DAILY\" scheduled: \"2025-08-05T09:00\" complete_instances: [\"2025-08-04\"] # After manually rescheduling next occurrence recurrence: \"DTSTART:20250804T090000Z;FREQ=DAILY\" scheduled: \"2025-08-05T14:30\" complete_instances: [\"2025-08-04\"] Calendar Drag and Drop# Calendar interactions follow the same model distinction: drag the concrete next item to reschedule execution, or drag a pattern instance to redefine the recurrence anchor. Recurring tasks can show: Next occurrence (solid border): dragging updates only scheduled Pattern instances (dashed border): dragging updates DTSTART and future pattern instances Materialized occurrence notes: dragging updates the occurrence note's own scheduled or due date like a normal task, without changing the parent's recurrence rule Materialized occurrence notes keep occurrence_date as their identity. If you drag the note for the June 1 occurrence to June 2, it is still the June 1 recurrence instance, now scheduled for June 2. TaskNotes suppresses the June 1 virtual parent event and leaves the June 2 virtual occurrence alone unless that date also has its own materialized note. Completion Tracking# Each occurrence can be completed or skipped independently (task cards, calendar menus, task edit modal completion calendar). Completed instances are stored in: complete_instances: [\"2025-08-04\", \"2025-08-06\", \"2025-08-08\"] Skipped instances are stored in: skipped_instances: [\"2025-08-05\"] When completion changes, scheduled updates to the next uncompleted instance. If a materialized occurrence note exists for a date, that note's own status takes precedence for that occurrence, and TaskNotes reconciles the parent compatibility lists during completion, uncompletion, skip, and unskip actions. This means completion history and next-action planning stay synchronized automatically, without manually advancing recurring tasks. Flexible Scheduling# TaskNotes intentionally allows off-pattern scheduling so recurring tasks can absorb real-world disruptions without rewriting the entire recurrence rule. The next occurrence can be: Before DTSTART Outside the pattern day At a different time than pattern instances Far ahead while pattern continues unchanged Examples# # Early start before DTSTART recurrence: \"DTSTART:20250810T090000Z;FREQ=WEEKLY;BYDAY=MO\" scheduled: \"2025-08-07T14:00\" # Off-pattern next occurrence recurrence: \"DTSTART:20250804T090000Z;FREQ=WEEKLY;BYDAY=MO\" scheduled: \"2025-08-06T15:30\" Timezone Handling# Recurring task logic uses a UTC anchor approach: Pattern generation uses UTC dates DTSTART dates are interpreted as UTC anchors Display adapts to local timezone Prevents common off-by-one date issues In other words, calculations stay stable internally while display remains local, which avoids drift when traveling or sharing vaults across timezones. Backward Compatibility# Recurring behavior remains compatible with older task data, so upgrades do not require manual note rewrites. Legacy RRule strings without DTSTART continue to work using scheduled as anchor Legacy recurrence objects are converted to RRule format Existing tasks continue to function without migration steps Mixed formats are handled transparently"},{"route":"/obsidian/features/reminders/","title":"Task Reminders","description":"TaskNotes reminders use iCalendar VALARM semantics and support both relative and absolute reminder types.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/features/reminders.md","namespace":"obsidian","relativePath":"features/reminders.md","raw":"# Task Reminders\n\n\nTaskNotes reminders use iCalendar `VALARM` semantics and support both relative and absolute reminder types.\n\nThe reminders system is designed to support both habit-like workflows (\"always remind me 15 minutes before\") and one-off commitments (\"alert me exactly at this date and time\"). Most users mix both styles depending on the task.\n\n## Reminder Types\n\n### Relative Reminders\n\nRelative reminders trigger from `due` or `scheduled` dates.\n\nUse relative reminders when you want reminder behavior to stay consistent even when task dates change.\n\nExamples:\n\n- 15 minutes before due date\n- 1 hour before scheduled date\n- 2 days before due date\n- 30 minutes after scheduled date\n\n### Absolute Reminders\n\nAbsolute reminders trigger at a fixed date/time.\n\nUse absolute reminders when the reminder itself is tied to a specific moment, independent of task rescheduling.\n\nExamples:\n\n- October 26, 2025 at 9:00 AM\n- Tomorrow at 2:30 PM\n- Next Monday at 10:00 AM\n\n## Adding Reminders\n\nYou can add reminders from:\n\n1. **Task Creation Modal**\n2. **Task Edit Modal**\n3. **Task Cards** (bell icon)\n4. **Reminder field context menu**\n\nFrom a workflow perspective, task cards and context menus are fastest for quick reminders, while task modals are better for reviewing multiple reminders on the same task.\n\n![Task edit modal](../assets/feature-task-modal-edit.png)\n\n### Quick Reminder Options\n\nCommon shortcuts are available for both due and scheduled anchors, such as:\n\n- 5 minutes before\n- 15 minutes before\n- 1 hour before\n- 1 day before\n\nQuick options appear only when the anchor date exists.\n\nThis prevents invalid reminder states and keeps the quick menu focused on options that can be applied immediately.\n\n![Task context menu](../assets/feature-task-context-menu.png)\n\n## Reminder Data Format\n\nReminders are stored in YAML frontmatter arrays.\n\nBecause reminders are stored in frontmatter, they remain portable and scriptable. You can inspect or transform reminder data with any tooling that reads Markdown + YAML.\n\n### Relative Structure\n\n```yaml\nreminders:\n - id: \"rem_1678886400000_abc123xyz\"\n type: \"relative\"\n relatedTo: \"due\"\n offset: \"-PT15M\"\n description: \"Review task details\"\n```\n\n### Absolute Structure\n\n```yaml\nreminders:\n - id: \"rem_1678886400001_def456uvw\"\n type: \"absolute\"\n absoluteTime: \"2025-10-26T09:00:00\"\n description: \"Follow up with client\"\n```\n\nField meanings:\n\n- `id`: unique identifier\n- `type`: `relative` or `absolute`\n- `relatedTo`: `due` or `scheduled` (relative only)\n- `offset`: ISO 8601 duration, negative before and positive after (relative only)\n- `absoluteTime`: ISO 8601 timestamp (absolute only)\n- `description`: optional message\n\nYou typically do not need to edit these fields manually, but understanding the structure helps when debugging automation or importing task data.\n\n## Visual Indicators\n\nTasks with reminders show a bell icon on task cards.\n\n- Solid bell indicates active reminders\n- Clicking opens quick reminder actions\n- Reminder UI shows task context (due/scheduled dates and reminder count)\n\nThese indicators are intended to make reminders discoverable in list-heavy views without opening every task.\n\n## Default Reminders\n\nDefault reminders can be configured in:\n\n`Settings -> TaskNotes -> Task Properties -> Reminders`\n\nDefaults are applied to:\n\n- Manual task creation\n- Instant conversion\n- Natural language task creation\n\nDefault reminders are useful for recurring habits, such as pre-deadline checks or day-before planning prompts.\n\n![Task properties settings](../assets/settings-task-properties.png)\n\n## Technical Notes\n\n- Reminders follow iCalendar `VALARM` concepts with ISO 8601 offsets\n- The reminder property name can be customized through field mapping\n\nFor settings-level behavior (notification channels, enable/disable state), see [Features Settings](../settings/features.md).\n","aliases":["/features/reminders/"],"toc":[{"level":2,"id":"reminder-types","text":"Reminder Types"},{"level":3,"id":"relative-reminders","text":"Relative Reminders"},{"level":3,"id":"absolute-reminders","text":"Absolute Reminders"},{"level":2,"id":"adding-reminders","text":"Adding Reminders"},{"level":3,"id":"quick-reminder-options","text":"Quick Reminder Options"},{"level":2,"id":"reminder-data-format","text":"Reminder Data Format"},{"level":3,"id":"relative-structure","text":"Relative Structure"},{"level":3,"id":"absolute-structure","text":"Absolute Structure"},{"level":2,"id":"visual-indicators","text":"Visual Indicators"},{"level":2,"id":"default-reminders","text":"Default Reminders"},{"level":2,"id":"technical-notes","text":"Technical Notes"}],"html":"

TaskNotes reminders use iCalendar VALARM semantics and support both relative and absolute reminder types.

\n

The reminders system is designed to support both habit-like workflows ("always remind me 15 minutes before") and one-off commitments ("alert me exactly at this date and time"). Most users mix both styles depending on the task.

\n

Reminder Types#

\n

Relative Reminders#

\n

Relative reminders trigger from due or scheduled dates.

\n

Use relative reminders when you want reminder behavior to stay consistent even when task dates change.

\n

Examples:

\n
    \n
  • 15 minutes before due date
  • \n
  • 1 hour before scheduled date
  • \n
  • 2 days before due date
  • \n
  • 30 minutes after scheduled date
  • \n
\n

Absolute Reminders#

\n

Absolute reminders trigger at a fixed date/time.

\n

Use absolute reminders when the reminder itself is tied to a specific moment, independent of task rescheduling.

\n

Examples:

\n
    \n
  • October 26, 2025 at 9:00 AM
  • \n
  • Tomorrow at 2:30 PM
  • \n
  • Next Monday at 10:00 AM
  • \n
\n

Adding Reminders#

\n

You can add reminders from:

\n
    \n
  1. Task Creation Modal
  2. \n
  3. Task Edit Modal
  4. \n
  5. Task Cards (bell icon)
  6. \n
  7. Reminder field context menu
  8. \n
\n

From a workflow perspective, task cards and context menus are fastest for quick reminders, while task modals are better for reviewing multiple reminders on the same task.

\n

\"Task

\n

Quick Reminder Options#

\n

Common shortcuts are available for both due and scheduled anchors, such as:

\n
    \n
  • 5 minutes before
  • \n
  • 15 minutes before
  • \n
  • 1 hour before
  • \n
  • 1 day before
  • \n
\n

Quick options appear only when the anchor date exists.

\n

This prevents invalid reminder states and keeps the quick menu focused on options that can be applied immediately.

\n

\"Task

\n

Reminder Data Format#

\n

Reminders are stored in YAML frontmatter arrays.

\n

Because reminders are stored in frontmatter, they remain portable and scriptable. You can inspect or transform reminder data with any tooling that reads Markdown + YAML.

\n

Relative Structure#

\n
reminders:\n  - id: "rem_1678886400000_abc123xyz"\n    type: "relative"\n    relatedTo: "due"\n    offset: "-PT15M"\n    description: "Review task details"\n

Absolute Structure#

\n
reminders:\n  - id: "rem_1678886400001_def456uvw"\n    type: "absolute"\n    absoluteTime: "2025-10-26T09:00:00"\n    description: "Follow up with client"\n

Field meanings:

\n
    \n
  • id: unique identifier
  • \n
  • type: relative or absolute
  • \n
  • relatedTo: due or scheduled (relative only)
  • \n
  • offset: ISO 8601 duration, negative before and positive after (relative only)
  • \n
  • absoluteTime: ISO 8601 timestamp (absolute only)
  • \n
  • description: optional message
  • \n
\n

You typically do not need to edit these fields manually, but understanding the structure helps when debugging automation or importing task data.

\n

Visual Indicators#

\n

Tasks with reminders show a bell icon on task cards.

\n
    \n
  • Solid bell indicates active reminders
  • \n
  • Clicking opens quick reminder actions
  • \n
  • Reminder UI shows task context (due/scheduled dates and reminder count)
  • \n
\n

These indicators are intended to make reminders discoverable in list-heavy views without opening every task.

\n

Default Reminders#

\n

Default reminders can be configured in:

\n

Settings -> TaskNotes -> Task Properties -> Reminders

\n

Defaults are applied to:

\n
    \n
  • Manual task creation
  • \n
  • Instant conversion
  • \n
  • Natural language task creation
  • \n
\n

Default reminders are useful for recurring habits, such as pre-deadline checks or day-before planning prompts.

\n

\"Task

\n

Technical Notes#

\n
    \n
  • Reminders follow iCalendar VALARM concepts with ISO 8601 offsets
  • \n
  • The reminder property name can be customized through field mapping
  • \n
\n

For settings-level behavior (notification channels, enable/disable state), see Features Settings.

\n","text":"TaskNotes reminders use iCalendar VALARM semantics and support both relative and absolute reminder types. The reminders system is designed to support both habit-like workflows (\"always remind me 15 minutes before\") and one-off commitments (\"alert me exactly at this date and time\"). Most users mix both styles depending on the task. Reminder Types# Relative Reminders# Relative reminders trigger from due or scheduled dates. Use relative reminders when you want reminder behavior to stay consistent even when task dates change. Examples: 15 minutes before due date 1 hour before scheduled date 2 days before due date 30 minutes after scheduled date Absolute Reminders# Absolute reminders trigger at a fixed date/time. Use absolute reminders when the reminder itself is tied to a specific moment, independent of task rescheduling. Examples: October 26, 2025 at 9:00 AM Tomorrow at 2:30 PM Next Monday at 10:00 AM Adding Reminders# You can add reminders from: Task Creation Modal Task Edit Modal Task Cards (bell icon) Reminder field context menu From a workflow perspective, task cards and context menus are fastest for quick reminders, while task modals are better for reviewing multiple reminders on the same task. Quick Reminder Options# Common shortcuts are available for both due and scheduled anchors, such as: 5 minutes before 15 minutes before 1 hour before 1 day before Quick options appear only when the anchor date exists. This prevents invalid reminder states and keeps the quick menu focused on options that can be applied immediately. Reminder Data Format# Reminders are stored in YAML frontmatter arrays. Because reminders are stored in frontmatter, they remain portable and scriptable. You can inspect or transform reminder data with any tooling that reads Markdown + YAML. Relative Structure# reminders: - id: \"rem_1678886400000_abc123xyz\" type: \"relative\" relatedTo: \"due\" offset: \"-PT15M\" description: \"Review task details\" Absolute Structure# reminders: - id: \"rem_1678886400001_def456uvw\" type: \"absolute\" absoluteTime: \"2025-10-26T09:00:00\" description: \"Follow up with client\" Field meanings: id: unique identifier type: relative or absolute relatedTo: due or scheduled (relative only) offset: ISO 8601 duration, negative before and positive after (relative only) absoluteTime: ISO 8601 timestamp (absolute only) description: optional message You typically do not need to edit these fields manually, but understanding the structure helps when debugging automation or importing task data. Visual Indicators# Tasks with reminders show a bell icon on task cards. Solid bell indicates active reminders Clicking opens quick reminder actions Reminder UI shows task context (due/scheduled dates and reminder count) These indicators are intended to make reminders discoverable in list-heavy views without opening every task. Default Reminders# Default reminders can be configured in: Settings -> TaskNotes -> Task Properties -> Reminders Defaults are applied to: Manual task creation Instant conversion Natural language task creation Default reminders are useful for recurring habits, such as pre-deadline checks or day-before planning prompts. Technical Notes# Reminders follow iCalendar VALARM concepts with ISO 8601 offsets The reminder property name can be customized through field mapping For settings-level behavior (notification channels, enable/disable state), see Features Settings."},{"route":"/obsidian/features/task-management/","title":"Task Management","description":"This page covers task creation, properties, projects, dependencies, recurring tasks, and reminders. For the underlying architecture, see Core Concepts.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/features/task-management.md","namespace":"obsidian","relativePath":"features/task-management.md","raw":"# Task Management\n\n\nThis page covers task creation, properties, projects, dependencies, recurring tasks, and reminders. For the underlying architecture, see [Core Concepts](../core-concepts.md).\n\nUse this page as the operational overview: how tasks are captured, how they are structured, and how relationships/automation behave. Detailed reference content for recurrence and reminders is split into dedicated pages linked near the end.\n\n## Creating and Editing Tasks\n\nYou can create and edit tasks in a variety of ways. The primary method is through the **Task Creation Modal**, which can be accessed via the \"Create new task\" command or by clicking on dates or time slots in the calendar views. This modal provides an interface for setting all available task properties, including title, status, priority, and due dates.\n\n![Task creation modal](../assets/feature-task-modal-filled.png)\n\nTaskNotes keeps a storage title and a filename-safe title separate. When **Store title in filename** is enabled, forbidden filename characters are removed from the filename while the task title is preserved whenever it cannot be represented exactly by that filename. With another filename format, such as timestamp or UUID, the full title is stored in frontmatter.\n\nFor existing tasks, the **Quick actions for current task** command opens a keyboard-searchable action palette. It includes status, priority, time-tracking, archive, edit, and date actions, including built-in due and scheduled date presets such as today, tomorrow, this weekend, next week, and next month.\n\nTaskNotes also supports **Natural Language Creation**, which allows you to create tasks by typing descriptions in plain English. The built-in parser can extract structured data from phrases like \"Buy groceries tomorrow at 3pm @home #errands high priority.\"\n\nIn most workflows, users combine both approaches: fast capture with natural language, then occasional structured edits in the modal when more precision is needed.\n\n### Auto-Suggestions in Natural Language Input\n\nThe natural language input field includes auto-suggestion functionality that activates when typing specific trigger characters:\n\n- **@** - Shows available contexts from existing tasks\n- **#** - Shows available tags from existing tasks\n- **+** - Shows files from your vault as project suggestions\n- **\\*** - Shows available status options (configurable trigger in Settings → Features)\n\nIn task creation and edit fields, focusing the tags or contexts input also opens the available suggestions immediately, so you can pick from the current vocabulary without typing a first character.\n\n#### Project Suggestions\n\nWhen typing `+` in the natural language input, you'll see up to 20 suggestions from your vault's markdown files. The suggestions display additional information to help identify files:\n\n```\nproject-alpha [title: Alpha Project Development | aliases: alpha, proj-alpha]\nmeeting-notes [title: Weekly Team Meeting Notes]\nsimple-project\nwork-file [aliases: work, office-tasks]\n```\n\nProject suggestions search across:\n- File names (basename without extension)\n- Frontmatter titles (using your configured field mapping)\n- Frontmatter aliases\n- Optional filtering by required tags, folders, and a specific frontmatter property/value defined in Settings → Appearance & UI → Project Autosuggest\n\nSelecting a project suggestion inserts it as `+[[filename]]`, creating a wikilink to the file while maintaining the `+` project marker that the natural language parser recognizes.\n\n\n#### Enhanced Project Auto‑suggester (configurable cards)\n\nProject suggestions can display configurable multi‑row cards and support smarter search. Configure up to 3 rows using a simple token syntax in Settings → Appearance & UI → Project Autosuggest.\n\n- Properties: file.basename, file.name, file.path, file.parent, title, aliases, and any frontmatter key\n- Flags:\n - n or n(Label) → show the field name/label before the value\n - s → include this field in + search (in addition to defaults)\n- Literals: you can mix in fixed text or emojis between tokens\n\nExamples\n\n- \"{title|n(Title)}\" → Title: Alpha Project\n- \"🔖 {aliases|n(Aliases)}\" → 🔖 Aliases: alpha, proj-alpha\n- \"{file.path|n(Path)|s}\" → include path in + search as well as display it\n\nSearch behavior\n\n- Defaults: + search always includes file basename, title (via your field mapping), and aliases\n- |s flag: add more searchable fields on top of the defaults (e.g., file.path or a custom frontmatter key like customer)\n- Fuzzy: optional fuzzy matching can be enabled in settings for broader, multi‑word matches\n\nPerformance tips\n\n- Keep rows to three or fewer for clarity and performance (the UI supports up to 3)\n- Prefer specific searchable fields with |s on large vaults\n\nDemo\n\n![Autosuggest projects with spaces](../assets/autosuggest_project_names_with_space.gif)\n\n![Enhanced project autosuggester](../assets/enhanced-project-auto-suggester.gif)\n\n\n#### Status Suggestions\n\nWhen typing the status trigger character (default `*`) in the natural language input, you'll see suggestions for all configured status options:\n\n![Status Auto-Suggestion](../assets/auto-suggest-status.gif)\n\nStatus suggestions allow quick selection of statuses when creating tasks. For example, typing `*in` shows \"In Progress\" as a suggestion if that's one of your configured statuses.\n\nClicking a task card's status indicator cycles through statuses in the order configured under **Settings → Task Properties → Status**. A status can optionally define a specific **Next status** for forward cycling; otherwise TaskNotes uses the configured order. Statuses marked **Skip when cycling** are left out of the ordered click cycle, but remain available through menus, suggestions, direct edits, and explicit next-status jumps.\n\nAdditionally, you can convert any line type in your notes to TaskNotes using the **Instant Conversion** feature. This works with checkboxes, bullet points, numbered lists, blockquotes, headers, and plain text lines.\n\n## Task Properties\n\nTasks store their data in YAML frontmatter with properties for status, priority, dates, contexts, projects, tags, time estimates, recurrence, and reminders. Custom fields can extend this structure.\n\nThis frontmatter-first design keeps task data editable and portable while supporting consistent behavior across views and widgets.\n\nFor property types and examples, see [Core Concepts](../core-concepts.md#yaml-frontmatter). For configuration options, see [Task Properties Settings](../settings/task-properties.md).\n\n## Projects\n\nTaskNotes supports organizing tasks into projects using note-based linking. Projects are represented as links to actual notes in your vault, allowing you to leverage Obsidian's linking and backlinking features for project management.\n\nThis model avoids creating a separate project database. Any note can become a project anchor, and task/project relationships remain visible through normal Obsidian link tooling.\n\n### Project Assignment\n\nTasks can be assigned to one or more projects through the task creation or editing interface. When creating or editing a task, click the \"Add Project\" button to open the project selection modal. This modal provides fuzzy search functionality to quickly find and select project notes from your vault.\n\n### Project Links\n\nProjects are stored as wikilinks in the task's frontmatter (e.g., `projects: [\"[[Project A]]\", \"[[Project B]]\"]`). These links are clickable in the task interface and will navigate directly to the project notes when clicked. Any note in your vault can serve as a project note simply by being linked from a task's projects field.\n\n### Organization and Filtering\n\nTasks can be filtered and grouped by their associated projects in all Bases-driven task views. Use the Bases filter editor to add `note.projects` conditions, and configure the grouping menu to organize Task List or Kanban boards by project. Tasks assigned to multiple projects will appear in each relevant project group, providing flexibility in project-based organization.\n\n### Project Indicators\n\nTaskCards display visual indicators when tasks are used as projects. These indicators help identify which tasks have other tasks linked to them as subtasks, making project hierarchy visible at a glance.\n\n### Subtask Creation\n\nTasks can have subtasks created directly from their context menu. When viewing a task that serves as a project, you can select \"Create subtask\" to create a new task automatically linked to the current project.\n\n## Dependencies\n\nTask dependencies capture prerequisite work using RFC 9253 terminology. Dependencies are stored in frontmatter as structured objects:\n\n```yaml\nblockedBy:\n - uid: \"[[Operations/Order hardware]]\"\n reltype: FINISHTOSTART\n gap: P1D\n```\n\n- `uid` references the blocking task, typically through an Obsidian wikilink.\n- `reltype` is stored with each dependency and defaults to `FINISHTOSTART` for dependencies created in the UI.\n- `gap` is optional and uses ISO 8601 duration syntax (for example `PT4H` or `P2D`).\n\nWhenever a dependency is added, TaskNotes updates the upstream note’s `blocking` list so the reverse relationship stays synchronized. Removing a dependency automatically clears both sides.\n\n### Selecting dependencies in the UI\n\n- The task creation and edit modals expose “Blocked by” and “Blocking” buttons that launch a fuzzy task selector. The picker only offers valid tasks, excludes the current note, and prevents duplicate entries.\n- The task context menu provides the same selector, enabling dependency management directly from the Task List, Kanban, and calendar views.\n- Task cards show a fork icon whenever a task blocks other work. Clicking it expands an inline list of downstream tasks without triggering the parent card’s modal, so you can inspect dependents in place.\n\nThese controls currently create and manage finish-to-start style blockers. Advanced `reltype` values and `gap` data are preserved in frontmatter, but blocking evaluation is currently based on whether unresolved dependencies exist rather than relationship-type-specific scheduling rules.\n\n![Task context menu](../assets/feature-task-context-menu.png)\n\n## Automation\n\n### Auto-Archiving\n\nTaskNotes can automatically archive tasks when they transition into a status that has auto-archiving enabled. This keeps completed work out of your active lists without requiring manual cleanup.\n\nConfigure auto-archiving per status from **Settings → Task Properties → Task Statuses**. Each status card includes an **Auto-archive** toggle and a **Delay (minutes)** input (1–1440). When you turn the toggle on for a status, any task moved into that status is queued for archiving once the delay elapses. Moving the task to a different status before the timer expires cancels the pending archive automatically.\n\nThe auto-archive queue runs in the background and persists across plugin restarts. If TaskNotes was closed while an archive was pending, the task will be archived shortly after the plugin loads again as long as it still matches the configured status.\n\nThis automation is intended to keep active views focused without manual cleanup, while still preserving archived task history in your vault.\n\n## File Management and Templates\n\nTaskNotes supports configurable task folder locations, filename generation patterns, archive behavior, and body templates for newly created tasks.\n\nThese settings let you align task files with existing vault conventions (for example, date-based folders, project-based routing, or template-driven task note scaffolds).\n\nFor configuration details, see [Task Defaults](../settings/task-defaults.md). \nFor template variables, see [Template Variables Reference](template-variables.md).\n\n## Recurring Tasks\n\nTaskNotes recurring tasks use RFC 5545 RRule syntax with `DTSTART`, separate pattern definition from next occurrence scheduling, and support independent instance completion. When an individual recurrence needs its own checklist, time entries, or notes, you can create a materialized occurrence note from the task or calendar context menu.\n\nFor full behavior, examples, and edge cases, see [Recurring Tasks](recurring-tasks.md).\n\n## Task Reminders\n\nTask reminders support relative offsets from due/scheduled dates and absolute date-time reminders. You can add reminders from task modals, task cards, and context menus.\n\nFor full setup, data format, defaults, and UI behavior, see [Task Reminders](reminders.md).\n","aliases":["/features/task-management/"],"toc":[{"level":2,"id":"creating-and-editing-tasks","text":"Creating and Editing Tasks"},{"level":3,"id":"auto-suggestions-in-natural-language-input","text":"Auto-Suggestions in Natural Language Input"},{"level":2,"id":"task-properties","text":"Task Properties"},{"level":2,"id":"projects","text":"Projects"},{"level":3,"id":"project-assignment","text":"Project Assignment"},{"level":3,"id":"project-links","text":"Project Links"},{"level":3,"id":"organization-and-filtering","text":"Organization and Filtering"},{"level":3,"id":"project-indicators","text":"Project Indicators"},{"level":3,"id":"subtask-creation","text":"Subtask Creation"},{"level":2,"id":"dependencies","text":"Dependencies"},{"level":3,"id":"selecting-dependencies-in-the-ui","text":"Selecting dependencies in the UI"},{"level":2,"id":"automation","text":"Automation"},{"level":3,"id":"auto-archiving","text":"Auto-Archiving"},{"level":2,"id":"file-management-and-templates","text":"File Management and Templates"},{"level":2,"id":"recurring-tasks","text":"Recurring Tasks"},{"level":2,"id":"task-reminders","text":"Task Reminders"}],"html":"

This page covers task creation, properties, projects, dependencies, recurring tasks, and reminders. For the underlying architecture, see Core Concepts.

\n

Use this page as the operational overview: how tasks are captured, how they are structured, and how relationships/automation behave. Detailed reference content for recurrence and reminders is split into dedicated pages linked near the end.

\n

Creating and Editing Tasks#

\n

You can create and edit tasks in a variety of ways. The primary method is through the Task Creation Modal, which can be accessed via the "Create new task" command or by clicking on dates or time slots in the calendar views. This modal provides an interface for setting all available task properties, including title, status, priority, and due dates.

\n

\"Task

\n

TaskNotes keeps a storage title and a filename-safe title separate. When Store title in filename is enabled, forbidden filename characters are removed from the filename while the task title is preserved whenever it cannot be represented exactly by that filename. With another filename format, such as timestamp or UUID, the full title is stored in frontmatter.

\n

For existing tasks, the Quick actions for current task command opens a keyboard-searchable action palette. It includes status, priority, time-tracking, archive, edit, and date actions, including built-in due and scheduled date presets such as today, tomorrow, this weekend, next week, and next month.

\n

TaskNotes also supports Natural Language Creation, which allows you to create tasks by typing descriptions in plain English. The built-in parser can extract structured data from phrases like "Buy groceries tomorrow at 3pm @home #errands high priority."

\n

In most workflows, users combine both approaches: fast capture with natural language, then occasional structured edits in the modal when more precision is needed.

\n

Auto-Suggestions in Natural Language Input#

\n

The natural language input field includes auto-suggestion functionality that activates when typing specific trigger characters:

\n
    \n
  • @ - Shows available contexts from existing tasks
  • \n
  • # - Shows available tags from existing tasks
  • \n
  • + - Shows files from your vault as project suggestions
  • \n
  • * - Shows available status options (configurable trigger in Settings → Features)
  • \n
\n

In task creation and edit fields, focusing the tags or contexts input also opens the available suggestions immediately, so you can pick from the current vocabulary without typing a first character.

\n

Project Suggestions#

\n

When typing + in the natural language input, you'll see up to 20 suggestions from your vault's markdown files. The suggestions display additional information to help identify files:

\n
project-alpha [title: Alpha Project Development | aliases: alpha, proj-alpha]\nmeeting-notes [title: Weekly Team Meeting Notes]\nsimple-project\nwork-file [aliases: work, office-tasks]\n

Project suggestions search across:

\n
    \n
  • File names (basename without extension)
  • \n
  • Frontmatter titles (using your configured field mapping)
  • \n
  • Frontmatter aliases
  • \n
  • Optional filtering by required tags, folders, and a specific frontmatter property/value defined in Settings → Appearance & UI → Project Autosuggest
  • \n
\n

Selecting a project suggestion inserts it as +[[filename]], creating a wikilink to the file while maintaining the + project marker that the natural language parser recognizes.

\n

Enhanced Project Auto‑suggester (configurable cards)#

\n

Project suggestions can display configurable multi‑row cards and support smarter search. Configure up to 3 rows using a simple token syntax in Settings → Appearance & UI → Project Autosuggest.

\n
    \n
  • Properties: file.basename, file.name, file.path, file.parent, title, aliases, and any frontmatter key
  • \n
  • Flags:
      \n
    • n or n(Label) → show the field name/label before the value
    • \n
    • s → include this field in + search (in addition to defaults)
    • \n
    \n
  • \n
  • Literals: you can mix in fixed text or emojis between tokens
  • \n
\n

Examples

\n
    \n
  • "{title|n(Title)}" → Title: Alpha Project
  • \n
  • "🔖 {aliases|n(Aliases)}" → 🔖 Aliases: alpha, proj-alpha
  • \n
  • "{file.path|n(Path)|s}" → include path in + search as well as display it
  • \n
\n

Search behavior

\n
    \n
  • Defaults: + search always includes file basename, title (via your field mapping), and aliases
  • \n
  • |s flag: add more searchable fields on top of the defaults (e.g., file.path or a custom frontmatter key like customer)
  • \n
  • Fuzzy: optional fuzzy matching can be enabled in settings for broader, multi‑word matches
  • \n
\n

Performance tips

\n
    \n
  • Keep rows to three or fewer for clarity and performance (the UI supports up to 3)
  • \n
  • Prefer specific searchable fields with |s on large vaults
  • \n
\n

Demo

\n

\"Autosuggest

\n

\"Enhanced

\n

Status Suggestions#

\n

When typing the status trigger character (default *) in the natural language input, you'll see suggestions for all configured status options:

\n

\"Status

\n

Status suggestions allow quick selection of statuses when creating tasks. For example, typing *in shows "In Progress" as a suggestion if that's one of your configured statuses.

\n

Clicking a task card's status indicator cycles through statuses in the order configured under Settings → Task Properties → Status. A status can optionally define a specific Next status for forward cycling; otherwise TaskNotes uses the configured order. Statuses marked Skip when cycling are left out of the ordered click cycle, but remain available through menus, suggestions, direct edits, and explicit next-status jumps.

\n

Additionally, you can convert any line type in your notes to TaskNotes using the Instant Conversion feature. This works with checkboxes, bullet points, numbered lists, blockquotes, headers, and plain text lines.

\n

Task Properties#

\n

Tasks store their data in YAML frontmatter with properties for status, priority, dates, contexts, projects, tags, time estimates, recurrence, and reminders. Custom fields can extend this structure.

\n

This frontmatter-first design keeps task data editable and portable while supporting consistent behavior across views and widgets.

\n

For property types and examples, see Core Concepts. For configuration options, see Task Properties Settings.

\n

Projects#

\n

TaskNotes supports organizing tasks into projects using note-based linking. Projects are represented as links to actual notes in your vault, allowing you to leverage Obsidian's linking and backlinking features for project management.

\n

This model avoids creating a separate project database. Any note can become a project anchor, and task/project relationships remain visible through normal Obsidian link tooling.

\n

Project Assignment#

\n

Tasks can be assigned to one or more projects through the task creation or editing interface. When creating or editing a task, click the "Add Project" button to open the project selection modal. This modal provides fuzzy search functionality to quickly find and select project notes from your vault.

\n

Project Links#

\n

Projects are stored as wikilinks in the task's frontmatter (e.g., projects: ["[[Project A]]", "[[Project B]]"]). These links are clickable in the task interface and will navigate directly to the project notes when clicked. Any note in your vault can serve as a project note simply by being linked from a task's projects field.

\n

Organization and Filtering#

\n

Tasks can be filtered and grouped by their associated projects in all Bases-driven task views. Use the Bases filter editor to add note.projects conditions, and configure the grouping menu to organize Task List or Kanban boards by project. Tasks assigned to multiple projects will appear in each relevant project group, providing flexibility in project-based organization.

\n

Project Indicators#

\n

TaskCards display visual indicators when tasks are used as projects. These indicators help identify which tasks have other tasks linked to them as subtasks, making project hierarchy visible at a glance.

\n

Subtask Creation#

\n

Tasks can have subtasks created directly from their context menu. When viewing a task that serves as a project, you can select "Create subtask" to create a new task automatically linked to the current project.

\n

Dependencies#

\n

Task dependencies capture prerequisite work using RFC 9253 terminology. Dependencies are stored in frontmatter as structured objects:

\n
blockedBy:\n  - uid: "[[Operations/Order hardware]]"\n    reltype: FINISHTOSTART\n    gap: P1D\n
    \n
  • uid references the blocking task, typically through an Obsidian wikilink.
  • \n
  • reltype is stored with each dependency and defaults to FINISHTOSTART for dependencies created in the UI.
  • \n
  • gap is optional and uses ISO 8601 duration syntax (for example PT4H or P2D).
  • \n
\n

Whenever a dependency is added, TaskNotes updates the upstream note’s blocking list so the reverse relationship stays synchronized. Removing a dependency automatically clears both sides.

\n

Selecting dependencies in the UI#

\n
    \n
  • The task creation and edit modals expose “Blocked by” and “Blocking” buttons that launch a fuzzy task selector. The picker only offers valid tasks, excludes the current note, and prevents duplicate entries.
  • \n
  • The task context menu provides the same selector, enabling dependency management directly from the Task List, Kanban, and calendar views.
  • \n
  • Task cards show a fork icon whenever a task blocks other work. Clicking it expands an inline list of downstream tasks without triggering the parent card’s modal, so you can inspect dependents in place.
  • \n
\n

These controls currently create and manage finish-to-start style blockers. Advanced reltype values and gap data are preserved in frontmatter, but blocking evaluation is currently based on whether unresolved dependencies exist rather than relationship-type-specific scheduling rules.

\n

\"Task

\n

Automation#

\n

Auto-Archiving#

\n

TaskNotes can automatically archive tasks when they transition into a status that has auto-archiving enabled. This keeps completed work out of your active lists without requiring manual cleanup.

\n

Configure auto-archiving per status from Settings → Task Properties → Task Statuses. Each status card includes an Auto-archive toggle and a Delay (minutes) input (1–1440). When you turn the toggle on for a status, any task moved into that status is queued for archiving once the delay elapses. Moving the task to a different status before the timer expires cancels the pending archive automatically.

\n

The auto-archive queue runs in the background and persists across plugin restarts. If TaskNotes was closed while an archive was pending, the task will be archived shortly after the plugin loads again as long as it still matches the configured status.

\n

This automation is intended to keep active views focused without manual cleanup, while still preserving archived task history in your vault.

\n

File Management and Templates#

\n

TaskNotes supports configurable task folder locations, filename generation patterns, archive behavior, and body templates for newly created tasks.

\n

These settings let you align task files with existing vault conventions (for example, date-based folders, project-based routing, or template-driven task note scaffolds).

\n

For configuration details, see Task Defaults.
For template variables, see Template Variables Reference.

\n

Recurring Tasks#

\n

TaskNotes recurring tasks use RFC 5545 RRule syntax with DTSTART, separate pattern definition from next occurrence scheduling, and support independent instance completion. When an individual recurrence needs its own checklist, time entries, or notes, you can create a materialized occurrence note from the task or calendar context menu.

\n

For full behavior, examples, and edge cases, see Recurring Tasks.

\n

Task Reminders#

\n

Task reminders support relative offsets from due/scheduled dates and absolute date-time reminders. You can add reminders from task modals, task cards, and context menus.

\n

For full setup, data format, defaults, and UI behavior, see Task Reminders.

\n","text":"This page covers task creation, properties, projects, dependencies, recurring tasks, and reminders. For the underlying architecture, see Core Concepts. Use this page as the operational overview: how tasks are captured, how they are structured, and how relationships/automation behave. Detailed reference content for recurrence and reminders is split into dedicated pages linked near the end. Creating and Editing Tasks# You can create and edit tasks in a variety of ways. The primary method is through the Task Creation Modal, which can be accessed via the \"Create new task\" command or by clicking on dates or time slots in the calendar views. This modal provides an interface for setting all available task properties, including title, status, priority, and due dates. TaskNotes keeps a storage title and a filename-safe title separate. When Store title in filename is enabled, forbidden filename characters are removed from the filename while the task title is preserved whenever it cannot be represented exactly by that filename. With another filename format, such as timestamp or UUID, the full title is stored in frontmatter. For existing tasks, the Quick actions for current task command opens a keyboard-searchable action palette. It includes status, priority, time-tracking, archive, edit, and date actions, including built-in due and scheduled date presets such as today, tomorrow, this weekend, next week, and next month. TaskNotes also supports Natural Language Creation, which allows you to create tasks by typing descriptions in plain English. The built-in parser can extract structured data from phrases like \"Buy groceries tomorrow at 3pm @home #errands high priority.\" In most workflows, users combine both approaches: fast capture with natural language, then occasional structured edits in the modal when more precision is needed. Auto-Suggestions in Natural Language Input# The natural language input field includes auto-suggestion functionality that activates when typing specific trigger characters: @ - Shows available contexts from existing tasks # - Shows available tags from existing tasks + - Shows files from your vault as project suggestions * - Shows available status options (configurable trigger in Settings → Features) In task creation and edit fields, focusing the tags or contexts input also opens the available suggestions immediately, so you can pick from the current vocabulary without typing a first character. Project Suggestions# When typing + in the natural language input, you'll see up to 20 suggestions from your vault's markdown files. The suggestions display additional information to help identify files: project-alpha [title: Alpha Project Development | aliases: alpha, proj-alpha] meeting-notes [title: Weekly Team Meeting Notes] simple-project work-file [aliases: work, office-tasks] Project suggestions search across: File names (basename without extension) Frontmatter titles (using your configured field mapping) Frontmatter aliases Optional filtering by required tags, folders, and a specific frontmatter property/value defined in Settings → Appearance & UI → Project Autosuggest Selecting a project suggestion inserts it as +[[filename]], creating a wikilink to the file while maintaining the + project marker that the natural language parser recognizes. Enhanced Project Auto‑suggester (configurable cards)# Project suggestions can display configurable multi‑row cards and support smarter search. Configure up to 3 rows using a simple token syntax in Settings → Appearance & UI → Project Autosuggest. Properties: file.basename, file.name, file.path, file.parent, title, aliases, and any frontmatter key Flags: n or n(Label) → show the field name/label before the value s → include this field in + search (in addition to defaults) Literals: you can mix in fixed text or emojis between tokens Examples \"{title|n(Title)}\" → Title: Alpha Project \"🔖 {aliases|n(Aliases)}\" → 🔖 Aliases: alpha, proj-alpha \"{file.path|n(Path)|s}\" → include path in + search as well as display it Search behavior Defaults: + search always includes file basename, title (via your field mapping), and aliases |s flag: add more searchable fields on top of the defaults (e.g., file.path or a custom frontmatter key like customer) Fuzzy: optional fuzzy matching can be enabled in settings for broader, multi‑word matches Performance tips Keep rows to three or fewer for clarity and performance (the UI supports up to 3) Prefer specific searchable fields with |s on large vaults Demo Status Suggestions# When typing the status trigger character (default *) in the natural language input, you'll see suggestions for all configured status options: Status suggestions allow quick selection of statuses when creating tasks. For example, typing *in shows \"In Progress\" as a suggestion if that's one of your configured statuses. Clicking a task card's status indicator cycles through statuses in the order configured under Settings → Task Properties → Status. A status can optionally define a specific Next status for forward cycling; otherwise TaskNotes uses the configured order. Statuses marked Skip when cycling are left out of the ordered click cycle, but remain available through menus, suggestions, direct edits, and explicit next-status jumps. Additionally, you can convert any line type in your notes to TaskNotes using the Instant Conversion feature. This works with checkboxes, bullet points, numbered lists, blockquotes, headers, and plain text lines. Task Properties# Tasks store their data in YAML frontmatter with properties for status, priority, dates, contexts, projects, tags, time estimates, recurrence, and reminders. Custom fields can extend this structure. This frontmatter-first design keeps task data editable and portable while supporting consistent behavior across views and widgets. For property types and examples, see Core Concepts. For configuration options, see Task Properties Settings. Projects# TaskNotes supports organizing tasks into projects using note-based linking. Projects are represented as links to actual notes in your vault, allowing you to leverage Obsidian's linking and backlinking features for project management. This model avoids creating a separate project database. Any note can become a project anchor, and task/project relationships remain visible through normal Obsidian link tooling. Project Assignment# Tasks can be assigned to one or more projects through the task creation or editing interface. When creating or editing a task, click the \"Add Project\" button to open the project selection modal. This modal provides fuzzy search functionality to quickly find and select project notes from your vault. Project Links# Projects are stored as wikilinks in the task's frontmatter (e.g., projects: [\"[[Project A]]\", \"[[Project B]]\"]). These links are clickable in the task interface and will navigate directly to the project notes when clicked. Any note in your vault can serve as a project note simply by being linked from a task's projects field. Organization and Filtering# Tasks can be filtered and grouped by their associated projects in all Bases-driven task views. Use the Bases filter editor to add note.projects conditions, and configure the grouping menu to organize Task List or Kanban boards by project. Tasks assigned to multiple projects will appear in each relevant project group, providing flexibility in project-based organization. Project Indicators# TaskCards display visual indicators when tasks are used as projects. These indicators help identify which tasks have other tasks linked to them as subtasks, making project hierarchy visible at a glance. Subtask Creation# Tasks can have subtasks created directly from their context menu. When viewing a task that serves as a project, you can select \"Create subtask\" to create a new task automatically linked to the current project. Dependencies# Task dependencies capture prerequisite work using RFC 9253 terminology. Dependencies are stored in frontmatter as structured objects: blockedBy: - uid: \"[[Operations/Order hardware]]\" reltype: FINISHTOSTART gap: P1D uid references the blocking task, typically through an Obsidian wikilink. reltype is stored with each dependency and defaults to FINISHTOSTART for dependencies created in the UI. gap is optional and uses ISO 8601 duration syntax (for example PT4H or P2D). Whenever a dependency is added, TaskNotes updates the upstream note’s blocking list so the reverse relationship stays synchronized. Removing a dependency automatically clears both sides. Selecting dependencies in the UI# The task creation and edit modals expose “Blocked by” and “Blocking” buttons that launch a fuzzy task selector. The picker only offers valid tasks, excludes the current note, and prevents duplicate entries. The task context menu provides the same selector, enabling dependency management directly from the Task List, Kanban, and calendar views. Task cards show a fork icon whenever a task blocks other work. Clicking it expands an inline list of downstream tasks without triggering the parent card’s modal, so you can inspect dependents in place. These controls currently create and manage finish-to-start style blockers. Advanced reltype values and gap data are preserved in frontmatter, but blocking evaluation is currently based on whether unresolved dependencies exist rather than relationship-type-specific scheduling rules. Automation# Auto-Archiving# TaskNotes can automatically archive tasks when they transition into a status that has auto-archiving enabled. This keeps completed work out of your active lists without requiring manual cleanup. Configure auto-archiving per status from Settings → Task Properties → Task Statuses. Each status card includes an Auto-archive toggle and a Delay (minutes) input (1–1440). When you turn the toggle on for a status, any task moved into that status is queued for archiving once the delay elapses. Moving the task to a different status before the timer expires cancels the pending archive automatically. The auto-archive queue runs in the background and persists across plugin restarts. If TaskNotes was closed while an archive was pending, the task will be archived shortly after the plugin loads again as long as it still matches the configured status. This automation is intended to keep active views focused without manual cleanup, while still preserving archived task history in your vault. File Management and Templates# TaskNotes supports configurable task folder locations, filename generation patterns, archive behavior, and body templates for newly created tasks. These settings let you align task files with existing vault conventions (for example, date-based folders, project-based routing, or template-driven task note scaffolds). For configuration details, see Task Defaults.For template variables, see Template Variables Reference. Recurring Tasks# TaskNotes recurring tasks use RFC 5545 RRule syntax with DTSTART, separate pattern definition from next occurrence scheduling, and support independent instance completion. When an individual recurrence needs its own checklist, time entries, or notes, you can create a materialized occurrence note from the task or calendar context menu. For full behavior, examples, and edge cases, see Recurring Tasks. Task Reminders# Task reminders support relative offsets from due/scheduled dates and absolute date-time reminders. You can add reminders from task modals, task cards, and context menus. For full setup, data format, defaults, and UI behavior, see Task Reminders."},{"route":"/obsidian/features/template-variables/","title":"Template Variables Reference","description":"TaskNotes supports template variables for dynamic content generation in body templates, folder paths, and filenames. Variables use the {{variableName}} syntax and are replaced w...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/features/template-variables.md","namespace":"obsidian","relativePath":"features/template-variables.md","raw":"# Template Variables Reference\n\nTaskNotes supports template variables for dynamic content generation in body templates, folder paths, and filenames. Variables use the `{{variableName}}` syntax and are replaced with actual values when content is created.\n\n## Overview\n\nTemplate variables are available in three contexts:\n\n- **Body templates** - Content templates for task and note files\n- **Folder templates** - Dynamic folder paths for file organization\n- **Filename templates** - Dynamic filename generation\n\nNot all variables are available in every context. The tables below indicate where each variable can be used.\n\n## Task Properties\n\nVariables for task-specific data.\n\n| Variable | Description | Body | Folder | Example |\n|----------|-------------|:----:|:------:|---------|\n| `{{title}}` | Task title | Yes | Yes | `My Task` |\n| `{{titleLower}}` | Title in lowercase | Yes | Yes | `my task` |\n| `{{titleUpper}}` | Title in uppercase | Yes | Yes | `MY TASK` |\n| `{{titleSnake}}` | Title in snake_case | Yes | Yes | `my_task` |\n| `{{titleKebab}}` | Title in kebab-case | Yes | Yes | `my-task` |\n| `{{titleCamel}}` | Title in camelCase | Yes | Yes | `myTask` |\n| `{{titlePascal}}` | Title in PascalCase | Yes | Yes | `MyTask` |\n| `{{priority}}` | Task priority value | Yes | Yes | `high` |\n| `{{priorityShort}}` | First character of priority (uppercase) | Yes | Yes | `H` |\n| `{{status}}` | Task status value | Yes | Yes | `active` |\n| `{{statusShort}}` | First character of status (uppercase) | Yes | Yes | `A` |\n| `{{context}}` | First context from contexts array | No | Yes | `work` |\n| `{{contexts}}` | All contexts (comma-separated in body, `/` in folder) | Yes | Yes | `work, home` or `work/home` |\n| `{{project}}` | First project from projects array | No | Yes | `ProjectA` |\n| `{{projects}}` | All projects joined by `/` | No | Yes | `ProjectA/ProjectB` |\n| `{{projectFilePath}}` | Full path of the first project, without `.md` | No | Yes | `Work/Projects/ProjectA` |\n| `{{projectFilePaths}}` | Full paths of all projects, joined by `/` | No | Yes | `Work/Alpha/Personal/Beta` |\n| `{{projectFolder}}` | Folder containing the first project note (its file path without the note's own name) | No | Yes | `Work/Projects` |\n| `{{projectFolders}}` | Folders of all projects, joined by `/` | No | Yes | `Work/Personal` |\n| `{{dueDate}}` | Task due date | Yes | Yes | `2025-01-15` |\n| `{{scheduledDate}}` | Task scheduled date | Yes | Yes | `2025-01-10` |\n\n## Body Template Only\n\nVariables available only in body templates (not folder templates).\n\n| Variable | Description | Example |\n|----------|-------------|---------|\n| `{{details}}` | User-provided details/description | `Task description text` |\n| `{{parentNote}}` | Parent note name/path where task was created | `Projects/MyNote` |\n| `{{tags}}` | Task tags (comma-separated) | `urgent, review` |\n| `{{hashtags}}` | Task tags as space-separated hashtags | `#urgent #review` |\n| `{{timeEstimate}}` | Time estimate in minutes | `30` |\n\n## Date and Time\n\nVariables for current date and time values.\n\n| Variable | Description | Format | Example |\n|----------|-------------|--------|---------|\n| `{{date}}` | Full current date | `YYYY-MM-DD` | `2025-01-07` |\n| `{{year}}` | Current year | `YYYY` | `2025` |\n| `{{shortYear}}` | Short year | `YY` | `25` |\n| `{{month}}` | Current month | `MM` | `01` |\n| `{{day}}` | Current day | `DD` | `07` |\n| `{{monthName}}` | Full month name | - | `January` |\n| `{{monthNameShort}}` | Abbreviated month name | - | `Jan` |\n| `{{dayName}}` | Full day name | - | `Tuesday` |\n| `{{dayNameShort}}` | Abbreviated day name | - | `Tue` |\n| `{{week}}` | Week number of year | `WW` | `02` |\n| `{{quarter}}` | Quarter of year | `Q` | `1` |\n| `{{shortDate}}` | Compact date | `YYMMDD` | `250107` |\n\n### Time Variables\n\n| Variable | Description | Format | Example |\n|----------|-------------|--------|---------|\n| `{{time}}` | Current time (compact) | `HHmmss` | `143052` |\n| `{{time24}}` | 24-hour time | `HH:mm` | `14:30` |\n| `{{time12}}` | 12-hour time with AM/PM | `hh:mm a` | `02:30 PM` |\n| `{{hour}}` | Current hour (24-hour) | `HH` | `14` |\n| `{{hourPadded}}` | Hour with leading zero | `HH` | `14` |\n| `{{hour12}}` | Hour in 12-hour format | `hh` | `02` |\n| `{{minute}}` | Current minute | `mm` | `30` |\n| `{{second}}` | Current second | `ss` | `52` |\n| `{{ampm}}` | AM/PM indicator | `a` | `PM` |\n\n### Timestamps\n\n| Variable | Description | Format | Example |\n|----------|-------------|--------|---------|\n| `{{timestamp}}` | Date and time combined | `YYYY-MM-DD-HHmmss` | `2025-01-07-143052` |\n| `{{dateTime}}` | Date and time (no seconds) | `YYYY-MM-DD-HHmm` | `2025-01-07-1430` |\n| `{{unix}}` | Unix timestamp (seconds) | - | `1736264852` |\n| `{{unixMs}}` | Unix timestamp (milliseconds) | - | `1736264852000` |\n| `{{milliseconds}}` | Current milliseconds | `SSS` | `123` |\n| `{{ms}}` | Milliseconds (alias) | `SSS` | `123` |\n\n### Timezone\n\n| Variable | Description | Example |\n|----------|-------------|---------|\n| `{{timezone}}` | Timezone offset | `+01:00` |\n| `{{timezoneShort}}` | Short timezone offset | `+0100` |\n| `{{utcOffset}}` | UTC offset | `+01:00` |\n| `{{utcOffsetShort}}` | Short UTC offset | `+0100` |\n| `{{utcZ}}` | UTC Z indicator | `Z` |\n\n### Unique Identifiers\n\n| Variable | Description | Example |\n|----------|-------------|---------|\n| `{{zettel}}` | Zettelkasten-style ID (date + seconds since midnight in base36) | `250107abc` |\n| `{{nano}}` | Unique nano ID (timestamp + random string) | `1736264852000x7k2m` |\n\n## ICS Calendar Event Variables\n\nVariables for content created from ICS calendar events. Available when creating notes or tasks from calendar events.\n\n### Event Information\n\n| Variable | Description | Body | Folder |\n|----------|-------------|:----:|:------:|\n| `{{icsEventTitle}}` | Event title | Yes | Yes |\n| `{{icsEventTitleLower}}` | Event title lowercase | No | Yes |\n| `{{icsEventTitleUpper}}` | Event title uppercase | No | Yes |\n| `{{icsEventTitleSnake}}` | Event title in snake_case | No | Yes |\n| `{{icsEventTitleKebab}}` | Event title in kebab-case | No | Yes |\n| `{{icsEventTitleCamel}}` | Event title in camelCase | No | Yes |\n| `{{icsEventTitlePascal}}` | Event title in PascalCase | No | Yes |\n| `{{icsEventStart}}` | Event start time (ISO format) | Yes | No |\n| `{{icsEventEnd}}` | Event end time (ISO format) | Yes | No |\n| `{{icsEventLocation}}` | Event location | Yes | Yes |\n| `{{icsEventDescription}}` | Event description | Yes | Yes |\n| `{{icsEventUrl}}` | Event URL | Yes | No |\n| `{{icsEventSubscription}}` | Calendar subscription name | Yes | No |\n| `{{icsEventId}}` | Unique event identifier (UUID) | Yes | No |\n\n## Current Note Folder Variables\n\nVariables available for inline-created tasks and the default tasks folder.\n\n| Variable | Description | Example |\n|----------|-------------|---------|\n| `{{currentNotePath}}` | Path to the current note's folder | `Projects/Notes` |\n| `{{currentNoteTitle}}` | Title/name of the current note | `Meeting Notes` |\n\n## Examples\n\n### Body Template\n\n```markdown\n---\ncreated: {{date}}\npriority: {{priority}}\nstatus: {{status}}\n---\n\n# {{title}}\n\n{{details}}\n\nCreated from: {{parentNote}}\nTags: {{hashtags}}\n```\n\n### Folder Template\n\nOrganize tasks by project and status:\n```\nTasks/{{project}}/{{status}}\n```\nResult: `Tasks/MyProject/active`\n\nOrganize by date hierarchy:\n```\nDaily/{{year}}/{{month}}/{{day}}\n```\nResult: `Daily/2025/01/07`\n\nOrganize ICS events by year and title:\n```\nEvents/{{year}}/{{icsEventTitleKebab}}\n```\nResult: `Events/2025/team-meeting`\n\n### Filename Template\n\nUsing Zettelkasten ID:\n```\n{{zettel}}-{{titleKebab}}\n```\nResult: `250107abc-my-task.md`\n\nUsing timestamp:\n```\n{{shortDate}}-{{title}}\n```\nResult: `250107-My Task.md`\n\n## Notes\n\n### YAML Safety\n\nWhen used in YAML frontmatter, values containing special characters (colons, brackets, quotes) are automatically quoted to prevent parsing errors.\n\n### Folder Path Sanitization\n\nIn folder templates, title values have filesystem-unsafe characters (`<>:\"/\\|?*`) replaced with underscores to ensure valid paths. Project file path variables preserve folder separators and sanitize unsafe characters within each path segment.\n\n### Empty Values\n\nIf a variable references data that isn't available (e.g., `{{project}}` when no project is set), it resolves to an empty string.\n\n### Case Transformations\n\nThe case transformation variables work as follows:\n\n| Transform | Input | Output |\n|-----------|-------|--------|\n| `titleLower` | `My Task Name` | `my task name` |\n| `titleUpper` | `My Task Name` | `MY TASK NAME` |\n| `titleSnake` | `My Task Name` | `my_task_name` |\n| `titleKebab` | `My Task Name` | `my-task-name` |\n| `titleCamel` | `My Task Name` | `myTaskName` |\n| `titlePascal` | `My Task Name` | `MyTaskName` |\n","aliases":["/features/template-variables/"],"toc":[{"level":2,"id":"overview","text":"Overview"},{"level":2,"id":"task-properties","text":"Task Properties"},{"level":2,"id":"body-template-only","text":"Body Template Only"},{"level":2,"id":"date-and-time","text":"Date and Time"},{"level":3,"id":"time-variables","text":"Time Variables"},{"level":3,"id":"timestamps","text":"Timestamps"},{"level":3,"id":"timezone","text":"Timezone"},{"level":3,"id":"unique-identifiers","text":"Unique Identifiers"},{"level":2,"id":"ics-calendar-event-variables","text":"ICS Calendar Event Variables"},{"level":3,"id":"event-information","text":"Event Information"},{"level":2,"id":"current-note-folder-variables","text":"Current Note Folder Variables"},{"level":2,"id":"examples","text":"Examples"},{"level":3,"id":"body-template","text":"Body Template"},{"level":3,"id":"folder-template","text":"Folder Template"},{"level":3,"id":"filename-template","text":"Filename Template"},{"level":2,"id":"notes","text":"Notes"},{"level":3,"id":"yaml-safety","text":"YAML Safety"},{"level":3,"id":"folder-path-sanitization","text":"Folder Path Sanitization"},{"level":3,"id":"empty-values","text":"Empty Values"},{"level":3,"id":"case-transformations","text":"Case Transformations"}],"html":"

TaskNotes supports template variables for dynamic content generation in body templates, folder paths, and filenames. Variables use the {{variableName}} syntax and are replaced with actual values when content is created.

\n

Overview#

\n

Template variables are available in three contexts:

\n
    \n
  • Body templates - Content templates for task and note files
  • \n
  • Folder templates - Dynamic folder paths for file organization
  • \n
  • Filename templates - Dynamic filename generation
  • \n
\n

Not all variables are available in every context. The tables below indicate where each variable can be used.

\n

Task Properties#

\n

Variables for task-specific data.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableDescriptionBodyFolderExample
{{title}}Task titleYesYesMy Task
{{titleLower}}Title in lowercaseYesYesmy task
{{titleUpper}}Title in uppercaseYesYesMY TASK
{{titleSnake}}Title in snake_caseYesYesmy_task
{{titleKebab}}Title in kebab-caseYesYesmy-task
{{titleCamel}}Title in camelCaseYesYesmyTask
{{titlePascal}}Title in PascalCaseYesYesMyTask
{{priority}}Task priority valueYesYeshigh
{{priorityShort}}First character of priority (uppercase)YesYesH
{{status}}Task status valueYesYesactive
{{statusShort}}First character of status (uppercase)YesYesA
{{context}}First context from contexts arrayNoYeswork
{{contexts}}All contexts (comma-separated in body, / in folder)YesYeswork, home or work/home
{{project}}First project from projects arrayNoYesProjectA
{{projects}}All projects joined by /NoYesProjectA/ProjectB
{{projectFilePath}}Full path of the first project, without .mdNoYesWork/Projects/ProjectA
{{projectFilePaths}}Full paths of all projects, joined by /NoYesWork/Alpha/Personal/Beta
{{projectFolder}}Folder containing the first project note (its file path without the note's own name)NoYesWork/Projects
{{projectFolders}}Folders of all projects, joined by /NoYesWork/Personal
{{dueDate}}Task due dateYesYes2025-01-15
{{scheduledDate}}Task scheduled dateYesYes2025-01-10
\n

Body Template Only#

\n

Variables available only in body templates (not folder templates).

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableDescriptionExample
{{details}}User-provided details/descriptionTask description text
{{parentNote}}Parent note name/path where task was createdProjects/MyNote
{{tags}}Task tags (comma-separated)urgent, review
{{hashtags}}Task tags as space-separated hashtags#urgent #review
{{timeEstimate}}Time estimate in minutes30
\n

Date and Time#

\n

Variables for current date and time values.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableDescriptionFormatExample
{{date}}Full current dateYYYY-MM-DD2025-01-07
{{year}}Current yearYYYY2025
{{shortYear}}Short yearYY25
{{month}}Current monthMM01
{{day}}Current dayDD07
{{monthName}}Full month name-January
{{monthNameShort}}Abbreviated month name-Jan
{{dayName}}Full day name-Tuesday
{{dayNameShort}}Abbreviated day name-Tue
{{week}}Week number of yearWW02
{{quarter}}Quarter of yearQ1
{{shortDate}}Compact dateYYMMDD250107
\n

Time Variables#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableDescriptionFormatExample
{{time}}Current time (compact)HHmmss143052
{{time24}}24-hour timeHH:mm14:30
{{time12}}12-hour time with AM/PMhh:mm a02:30 PM
{{hour}}Current hour (24-hour)HH14
{{hourPadded}}Hour with leading zeroHH14
{{hour12}}Hour in 12-hour formathh02
{{minute}}Current minutemm30
{{second}}Current secondss52
{{ampm}}AM/PM indicatoraPM
\n

Timestamps#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableDescriptionFormatExample
{{timestamp}}Date and time combinedYYYY-MM-DD-HHmmss2025-01-07-143052
{{dateTime}}Date and time (no seconds)YYYY-MM-DD-HHmm2025-01-07-1430
{{unix}}Unix timestamp (seconds)-1736264852
{{unixMs}}Unix timestamp (milliseconds)-1736264852000
{{milliseconds}}Current millisecondsSSS123
{{ms}}Milliseconds (alias)SSS123
\n

Timezone#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableDescriptionExample
{{timezone}}Timezone offset+01:00
{{timezoneShort}}Short timezone offset+0100
{{utcOffset}}UTC offset+01:00
{{utcOffsetShort}}Short UTC offset+0100
{{utcZ}}UTC Z indicatorZ
\n

Unique Identifiers#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableDescriptionExample
{{zettel}}Zettelkasten-style ID (date + seconds since midnight in base36)250107abc
{{nano}}Unique nano ID (timestamp + random string)1736264852000x7k2m
\n

ICS Calendar Event Variables#

\n

Variables for content created from ICS calendar events. Available when creating notes or tasks from calendar events.

\n

Event Information#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableDescriptionBodyFolder
{{icsEventTitle}}Event titleYesYes
{{icsEventTitleLower}}Event title lowercaseNoYes
{{icsEventTitleUpper}}Event title uppercaseNoYes
{{icsEventTitleSnake}}Event title in snake_caseNoYes
{{icsEventTitleKebab}}Event title in kebab-caseNoYes
{{icsEventTitleCamel}}Event title in camelCaseNoYes
{{icsEventTitlePascal}}Event title in PascalCaseNoYes
{{icsEventStart}}Event start time (ISO format)YesNo
{{icsEventEnd}}Event end time (ISO format)YesNo
{{icsEventLocation}}Event locationYesYes
{{icsEventDescription}}Event descriptionYesYes
{{icsEventUrl}}Event URLYesNo
{{icsEventSubscription}}Calendar subscription nameYesNo
{{icsEventId}}Unique event identifier (UUID)YesNo
\n

Current Note Folder Variables#

\n

Variables available for inline-created tasks and the default tasks folder.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableDescriptionExample
{{currentNotePath}}Path to the current note's folderProjects/Notes
{{currentNoteTitle}}Title/name of the current noteMeeting Notes
\n

Examples#

\n

Body Template#

\n
---\ncreated: {{date}}\npriority: {{priority}}\nstatus: {{status}}\n---\n\n# {{title}}\n\n{{details}}\n\nCreated from: {{parentNote}}\nTags: {{hashtags}}\n

Folder Template#

\n

Organize tasks by project and status:

\n
Tasks/{{project}}/{{status}}\n

Result: Tasks/MyProject/active

\n

Organize by date hierarchy:

\n
Daily/{{year}}/{{month}}/{{day}}\n

Result: Daily/2025/01/07

\n

Organize ICS events by year and title:

\n
Events/{{year}}/{{icsEventTitleKebab}}\n

Result: Events/2025/team-meeting

\n

Filename Template#

\n

Using Zettelkasten ID:

\n
{{zettel}}-{{titleKebab}}\n

Result: 250107abc-my-task.md

\n

Using timestamp:

\n
{{shortDate}}-{{title}}\n

Result: 250107-My Task.md

\n

Notes#

\n

YAML Safety#

\n

When used in YAML frontmatter, values containing special characters (colons, brackets, quotes) are automatically quoted to prevent parsing errors.

\n

Folder Path Sanitization#

\n

In folder templates, title values have filesystem-unsafe characters (<>:"/\\|?*) replaced with underscores to ensure valid paths. Project file path variables preserve folder separators and sanitize unsafe characters within each path segment.

\n

Empty Values#

\n

If a variable references data that isn't available (e.g., {{project}} when no project is set), it resolves to an empty string.

\n

Case Transformations#

\n

The case transformation variables work as follows:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
TransformInputOutput
titleLowerMy Task Namemy task name
titleUpperMy Task NameMY TASK NAME
titleSnakeMy Task Namemy_task_name
titleKebabMy Task Namemy-task-name
titleCamelMy Task NamemyTaskName
titlePascalMy Task NameMyTaskName
\n","text":"TaskNotes supports template variables for dynamic content generation in body templates, folder paths, and filenames. Variables use the {{variableName}} syntax and are replaced with actual values when content is created. Overview# Template variables are available in three contexts: Body templates - Content templates for task and note files Folder templates - Dynamic folder paths for file organization Filename templates - Dynamic filename generation Not all variables are available in every context. The tables below indicate where each variable can be used. Task Properties# Variables for task-specific data. Variable Description Body Folder Example {{title}} Task title Yes Yes My Task {{titleLower}} Title in lowercase Yes Yes my task {{titleUpper}} Title in uppercase Yes Yes MY TASK {{titleSnake}} Title in snake_case Yes Yes my_task {{titleKebab}} Title in kebab-case Yes Yes my-task {{titleCamel}} Title in camelCase Yes Yes myTask {{titlePascal}} Title in PascalCase Yes Yes MyTask {{priority}} Task priority value Yes Yes high {{priorityShort}} First character of priority (uppercase) Yes Yes H {{status}} Task status value Yes Yes active {{statusShort}} First character of status (uppercase) Yes Yes A {{context}} First context from contexts array No Yes work {{contexts}} All contexts (comma-separated in body, / in folder) Yes Yes work, home or work/home {{project}} First project from projects array No Yes ProjectA {{projects}} All projects joined by / No Yes ProjectA/ProjectB {{projectFilePath}} Full path of the first project, without .md No Yes Work/Projects/ProjectA {{projectFilePaths}} Full paths of all projects, joined by / No Yes Work/Alpha/Personal/Beta {{projectFolder}} Folder containing the first project note (its file path without the note's own name) No Yes Work/Projects {{projectFolders}} Folders of all projects, joined by / No Yes Work/Personal {{dueDate}} Task due date Yes Yes 2025-01-15 {{scheduledDate}} Task scheduled date Yes Yes 2025-01-10 Body Template Only# Variables available only in body templates (not folder templates). Variable Description Example {{details}} User-provided details/description Task description text {{parentNote}} Parent note name/path where task was created Projects/MyNote {{tags}} Task tags (comma-separated) urgent, review {{hashtags}} Task tags as space-separated hashtags #urgent #review {{timeEstimate}} Time estimate in minutes 30 Date and Time# Variables for current date and time values. Variable Description Format Example {{date}} Full current date YYYY-MM-DD 2025-01-07 {{year}} Current year YYYY 2025 {{shortYear}} Short year YY 25 {{month}} Current month MM 01 {{day}} Current day DD 07 {{monthName}} Full month name - January {{monthNameShort}} Abbreviated month name - Jan {{dayName}} Full day name - Tuesday {{dayNameShort}} Abbreviated day name - Tue {{week}} Week number of year WW 02 {{quarter}} Quarter of year Q 1 {{shortDate}} Compact date YYMMDD 250107 Time Variables# Variable Description Format Example {{time}} Current time (compact) HHmmss 143052 {{time24}} 24-hour time HH:mm 14:30 {{time12}} 12-hour time with AM/PM hh:mm a 02:30 PM {{hour}} Current hour (24-hour) HH 14 {{hourPadded}} Hour with leading zero HH 14 {{hour12}} Hour in 12-hour format hh 02 {{minute}} Current minute mm 30 {{second}} Current second ss 52 {{ampm}} AM/PM indicator a PM Timestamps# Variable Description Format Example {{timestamp}} Date and time combined YYYY-MM-DD-HHmmss 2025-01-07-143052 {{dateTime}} Date and time (no seconds) YYYY-MM-DD-HHmm 2025-01-07-1430 {{unix}} Unix timestamp (seconds) - 1736264852 {{unixMs}} Unix timestamp (milliseconds) - 1736264852000 {{milliseconds}} Current milliseconds SSS 123 {{ms}} Milliseconds (alias) SSS 123 Timezone# Variable Description Example {{timezone}} Timezone offset +01:00 {{timezoneShort}} Short timezone offset +0100 {{utcOffset}} UTC offset +01:00 {{utcOffsetShort}} Short UTC offset +0100 {{utcZ}} UTC Z indicator Z Unique Identifiers# Variable Description Example {{zettel}} Zettelkasten-style ID (date + seconds since midnight in base36) 250107abc {{nano}} Unique nano ID (timestamp + random string) 1736264852000x7k2m ICS Calendar Event Variables# Variables for content created from ICS calendar events. Available when creating notes or tasks from calendar events. Event Information# Variable Description Body Folder {{icsEventTitle}} Event title Yes Yes {{icsEventTitleLower}} Event title lowercase No Yes {{icsEventTitleUpper}} Event title uppercase No Yes {{icsEventTitleSnake}} Event title in snake_case No Yes {{icsEventTitleKebab}} Event title in kebab-case No Yes {{icsEventTitleCamel}} Event title in camelCase No Yes {{icsEventTitlePascal}} Event title in PascalCase No Yes {{icsEventStart}} Event start time (ISO format) Yes No {{icsEventEnd}} Event end time (ISO format) Yes No {{icsEventLocation}} Event location Yes Yes {{icsEventDescription}} Event description Yes Yes {{icsEventUrl}} Event URL Yes No {{icsEventSubscription}} Calendar subscription name Yes No {{icsEventId}} Unique event identifier (UUID) Yes No Current Note Folder Variables# Variables available for inline-created tasks and the default tasks folder. Variable Description Example {{currentNotePath}} Path to the current note's folder Projects/Notes {{currentNoteTitle}} Title/name of the current note Meeting Notes Examples# Body Template# --- created: {{date}} priority: {{priority}} status: {{status}} --- # {{title}} {{details}} Created from: {{parentNote}} Tags: {{hashtags}} Folder Template# Organize tasks by project and status: Tasks/{{project}}/{{status}} Result: Tasks/MyProject/active Organize by date hierarchy: Daily/{{year}}/{{month}}/{{day}} Result: Daily/2025/01/07 Organize ICS events by year and title: Events/{{year}}/{{icsEventTitleKebab}} Result: Events/2025/team-meeting Filename Template# Using Zettelkasten ID: {{zettel}}-{{titleKebab}} Result: 250107abc-my-task.md Using timestamp: {{shortDate}}-{{title}} Result: 250107-My Task.md Notes# YAML Safety# When used in YAML frontmatter, values containing special characters (colons, brackets, quotes) are automatically quoted to prevent parsing errors. Folder Path Sanitization# In folder templates, title values have filesystem-unsafe characters (<>:\"/\\|?*) replaced with underscores to ensure valid paths. Project file path variables preserve folder separators and sanitize unsafe characters within each path segment. Empty Values# If a variable references data that isn't available (e.g., {{project}} when no project is set), it resolves to an empty string. Case Transformations# The case transformation variables work as follows: Transform Input Output titleLower My Task Name my task name titleUpper My Task Name MY TASK NAME titleSnake My Task Name my_task_name titleKebab My Task Name my-task-name titleCamel My Task Name myTaskName titlePascal My Task Name MyTaskName"},{"route":"/obsidian/features/time-management/","title":"Time Management","description":"TaskNotes includes features for time tracking and productivity, such as a time tracker and a Pomodoro timer.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/features/time-management.md","namespace":"obsidian","relativePath":"features/time-management.md","raw":"# Time Management\n\nTaskNotes includes features for time tracking and productivity, such as a time tracker and a Pomodoro timer.\n\n## Time Tracking\n\nTaskNotes has a time tracker to record the time spent on each task. Time tracking information is stored in the `timeEntries` array within each task's YAML frontmatter. Each time entry includes a start time and an end time.\n\nThe time tracking interface includes controls to start and stop tracking in task views and task cards. TaskNotes prevents duplicate active sessions on the same task. Active sessions on different tasks can exist at the same time, and total time spent on each task is calculated from completed sessions.\n\n### Auto-Stop Time Tracking\n\nTaskNotes can automatically stop time tracking when a task is marked as completed. This feature ensures that time tracking data accurately reflects work completion without requiring manual timer management.\n\nThe auto-stop feature works by monitoring task status changes across all views and interfaces. When a task's status changes from any non-completed state to a completed state (as defined by the custom status configuration), any active time tracking session for that task is automatically terminated.\n\n**Configuration Options:** Configure these under `Settings -> TaskNotes -> Features` (Time Tracking section).\n\n- **Auto-stop tracking** - Enable or disable the automatic stopping behavior (enabled by default)\n- **Completion notification** - Show a notice when auto-stop occurs (disabled by default)\n\n**Behavior:**\n\n- Monitors all task status changes in real-time\n- Stops only the specific task that was completed (other active timers continue)\n- Preserves the recorded time data in the task's time entries\n- Works with both standard and recurring task completions\n- Functions across all task views (list, kanban, calendar, etc.)\n\nThe feature integrates with the custom status system, so completion detection respects your configured workflow statuses rather than relying on hardcoded completion states.\n\n## Pomodoro Timer\n\nTaskNotes also includes a Pomodoro timer, which is a tool for time management that uses a timer to break down work into intervals, separated by short breaks. The Pomodoro timer in TaskNotes has a dedicated view with controls to start, stop, and reset the timer.\n\nWhen a task is associated with a Pomodoro session, the time is automatically recorded in the task's time tracking data upon completion of the session.\n\n## Productivity Analytics\n\nThe **Pomodoro Stats View** provides analytics and historical data about your Pomodoro sessions. This includes a history of completed sessions, as well as metrics like completion rates and total time spent on tasks. The data can be visualized to show productivity patterns over time.\n\n![Task Statistics](../assets/feature-task-statistics.png)\n","aliases":["/features/time-management/"],"toc":[{"level":2,"id":"time-tracking","text":"Time Tracking"},{"level":3,"id":"auto-stop-time-tracking","text":"Auto-Stop Time Tracking"},{"level":2,"id":"pomodoro-timer","text":"Pomodoro Timer"},{"level":2,"id":"productivity-analytics","text":"Productivity Analytics"}],"html":"

TaskNotes includes features for time tracking and productivity, such as a time tracker and a Pomodoro timer.

\n

Time Tracking#

\n

TaskNotes has a time tracker to record the time spent on each task. Time tracking information is stored in the timeEntries array within each task's YAML frontmatter. Each time entry includes a start time and an end time.

\n

The time tracking interface includes controls to start and stop tracking in task views and task cards. TaskNotes prevents duplicate active sessions on the same task. Active sessions on different tasks can exist at the same time, and total time spent on each task is calculated from completed sessions.

\n

Auto-Stop Time Tracking#

\n

TaskNotes can automatically stop time tracking when a task is marked as completed. This feature ensures that time tracking data accurately reflects work completion without requiring manual timer management.

\n

The auto-stop feature works by monitoring task status changes across all views and interfaces. When a task's status changes from any non-completed state to a completed state (as defined by the custom status configuration), any active time tracking session for that task is automatically terminated.

\n

Configuration Options: Configure these under Settings -> TaskNotes -> Features (Time Tracking section).

\n
    \n
  • Auto-stop tracking - Enable or disable the automatic stopping behavior (enabled by default)
  • \n
  • Completion notification - Show a notice when auto-stop occurs (disabled by default)
  • \n
\n

Behavior:

\n
    \n
  • Monitors all task status changes in real-time
  • \n
  • Stops only the specific task that was completed (other active timers continue)
  • \n
  • Preserves the recorded time data in the task's time entries
  • \n
  • Works with both standard and recurring task completions
  • \n
  • Functions across all task views (list, kanban, calendar, etc.)
  • \n
\n

The feature integrates with the custom status system, so completion detection respects your configured workflow statuses rather than relying on hardcoded completion states.

\n

Pomodoro Timer#

\n

TaskNotes also includes a Pomodoro timer, which is a tool for time management that uses a timer to break down work into intervals, separated by short breaks. The Pomodoro timer in TaskNotes has a dedicated view with controls to start, stop, and reset the timer.

\n

When a task is associated with a Pomodoro session, the time is automatically recorded in the task's time tracking data upon completion of the session.

\n

Productivity Analytics#

\n

The Pomodoro Stats View provides analytics and historical data about your Pomodoro sessions. This includes a history of completed sessions, as well as metrics like completion rates and total time spent on tasks. The data can be visualized to show productivity patterns over time.

\n

\"Task

\n","text":"TaskNotes includes features for time tracking and productivity, such as a time tracker and a Pomodoro timer. Time Tracking# TaskNotes has a time tracker to record the time spent on each task. Time tracking information is stored in the timeEntries array within each task's YAML frontmatter. Each time entry includes a start time and an end time. The time tracking interface includes controls to start and stop tracking in task views and task cards. TaskNotes prevents duplicate active sessions on the same task. Active sessions on different tasks can exist at the same time, and total time spent on each task is calculated from completed sessions. Auto-Stop Time Tracking# TaskNotes can automatically stop time tracking when a task is marked as completed. This feature ensures that time tracking data accurately reflects work completion without requiring manual timer management. The auto-stop feature works by monitoring task status changes across all views and interfaces. When a task's status changes from any non-completed state to a completed state (as defined by the custom status configuration), any active time tracking session for that task is automatically terminated. Configuration Options: Configure these under Settings -> TaskNotes -> Features (Time Tracking section). Auto-stop tracking - Enable or disable the automatic stopping behavior (enabled by default) Completion notification - Show a notice when auto-stop occurs (disabled by default) Behavior: Monitors all task status changes in real-time Stops only the specific task that was completed (other active timers continue) Preserves the recorded time data in the task's time entries Works with both standard and recurring task completions Functions across all task views (list, kanban, calendar, etc.) The feature integrates with the custom status system, so completion detection respects your configured workflow statuses rather than relying on hardcoded completion states. Pomodoro Timer# TaskNotes also includes a Pomodoro timer, which is a tool for time management that uses a timer to break down work into intervals, separated by short breaks. The Pomodoro timer in TaskNotes has a dedicated view with controls to start, stop, and reset the timer. When a task is associated with a Pomodoro session, the time is automatically recorded in the task's time tracking data upon completion of the session. Productivity Analytics# The Pomodoro Stats View provides analytics and historical data about your Pomodoro sessions. This includes a history of completed sessions, as well as metrics like completion rates and total time spent on tasks. The data can be visualized to show productivity patterns over time."},{"route":"/obsidian/features/user-fields/","title":"User Fields","description":"TaskNotes allows you to define your own custom fields for tasks. This feature allows you to add custom data to your tasks and use it for filtering, sorting, and grouping. User f...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/features/user-fields.md","namespace":"obsidian","relativePath":"features/user-fields.md","raw":"\n# User Fields\n\nTaskNotes allows you to define your own custom fields for tasks. This feature allows you to add custom data to your tasks and use it for filtering, sorting, and grouping.\nUser fields can store workflow-specific metadata such as owner, effort class, client, or review stage.\n\n\n## Creating User Fields\n\nUser fields are created in the TaskNotes settings, under the \"Task Properties\" tab. To create a new user field, click the \"Add new user field\" button.\nFields that are not used in filters or grouping still add frontmatter overhead, so this section focuses on fields used in views.\n\nEach user field has the following properties:\n\n- **Display Name**: The name of the field as it will be displayed in the UI.\n- **Property Name**: The name of the field as it will be stored in the frontmatter of the task note.\n- **Type**: The data type of the field. The following types are supported:\n - **Text**: A single line of text.\n - **Number**: A numeric value (supports ranges in filters and sorting).\n - **Boolean**: A true/false value stored as a checkbox in the task modal.\n - **Date**: A date.\n - **List**: A list of values.\n- **Default Value** (optional): A default value to pre-fill when creating new tasks. The input format depends on the field type:\n - **Text**: Enter the default text value.\n - **Number**: Enter the default number.\n - **Boolean**: Toggle to set the default state (checked/unchecked).\n - **Date**: Select from presets: None, Today, Tomorrow, or Next Week.\n - **List**: Enter comma-separated default values.\n\n## Link Values\n\nUse a **Text** field for one related link, such as a pull request or specification, and a **List** field for multiple related links. Task cards render wikilinks, markdown links, angle-bracket autolinks, and bare `https://` URLs as clickable links.\n\nFor internal note links, type `[[` in a text or list field to use the same file suggestions as other TaskNotes link fields. Autosuggestion filters can narrow those note suggestions without changing how the stored field value is filtered, sorted, or grouped.\n\n## File Suggestion Filtering (Advanced)\n\nWhen using text or list type custom fields, you can configure **autosuggestion filters** to control which files appear in the autocomplete dropdown when you type `[[` in the field.\n\n![Custom field autosuggestion filters for tags, folders, and property values](../assets/custom-fields-selection-filter.webp)\n\nThis is useful when you want to limit suggestions to specific types of notes. For example:\n- An \"Assignee\" field that only suggests notes tagged with `#person`\n- A \"Project\" field that only shows notes in the `Projects/` folder\n- A \"Related Document\" field filtered by a specific frontmatter property\nFiltering narrows wikilink suggestions in large vaults.\n\n### Configuring Filters\n\nTo configure filters for a custom field:\n\n1. Go to **Settings → Task Properties → Custom User Fields**\n2. Expand the custom field card you want to configure\n3. Expand the **\"Autosuggestion filters (Advanced)\"** section\n4. Configure one or more of the following filters:\n\n#### Filter Options\n\n- **Required tags**: Only show files that have ANY of these tags (comma-separated)\n - Example: `person, team` - shows files with either `#person` OR `#team` tag\n - Supports hierarchical tags: `project/active` matches `#project/active`\n\n- **Include folders**: Only show files in these folders (comma-separated)\n - Example: `People/, Teams/` - shows files in either folder\n - Supports nested folders: `Projects/Active/` matches files in that specific folder\n\n- **Required property key**: Only show files that have this frontmatter property\n - Example: `role` - shows files with a `role:` property in frontmatter\n\n- **Required property value**: Expected value for the property (optional)\n - Example: `developer` - when combined with property key `role`, shows files with `role: developer`\n - Leave empty to match any value (just checks property exists)\n\n#### Filter Indicator\n\nWhen filters are configured, a **\"Filters On\"** badge with a funnel icon appears next to the section title. This prevents you from forgetting that filters are active.\n\n### Filter Behavior\n\n- **All filters are combined with AND logic**: Files must match ALL configured filters to appear\n- **Empty filters are ignored**: If you don't configure a filter, it won't restrict results\n- **No filters = all files**: If no filters are configured, all markdown files in your vault will appear\n- **Filters only affect autocomplete**: They don't affect the actual field value or validation\nAutocomplete filtering and stored field values are handled independently.\n\n### Example Configurations\n\n#### Assignee Field (People Only)\n```\nDisplay Name: Assignee\nProperty Key: assignee\nType: List\n\nAutosuggestion filters:\n Required tags: person\n Include folders: People/\n```\n\n#### Project Field (Active Projects)\n```\nDisplay Name: Project\nProperty Key: project\nType: Text\n\nAutosuggestion filters:\n Required tags: project\n Required property key: status\n Required property value: active\n```\n\n#### Related Note (Specific Folder)\n```\nDisplay Name: Related Note\nProperty Key: related-note\nType: Text\n\nAutosuggestion filters:\n Include folders: Documentation/, Guides/\n```\n\n## Using User Fields\n\nOnce you have created a user field, it will be available in the following places:\n\n- **Task Modals**: The user field will be displayed in the task creation and edit modals.\n- **Bases Filters**: Add the field to Bases filter expressions (for example `note.effort == \"high\"`) to narrow task lists and Kanban boards.\n- **Sorting**: Use the Bases sort menu to order tasks by the user field.\n- **Grouping**: Use the Bases group menu to create swimlanes or list groupings based on the user field.\nTo verify a new field is active in workflow, add it to at least one saved view.\n\n## Frontmatter\n\nUser field data is stored in the frontmatter of the task note. The property name you define for the user field is used as the key in the frontmatter.\n\nFor example, if you create a user field with the property name \"my_field\", the data for that field will be stored in the frontmatter as follows:\n\n```yaml\n---\nmy_field: value\n---\n```\n","aliases":["/features/user-fields/"],"toc":[{"level":2,"id":"creating-user-fields","text":"Creating User Fields"},{"level":2,"id":"link-values","text":"Link Values"},{"level":2,"id":"file-suggestion-filtering-advanced","text":"File Suggestion Filtering (Advanced)"},{"level":3,"id":"configuring-filters","text":"Configuring Filters"},{"level":3,"id":"filter-behavior","text":"Filter Behavior"},{"level":3,"id":"example-configurations","text":"Example Configurations"},{"level":2,"id":"using-user-fields","text":"Using User Fields"},{"level":2,"id":"frontmatter","text":"Frontmatter"}],"html":"

TaskNotes allows you to define your own custom fields for tasks. This feature allows you to add custom data to your tasks and use it for filtering, sorting, and grouping.\nUser fields can store workflow-specific metadata such as owner, effort class, client, or review stage.

\n

Creating User Fields#

\n

User fields are created in the TaskNotes settings, under the "Task Properties" tab. To create a new user field, click the "Add new user field" button.\nFields that are not used in filters or grouping still add frontmatter overhead, so this section focuses on fields used in views.

\n

Each user field has the following properties:

\n
    \n
  • Display Name: The name of the field as it will be displayed in the UI.
  • \n
  • Property Name: The name of the field as it will be stored in the frontmatter of the task note.
  • \n
  • Type: The data type of the field. The following types are supported:
      \n
    • Text: A single line of text.
    • \n
    • Number: A numeric value (supports ranges in filters and sorting).
    • \n
    • Boolean: A true/false value stored as a checkbox in the task modal.
    • \n
    • Date: A date.
    • \n
    • List: A list of values.
    • \n
    \n
  • \n
  • Default Value (optional): A default value to pre-fill when creating new tasks. The input format depends on the field type:
      \n
    • Text: Enter the default text value.
    • \n
    • Number: Enter the default number.
    • \n
    • Boolean: Toggle to set the default state (checked/unchecked).
    • \n
    • Date: Select from presets: None, Today, Tomorrow, or Next Week.
    • \n
    • List: Enter comma-separated default values.
    • \n
    \n
  • \n
\n\n

Use a Text field for one related link, such as a pull request or specification, and a List field for multiple related links. Task cards render wikilinks, markdown links, angle-bracket autolinks, and bare https:// URLs as clickable links.

\n

For internal note links, type [[ in a text or list field to use the same file suggestions as other TaskNotes link fields. Autosuggestion filters can narrow those note suggestions without changing how the stored field value is filtered, sorted, or grouped.

\n

File Suggestion Filtering (Advanced)#

\n

When using text or list type custom fields, you can configure autosuggestion filters to control which files appear in the autocomplete dropdown when you type [[ in the field.

\n

\"Custom

\n

This is useful when you want to limit suggestions to specific types of notes. For example:

\n
    \n
  • An "Assignee" field that only suggests notes tagged with #person
  • \n
  • A "Project" field that only shows notes in the Projects/ folder
  • \n
  • A "Related Document" field filtered by a specific frontmatter property\nFiltering narrows wikilink suggestions in large vaults.
  • \n
\n

Configuring Filters#

\n

To configure filters for a custom field:

\n
    \n
  1. Go to Settings → Task Properties → Custom User Fields
  2. \n
  3. Expand the custom field card you want to configure
  4. \n
  5. Expand the "Autosuggestion filters (Advanced)" section
  6. \n
  7. Configure one or more of the following filters:
  8. \n
\n

Filter Options#

\n
    \n
  • Required tags: Only show files that have ANY of these tags (comma-separated)

    \n
      \n
    • Example: person, team - shows files with either #person OR #team tag
    • \n
    • Supports hierarchical tags: project/active matches #project/active
    • \n
    \n
  • \n
  • Include folders: Only show files in these folders (comma-separated)

    \n
      \n
    • Example: People/, Teams/ - shows files in either folder
    • \n
    • Supports nested folders: Projects/Active/ matches files in that specific folder
    • \n
    \n
  • \n
  • Required property key: Only show files that have this frontmatter property

    \n
      \n
    • Example: role - shows files with a role: property in frontmatter
    • \n
    \n
  • \n
  • Required property value: Expected value for the property (optional)

    \n
      \n
    • Example: developer - when combined with property key role, shows files with role: developer
    • \n
    • Leave empty to match any value (just checks property exists)
    • \n
    \n
  • \n
\n

Filter Indicator#

\n

When filters are configured, a "Filters On" badge with a funnel icon appears next to the section title. This prevents you from forgetting that filters are active.

\n

Filter Behavior#

\n
    \n
  • All filters are combined with AND logic: Files must match ALL configured filters to appear
  • \n
  • Empty filters are ignored: If you don't configure a filter, it won't restrict results
  • \n
  • No filters = all files: If no filters are configured, all markdown files in your vault will appear
  • \n
  • Filters only affect autocomplete: They don't affect the actual field value or validation\nAutocomplete filtering and stored field values are handled independently.
  • \n
\n

Example Configurations#

\n

Assignee Field (People Only)#

\n
Display Name: Assignee\nProperty Key: assignee\nType: List\n\nAutosuggestion filters:\n  Required tags: person\n  Include folders: People/\n

Project Field (Active Projects)#

\n
Display Name: Project\nProperty Key: project\nType: Text\n\nAutosuggestion filters:\n  Required tags: project\n  Required property key: status\n  Required property value: active\n

Related Note (Specific Folder)#

\n
Display Name: Related Note\nProperty Key: related-note\nType: Text\n\nAutosuggestion filters:\n  Include folders: Documentation/, Guides/\n

Using User Fields#

\n

Once you have created a user field, it will be available in the following places:

\n
    \n
  • Task Modals: The user field will be displayed in the task creation and edit modals.
  • \n
  • Bases Filters: Add the field to Bases filter expressions (for example note.effort == "high") to narrow task lists and Kanban boards.
  • \n
  • Sorting: Use the Bases sort menu to order tasks by the user field.
  • \n
  • Grouping: Use the Bases group menu to create swimlanes or list groupings based on the user field.\nTo verify a new field is active in workflow, add it to at least one saved view.
  • \n
\n

Frontmatter#

\n

User field data is stored in the frontmatter of the task note. The property name you define for the user field is used as the key in the frontmatter.

\n

For example, if you create a user field with the property name "my_field", the data for that field will be stored in the frontmatter as follows:

\n
---\nmy_field: value\n---\n
","text":"TaskNotes allows you to define your own custom fields for tasks. This feature allows you to add custom data to your tasks and use it for filtering, sorting, and grouping. User fields can store workflow-specific metadata such as owner, effort class, client, or review stage. Creating User Fields# User fields are created in the TaskNotes settings, under the \"Task Properties\" tab. To create a new user field, click the \"Add new user field\" button. Fields that are not used in filters or grouping still add frontmatter overhead, so this section focuses on fields used in views. Each user field has the following properties: Display Name: The name of the field as it will be displayed in the UI. Property Name: The name of the field as it will be stored in the frontmatter of the task note. Type: The data type of the field. The following types are supported: Text: A single line of text. Number: A numeric value (supports ranges in filters and sorting). Boolean: A true/false value stored as a checkbox in the task modal. Date: A date. List: A list of values. Default Value (optional): A default value to pre-fill when creating new tasks. The input format depends on the field type: Text: Enter the default text value. Number: Enter the default number. Boolean: Toggle to set the default state (checked/unchecked). Date: Select from presets: None, Today, Tomorrow, or Next Week. List: Enter comma-separated default values. Link Values# Use a Text field for one related link, such as a pull request or specification, and a List field for multiple related links. Task cards render wikilinks, markdown links, angle-bracket autolinks, and bare https:// URLs as clickable links. For internal note links, type [[ in a text or list field to use the same file suggestions as other TaskNotes link fields. Autosuggestion filters can narrow those note suggestions without changing how the stored field value is filtered, sorted, or grouped. File Suggestion Filtering (Advanced)# When using text or list type custom fields, you can configure autosuggestion filters to control which files appear in the autocomplete dropdown when you type [[ in the field. This is useful when you want to limit suggestions to specific types of notes. For example: An \"Assignee\" field that only suggests notes tagged with #person A \"Project\" field that only shows notes in the Projects/ folder A \"Related Document\" field filtered by a specific frontmatter property Filtering narrows wikilink suggestions in large vaults. Configuring Filters# To configure filters for a custom field: Go to Settings → Task Properties → Custom User Fields Expand the custom field card you want to configure Expand the \"Autosuggestion filters (Advanced)\" section Configure one or more of the following filters: Filter Options# Required tags: Only show files that have ANY of these tags (comma-separated) Example: person, team - shows files with either #person OR #team tag Supports hierarchical tags: project/active matches #project/active Include folders: Only show files in these folders (comma-separated) Example: People/, Teams/ - shows files in either folder Supports nested folders: Projects/Active/ matches files in that specific folder Required property key: Only show files that have this frontmatter property Example: role - shows files with a role: property in frontmatter Required property value: Expected value for the property (optional) Example: developer - when combined with property key role, shows files with role: developer Leave empty to match any value (just checks property exists) Filter Indicator# When filters are configured, a \"Filters On\" badge with a funnel icon appears next to the section title. This prevents you from forgetting that filters are active. Filter Behavior# All filters are combined with AND logic: Files must match ALL configured filters to appear Empty filters are ignored: If you don't configure a filter, it won't restrict results No filters = all files: If no filters are configured, all markdown files in your vault will appear Filters only affect autocomplete: They don't affect the actual field value or validation Autocomplete filtering and stored field values are handled independently. Example Configurations# Assignee Field (People Only)# Display Name: Assignee Property Key: assignee Type: List Autosuggestion filters: Required tags: person Include folders: People/ Project Field (Active Projects)# Display Name: Project Property Key: project Type: Text Autosuggestion filters: Required tags: project Required property key: status Required property value: active Related Note (Specific Folder)# Display Name: Related Note Property Key: related-note Type: Text Autosuggestion filters: Include folders: Documentation/, Guides/ Using User Fields# Once you have created a user field, it will be available in the following places: Task Modals: The user field will be displayed in the task creation and edit modals. Bases Filters: Add the field to Bases filter expressions (for example note.effort == \"high\") to narrow task lists and Kanban boards. Sorting: Use the Bases sort menu to order tasks by the user field. Grouping: Use the Bases group menu to create swimlanes or list groupings based on the user field. To verify a new field is active in workflow, add it to at least one saved view. Frontmatter# User field data is stored in the frontmatter of the task note. The property name you define for the user field is used as the key in the frontmatter. For example, if you create a user field with the property name \"my_field\", the data for that field will be stored in the frontmatter as follows: --- my_field: value ---"},{"route":"/obsidian/getting-started/existing-vault/","title":"Adopt TaskNotes in an existing vault","description":"Adopt TaskNotes in a vault that already contains tasks, tags, and custom frontmatter without rewriting everything first.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/getting-started/existing-vault.md","namespace":"obsidian","relativePath":"getting-started/existing-vault.md","raw":"---\ndescription: Adopt TaskNotes in a vault that already contains tasks, tags, and custom frontmatter without rewriting everything first.\n---\n\n# Adopt TaskNotes in an existing vault\n\nTaskNotes can use your current folders and property names. Configure identification and field mapping before creating or converting tasks so the first write follows your vault conventions.\n\n## 1. Back up the vault\n\nMake a complete vault backup, including the hidden `.obsidian` directory. The task notes themselves are Markdown, while TaskNotes settings live in `.obsidian/plugins/tasknotes/data.json`.\n\n## 2. Inspect a representative note\n\nChoose one existing task and record:\n\n- The property or tag that distinguishes tasks from ordinary notes\n- The property names used for title, status, priority, due date, and scheduled date\n- Whether contexts and tags are stored with or without display prefixes\n- The folder patterns that should be included or excluded\n\nCanonical frontmatter values do not include natural-language trigger characters. Store `office`, not `@office`, and `review`, not `#review`.\n\n```yaml\n---\ntype: task\nstatus: open\ncontexts:\n - office\ntags:\n - review\n---\n```\n\n## 3. Choose task identification\n\nOpen **Settings → TaskNotes → General**.\n\n- Choose **Tag** if every task contains one identifying tag, such as `task`.\n- Choose **Property** if a property/value pair identifies tasks, such as `type: task`.\n- Add archive, template, attachment, or other non-task locations to **Excluded folders**.\n\nTask identification controls indexing and every generated Base filter. Confirm it before regenerating Base files.\n\n## 4. Map properties\n\nOpen **Settings → TaskNotes → Task properties** and map TaskNotes fields to the names already used in your notes. Avoid creating two properties for one concept, such as both `due` and `deadline`.\n\nStart with title, status, priority, due, scheduled, projects, contexts, and recurrence. Use the [property types reference](../settings/property-types-reference.md) to check value shapes.\n\n## 5. Test one note\n\nOpen one existing note and confirm that TaskNotes recognizes it. Use **TaskNotes: Quick actions for current task** and make a reversible edit, such as changing priority. Inspect the frontmatter before testing a larger set.\n\nIf the note is not recognized, use the [troubleshooting decision tree](../troubleshooting.md#tasks-not-appearing-in-views).\n\n## 6. Generate views from the final mapping\n\nOpen **Settings → TaskNotes → General → Views & base files** and create or update the default Base files. Generated filters and columns use the current task identifier and field mapping.\n\nThe update action replaces configured default Base files. Copy any customized Base to a new filename before updating it.\n\n## 7. Convert incrementally\n\nConvert or edit a small group first. Keep normal version-control or backup checkpoints between batches. Existing notes do not need to move into the default `TaskNotes/Tasks` folder if your storage and exclusion settings already cover their location.\n","aliases":["/getting-started/existing-vault/"],"toc":[{"level":2,"id":"1-back-up-the-vault","text":"1. Back up the vault"},{"level":2,"id":"2-inspect-a-representative-note","text":"2. Inspect a representative note"},{"level":2,"id":"3-choose-task-identification","text":"3. Choose task identification"},{"level":2,"id":"4-map-properties","text":"4. Map properties"},{"level":2,"id":"5-test-one-note","text":"5. Test one note"},{"level":2,"id":"6-generate-views-from-the-final-mapping","text":"6. Generate views from the final mapping"},{"level":2,"id":"7-convert-incrementally","text":"7. Convert incrementally"}],"html":"

TaskNotes can use your current folders and property names. Configure identification and field mapping before creating or converting tasks so the first write follows your vault conventions.

\n

1. Back up the vault#

\n

Make a complete vault backup, including the hidden .obsidian directory. The task notes themselves are Markdown, while TaskNotes settings live in .obsidian/plugins/tasknotes/data.json.

\n

2. Inspect a representative note#

\n

Choose one existing task and record:

\n
    \n
  • The property or tag that distinguishes tasks from ordinary notes
  • \n
  • The property names used for title, status, priority, due date, and scheduled date
  • \n
  • Whether contexts and tags are stored with or without display prefixes
  • \n
  • The folder patterns that should be included or excluded
  • \n
\n

Canonical frontmatter values do not include natural-language trigger characters. Store office, not @office, and review, not #review.

\n
---\ntype: task\nstatus: open\ncontexts:\n  - office\ntags:\n  - review\n---\n

3. Choose task identification#

\n

Open Settings → TaskNotes → General.

\n
    \n
  • Choose Tag if every task contains one identifying tag, such as task.
  • \n
  • Choose Property if a property/value pair identifies tasks, such as type: task.
  • \n
  • Add archive, template, attachment, or other non-task locations to Excluded folders.
  • \n
\n

Task identification controls indexing and every generated Base filter. Confirm it before regenerating Base files.

\n

4. Map properties#

\n

Open Settings → TaskNotes → Task properties and map TaskNotes fields to the names already used in your notes. Avoid creating two properties for one concept, such as both due and deadline.

\n

Start with title, status, priority, due, scheduled, projects, contexts, and recurrence. Use the property types reference to check value shapes.

\n

5. Test one note#

\n

Open one existing note and confirm that TaskNotes recognizes it. Use TaskNotes: Quick actions for current task and make a reversible edit, such as changing priority. Inspect the frontmatter before testing a larger set.

\n

If the note is not recognized, use the troubleshooting decision tree.

\n

6. Generate views from the final mapping#

\n

Open Settings → TaskNotes → General → Views & base files and create or update the default Base files. Generated filters and columns use the current task identifier and field mapping.

\n

The update action replaces configured default Base files. Copy any customized Base to a new filename before updating it.

\n

7. Convert incrementally#

\n

Convert or edit a small group first. Keep normal version-control or backup checkpoints between batches. Existing notes do not need to move into the default TaskNotes/Tasks folder if your storage and exclusion settings already cover their location.

\n","text":"TaskNotes can use your current folders and property names. Configure identification and field mapping before creating or converting tasks so the first write follows your vault conventions. 1. Back up the vault# Make a complete vault backup, including the hidden .obsidian directory. The task notes themselves are Markdown, while TaskNotes settings live in .obsidian/plugins/tasknotes/data.json. 2. Inspect a representative note# Choose one existing task and record: The property or tag that distinguishes tasks from ordinary notes The property names used for title, status, priority, due date, and scheduled date Whether contexts and tags are stored with or without display prefixes The folder patterns that should be included or excluded Canonical frontmatter values do not include natural-language trigger characters. Store office, not @office, and review, not #review. --- type: task status: open contexts: - office tags: - review --- 3. Choose task identification# Open Settings → TaskNotes → General. Choose Tag if every task contains one identifying tag, such as task. Choose Property if a property/value pair identifies tasks, such as type: task. Add archive, template, attachment, or other non-task locations to Excluded folders. Task identification controls indexing and every generated Base filter. Confirm it before regenerating Base files. 4. Map properties# Open Settings → TaskNotes → Task properties and map TaskNotes fields to the names already used in your notes. Avoid creating two properties for one concept, such as both due and deadline. Start with title, status, priority, due, scheduled, projects, contexts, and recurrence. Use the property types reference to check value shapes. 5. Test one note# Open one existing note and confirm that TaskNotes recognizes it. Use TaskNotes: Quick actions for current task and make a reversible edit, such as changing priority. Inspect the frontmatter before testing a larger set. If the note is not recognized, use the troubleshooting decision tree. 6. Generate views from the final mapping# Open Settings → TaskNotes → General → Views & base files and create or update the default Base files. Generated filters and columns use the current task identifier and field mapping. The update action replaces configured default Base files. Copy any customized Base to a new filename before updating it. 7. Convert incrementally# Convert or edit a small group first. Keep normal version-control or backup checkpoints between batches. Existing notes do not need to move into the default TaskNotes/Tasks folder if your storage and exclusion settings already cover their location."},{"route":"/obsidian/getting-started/mobile/","title":"Obsidian mobile guide","description":"What is shared between TaskNotes desktop and mobile, and which integrations differ on mobile.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/getting-started/mobile.md","namespace":"obsidian","relativePath":"getting-started/mobile.md","raw":"---\ndescription: What is shared between TaskNotes desktop and mobile, and which integrations differ on mobile.\n---\n\n# Obsidian mobile guide\n\nTaskNotes task files, Base files, settings, and most commands work on Obsidian mobile. Sync the complete vault, including `.base` files and `.obsidian/plugins/tasknotes/data.json`, when you want the same configuration on every device.\n\n## Before opening TaskNotes\n\n1. Install an Obsidian mobile version compatible with the current [TaskNotes requirement](../reference/compatibility.md).\n2. Enable the **Bases** core plugin.\n3. Confirm the TaskNotes plugin and its `data.json` have finished syncing before changing settings.\n4. Open a small default Base first and allow the initial index to finish.\n\n## Mobile differences\n\n| Area | Mobile behavior |\n| --- | --- |\n| HTTP API and MCP server | Desktop only. The HTTP API settings section is hidden on mobile. |\n| Calendar integrations | Available, with an option to disable calendar integration on mobile when startup time or provider behavior is a problem. |\n| Settings layout | Uses the same six tabs. Desktop-only controls are omitted where they cannot run. |\n| Keyboard commands | Commands remain available in the command palette; desktop key bindings may not have a mobile equivalent. |\n| Wide views | Calendar, Kanban, and large tables may require horizontal scrolling or a narrower Base configuration. |\n\n## A practical mobile setup\n\n- Keep task cards compact under **Settings → Appearance and UI**.\n- Limit visible Base columns and calendar event layers.\n- Increase remote calendar refresh intervals when mobile networking or battery use matters.\n- Use the task creation modal or command palette for predictable capture.\n- Keep HTTP automation on a desktop Obsidian instance.\n\n## If mobile stops loading tasks\n\nWait for vault sync to finish, confirm Bases is enabled, and run **TaskNotes: Refresh cache**. Then reopen the affected Base. If the problem is isolated to calendar data, enable **Disable calendar integration on mobile** and restart Obsidian before investigating the provider connection on desktop.\n","aliases":["/getting-started/mobile/"],"toc":[{"level":2,"id":"before-opening-tasknotes","text":"Before opening TaskNotes"},{"level":2,"id":"mobile-differences","text":"Mobile differences"},{"level":2,"id":"a-practical-mobile-setup","text":"A practical mobile setup"},{"level":2,"id":"if-mobile-stops-loading-tasks","text":"If mobile stops loading tasks"}],"html":"

TaskNotes task files, Base files, settings, and most commands work on Obsidian mobile. Sync the complete vault, including .base files and .obsidian/plugins/tasknotes/data.json, when you want the same configuration on every device.

\n

Before opening TaskNotes#

\n
    \n
  1. Install an Obsidian mobile version compatible with the current TaskNotes requirement.
  2. \n
  3. Enable the Bases core plugin.
  4. \n
  5. Confirm the TaskNotes plugin and its data.json have finished syncing before changing settings.
  6. \n
  7. Open a small default Base first and allow the initial index to finish.
  8. \n
\n

Mobile differences#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
AreaMobile behavior
HTTP API and MCP serverDesktop only. The HTTP API settings section is hidden on mobile.
Calendar integrationsAvailable, with an option to disable calendar integration on mobile when startup time or provider behavior is a problem.
Settings layoutUses the same six tabs. Desktop-only controls are omitted where they cannot run.
Keyboard commandsCommands remain available in the command palette; desktop key bindings may not have a mobile equivalent.
Wide viewsCalendar, Kanban, and large tables may require horizontal scrolling or a narrower Base configuration.
\n

A practical mobile setup#

\n
    \n
  • Keep task cards compact under Settings → Appearance and UI.
  • \n
  • Limit visible Base columns and calendar event layers.
  • \n
  • Increase remote calendar refresh intervals when mobile networking or battery use matters.
  • \n
  • Use the task creation modal or command palette for predictable capture.
  • \n
  • Keep HTTP automation on a desktop Obsidian instance.
  • \n
\n

If mobile stops loading tasks#

\n

Wait for vault sync to finish, confirm Bases is enabled, and run TaskNotes: Refresh cache. Then reopen the affected Base. If the problem is isolated to calendar data, enable Disable calendar integration on mobile and restart Obsidian before investigating the provider connection on desktop.

\n","text":"TaskNotes task files, Base files, settings, and most commands work on Obsidian mobile. Sync the complete vault, including .base files and .obsidian/plugins/tasknotes/data.json, when you want the same configuration on every device. Before opening TaskNotes# Install an Obsidian mobile version compatible with the current TaskNotes requirement. Enable the Bases core plugin. Confirm the TaskNotes plugin and its data.json have finished syncing before changing settings. Open a small default Base first and allow the initial index to finish. Mobile differences# Area Mobile behavior HTTP API and MCP server Desktop only. The HTTP API settings section is hidden on mobile. Calendar integrations Available, with an option to disable calendar integration on mobile when startup time or provider behavior is a problem. Settings layout Uses the same six tabs. Desktop-only controls are omitted where they cannot run. Keyboard commands Commands remain available in the command palette; desktop key bindings may not have a mobile equivalent. Wide views Calendar, Kanban, and large tables may require horizontal scrolling or a narrower Base configuration. A practical mobile setup# Keep task cards compact under Settings → Appearance and UI. Limit visible Base columns and calendar event layers. Increase remote calendar refresh intervals when mobile networking or battery use matters. Use the task creation modal or command palette for predictable capture. Keep HTTP automation on a desktop Obsidian instance. If mobile stops loading tasks# Wait for vault sync to finish, confirm Bases is enabled, and run TaskNotes: Refresh cache. Then reopen the affected Base. If the problem is isolated to calendar data, enable Disable calendar integration on mobile and restart Obsidian before investigating the provider connection on desktop."},{"route":"/obsidian/guides/backup-recovery/","title":"Backup, restore, and removal","description":"Back up, restore, reset, and uninstall TaskNotes while protecting task notes, views, settings, and integration data.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/guides/backup-recovery.md","namespace":"obsidian","relativePath":"guides/backup-recovery.md","raw":"---\ndescription: Back up, restore, reset, and uninstall TaskNotes while protecting task notes, views, settings, and integration data.\n---\n\n# Backup, restore, and removal\n\nTaskNotes keeps task content in your vault and configuration in the plugin data file. A complete backup includes both.\n\n## What to back up\n\n| Data | Typical location | Why it matters |\n| --- | --- | --- |\n| Task notes | Your configured task folders | Titles, properties, details, recurrence, and time entries |\n| Base views | `TaskNotes/Views/` or custom paths | Filters, formulas, layout, and custom views |\n| Plugin settings | `.obsidian/plugins/tasknotes/data.json` | Field mapping, statuses, defaults, integrations, and view command paths |\n| Daily notes | Your daily-note folder | Pomodoro history when daily-note storage is enabled |\n| mdbase configuration | `tasknotes.yaml`, `mdbase.yaml`, or `.mdbase/` when configured | Shared collection and schema configuration |\n\nTreat `data.json` as sensitive because integration configuration can include credentials or tokens. Store backups accordingly.\n\n## Create a restorable backup\n\n1. Close Obsidian or disable TaskNotes so settings are not being written.\n2. Copy the entire vault, including hidden files.\n3. Verify the backup contains `.obsidian/plugins/tasknotes/data.json`.\n4. Keep at least one version from before a migration or bulk edit.\n\nFile-history sync is useful, but it is not a substitute for a separate tested backup.\n\n## Restore\n\n1. Close Obsidian.\n2. Restore task notes and Base files first.\n3. Restore `.obsidian/plugins/tasknotes/data.json` if you also need the previous settings.\n4. Reopen Obsidian and confirm Bases is enabled.\n5. Run **TaskNotes: Refresh cache** and open one default Base.\n\nIf provider credentials have expired or were intentionally excluded from the backup, reconnect those integrations instead of restoring stale tokens.\n\n## Reset configuration safely\n\nDo not delete `data.json` as a first troubleshooting step.\n\n1. Close Obsidian.\n2. Rename `data.json` to `data.json.backup-YYYY-MM-DD`.\n3. Reopen Obsidian and test with fresh defaults.\n4. Restore the backup while Obsidian is closed if the reset does not help.\n\nA reset affects settings, configured statuses and priorities, integration state, saved views, and plugin-stored Pomodoro history. It does not delete task Markdown files.\n\n## Uninstall\n\nDisabling or uninstalling TaskNotes leaves task notes and `.base` files in the vault. After uninstalling, remove generated folders only if you have inspected them and confirmed they contain no content you want to keep.\n\nTo remove plugin settings as well, close Obsidian and remove `.obsidian/plugins/tasknotes/` after making a backup. Task metadata remains readable YAML, but TaskNotes-specific Base view types and interactive widgets will no longer render.\n\n## Recovery checklist\n\n- Missing tasks: restore the note files, then verify task identification and excluded folders.\n- Missing settings: restore `data.json` with Obsidian closed.\n- Broken default views: regenerate them from **General → Views & base files**.\n- Broken custom views: restore the individual `.base` files from history.\n- Lost Pomodoro history: restore the configured storage source, which may be plugin data or daily-note frontmatter.\n","aliases":["/guides/backup-recovery/"],"toc":[{"level":2,"id":"what-to-back-up","text":"What to back up"},{"level":2,"id":"create-a-restorable-backup","text":"Create a restorable backup"},{"level":2,"id":"restore","text":"Restore"},{"level":2,"id":"reset-configuration-safely","text":"Reset configuration safely"},{"level":2,"id":"uninstall","text":"Uninstall"},{"level":2,"id":"recovery-checklist","text":"Recovery checklist"}],"html":"

TaskNotes keeps task content in your vault and configuration in the plugin data file. A complete backup includes both.

\n

What to back up#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
DataTypical locationWhy it matters
Task notesYour configured task foldersTitles, properties, details, recurrence, and time entries
Base viewsTaskNotes/Views/ or custom pathsFilters, formulas, layout, and custom views
Plugin settings.obsidian/plugins/tasknotes/data.jsonField mapping, statuses, defaults, integrations, and view command paths
Daily notesYour daily-note folderPomodoro history when daily-note storage is enabled
mdbase configurationtasknotes.yaml, mdbase.yaml, or .mdbase/ when configuredShared collection and schema configuration
\n

Treat data.json as sensitive because integration configuration can include credentials or tokens. Store backups accordingly.

\n

Create a restorable backup#

\n
    \n
  1. Close Obsidian or disable TaskNotes so settings are not being written.
  2. \n
  3. Copy the entire vault, including hidden files.
  4. \n
  5. Verify the backup contains .obsidian/plugins/tasknotes/data.json.
  6. \n
  7. Keep at least one version from before a migration or bulk edit.
  8. \n
\n

File-history sync is useful, but it is not a substitute for a separate tested backup.

\n

Restore#

\n
    \n
  1. Close Obsidian.
  2. \n
  3. Restore task notes and Base files first.
  4. \n
  5. Restore .obsidian/plugins/tasknotes/data.json if you also need the previous settings.
  6. \n
  7. Reopen Obsidian and confirm Bases is enabled.
  8. \n
  9. Run TaskNotes: Refresh cache and open one default Base.
  10. \n
\n

If provider credentials have expired or were intentionally excluded from the backup, reconnect those integrations instead of restoring stale tokens.

\n

Reset configuration safely#

\n

Do not delete data.json as a first troubleshooting step.

\n
    \n
  1. Close Obsidian.
  2. \n
  3. Rename data.json to data.json.backup-YYYY-MM-DD.
  4. \n
  5. Reopen Obsidian and test with fresh defaults.
  6. \n
  7. Restore the backup while Obsidian is closed if the reset does not help.
  8. \n
\n

A reset affects settings, configured statuses and priorities, integration state, saved views, and plugin-stored Pomodoro history. It does not delete task Markdown files.

\n

Uninstall#

\n

Disabling or uninstalling TaskNotes leaves task notes and .base files in the vault. After uninstalling, remove generated folders only if you have inspected them and confirmed they contain no content you want to keep.

\n

To remove plugin settings as well, close Obsidian and remove .obsidian/plugins/tasknotes/ after making a backup. Task metadata remains readable YAML, but TaskNotes-specific Base view types and interactive widgets will no longer render.

\n

Recovery checklist#

\n
    \n
  • Missing tasks: restore the note files, then verify task identification and excluded folders.
  • \n
  • Missing settings: restore data.json with Obsidian closed.
  • \n
  • Broken default views: regenerate them from General → Views & base files.
  • \n
  • Broken custom views: restore the individual .base files from history.
  • \n
  • Lost Pomodoro history: restore the configured storage source, which may be plugin data or daily-note frontmatter.
  • \n
\n","text":"TaskNotes keeps task content in your vault and configuration in the plugin data file. A complete backup includes both. What to back up# Data Typical location Why it matters Task notes Your configured task folders Titles, properties, details, recurrence, and time entries Base views TaskNotes/Views/ or custom paths Filters, formulas, layout, and custom views Plugin settings .obsidian/plugins/tasknotes/data.json Field mapping, statuses, defaults, integrations, and view command paths Daily notes Your daily-note folder Pomodoro history when daily-note storage is enabled mdbase configuration tasknotes.yaml, mdbase.yaml, or .mdbase/ when configured Shared collection and schema configuration Treat data.json as sensitive because integration configuration can include credentials or tokens. Store backups accordingly. Create a restorable backup# Close Obsidian or disable TaskNotes so settings are not being written. Copy the entire vault, including hidden files. Verify the backup contains .obsidian/plugins/tasknotes/data.json. Keep at least one version from before a migration or bulk edit. File-history sync is useful, but it is not a substitute for a separate tested backup. Restore# Close Obsidian. Restore task notes and Base files first. Restore .obsidian/plugins/tasknotes/data.json if you also need the previous settings. Reopen Obsidian and confirm Bases is enabled. Run TaskNotes: Refresh cache and open one default Base. If provider credentials have expired or were intentionally excluded from the backup, reconnect those integrations instead of restoring stale tokens. Reset configuration safely# Do not delete data.json as a first troubleshooting step. Close Obsidian. Rename data.json to data.json.backup-YYYY-MM-DD. Reopen Obsidian and test with fresh defaults. Restore the backup while Obsidian is closed if the reset does not help. A reset affects settings, configured statuses and priorities, integration state, saved views, and plugin-stored Pomodoro history. It does not delete task Markdown files. Uninstall# Disabling or uninstalling TaskNotes leaves task notes and .base files in the vault. After uninstalling, remove generated folders only if you have inspected them and confirmed they contain no content you want to keep. To remove plugin settings as well, close Obsidian and remove .obsidian/plugins/tasknotes/ after making a backup. Task metadata remains readable YAML, but TaskNotes-specific Base view types and interactive widgets will no longer render. Recovery checklist# Missing tasks: restore the note files, then verify task identification and excluded folders. Missing settings: restore data.json with Obsidian closed. Broken default views: regenerate them from General → Views & base files. Broken custom views: restore the individual .base files from history. Lost Pomodoro history: restore the configured storage source, which may be plugin data or daily-note frontmatter."},{"route":"/obsidian/guides/custom-bases/","title":"Build a custom Base","description":"Create a custom Obsidian Base for TaskNotes while keeping generated defaults safe and upgradeable.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/guides/custom-bases.md","namespace":"obsidian","relativePath":"guides/custom-bases.md","raw":"---\ndescription: Create a custom Obsidian Base for TaskNotes while keeping generated defaults safe and upgradeable.\n---\n\n# Build a custom Base\n\nTaskNotes views are ordinary Obsidian `.base` files. The safest workflow is to copy a generated Base, give it a new path, and customize the copy.\n\n## Start from a copy\n\n1. Open `TaskNotes/Views/` in the file explorer.\n2. Duplicate the closest default, such as `tasks-default.base`.\n3. Rename the copy, for example `work-tasks.base`.\n4. Open the copy and make changes with the Bases interface or source editor.\n\nAvoid editing the only copy of a generated default. **Update default base files** replaces the files configured as defaults.\n\n## Preserve task identification\n\nEvery task view needs a filter that matches the identification method in **Settings → TaskNotes → General**.\n\nFor tag identification:\n\n```yaml\nfilters:\n and:\n - file.hasTag(\"task\")\n```\n\nFor property identification:\n\n```yaml\nfilters:\n and:\n - note[\"type\"] == \"task\"\n```\n\nAlso preserve any excluded-folder conditions generated from your settings.\n\n## Add a focused view\n\nThis example starts with recognized tasks, then limits the view to the `work` context:\n\n```yaml\nfilters:\n and:\n - file.hasTag(\"task\")\n - list(contexts).contains(\"work\")\n\nviews:\n - type: tasknotesTaskList\n name: Work\n order:\n - status\n - priority\n - due\n - file.name\n sort:\n - column: due\n direction: ASC\n```\n\nUse canonical stored values in filters. Natural-language prefixes such as `@` and `#` are input syntax, not part of stored context and tag values.\n\n## Point a command at the custom Base\n\nOpen **Settings → TaskNotes → General → View commands** and change the relevant command path. Resetting that mapping returns it to the generated default path.\n\n## Upgrade safely\n\nWhen TaskNotes ships improved templates:\n\n1. Keep your custom file at its own path.\n2. Run **Update default base files**.\n3. Compare the regenerated default with your copy.\n4. Bring across only the formulas, filters, or view options you want.\n\nThe [generated template reference](../reference/default-base-templates.md) always reflects the current source and default field mapping.\n\n## Recovery\n\nIf a custom Base no longer opens, validate its YAML indentation and remove the most recent filter or formula change. You can create a fresh default from settings at any time, then copy your custom view into it one section at a time.\n","aliases":["/guides/custom-bases/"],"toc":[{"level":2,"id":"start-from-a-copy","text":"Start from a copy"},{"level":2,"id":"preserve-task-identification","text":"Preserve task identification"},{"level":2,"id":"add-a-focused-view","text":"Add a focused view"},{"level":2,"id":"point-a-command-at-the-custom-base","text":"Point a command at the custom Base"},{"level":2,"id":"upgrade-safely","text":"Upgrade safely"},{"level":2,"id":"recovery","text":"Recovery"}],"html":"

TaskNotes views are ordinary Obsidian .base files. The safest workflow is to copy a generated Base, give it a new path, and customize the copy.

\n

Start from a copy#

\n
    \n
  1. Open TaskNotes/Views/ in the file explorer.
  2. \n
  3. Duplicate the closest default, such as tasks-default.base.
  4. \n
  5. Rename the copy, for example work-tasks.base.
  6. \n
  7. Open the copy and make changes with the Bases interface or source editor.
  8. \n
\n

Avoid editing the only copy of a generated default. Update default base files replaces the files configured as defaults.

\n

Preserve task identification#

\n

Every task view needs a filter that matches the identification method in Settings → TaskNotes → General.

\n

For tag identification:

\n
filters:\n  and:\n    - file.hasTag("task")\n

For property identification:

\n
filters:\n  and:\n    - note["type"] == "task"\n

Also preserve any excluded-folder conditions generated from your settings.

\n

Add a focused view#

\n

This example starts with recognized tasks, then limits the view to the work context:

\n
filters:\n  and:\n    - file.hasTag("task")\n    - list(contexts).contains("work")\n\nviews:\n  - type: tasknotesTaskList\n    name: Work\n    order:\n      - status\n      - priority\n      - due\n      - file.name\n    sort:\n      - column: due\n        direction: ASC\n

Use canonical stored values in filters. Natural-language prefixes such as @ and # are input syntax, not part of stored context and tag values.

\n

Point a command at the custom Base#

\n

Open Settings → TaskNotes → General → View commands and change the relevant command path. Resetting that mapping returns it to the generated default path.

\n

Upgrade safely#

\n

When TaskNotes ships improved templates:

\n
    \n
  1. Keep your custom file at its own path.
  2. \n
  3. Run Update default base files.
  4. \n
  5. Compare the regenerated default with your copy.
  6. \n
  7. Bring across only the formulas, filters, or view options you want.
  8. \n
\n

The generated template reference always reflects the current source and default field mapping.

\n

Recovery#

\n

If a custom Base no longer opens, validate its YAML indentation and remove the most recent filter or formula change. You can create a fresh default from settings at any time, then copy your custom view into it one section at a time.

\n","text":"TaskNotes views are ordinary Obsidian .base files. The safest workflow is to copy a generated Base, give it a new path, and customize the copy. Start from a copy# Open TaskNotes/Views/ in the file explorer. Duplicate the closest default, such as tasks-default.base. Rename the copy, for example work-tasks.base. Open the copy and make changes with the Bases interface or source editor. Avoid editing the only copy of a generated default. Update default base files replaces the files configured as defaults. Preserve task identification# Every task view needs a filter that matches the identification method in Settings → TaskNotes → General. For tag identification: filters: and: - file.hasTag(\"task\") For property identification: filters: and: - note[\"type\"] == \"task\" Also preserve any excluded-folder conditions generated from your settings. Add a focused view# This example starts with recognized tasks, then limits the view to the work context: filters: and: - file.hasTag(\"task\") - list(contexts).contains(\"work\") views: - type: tasknotesTaskList name: Work order: - status - priority - due - file.name sort: - column: due direction: ASC Use canonical stored values in filters. Natural-language prefixes such as @ and # are input syntax, not part of stored context and tag values. Point a command at the custom Base# Open Settings → TaskNotes → General → View commands and change the relevant command path. Resetting that mapping returns it to the generated default path. Upgrade safely# When TaskNotes ships improved templates: Keep your custom file at its own path. Run Update default base files. Compare the regenerated default with your copy. Bring across only the formulas, filters, or view options you want. The generated template reference always reflects the current source and default field mapping. Recovery# If a custom Base no longer opens, validate its YAML indentation and remove the most recent filter or formula change. You can create a fresh default from settings at any time, then copy your custom view into it one section at a time."},{"route":"/obsidian/HTTP_API/","title":"TaskNotes HTTP API","description":"The TaskNotes HTTP API provides local HTTP access to tasks, time tracking, pomodoro, calendars, webhooks, and NLP parsing.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/HTTP_API.md","namespace":"obsidian","relativePath":"HTTP_API.md","raw":"# TaskNotes HTTP API\n\nThe TaskNotes HTTP API provides local HTTP access to tasks, time tracking, pomodoro, calendars, webhooks, and NLP parsing.\n\n## Availability\n\n- Desktop only\n- Disabled by default\n- Started when Obsidian starts and TaskNotes API is enabled\n- Bound to loopback (`127.0.0.1`) only, not the local network\n- Browser CORS requests are allowed only from loopback origins such as\n `localhost`, `127.0.0.1`, and `[::1]`\n- Not available on mobile\n\nEnable it in `Settings -> TaskNotes -> Integrations -> HTTP API`.\n\n## Base URL\n\n`http://localhost:{PORT}`\n\nDefault port is `8080`.\n\n## Authentication\n\nAuthentication is optional.\n\n- If `apiAuthToken` is empty, all API requests are accepted.\n- If `apiAuthToken` is set, send `Authorization: Bearer `.\n- Set a token for any workflow where local browser pages, scripts, or other\n desktop apps are not fully trusted.\n\nExample:\n\n```bash\ncurl -H \"Authorization: Bearer YOUR_TOKEN\" http://localhost:8080/api/health\n```\n\n## Response Format\n\nSuccess:\n\n```json\n{\n \"success\": true,\n \"data\": {}\n}\n```\n\nError:\n\n```json\n{\n \"success\": false,\n \"error\": \"Error message\"\n}\n```\n\n## Endpoint Index\n\n### System\n\n- `GET /api/health`\n- `GET /api/docs`\n- `GET /api/docs/ui`\n- `POST /api/nlp/parse`\n- `POST /api/nlp/create`\n\n### Tasks\n\n- `GET /api/tasks`\n- `POST /api/tasks`\n- `GET /api/tasks/:id`\n- `PUT /api/tasks/:id`\n- `DELETE /api/tasks/:id`\n- `POST /api/tasks/:id/toggle-status`\n- `POST /api/tasks/:id/archive`\n- `POST /api/tasks/:id/complete-instance`\n- `POST /api/tasks/:id/materialize-occurrence`\n- `POST /api/tasks/query`\n- `GET /api/filter-options`\n- `GET /api/stats`\n\n### Bases\n\n- `POST /api/bases/default-files/update`\n\n### Time Tracking\n\n- `POST /api/tasks/:id/time/start`\n- `POST /api/tasks/:id/time/start-with-description`\n- `POST /api/tasks/:id/time/stop`\n- `GET /api/tasks/:id/time`\n- `GET /api/time/active`\n- `GET /api/time/summary`\n\n### Pomodoro\n\n- `POST /api/pomodoro/start`\n- `POST /api/pomodoro/stop`\n- `POST /api/pomodoro/pause`\n- `POST /api/pomodoro/resume`\n- `GET /api/pomodoro/status`\n- `GET /api/pomodoro/sessions`\n- `GET /api/pomodoro/stats`\n\n### Calendars\n\n- `GET /api/calendars`\n- `GET /api/calendars/google`\n- `GET /api/calendars/microsoft`\n- `GET /api/calendars/subscriptions`\n- `GET /api/calendars/events`\n\n### Webhooks\n\n- `POST /api/webhooks`\n- `GET /api/webhooks`\n- `DELETE /api/webhooks/:id`\n- `GET /api/webhooks/deliveries`\n\nSee `docs/webhooks.md` for event and transform details.\n\n## Route Details\n\n## Health\n\n### `GET /api/health`\n\nReturns service state plus vault metadata.\n\n```bash\ncurl http://localhost:8080/api/health\n```\n\n## Tasks\n\n### `GET /api/tasks`\n\nBasic task listing with pagination only.\n\nQuery params:\n\n- `limit` (default `50`, max `200`)\n- `offset` (default `0`)\n\nImportant:\n\n- Filtering params such as `status`, `priority`, `tag`, `project`, `context`, `due_before`, `due_after`, `overdue`, `completed`, `archived`, and `sort` are rejected on this endpoint with HTTP `400`.\n- Use `POST /api/tasks/query` for filtering.\n\nExample:\n\n```bash\ncurl \"http://localhost:8080/api/tasks?limit=25&offset=0\"\n```\n\nResponse fields:\n\n- `data.tasks`\n- `data.pagination` with `total`, `offset`, `limit`, `hasMore`\n- `data.vault`\n- `data.note`\n- Task objects include configured TaskNotes user fields in `customProperties`, keyed by their frontmatter property key.\n\n### `POST /api/tasks`\n\nCreate one task.\n\nRequired:\n\n- `title`\n\nCommon optional fields:\n\n- `details`, `status`, `priority`, `due`, `scheduled`\n- `tags`, `contexts`, `projects`\n- `recurrence`, `recurrence_anchor`, `timeEstimate`, `reminders`\n- `blockedBy`\n\n`blockedBy` accepts an array of dependency objects:\n\n- `uid`: link or identifier for the blocking task, such as `[[Project setup]]`\n- `reltype`: one of `FINISHTOSTART`, `FINISHTOFINISH`, `STARTTOSTART`, or `STARTTOFINISH`\n- `gap`: optional ISO 8601 duration, such as `P1D`\n\n`blocking` is a read-only reverse relationship in API responses. To make a task block existing tasks, update those existing tasks' `blockedBy` fields.\n\n```bash\ncurl -X POST http://localhost:8080/api/tasks \\\n -H \"Content-Type: application/json\" \\\n -d '{\"title\":\"Review docs\",\"priority\":\"high\",\"blockedBy\":[{\"uid\":\"[[Draft docs]]\",\"reltype\":\"FINISHTOSTART\"}]}'\n```\n\nReturns HTTP `201` with created task data.\n\n### `GET /api/tasks/:id`\n\nGet one task by path id.\n\n- `:id` must be URL-encoded task path.\n- Single-task reads include the task body in `details`.\n- Configured TaskNotes user fields are returned in `customProperties`, keyed by their frontmatter property key.\n\n```bash\ncurl \"http://localhost:8080/api/tasks/TaskNotes%2FTasks%2FReview%20docs.md\"\n```\n\n### `PUT /api/tasks/:id`\n\nUpdate task with partial payload.\n\nConfigured TaskNotes user fields can be updated either by their frontmatter property key or via `customProperties`.\n\n```bash\ncurl -X PUT \"http://localhost:8080/api/tasks/TaskNotes%2FTasks%2FReview%20docs.md\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"status\":\"in-progress\"}'\n```\n\n### `DELETE /api/tasks/:id`\n\nDelete task file.\n\n### `POST /api/tasks/:id/toggle-status`\n\nToggle task status via configured workflow.\n\n### `POST /api/tasks/:id/archive`\n\nToggle archive state.\n\n### `POST /api/tasks/:id/complete-instance`\n\nComplete recurring instance.\n\nRequest body:\n\n- Optional `date` (ISO string). If omitted, uses current date context.\n\nWhen the recurring parent uses materialized occurrence notes, this endpoint completes the matching occurrence note if one exists. If the parent is set to **Create next after completion** and no matching occurrence note exists yet, TaskNotes creates and completes that occurrence note instead of only recording a virtual `complete_instances` entry.\n\n### `POST /api/tasks/:id/materialize-occurrence`\n\nCreate or return a materialized occurrence note for a recurring task date. This endpoint is idempotent for the same parent and date.\n\nRequest body:\n\n- Required `date` (ISO date string, for example `2026-06-01`)\n\n### `POST /api/tasks/query`\n\nAdvanced filtering.\n\nRequest body is a `FilterQuery` object. `FilterQuery` is still the supported advanced query shape for the HTTP API.\n\nThe root object is a group with:\n\n- `type: \"group\"`\n- `id`\n- `conjunction: \"and\" | \"or\"`\n- `children` (conditions or groups)\n\nOptional top-level query options:\n\n- `sortKey`, `sortDirection`\n- `groupKey`, `subgroupKey`\n\nExample:\n\n```json\n{\n \"type\": \"group\",\n \"id\": \"root\",\n \"conjunction\": \"and\",\n \"children\": [\n {\n \"type\": \"condition\",\n \"id\": \"c1\",\n \"property\": \"status\",\n \"operator\": \"is\",\n \"value\": \"open\"\n }\n ],\n \"sortKey\": \"due\",\n \"sortDirection\": \"asc\"\n}\n```\n\nFilter tasks by context:\n\n```json\n{\n \"type\": \"group\",\n \"id\": \"root\",\n \"conjunction\": \"and\",\n \"children\": [\n {\n \"type\": \"condition\",\n \"id\": \"context\",\n \"property\": \"contexts\",\n \"operator\": \"contains\",\n \"value\": \"@office\"\n }\n ],\n \"sortKey\": \"due\",\n \"sortDirection\": \"asc\"\n}\n```\n\nFilter active, unarchived tasks, similar to the default available-task view:\n\n```json\n{\n \"type\": \"group\",\n \"id\": \"root\",\n \"conjunction\": \"and\",\n \"children\": [\n {\n \"type\": \"condition\",\n \"id\": \"not-archived\",\n \"property\": \"archived\",\n \"operator\": \"is-not-checked\"\n },\n {\n \"type\": \"condition\",\n \"id\": \"not-completed\",\n \"property\": \"status.isCompleted\",\n \"operator\": \"is-not-checked\"\n }\n ],\n \"sortKey\": \"due\",\n \"sortDirection\": \"asc\",\n \"groupKey\": \"none\"\n}\n```\n\nCondition fields:\n\n- `type`: `\"condition\"`\n- `id`: any stable string for your client\n- `property`: a task property, such as `title`, `status`, `priority`, `tags`, `contexts`, `projects`, `blockedBy`, `blocking`, `due`, `scheduled`, `completedDate`, `dateCreated`, `dateModified`, `archived`, `hasSubtasks`, `dependencies.isBlocked`, `dependencies.isBlocking`, `timeEstimate`, `recurrence`, or `status.isCompleted`\n- `operator`: one of `is`, `is-not`, `contains`, `does-not-contain`, `is-before`, `is-after`, `is-on-or-before`, `is-on-or-after`, `is-empty`, `is-not-empty`, `is-checked`, `is-not-checked`, `is-greater-than`, `is-less-than`, `is-greater-than-or-equal`, or `is-less-than-or-equal`\n- `value`: required for comparison operators, omitted for empty/checked operators\n\nFor user-defined fields, use `property: \"user:\"`.\n\nResponse:\n\n- `data.tasks`\n- `data.total`\n- `data.filtered`\n- `data.vault`\n\n### `GET /api/filter-options`\n\nReturns filter options for UI builders.\n\n### `GET /api/stats`\n\nReturns summary counts:\n\n- `total`, `completed`, `active`, `overdue`, `archived`, `withTimeTracking`\n\n## Bases\n\n### `POST /api/bases/default-files/update`\n\nOverwrite the configured default TaskNotes `.base` files with templates generated from the current TaskNotes settings. This is the same write operation as **Settings -> TaskNotes -> Views & base files -> Update files** and replaces manual edits in those configured default files.\n\n```bash\ncurl -X POST http://localhost:8080/api/bases/default-files/update\n```\n\nResponse fields:\n\n- `data.created`: default files created because they were missing\n- `data.updated`: existing default files overwritten with current templates\n- `data.skipped`: configured default files skipped\n\n## Time Tracking\n\n### `POST /api/tasks/:id/time/start`\n\nStarts a new active time entry for that task.\n\n### `POST /api/tasks/:id/time/start-with-description`\n\nStarts time tracking and writes `description` on the new active entry.\n\nRequest body:\n\n```json\n{\n \"description\": \"Implementation\"\n}\n```\n\n### `POST /api/tasks/:id/time/stop`\n\nStops active time entry for that task.\n\n### `GET /api/tasks/:id/time`\n\nReturns per-task time summary and entries.\n\n### `GET /api/time/active`\n\nReturns currently active sessions across tasks.\n\nImportant:\n\n- Multiple active sessions can exist across different tasks.\n\n### `GET /api/time/summary`\n\nReturns aggregate time summary.\n\nQuery params:\n\n- `period` (for example `today`, `week`, `month`, `all`)\n- `from` (ISO date)\n- `to` (ISO date)\n\nExample:\n\n```bash\ncurl \"http://localhost:8080/api/time/summary?period=week\"\n```\n\n## Pomodoro\n\n### `POST /api/pomodoro/start`\n\nStarts a session.\n\nOptional request fields:\n\n- `taskId` (URL path of task)\n- `duration` (number)\n\n### `POST /api/pomodoro/stop`\n\nStops and resets current session.\n\n### `POST /api/pomodoro/pause`\n\nPauses running session.\n\n### `POST /api/pomodoro/resume`\n\nResumes paused session.\n\n### `GET /api/pomodoro/status`\n\nReturns current state plus computed totals (`totalPomodoros`, `currentStreak`, `totalMinutesToday`).\n\n### `GET /api/pomodoro/sessions`\n\nReturns history.\n\nQuery params:\n\n- `limit`\n- `date` (`YYYY-MM-DD`)\n\n### `GET /api/pomodoro/stats`\n\nReturns stats for today or provided date.\n\nQuery params:\n\n- `date` (`YYYY-MM-DD`)\n\n## Calendars\n\n### `GET /api/calendars`\n\nReturns provider connectivity overview and subscription counts.\n\n### `GET /api/calendars/google`\n\nReturns Google provider details.\n\n- If disconnected, returns `{ \"connected\": false }`.\n\n### `GET /api/calendars/microsoft`\n\nReturns Microsoft provider details.\n\n- If disconnected, returns `{ \"connected\": false }`.\n\n### `GET /api/calendars/subscriptions`\n\nReturns ICS subscriptions with runtime fields such as `lastFetched` and `lastError`.\n\n### `GET /api/calendars/events`\n\nReturns merged event list from connected providers and ICS subscriptions.\n\nQuery params:\n\n- `start` (ISO date/datetime)\n- `end` (ISO date/datetime)\n\nResponse includes:\n\n- `events`\n- `total`\n- `sources` (counts by provider)\n\n## Webhooks\n\n### `POST /api/webhooks`\n\nRegisters webhook.\n\nRequired fields:\n\n- `url`\n- `events` (non-empty array)\n\nOptional fields:\n\n- `id`\n- `secret`\n- `active`\n- `transformFile`\n- `corsHeaders`\n\n### `GET /api/webhooks`\n\nLists registered webhooks. Stored secrets are not returned.\n\n### `DELETE /api/webhooks/:id`\n\nDeletes webhook.\n\n### `GET /api/webhooks/deliveries`\n\nReturns last 100 delivery records.\n\n## OpenAPI Docs\n\n### `GET /api/docs`\n\nReturns OpenAPI JSON generated from registered controllers.\n\n### `GET /api/docs/ui`\n\nReturns Swagger UI.\n\n## Errors\n\nCommon status codes:\n\n- `400` invalid request or invalid state\n- `401` missing/invalid bearer token (when auth token is configured)\n- `404` missing task/webhook/resource\n- `500` internal error\n\n## Security Notes\n\nCurrent behavior:\n\n- CORS allows all origins (`*`).\n- Transport is HTTP only (no TLS).\n- Node server is started with `server.listen(port)` and does not explicitly bind to `127.0.0.1`.\n\nPractical guidance:\n\n- Set an auth token.\n- Treat API port as sensitive and keep it firewalled.\n- If you expose this port outside localhost, route through a trusted reverse proxy and TLS.\n\n## Troubleshooting\n\n### API unavailable\n\n1. Confirm API is enabled in settings.\n2. Confirm Obsidian is running.\n3. Confirm selected port is free.\n4. Reload plugin or restart Obsidian after changing API enable/port.\n\n### `401 Authentication required`\n\n1. Check token value.\n2. Check `Bearer ` prefix.\n3. Remove whitespace around token.\n\n### Unexpected task list behavior\n\nIf you pass filters to `GET /api/tasks`, the endpoint returns `400` by design. Use `POST /api/tasks/query`.\n","aliases":["/HTTP_API/"],"toc":[{"level":2,"id":"availability","text":"Availability"},{"level":2,"id":"base-url","text":"Base URL"},{"level":2,"id":"authentication","text":"Authentication"},{"level":2,"id":"response-format","text":"Response Format"},{"level":2,"id":"endpoint-index","text":"Endpoint Index"},{"level":3,"id":"system","text":"System"},{"level":3,"id":"tasks","text":"Tasks"},{"level":3,"id":"bases","text":"Bases"},{"level":3,"id":"time-tracking","text":"Time Tracking"},{"level":3,"id":"pomodoro","text":"Pomodoro"},{"level":3,"id":"calendars","text":"Calendars"},{"level":3,"id":"webhooks","text":"Webhooks"},{"level":2,"id":"route-details","text":"Route Details"},{"level":2,"id":"health","text":"Health"},{"level":3,"id":"get-apihealth","text":"GET /api/health"},{"level":2,"id":"tasks-2","text":"Tasks"},{"level":3,"id":"get-apitasks","text":"GET /api/tasks"},{"level":3,"id":"post-apitasks","text":"POST /api/tasks"},{"level":3,"id":"get-apitasksid","text":"GET /api/tasks/:id"},{"level":3,"id":"put-apitasksid","text":"PUT /api/tasks/:id"},{"level":3,"id":"delete-apitasksid","text":"DELETE /api/tasks/:id"},{"level":3,"id":"post-apitasksidtoggle-status","text":"POST /api/tasks/:id/toggle-status"},{"level":3,"id":"post-apitasksidarchive","text":"POST /api/tasks/:id/archive"},{"level":3,"id":"post-apitasksidcomplete-instance","text":"POST /api/tasks/:id/complete-instance"},{"level":3,"id":"post-apitasksidmaterialize-occurrence","text":"POST /api/tasks/:id/materialize-occurrence"},{"level":3,"id":"post-apitasksquery","text":"POST /api/tasks/query"},{"level":3,"id":"get-apifilter-options","text":"GET /api/filter-options"},{"level":3,"id":"get-apistats","text":"GET /api/stats"},{"level":2,"id":"bases-2","text":"Bases"},{"level":3,"id":"post-apibasesdefault-filesupdate","text":"POST /api/bases/default-files/update"},{"level":2,"id":"time-tracking-2","text":"Time Tracking"},{"level":3,"id":"post-apitasksidtimestart","text":"POST /api/tasks/:id/time/start"},{"level":3,"id":"post-apitasksidtimestart-with-description","text":"POST /api/tasks/:id/time/start-with-description"},{"level":3,"id":"post-apitasksidtimestop","text":"POST /api/tasks/:id/time/stop"},{"level":3,"id":"get-apitasksidtime","text":"GET /api/tasks/:id/time"},{"level":3,"id":"get-apitimeactive","text":"GET /api/time/active"},{"level":3,"id":"get-apitimesummary","text":"GET /api/time/summary"},{"level":2,"id":"pomodoro-2","text":"Pomodoro"},{"level":3,"id":"post-apipomodorostart","text":"POST /api/pomodoro/start"},{"level":3,"id":"post-apipomodorostop","text":"POST /api/pomodoro/stop"},{"level":3,"id":"post-apipomodoropause","text":"POST /api/pomodoro/pause"},{"level":3,"id":"post-apipomodororesume","text":"POST /api/pomodoro/resume"},{"level":3,"id":"get-apipomodorostatus","text":"GET /api/pomodoro/status"},{"level":3,"id":"get-apipomodorosessions","text":"GET /api/pomodoro/sessions"},{"level":3,"id":"get-apipomodorostats","text":"GET /api/pomodoro/stats"},{"level":2,"id":"calendars-2","text":"Calendars"},{"level":3,"id":"get-apicalendars","text":"GET /api/calendars"},{"level":3,"id":"get-apicalendarsgoogle","text":"GET /api/calendars/google"},{"level":3,"id":"get-apicalendarsmicrosoft","text":"GET /api/calendars/microsoft"},{"level":3,"id":"get-apicalendarssubscriptions","text":"GET /api/calendars/subscriptions"},{"level":3,"id":"get-apicalendarsevents","text":"GET /api/calendars/events"},{"level":2,"id":"webhooks-2","text":"Webhooks"},{"level":3,"id":"post-apiwebhooks","text":"POST /api/webhooks"},{"level":3,"id":"get-apiwebhooks","text":"GET /api/webhooks"},{"level":3,"id":"delete-apiwebhooksid","text":"DELETE /api/webhooks/:id"},{"level":3,"id":"get-apiwebhooksdeliveries","text":"GET /api/webhooks/deliveries"},{"level":2,"id":"openapi-docs","text":"OpenAPI Docs"},{"level":3,"id":"get-apidocs","text":"GET /api/docs"},{"level":3,"id":"get-apidocsui","text":"GET /api/docs/ui"},{"level":2,"id":"errors","text":"Errors"},{"level":2,"id":"security-notes","text":"Security Notes"},{"level":2,"id":"troubleshooting","text":"Troubleshooting"},{"level":3,"id":"api-unavailable","text":"API unavailable"},{"level":3,"id":"401-authentication-required","text":"401 Authentication required"},{"level":3,"id":"unexpected-task-list-behavior","text":"Unexpected task list behavior"}],"html":"

The TaskNotes HTTP API provides local HTTP access to tasks, time tracking, pomodoro, calendars, webhooks, and NLP parsing.

\n

Availability#

\n
    \n
  • Desktop only
  • \n
  • Disabled by default
  • \n
  • Started when Obsidian starts and TaskNotes API is enabled
  • \n
  • Bound to loopback (127.0.0.1) only, not the local network
  • \n
  • Browser CORS requests are allowed only from loopback origins such as\nlocalhost, 127.0.0.1, and [::1]
  • \n
  • Not available on mobile
  • \n
\n

Enable it in Settings -> TaskNotes -> Integrations -> HTTP API.

\n

Base URL#

\n

http://localhost:{PORT}

\n

Default port is 8080.

\n

Authentication#

\n

Authentication is optional.

\n
    \n
  • If apiAuthToken is empty, all API requests are accepted.
  • \n
  • If apiAuthToken is set, send Authorization: Bearer <token>.
  • \n
  • Set a token for any workflow where local browser pages, scripts, or other\ndesktop apps are not fully trusted.
  • \n
\n

Example:

\n
curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:8080/api/health\n

Response Format#

\n

Success:

\n
{\n  "success": true,\n  "data": {}\n}\n

Error:

\n
{\n  "success": false,\n  "error": "Error message"\n}\n

Endpoint Index#

\n

System#

\n
    \n
  • GET /api/health
  • \n
  • GET /api/docs
  • \n
  • GET /api/docs/ui
  • \n
  • POST /api/nlp/parse
  • \n
  • POST /api/nlp/create
  • \n
\n

Tasks#

\n
    \n
  • GET /api/tasks
  • \n
  • POST /api/tasks
  • \n
  • GET /api/tasks/:id
  • \n
  • PUT /api/tasks/:id
  • \n
  • DELETE /api/tasks/:id
  • \n
  • POST /api/tasks/:id/toggle-status
  • \n
  • POST /api/tasks/:id/archive
  • \n
  • POST /api/tasks/:id/complete-instance
  • \n
  • POST /api/tasks/:id/materialize-occurrence
  • \n
  • POST /api/tasks/query
  • \n
  • GET /api/filter-options
  • \n
  • GET /api/stats
  • \n
\n

Bases#

\n
    \n
  • POST /api/bases/default-files/update
  • \n
\n

Time Tracking#

\n
    \n
  • POST /api/tasks/:id/time/start
  • \n
  • POST /api/tasks/:id/time/start-with-description
  • \n
  • POST /api/tasks/:id/time/stop
  • \n
  • GET /api/tasks/:id/time
  • \n
  • GET /api/time/active
  • \n
  • GET /api/time/summary
  • \n
\n

Pomodoro#

\n
    \n
  • POST /api/pomodoro/start
  • \n
  • POST /api/pomodoro/stop
  • \n
  • POST /api/pomodoro/pause
  • \n
  • POST /api/pomodoro/resume
  • \n
  • GET /api/pomodoro/status
  • \n
  • GET /api/pomodoro/sessions
  • \n
  • GET /api/pomodoro/stats
  • \n
\n

Calendars#

\n
    \n
  • GET /api/calendars
  • \n
  • GET /api/calendars/google
  • \n
  • GET /api/calendars/microsoft
  • \n
  • GET /api/calendars/subscriptions
  • \n
  • GET /api/calendars/events
  • \n
\n

Webhooks#

\n
    \n
  • POST /api/webhooks
  • \n
  • GET /api/webhooks
  • \n
  • DELETE /api/webhooks/:id
  • \n
  • GET /api/webhooks/deliveries
  • \n
\n

See docs/webhooks.md for event and transform details.

\n

Route Details#

\n

Health#

\n

GET /api/health#

\n

Returns service state plus vault metadata.

\n
curl http://localhost:8080/api/health\n

Tasks#

\n

GET /api/tasks#

\n

Basic task listing with pagination only.

\n

Query params:

\n
    \n
  • limit (default 50, max 200)
  • \n
  • offset (default 0)
  • \n
\n

Important:

\n
    \n
  • Filtering params such as status, priority, tag, project, context, due_before, due_after, overdue, completed, archived, and sort are rejected on this endpoint with HTTP 400.
  • \n
  • Use POST /api/tasks/query for filtering.
  • \n
\n

Example:

\n
curl "http://localhost:8080/api/tasks?limit=25&offset=0"\n

Response fields:

\n
    \n
  • data.tasks
  • \n
  • data.pagination with total, offset, limit, hasMore
  • \n
  • data.vault
  • \n
  • data.note
  • \n
  • Task objects include configured TaskNotes user fields in customProperties, keyed by their frontmatter property key.
  • \n
\n

POST /api/tasks#

\n

Create one task.

\n

Required:

\n
    \n
  • title
  • \n
\n

Common optional fields:

\n
    \n
  • details, status, priority, due, scheduled
  • \n
  • tags, contexts, projects
  • \n
  • recurrence, recurrence_anchor, timeEstimate, reminders
  • \n
  • blockedBy
  • \n
\n

blockedBy accepts an array of dependency objects:

\n
    \n
  • uid: link or identifier for the blocking task, such as [[Project setup]]
  • \n
  • reltype: one of FINISHTOSTART, FINISHTOFINISH, STARTTOSTART, or STARTTOFINISH
  • \n
  • gap: optional ISO 8601 duration, such as P1D
  • \n
\n

blocking is a read-only reverse relationship in API responses. To make a task block existing tasks, update those existing tasks' blockedBy fields.

\n
curl -X POST http://localhost:8080/api/tasks \\\n  -H "Content-Type: application/json" \\\n  -d '{"title":"Review docs","priority":"high","blockedBy":[{"uid":"[[Draft docs]]","reltype":"FINISHTOSTART"}]}'\n

Returns HTTP 201 with created task data.

\n

GET /api/tasks/:id#

\n

Get one task by path id.

\n
    \n
  • :id must be URL-encoded task path.
  • \n
  • Single-task reads include the task body in details.
  • \n
  • Configured TaskNotes user fields are returned in customProperties, keyed by their frontmatter property key.
  • \n
\n
curl "http://localhost:8080/api/tasks/TaskNotes%2FTasks%2FReview%20docs.md"\n

PUT /api/tasks/:id#

\n

Update task with partial payload.

\n

Configured TaskNotes user fields can be updated either by their frontmatter property key or via customProperties.

\n
curl -X PUT "http://localhost:8080/api/tasks/TaskNotes%2FTasks%2FReview%20docs.md" \\\n  -H "Content-Type: application/json" \\\n  -d '{"status":"in-progress"}'\n

DELETE /api/tasks/:id#

\n

Delete task file.

\n

POST /api/tasks/:id/toggle-status#

\n

Toggle task status via configured workflow.

\n

POST /api/tasks/:id/archive#

\n

Toggle archive state.

\n

POST /api/tasks/:id/complete-instance#

\n

Complete recurring instance.

\n

Request body:

\n
    \n
  • Optional date (ISO string). If omitted, uses current date context.
  • \n
\n

When the recurring parent uses materialized occurrence notes, this endpoint completes the matching occurrence note if one exists. If the parent is set to Create next after completion and no matching occurrence note exists yet, TaskNotes creates and completes that occurrence note instead of only recording a virtual complete_instances entry.

\n

POST /api/tasks/:id/materialize-occurrence#

\n

Create or return a materialized occurrence note for a recurring task date. This endpoint is idempotent for the same parent and date.

\n

Request body:

\n
    \n
  • Required date (ISO date string, for example 2026-06-01)
  • \n
\n

POST /api/tasks/query#

\n

Advanced filtering.

\n

Request body is a FilterQuery object. FilterQuery is still the supported advanced query shape for the HTTP API.

\n

The root object is a group with:

\n
    \n
  • type: "group"
  • \n
  • id
  • \n
  • conjunction: "and" | "or"
  • \n
  • children (conditions or groups)
  • \n
\n

Optional top-level query options:

\n
    \n
  • sortKey, sortDirection
  • \n
  • groupKey, subgroupKey
  • \n
\n

Example:

\n
{\n  "type": "group",\n  "id": "root",\n  "conjunction": "and",\n  "children": [\n    {\n      "type": "condition",\n      "id": "c1",\n      "property": "status",\n      "operator": "is",\n      "value": "open"\n    }\n  ],\n  "sortKey": "due",\n  "sortDirection": "asc"\n}\n

Filter tasks by context:

\n
{\n  "type": "group",\n  "id": "root",\n  "conjunction": "and",\n  "children": [\n    {\n      "type": "condition",\n      "id": "context",\n      "property": "contexts",\n      "operator": "contains",\n      "value": "@office"\n    }\n  ],\n  "sortKey": "due",\n  "sortDirection": "asc"\n}\n

Filter active, unarchived tasks, similar to the default available-task view:

\n
{\n  "type": "group",\n  "id": "root",\n  "conjunction": "and",\n  "children": [\n    {\n      "type": "condition",\n      "id": "not-archived",\n      "property": "archived",\n      "operator": "is-not-checked"\n    },\n    {\n      "type": "condition",\n      "id": "not-completed",\n      "property": "status.isCompleted",\n      "operator": "is-not-checked"\n    }\n  ],\n  "sortKey": "due",\n  "sortDirection": "asc",\n  "groupKey": "none"\n}\n

Condition fields:

\n
    \n
  • type: "condition"
  • \n
  • id: any stable string for your client
  • \n
  • property: a task property, such as title, status, priority, tags, contexts, projects, blockedBy, blocking, due, scheduled, completedDate, dateCreated, dateModified, archived, hasSubtasks, dependencies.isBlocked, dependencies.isBlocking, timeEstimate, recurrence, or status.isCompleted
  • \n
  • operator: one of is, is-not, contains, does-not-contain, is-before, is-after, is-on-or-before, is-on-or-after, is-empty, is-not-empty, is-checked, is-not-checked, is-greater-than, is-less-than, is-greater-than-or-equal, or is-less-than-or-equal
  • \n
  • value: required for comparison operators, omitted for empty/checked operators
  • \n
\n

For user-defined fields, use property: "user:<fieldId>".

\n

Response:

\n
    \n
  • data.tasks
  • \n
  • data.total
  • \n
  • data.filtered
  • \n
  • data.vault
  • \n
\n

GET /api/filter-options#

\n

Returns filter options for UI builders.

\n

GET /api/stats#

\n

Returns summary counts:

\n
    \n
  • total, completed, active, overdue, archived, withTimeTracking
  • \n
\n

Bases#

\n

POST /api/bases/default-files/update#

\n

Overwrite the configured default TaskNotes .base files with templates generated from the current TaskNotes settings. This is the same write operation as Settings -> TaskNotes -> Views & base files -> Update files and replaces manual edits in those configured default files.

\n
curl -X POST http://localhost:8080/api/bases/default-files/update\n

Response fields:

\n
    \n
  • data.created: default files created because they were missing
  • \n
  • data.updated: existing default files overwritten with current templates
  • \n
  • data.skipped: configured default files skipped
  • \n
\n

Time Tracking#

\n

POST /api/tasks/:id/time/start#

\n

Starts a new active time entry for that task.

\n

POST /api/tasks/:id/time/start-with-description#

\n

Starts time tracking and writes description on the new active entry.

\n

Request body:

\n
{\n  "description": "Implementation"\n}\n

POST /api/tasks/:id/time/stop#

\n

Stops active time entry for that task.

\n

GET /api/tasks/:id/time#

\n

Returns per-task time summary and entries.

\n

GET /api/time/active#

\n

Returns currently active sessions across tasks.

\n

Important:

\n
    \n
  • Multiple active sessions can exist across different tasks.
  • \n
\n

GET /api/time/summary#

\n

Returns aggregate time summary.

\n

Query params:

\n
    \n
  • period (for example today, week, month, all)
  • \n
  • from (ISO date)
  • \n
  • to (ISO date)
  • \n
\n

Example:

\n
curl "http://localhost:8080/api/time/summary?period=week"\n

Pomodoro#

\n

POST /api/pomodoro/start#

\n

Starts a session.

\n

Optional request fields:

\n
    \n
  • taskId (URL path of task)
  • \n
  • duration (number)
  • \n
\n

POST /api/pomodoro/stop#

\n

Stops and resets current session.

\n

POST /api/pomodoro/pause#

\n

Pauses running session.

\n

POST /api/pomodoro/resume#

\n

Resumes paused session.

\n

GET /api/pomodoro/status#

\n

Returns current state plus computed totals (totalPomodoros, currentStreak, totalMinutesToday).

\n

GET /api/pomodoro/sessions#

\n

Returns history.

\n

Query params:

\n
    \n
  • limit
  • \n
  • date (YYYY-MM-DD)
  • \n
\n

GET /api/pomodoro/stats#

\n

Returns stats for today or provided date.

\n

Query params:

\n
    \n
  • date (YYYY-MM-DD)
  • \n
\n

Calendars#

\n

GET /api/calendars#

\n

Returns provider connectivity overview and subscription counts.

\n

GET /api/calendars/google#

\n

Returns Google provider details.

\n
    \n
  • If disconnected, returns { "connected": false }.
  • \n
\n

GET /api/calendars/microsoft#

\n

Returns Microsoft provider details.

\n
    \n
  • If disconnected, returns { "connected": false }.
  • \n
\n

GET /api/calendars/subscriptions#

\n

Returns ICS subscriptions with runtime fields such as lastFetched and lastError.

\n

GET /api/calendars/events#

\n

Returns merged event list from connected providers and ICS subscriptions.

\n

Query params:

\n
    \n
  • start (ISO date/datetime)
  • \n
  • end (ISO date/datetime)
  • \n
\n

Response includes:

\n
    \n
  • events
  • \n
  • total
  • \n
  • sources (counts by provider)
  • \n
\n

Webhooks#

\n

POST /api/webhooks#

\n

Registers webhook.

\n

Required fields:

\n
    \n
  • url
  • \n
  • events (non-empty array)
  • \n
\n

Optional fields:

\n
    \n
  • id
  • \n
  • secret
  • \n
  • active
  • \n
  • transformFile
  • \n
  • corsHeaders
  • \n
\n

GET /api/webhooks#

\n

Lists registered webhooks. Stored secrets are not returned.

\n

DELETE /api/webhooks/:id#

\n

Deletes webhook.

\n

GET /api/webhooks/deliveries#

\n

Returns last 100 delivery records.

\n

OpenAPI Docs#

\n

GET /api/docs#

\n

Returns OpenAPI JSON generated from registered controllers.

\n

GET /api/docs/ui#

\n

Returns Swagger UI.

\n

Errors#

\n

Common status codes:

\n
    \n
  • 400 invalid request or invalid state
  • \n
  • 401 missing/invalid bearer token (when auth token is configured)
  • \n
  • 404 missing task/webhook/resource
  • \n
  • 500 internal error
  • \n
\n

Security Notes#

\n

Current behavior:

\n
    \n
  • CORS allows all origins (*).
  • \n
  • Transport is HTTP only (no TLS).
  • \n
  • Node server is started with server.listen(port) and does not explicitly bind to 127.0.0.1.
  • \n
\n

Practical guidance:

\n
    \n
  • Set an auth token.
  • \n
  • Treat API port as sensitive and keep it firewalled.
  • \n
  • If you expose this port outside localhost, route through a trusted reverse proxy and TLS.
  • \n
\n

Troubleshooting#

\n

API unavailable#

\n
    \n
  1. Confirm API is enabled in settings.
  2. \n
  3. Confirm Obsidian is running.
  4. \n
  5. Confirm selected port is free.
  6. \n
  7. Reload plugin or restart Obsidian after changing API enable/port.
  8. \n
\n

401 Authentication required#

\n
    \n
  1. Check token value.
  2. \n
  3. Check Bearer prefix.
  4. \n
  5. Remove whitespace around token.
  6. \n
\n

Unexpected task list behavior#

\n

If you pass filters to GET /api/tasks, the endpoint returns 400 by design. Use POST /api/tasks/query.

\n","text":"The TaskNotes HTTP API provides local HTTP access to tasks, time tracking, pomodoro, calendars, webhooks, and NLP parsing. Availability# Desktop only Disabled by default Started when Obsidian starts and TaskNotes API is enabled Bound to loopback (127.0.0.1) only, not the local network Browser CORS requests are allowed only from loopback origins such as localhost, 127.0.0.1, and [::1] Not available on mobile Enable it in Settings -> TaskNotes -> Integrations -> HTTP API. Base URL# http://localhost:{PORT} Default port is 8080. Authentication# Authentication is optional. If apiAuthToken is empty, all API requests are accepted. If apiAuthToken is set, send Authorization: Bearer . Set a token for any workflow where local browser pages, scripts, or other desktop apps are not fully trusted. Example: curl -H \"Authorization: Bearer YOUR_TOKEN\" http://localhost:8080/api/health Response Format# Success: { \"success\": true, \"data\": {} } Error: { \"success\": false, \"error\": \"Error message\" } Endpoint Index# System# GET /api/health GET /api/docs GET /api/docs/ui POST /api/nlp/parse POST /api/nlp/create Tasks# GET /api/tasks POST /api/tasks GET /api/tasks/:id PUT /api/tasks/:id DELETE /api/tasks/:id POST /api/tasks/:id/toggle-status POST /api/tasks/:id/archive POST /api/tasks/:id/complete-instance POST /api/tasks/:id/materialize-occurrence POST /api/tasks/query GET /api/filter-options GET /api/stats Bases# POST /api/bases/default-files/update Time Tracking# POST /api/tasks/:id/time/start POST /api/tasks/:id/time/start-with-description POST /api/tasks/:id/time/stop GET /api/tasks/:id/time GET /api/time/active GET /api/time/summary Pomodoro# POST /api/pomodoro/start POST /api/pomodoro/stop POST /api/pomodoro/pause POST /api/pomodoro/resume GET /api/pomodoro/status GET /api/pomodoro/sessions GET /api/pomodoro/stats Calendars# GET /api/calendars GET /api/calendars/google GET /api/calendars/microsoft GET /api/calendars/subscriptions GET /api/calendars/events Webhooks# POST /api/webhooks GET /api/webhooks DELETE /api/webhooks/:id GET /api/webhooks/deliveries See docs/webhooks.md for event and transform details. Route Details# Health# GET /api/health# Returns service state plus vault metadata. curl http://localhost:8080/api/health Tasks# GET /api/tasks# Basic task listing with pagination only. Query params: limit (default 50, max 200) offset (default 0) Important: Filtering params such as status, priority, tag, project, context, due_before, due_after, overdue, completed, archived, and sort are rejected on this endpoint with HTTP 400. Use POST /api/tasks/query for filtering. Example: curl \"http://localhost:8080/api/tasks?limit=25&offset=0\" Response fields: data.tasks data.pagination with total, offset, limit, hasMore data.vault data.note Task objects include configured TaskNotes user fields in customProperties, keyed by their frontmatter property key. POST /api/tasks# Create one task. Required: title Common optional fields: details, status, priority, due, scheduled tags, contexts, projects recurrence, recurrence_anchor, timeEstimate, reminders blockedBy blockedBy accepts an array of dependency objects: uid: link or identifier for the blocking task, such as [[Project setup]] reltype: one of FINISHTOSTART, FINISHTOFINISH, STARTTOSTART, or STARTTOFINISH gap: optional ISO 8601 duration, such as P1D blocking is a read-only reverse relationship in API responses. To make a task block existing tasks, update those existing tasks' blockedBy fields. curl -X POST http://localhost:8080/api/tasks \\ -H \"Content-Type: application/json\" \\ -d '{\"title\":\"Review docs\",\"priority\":\"high\",\"blockedBy\":[{\"uid\":\"[[Draft docs]]\",\"reltype\":\"FINISHTOSTART\"}]}' Returns HTTP 201 with created task data. GET /api/tasks/:id# Get one task by path id. :id must be URL-encoded task path. Single-task reads include the task body in details. Configured TaskNotes user fields are returned in customProperties, keyed by their frontmatter property key. curl \"http://localhost:8080/api/tasks/TaskNotes%2FTasks%2FReview%20docs.md\" PUT /api/tasks/:id# Update task with partial payload. Configured TaskNotes user fields can be updated either by their frontmatter property key or via customProperties. curl -X PUT \"http://localhost:8080/api/tasks/TaskNotes%2FTasks%2FReview%20docs.md\" \\ -H \"Content-Type: application/json\" \\ -d '{\"status\":\"in-progress\"}' DELETE /api/tasks/:id# Delete task file. POST /api/tasks/:id/toggle-status# Toggle task status via configured workflow. POST /api/tasks/:id/archive# Toggle archive state. POST /api/tasks/:id/complete-instance# Complete recurring instance. Request body: Optional date (ISO string). If omitted, uses current date context. When the recurring parent uses materialized occurrence notes, this endpoint completes the matching occurrence note if one exists. If the parent is set to Create next after completion and no matching occurrence note exists yet, TaskNotes creates and completes that occurrence note instead of only recording a virtual complete_instances entry. POST /api/tasks/:id/materialize-occurrence# Create or return a materialized occurrence note for a recurring task date. This endpoint is idempotent for the same parent and date. Request body: Required date (ISO date string, for example 2026-06-01) POST /api/tasks/query# Advanced filtering. Request body is a FilterQuery object. FilterQuery is still the supported advanced query shape for the HTTP API. The root object is a group with: type: \"group\" id conjunction: \"and\" | \"or\" children (conditions or groups) Optional top-level query options: sortKey, sortDirection groupKey, subgroupKey Example: { \"type\": \"group\", \"id\": \"root\", \"conjunction\": \"and\", \"children\": [ { \"type\": \"condition\", \"id\": \"c1\", \"property\": \"status\", \"operator\": \"is\", \"value\": \"open\" } ], \"sortKey\": \"due\", \"sortDirection\": \"asc\" } Filter tasks by context: { \"type\": \"group\", \"id\": \"root\", \"conjunction\": \"and\", \"children\": [ { \"type\": \"condition\", \"id\": \"context\", \"property\": \"contexts\", \"operator\": \"contains\", \"value\": \"@office\" } ], \"sortKey\": \"due\", \"sortDirection\": \"asc\" } Filter active, unarchived tasks, similar to the default available-task view: { \"type\": \"group\", \"id\": \"root\", \"conjunction\": \"and\", \"children\": [ { \"type\": \"condition\", \"id\": \"not-archived\", \"property\": \"archived\", \"operator\": \"is-not-checked\" }, { \"type\": \"condition\", \"id\": \"not-completed\", \"property\": \"status.isCompleted\", \"operator\": \"is-not-checked\" } ], \"sortKey\": \"due\", \"sortDirection\": \"asc\", \"groupKey\": \"none\" } Condition fields: type: \"condition\" id: any stable string for your client property: a task property, such as title, status, priority, tags, contexts, projects, blockedBy, blocking, due, scheduled, completedDate, dateCreated, dateModified, archived, hasSubtasks, dependencies.isBlocked, dependencies.isBlocking, timeEstimate, recurrence, or status.isCompleted operator: one of is, is-not, contains, does-not-contain, is-before, is-after, is-on-or-before, is-on-or-after, is-empty, is-not-empty, is-checked, is-not-checked, is-greater-than, is-less-than, is-greater-than-or-equal, or is-less-than-or-equal value: required for comparison operators, omitted for empty/checked operators For user-defined fields, use property: \"user:\". Response: data.tasks data.total data.filtered data.vault GET /api/filter-options# Returns filter options for UI builders. GET /api/stats# Returns summary counts: total, completed, active, overdue, archived, withTimeTracking Bases# POST /api/bases/default-files/update# Overwrite the configured default TaskNotes .base files with templates generated from the current TaskNotes settings. This is the same write operation as Settings -> TaskNotes -> Views & base files -> Update files and replaces manual edits in those configured default files. curl -X POST http://localhost:8080/api/bases/default-files/update Response fields: data.created: default files created because they were missing data.updated: existing default files overwritten with current templates data.skipped: configured default files skipped Time Tracking# POST /api/tasks/:id/time/start# Starts a new active time entry for that task. POST /api/tasks/:id/time/start-with-description# Starts time tracking and writes description on the new active entry. Request body: { \"description\": \"Implementation\" } POST /api/tasks/:id/time/stop# Stops active time entry for that task. GET /api/tasks/:id/time# Returns per-task time summary and entries. GET /api/time/active# Returns currently active sessions across tasks. Important: Multiple active sessions can exist across different tasks. GET /api/time/summary# Returns aggregate time summary. Query params: period (for example today, week, month, all) from (ISO date) to (ISO date) Example: curl \"http://localhost:8080/api/time/summary?period=week\" Pomodoro# POST /api/pomodoro/start# Starts a session. Optional request fields: taskId (URL path of task) duration (number) POST /api/pomodoro/stop# Stops and resets current session. POST /api/pomodoro/pause# Pauses running session. POST /api/pomodoro/resume# Resumes paused session. GET /api/pomodoro/status# Returns current state plus computed totals (totalPomodoros, currentStreak, totalMinutesToday). GET /api/pomodoro/sessions# Returns history. Query params: limit date (YYYY-MM-DD) GET /api/pomodoro/stats# Returns stats for today or provided date. Query params: date (YYYY-MM-DD) Calendars# GET /api/calendars# Returns provider connectivity overview and subscription counts. GET /api/calendars/google# Returns Google provider details. If disconnected, returns { \"connected\": false }. GET /api/calendars/microsoft# Returns Microsoft provider details. If disconnected, returns { \"connected\": false }. GET /api/calendars/subscriptions# Returns ICS subscriptions with runtime fields such as lastFetched and lastError. GET /api/calendars/events# Returns merged event list from connected providers and ICS subscriptions. Query params: start (ISO date/datetime) end (ISO date/datetime) Response includes: events total sources (counts by provider) Webhooks# POST /api/webhooks# Registers webhook. Required fields: url events (non-empty array) Optional fields: id secret active transformFile corsHeaders GET /api/webhooks# Lists registered webhooks. Stored secrets are not returned. DELETE /api/webhooks/:id# Deletes webhook. GET /api/webhooks/deliveries# Returns last 100 delivery records. OpenAPI Docs# GET /api/docs# Returns OpenAPI JSON generated from registered controllers. GET /api/docs/ui# Returns Swagger UI. Errors# Common status codes: 400 invalid request or invalid state 401 missing/invalid bearer token (when auth token is configured) 404 missing task/webhook/resource 500 internal error Security Notes# Current behavior: CORS allows all origins (*). Transport is HTTP only (no TLS). Node server is started with server.listen(port) and does not explicitly bind to 127.0.0.1. Practical guidance: Set an auth token. Treat API port as sensitive and keep it firewalled. If you expose this port outside localhost, route through a trusted reverse proxy and TLS. Troubleshooting# API unavailable# Confirm API is enabled in settings. Confirm Obsidian is running. Confirm selected port is free. Reload plugin or restart Obsidian after changing API enable/port. 401 Authentication required# Check token value. Check Bearer prefix. Remove whitespace around token. Unexpected task list behavior# If you pass filters to GET /api/tasks, the endpoint returns 400 by design. Use POST /api/tasks/query."},{"route":"/obsidian/javascript-api/","title":"TaskNotes JavaScript Runtime API","description":"TaskNotes exposes an in-process runtime API on the loaded Obsidian plugin instance:","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/javascript-api.md","namespace":"obsidian","relativePath":"javascript-api.md","raw":"# TaskNotes JavaScript Runtime API\n\nTaskNotes exposes an in-process runtime API on the loaded Obsidian plugin instance:\n\n```javascript\nconst tasknotes = app.plugins.plugins.tasknotes;\nconst api = tasknotes?.api;\n```\n\nThis API is for Obsidian companion plugins and in-vault scripting tools such as Templater, QuickAdd, and MetaBind. It runs inside Obsidian and uses the same TaskNotes services, settings, cache, and vault permissions as the plugin UI.\n\nThis is separate from the [HTTP API](HTTP_API.md). The runtime API does not start a server, does not use bearer-token authentication, and is only available inside the running Obsidian app.\n\nFor user-facing extensions built on this API, see [Companion Plugins](companion-plugins.md). For a concrete automation companion plugin, see [TaskNotes Workflows](companion-plugins/tasknotes-workflows.md).\n\nThe TypeScript contract lives in `src/api/runtime-api.ts`. It is intentionally small and type-focused so it can later become a standalone `@tasknotes/runtime-api` package for companion plugins.\n\n## Version and Capabilities\n\nCheck the API version and capabilities before using methods that may not exist in older TaskNotes versions:\n\n```javascript\nconst tasknotes = app.plugins.plugins.tasknotes;\nconst api = tasknotes?.api;\n\nif (!api || api.apiVersion !== 1 || !api.hasCapability(\"tasks.write\")) {\n\tthrow new Error(\"This workflow requires TaskNotes runtime API v1 task writes\");\n}\n```\n\nCurrent capabilities:\n\n- `model.read`\n- `model.validate`\n- `catalog.read`\n- `extensions.read`\n- `extensions.register`\n- `tasks.read`\n- `tasks.write`\n- `tasks.delete`\n- `tasks.move`\n- `tasks.events`\n- `relationships.read`\n- `events.list`\n- `time.read`\n- `time.write`\n- `time.summary`\n- `pomodoro.read`\n- `pomodoro.write`\n- `pomodoro.events`\n- `recurring.write`\n- `recurring.materialize`\n- `recurring.events`\n- `settings.snapshot`\n- `bases.write`\n- `nlp.parse`\n- `ui.task-menu`\n- `query.tasks`\n- `query.validate`\n- `query.explain`\n- `query.filter-options`\n- `stats.tasks`\n- `system.health`\n- `lifecycle.events`\n- `errors.typed`\n\n## Namespaces\n\nPrefer the namespaced API for new code:\n\n```javascript\nawait api.tasks.update(\"Tasks/example.md\", { status: \"active\" });\nconst subtasks = await api.relationships.subtasks(\"Tasks/example.md\");\nawait api.time.start(\"Tasks/example.md\", { description: \"Deep work\" });\nawait api.pomodoro.start({ taskPath: \"Tasks/example.md\", duration: 25 });\n```\n\nThe older flat methods, such as `api.getTask(path)` and `api.parseNaturalLanguage(text)`, remain available as compatibility aliases.\n\n## Extension Registry\n\nCompanion plugins can publish their own runtime API namespace through `api.extensions`. This is the preferred way to extend TaskNotes without adding arbitrary properties to the core API object.\n\n```javascript\nconst tasknotes = this.app.plugins.getPlugin(\"tasknotes\");\nconst api = tasknotes?.api;\n\nif (!api?.hasCapability(\"extensions.register\")) {\n\treturn;\n}\n\nconst handle = api.extensions.register({\n\tid: this.manifest.id,\n\tnamespace: \"tasknotes-workflows\",\n\tdisplayName: \"TaskNotes Workflows\",\n\tversion: this.manifest.version,\n\tcapabilities: [\"tasknotes-workflows.run\", \"tasknotes-workflows.events\"],\n\tapi: {\n\t\trunWorkflow: async (workflowId, input) => {\n\t\t\t// companion plugin implementation\n\t\t},\n\t},\n});\n\nthis.register(() => handle.unregister());\n```\n\nOther plugins can discover and consume extension namespaces:\n\n```javascript\nconst workflows = api.extensions.get(\"tasknotes-workflows\");\n\nif (api.hasCapability(\"tasknotes-workflows.run\")) {\n\tawait workflows.runWorkflow(\"start-timer-on-active\", { taskPath: \"Tasks/example.md\" });\n}\n```\n\nExtension namespaces are normalized to lowercase and may use letters, numbers, dots, underscores, or dashes. Capability names are also normalized to lowercase. Prefix extension capabilities with the extension namespace to avoid collisions.\n\n## Companion Plugin Access\n\nCompanion plugins can read the TaskNotes plugin instance from Obsidian's plugin registry:\n\n```javascript\nconst tasknotes = this.app.plugins.getPlugin(\"tasknotes\");\nconst api = tasknotes?.api;\n\nif (!api?.hasCapability(\"tasks.events\")) {\n\treturn;\n}\n\nthis.registerEvent(\n\tapi.events.on(\"task.status.changed\", (event) => {\n\t\tconsole.log(event.taskPath, event.changes.status);\n\t})\n);\n```\n\nIf TaskNotes is disabled or has not loaded yet, `api` will be unavailable. Companion plugins should handle that case and retry after plugin load if needed.\n\n## TypeScript\n\nUse the exported runtime contract for type safety:\n\n```typescript\nimport type { TaskNotesRuntimeApiV1 } from \"tasknotes/src/api/runtime-api\";\n\ntype TaskNotesPluginInstance = {\n\tapi?: TaskNotesRuntimeApiV1;\n};\n\nconst tasknotes = app.plugins.getPlugin(\"tasknotes\") as TaskNotesPluginInstance | null;\nconst api = tasknotes?.api;\n\nif (api?.apiVersion === 1 && api.hasCapability(\"tasks.write\")) {\n\tawait api.tasks.setStatus(\"Tasks/example.md\", \"active\");\n}\n```\n\nTaskNotes is still loaded by Obsidian at runtime. The TypeScript contract only gives companion plugins compile-time checking and autocomplete.\n\n## Model\n\nThe runtime API exposes a small model namespace backed by `@tasknotes/model`:\n\n```javascript\nconst info = api.model.info();\nconst config = api.model.config();\nconst validation = api.model.validateTask(task);\n```\n\n| Method | Description |\n| -------------------------------- | ------------------------------------------------------------------------------------------------ |\n| `api.model.info()` | Returns the model package name, TaskNotes spec version, and runtime API version. |\n| `api.model.config()` | Returns a resolved, Obsidian-free model configuration snapshot derived from TaskNotes settings. |\n| `api.model.validateTask(task)` | Validates a partial or complete task against the shared model schema and TaskNotes status rules. |\n| `api.model.validatePatch(patch)` | Validates a task patch before passing it to a runtime task mutation. |\n\n## Catalog\n\nUse `api.catalog` to build companion-plugin editors without hardcoding TaskNotes values:\n\n```javascript\nconst statuses = api.catalog.statuses();\nconst writableFields = api.catalog.writableFields();\nconst operators = api.catalog.filterOperators();\n```\n\n| Method | Description |\n| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------- |\n| `api.catalog.statuses()` | Returns configured TaskNotes status definitions. |\n| `api.catalog.priorities()` | Returns configured TaskNotes priority definitions. |\n| `api.catalog.userFields()` | Returns configured user-defined field mappings. |\n| `api.catalog.fields()` | Returns core, computed, and user field metadata with value type, writability, and frontmatter key when available. |\n| `api.catalog.writableFields()` | Returns only fields that runtime task mutations may write. |\n| `api.catalog.filterProperties()` | Returns canonical query fields, aliases, value types, and supported operators. |\n| `api.catalog.filterOperators()` | Returns canonical query operators, labels, value requirements, and accepted aliases. |\n| `api.catalog.relationships()` | Returns relationship categories supported by `api.relationships`. |\n| `api.catalog.dependencyRelTypes()` | Returns dependency relationship types accepted by `api.tasks.addDependency`. |\n| `api.catalog.events()` | Returns the same runtime event catalogue as `api.events.list()`. |\n\n## Tasks\n\nAll paths are vault-relative Markdown file paths.\n\n| Method | Description |\n| --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |\n| `api.tasks.get(path)` | Returns a task by path, or `null` when no task is cached at that path. |\n| `api.tasks.list(query?)` | Returns all tasks, or tasks matching a runtime task query. Prefer `api.query.tasks()` when count and grouping metadata matters. |\n| `api.tasks.create(taskData, context?)` | Creates a task using the normal TaskNotes creation service. |\n| `api.tasks.update(path, patch, context?)` | Updates one or more task fields using the normal TaskNotes update service. |\n| `api.tasks.delete(path, context?)` | Deletes the task file through TaskNotes' delete service. |\n| `api.tasks.complete(path, options?, context?)` | Marks a task complete. |\n| `api.tasks.uncomplete(path, options?, context?)` | Moves a completed task back to a non-completed status. |\n| `api.tasks.setStatus(path, status, context?)` | Sets task status. |\n| `api.tasks.setPriority(path, priority, context?)` | Sets task priority. |\n| `api.tasks.setDue(path, date, context?)` / `clearDue(path, context?)` | Sets or clears due date. |\n| `api.tasks.setScheduled(path, date, context?)` / `clearScheduled(path, context?)` | Sets or clears scheduled date. |\n| `api.tasks.archive(path, archived, context?)` | Archives or unarchives a task, including archive-folder movement when configured. |\n| `api.tasks.move(path, targetFolder, context?)` | Moves the task note and refuses to overwrite an existing file. |\n| `api.tasks.addTag/removeTag` | Mutates task tags. |\n| `api.tasks.addProject/removeProject` | Mutates project links. |\n| `api.tasks.addContext/removeContext` | Mutates contexts. |\n| `api.tasks.setReminders/addReminder/removeReminder` | Mutates reminders. |\n| `api.tasks.addDependency/removeDependency` | Mutates blocking dependencies stored in `blockedBy`. |\n\nExample:\n\n```javascript\nconst task = await api.tasks.create(\n\t{\n\t\ttitle: \"Review automation design\",\n\t\tstatus: \"open\",\n\t\tpriority: \"normal\",\n\t\tscheduled: \"2026-06-01\",\n\t\ttags: [\"tasknotes\"],\n\t},\n\t{\n\t\tsource: \"my-companion-plugin\",\n\t\tcorrelationId: crypto.randomUUID(),\n\t\treason: \"manual workflow command\",\n\t}\n);\n\nawait api.tasks.complete(task.path);\n```\n\n## Relationships\n\nRelationship methods resolve TaskNotes' project-as-parent links and `blockedBy` dependencies into task records where possible.\n\n| Method | Description |\n| -------------------------------------- | -------------------------------------------------------------------------- |\n| `api.relationships.parents(path)` | Returns parent tasks referenced from the task's projects. |\n| `api.relationships.subtasks(path)` | Returns tasks that reference this task as a project. |\n| `api.relationships.dependencies(path)` | Returns `blockedBy` dependencies with resolved task data when available. |\n| `api.relationships.blocking(path)` | Returns tasks that are blocked by this task. |\n| `api.relationships.all(path)` | Returns the task plus parents, subtasks, dependencies, and blocking tasks. |\n\nExample:\n\n```javascript\nconst relationships = await api.relationships.all(\"Tasks/example.md\");\n\nfor (const subtask of relationships.subtasks) {\n\tawait api.tasks.setPriority(subtask.path, relationships.task.priority);\n}\n```\n\n## Time Tracking\n\n| Method | Description |\n| -------------------------------------------------- | -------------------------------------------------------------------- |\n| `api.time.start(path, options?, context?)` | Starts time tracking and returns the updated task. |\n| `api.time.stop(path, context?)` | Stops the active time entry and returns the updated task. |\n| `api.time.active()` | Returns active time entries with task, path, entry, and entry index. |\n| `api.time.summary(options?)` | Returns aggregate time totals, top tasks, projects, and tags. |\n| `api.time.task(path)` | Returns one task's time summary and normalized time entries. |\n| `api.time.append(path, entry, context?)` | Appends a time entry. |\n| `api.time.deleteEntry(path, entryIndex, context?)` | Deletes a time entry through TaskNotes' service. |\n\n## Query, Stats, And System\n\nThe query, stats, and system namespaces expose HTTP/MCP-style support data without requiring companion plugins to reach into TaskNotes internals. Runtime queries use a stable DTO rather than TaskNotes' internal view state.\n\n```javascript\nconst result = await api.query.tasks({\n\twhere: {\n\t\tall: [\n\t\t\t{ field: \"task.status\", op: \"eq\", value: \"active\" },\n\t\t\t{ field: \"task.due\", op: \"lte\", value: { fn: \"today\" } },\n\t\t],\n\t},\n\tsort: [{ field: \"task.due\", direction: \"asc\" }],\n\tgroup: [{ field: \"task.status\" }],\n\tlimit: 25,\n\tscope: {\n\t\tincludeArchived: false,\n\t\tfolders: [\"Tasks\"],\n\t},\n});\n```\n\nRuntime query fields are canonical IDs such as `task.status`, `task.priority`, `task.due`, `task.projects`, `task.isBlocked`, `file.path`, and `user.`. `api.catalog.filterProperties()` returns the complete queryable field catalog, including aliases such as `status` and `user:`.\n\nCanonical operators are `eq`, `ne`, `contains`, `notContains`, `in`, `notIn`, `exists`, `missing`, `lt`, `lte`, `gt`, `gte`, `isTrue`, and `isFalse`. Legacy operator aliases such as `is`, `is-not`, `is-on-or-before`, and `is-not-empty` are accepted and normalized.\n\n`api.query.tasks()` returns explicit count semantics:\n\n- `total`: tasks in scope before filtering\n- `matched`: tasks matching `where` before `offset` and `limit`\n- `returned`: tasks returned after `offset` and `limit`\n- `tasks`: returned task records\n- `groups`: optional group details with task paths\n- `query`: the normalized canonical query\n- `warnings`: non-fatal normalization notes\n\n| Method | Description |\n| ---------------------------- | -------------------------------------------------------------------------------------------------- |\n| `api.query.tasks(query?)` | Validates, normalizes, and executes a runtime task query. |\n| `api.query.validate(query)` | Validates a query without executing it. |\n| `api.query.normalize(query)` | Returns the canonical normalized query, or throws a typed `invalid_input` API error. |\n| `api.query.explain(query)` | Returns validation, normalized query, count, grouping, and applied sort/limit details for dry run. |\n| `api.query.filterOptions()` | Returns available statuses, priorities, contexts, projects, tags, folders, and user properties. |\n| `api.stats.tasks(query?)` | Returns task counts, status/priority counts, archive/completion counts, and time-tracking totals. |\n| `api.system.health()` | Returns runtime status, API version, capabilities, vault identity, and task count. |\n\nTaskNotes compiles this DTO into its internal filter engine. Companion plugins should treat the runtime DTO and the catalog metadata as the public query contract.\n\n## Task Menu UI\n\nCompanion plugins can reuse the standard TaskNotes task context menu through `api.ui.taskMenu`. This keeps task actions, relationship actions, recurrence controls, and future menu changes behind the runtime API boundary instead of requiring companion plugins to import TaskNotes internals.\n\nThis surface is only available inside Obsidian. It is not exposed through the HTTP API.\n\n| Method | Description |\n| ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |\n| `api.ui.taskMenu.show({ taskPath, event, targetDate?, onUpdate?, promoteOccurrenceControls? })` | Shows the standard TaskNotes task context menu at a mouse event. |\n| `api.ui.taskMenu.showAtElement({ taskPath, element, targetDate?, onUpdate?, ... })` | Shows the standard TaskNotes task context menu anchored to an element. |\n| `api.ui.taskMenu.populate(menu, { taskPath, targetDate?, onUpdate?, ... })` | Adds the standard TaskNotes task context menu items to an existing Obsidian `Menu` so plugins can extend it. |\n\nAll methods resolve `taskPath` through the TaskNotes task cache and throw a typed `task_not_found` error when the path does not point to a cached task.\n\n`targetDate` defaults to today and is used by date-sensitive recurring-task menu items. `onUpdate` is called after menu actions mutate the task; when omitted, TaskNotes refreshes its own task views. `promoteOccurrenceControls` moves recurring-instance controls to the top of the menu.\n\nExample context menu:\n\n```javascript\nnodeEl.addEventListener(\"contextmenu\", async (event) => {\n\tevent.preventDefault();\n\n\tawait api.ui.taskMenu.show({\n\t\ttaskPath: task.path,\n\t\tevent,\n\t\tonUpdate: () => refreshGraph(),\n\t});\n});\n```\n\nExample composed menu:\n\n```javascript\nconst menu = new Menu();\n\nawait api.ui.taskMenu.populate(menu, {\n\ttaskPath: task.path,\n\tonUpdate: () => refreshGraph(),\n});\n\nmenu.addSeparator();\nmenu.addItem((item) =>\n\titem\n\t\t.setTitle(\"Focus in graph\")\n\t\t.setIcon(\"network\")\n\t\t.onClick(() => selectGraphNode(task.path))\n);\n\nmenu.showAtMouseEvent(event);\n```\n\n## Pomodoro\n\n| Method | Description |\n| ----------------------------------------------- | --------------------------------------------- |\n| `api.pomodoro.status()` | Returns current Pomodoro state. |\n| `api.pomodoro.start(options?, context?)` | Starts a Pomodoro session. |\n| `api.pomodoro.stop(context?)` | Stops and resets the active Pomodoro session. |\n| `api.pomodoro.pause(context?)` | Pauses the current session. |\n| `api.pomodoro.resume(context?)` | Resumes a paused session. |\n| `api.pomodoro.assignTask(pathOrNull, context?)` | Assigns or clears the current session task. |\n| `api.pomodoro.sessions(options?)` | Returns Pomodoro session history. |\n| `api.pomodoro.stats(date?)` | Returns Pomodoro stats for a date or today. |\n\n## Recurring Tasks\n\n| Method | Description |\n| ------------------------------------------------------------- | ---------------------------------------------------- |\n| `api.recurring.toggleCompleteInstance(path, date?, context?)` | Toggles completion for a recurring task instance. |\n| `api.recurring.toggleSkippedInstance(path, date?, context?)` | Toggles skipped state for a recurring task instance. |\n| `api.recurring.materializeOccurrence(path, date, context?)` | Creates or returns an occurrence note for a recurring task date. |\n\n## Natural Language Parser\n\n```javascript\nconst parsed = api.nlp.parse(\"Write draft friday 2pm #writing @desk\");\n```\n\n`api.parseNaturalLanguage(text)` remains as a compatibility alias. Parsing does not create or modify task files.\n\nSee [NLP API](nlp-api.md) for HTTP endpoint details and parser behavior.\n\n## Settings Snapshot\n\n```javascript\nconst settings = api.settings.snapshot();\nconsole.log(settings.defaultTaskStatus);\n```\n\nThe returned object is a snapshot. Mutating it does not change TaskNotes settings. `api.getSettingsSnapshot()` remains available as a compatibility alias.\n\n## Bases\n\n`api.bases.updateDefaultFiles()` regenerates the configured default TaskNotes `.base` files from the current TaskNotes settings and returns the created, updated, and skipped file paths.\n\n```javascript\nconst result = await api.bases.updateDefaultFiles();\nconsole.log(result.updated);\n```\n\n## Mutation Context\n\nMutating methods accept an optional context object:\n\n```javascript\n{\n source: \"tasknotes-workflows\",\n correlationId: \"run-2026-06-01T09-00-00\",\n reason: \"status changed to active\"\n}\n```\n\nTaskNotes attaches this context to normalized events emitted during the mutation. Use it to make workflow runs debuggable, connect multiple API calls to one run, and prevent companion plugins from responding to their own writes.\n\n## Events\n\nSubscribe with `api.events.on(eventName, handler)` and unsubscribe with `api.events.off(ref)`. In an Obsidian plugin, pass the returned `EventRef` to `this.registerEvent(ref)`.\n\nUse `api.events.list()` to discover the event catalogue for companion-plugin UIs:\n\n```javascript\nconst events = api.events.list();\n// [{ name: \"task.status.changed\", label: \"Task status changed\", category: \"task\", ... }]\n```\n\nTask events:\n\n- `task.created`\n- `task.updated`\n- `task.deleted`\n- `task.moved`\n- `task.status.changed`\n- `task.completed`\n- `task.uncompleted`\n- `task.archived`\n- `task.unarchived`\n- `task.scheduled.changed`\n- `task.due.changed`\n- `task.priority.changed`\n- `task.tags.changed`\n- `task.contexts.changed`\n- `task.projects.changed`\n- `task.reminders.changed`\n- `task.dependencies.changed`\n- `task.recurrence.changed`\n\nTime, Pomodoro, and recurring events:\n\n- `time.started`\n- `time.stopped`\n- `pomodoro.started`\n- `pomodoro.completed`\n- `pomodoro.interrupted`\n- `recurring.instance.completed`\n- `recurring.instance.skipped`\n\nSpecific events are emitted in addition to `task.updated`. For example, changing a task from `open` to `done` emits `task.updated`, `task.status.changed`, and `task.completed`.\n\nEvent payloads have this shape:\n\n```javascript\n{\n event: \"task.status.changed\",\n timestamp: \"2026-06-01T09:00:00.000Z\",\n taskPath: \"Tasks/Review automation design.md\",\n task: { /* current task */ },\n before: { /* task before change */ },\n after: { /* task after change */ },\n deletedTask: undefined,\n changes: {\n status: {\n before: \"open\",\n after: \"done\"\n }\n },\n data: undefined,\n context: {\n source: \"tasknotes-workflows\",\n correlationId: \"run-2026-06-01T09-00-00\",\n reason: \"status changed to done\"\n },\n source: \"tasknotes-workflows\",\n correlationId: \"run-2026-06-01T09-00-00\",\n reason: \"status changed to done\",\n rawEvent: \"task-updated\"\n}\n```\n\nEvents caused outside the runtime API may not include `context`, `source`, `correlationId`, or `reason`.\n\nExample automation-style listener:\n\n```javascript\nconst source = \"my-workflow-plugin\";\n\nthis.registerEvent(\n\tapi.events.on(\"task.status.changed\", async (event) => {\n\t\tif (event.source === source) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.after?.status !== \"active\") {\n\t\t\treturn;\n\t\t}\n\n\t\tawait api.time.start(event.after.path, undefined, {\n\t\t\tsource,\n\t\t\tcorrelationId: event.correlationId ?? crypto.randomUUID(),\n\t\t\treason: \"status changed to active\",\n\t\t});\n\t})\n);\n```\n\n## Lifecycle\n\nUse `api.lifecycle` to coordinate companion plugin startup, reload, and cache-sensitive UI state:\n\n```javascript\nawait api.lifecycle.ready();\n\nthis.registerEvent(\n\tapi.lifecycle.on(\"settings.changed\", () => {\n\t\trefreshCompanionCatalogs();\n\t})\n);\n```\n\nLifecycle events:\n\n- `ready`\n- `layout.ready`\n- `settings.changed`\n- `cache.changed`\n- `cache.rebuilt`\n- `extension.registered`\n- `extension.unregistered`\n- `unloading`\n\n`api.lifecycle.list()` returns labels, descriptions, and categories for these events.\n\n## Error Handling\n\nAPI methods throw `TaskNotesApiError` for invalid input or failed operations that the runtime API can classify. The error object includes:\n\n- `name`: always `TaskNotesApiError`\n- `code`: a stable machine-readable code\n- `message`: a human-readable message for logs\n- `status`: an HTTP-style status code for tools that mirror runtime calls over HTTP or MCP\n- `details`: optional structured context such as the task path, extension namespace, or invalid status\n\nCommon examples:\n\n- The task path is empty or invalid.\n- No task exists at the requested path.\n- A target move folder already contains a file with the same name.\n- `complete` is called with a status that is not configured as completed.\n\nCurrent error codes:\n\n- `invalid_input`\n- `invalid_task_path`\n- `invalid_status`\n- `task_not_found`\n- `task_file_not_found`\n- `file_already_exists`\n- `extension_invalid`\n- `extension_namespace_reserved`\n- `extension_namespace_conflict`\n- `extension_not_registered`\n- `operation_failed`\n\nUse `api.errors` when workflow engines or background listeners need consistent result objects instead of thrown exceptions:\n\n```javascript\nconst result = await api.errors.toResult(() =>\n\tapi.tasks.complete(\"Tasks/example.md\", { status: \"done\" })\n);\n\nif (!result.ok) {\n\tconsole.warn(result.error.code, result.error.details);\n\treturn;\n}\n\nconsole.log(result.value.path);\n```\n\n`api.errors.normalize(error)` converts unknown thrown values into a `TaskNotesApiError` payload. Unknown JavaScript errors use `operation_failed` with status `500`.\n","aliases":["/javascript-api/"],"toc":[{"level":2,"id":"version-and-capabilities","text":"Version and Capabilities"},{"level":2,"id":"namespaces","text":"Namespaces"},{"level":2,"id":"extension-registry","text":"Extension Registry"},{"level":2,"id":"companion-plugin-access","text":"Companion Plugin Access"},{"level":2,"id":"typescript","text":"TypeScript"},{"level":2,"id":"model","text":"Model"},{"level":2,"id":"catalog","text":"Catalog"},{"level":2,"id":"tasks","text":"Tasks"},{"level":2,"id":"relationships","text":"Relationships"},{"level":2,"id":"time-tracking","text":"Time Tracking"},{"level":2,"id":"query-stats-and-system","text":"Query, Stats, And System"},{"level":2,"id":"task-menu-ui","text":"Task Menu UI"},{"level":2,"id":"pomodoro","text":"Pomodoro"},{"level":2,"id":"recurring-tasks","text":"Recurring Tasks"},{"level":2,"id":"natural-language-parser","text":"Natural Language Parser"},{"level":2,"id":"settings-snapshot","text":"Settings Snapshot"},{"level":2,"id":"bases","text":"Bases"},{"level":2,"id":"mutation-context","text":"Mutation Context"},{"level":2,"id":"events","text":"Events"},{"level":2,"id":"lifecycle","text":"Lifecycle"},{"level":2,"id":"error-handling","text":"Error Handling"}],"html":"

TaskNotes exposes an in-process runtime API on the loaded Obsidian plugin instance:

\n
const tasknotes = app.plugins.plugins.tasknotes;\nconst api = tasknotes?.api;\n

This API is for Obsidian companion plugins and in-vault scripting tools such as Templater, QuickAdd, and MetaBind. It runs inside Obsidian and uses the same TaskNotes services, settings, cache, and vault permissions as the plugin UI.

\n

This is separate from the HTTP API. The runtime API does not start a server, does not use bearer-token authentication, and is only available inside the running Obsidian app.

\n

For user-facing extensions built on this API, see Companion Plugins. For a concrete automation companion plugin, see TaskNotes Workflows.

\n

The TypeScript contract lives in src/api/runtime-api.ts. It is intentionally small and type-focused so it can later become a standalone @tasknotes/runtime-api package for companion plugins.

\n

Version and Capabilities#

\n

Check the API version and capabilities before using methods that may not exist in older TaskNotes versions:

\n
const tasknotes = app.plugins.plugins.tasknotes;\nconst api = tasknotes?.api;\n\nif (!api || api.apiVersion !== 1 || !api.hasCapability("tasks.write")) {\n    throw new Error("This workflow requires TaskNotes runtime API v1 task writes");\n}\n

Current capabilities:

\n
    \n
  • model.read
  • \n
  • model.validate
  • \n
  • catalog.read
  • \n
  • extensions.read
  • \n
  • extensions.register
  • \n
  • tasks.read
  • \n
  • tasks.write
  • \n
  • tasks.delete
  • \n
  • tasks.move
  • \n
  • tasks.events
  • \n
  • relationships.read
  • \n
  • events.list
  • \n
  • time.read
  • \n
  • time.write
  • \n
  • time.summary
  • \n
  • pomodoro.read
  • \n
  • pomodoro.write
  • \n
  • pomodoro.events
  • \n
  • recurring.write
  • \n
  • recurring.materialize
  • \n
  • recurring.events
  • \n
  • settings.snapshot
  • \n
  • bases.write
  • \n
  • nlp.parse
  • \n
  • ui.task-menu
  • \n
  • query.tasks
  • \n
  • query.validate
  • \n
  • query.explain
  • \n
  • query.filter-options
  • \n
  • stats.tasks
  • \n
  • system.health
  • \n
  • lifecycle.events
  • \n
  • errors.typed
  • \n
\n

Namespaces#

\n

Prefer the namespaced API for new code:

\n
await api.tasks.update("Tasks/example.md", { status: "active" });\nconst subtasks = await api.relationships.subtasks("Tasks/example.md");\nawait api.time.start("Tasks/example.md", { description: "Deep work" });\nawait api.pomodoro.start({ taskPath: "Tasks/example.md", duration: 25 });\n

The older flat methods, such as api.getTask(path) and api.parseNaturalLanguage(text), remain available as compatibility aliases.

\n

Extension Registry#

\n

Companion plugins can publish their own runtime API namespace through api.extensions. This is the preferred way to extend TaskNotes without adding arbitrary properties to the core API object.

\n
const tasknotes = this.app.plugins.getPlugin("tasknotes");\nconst api = tasknotes?.api;\n\nif (!api?.hasCapability("extensions.register")) {\n    return;\n}\n\nconst handle = api.extensions.register({\n    id: this.manifest.id,\n    namespace: "tasknotes-workflows",\n    displayName: "TaskNotes Workflows",\n    version: this.manifest.version,\n    capabilities: ["tasknotes-workflows.run", "tasknotes-workflows.events"],\n    api: {\n        runWorkflow: async (workflowId, input) => {\n            // companion plugin implementation\n        },\n    },\n});\n\nthis.register(() => handle.unregister());\n

Other plugins can discover and consume extension namespaces:

\n
const workflows = api.extensions.get("tasknotes-workflows");\n\nif (api.hasCapability("tasknotes-workflows.run")) {\n    await workflows.runWorkflow("start-timer-on-active", { taskPath: "Tasks/example.md" });\n}\n

Extension namespaces are normalized to lowercase and may use letters, numbers, dots, underscores, or dashes. Capability names are also normalized to lowercase. Prefix extension capabilities with the extension namespace to avoid collisions.

\n

Companion Plugin Access#

\n

Companion plugins can read the TaskNotes plugin instance from Obsidian's plugin registry:

\n
const tasknotes = this.app.plugins.getPlugin("tasknotes");\nconst api = tasknotes?.api;\n\nif (!api?.hasCapability("tasks.events")) {\n    return;\n}\n\nthis.registerEvent(\n    api.events.on("task.status.changed", (event) => {\n        console.log(event.taskPath, event.changes.status);\n    })\n);\n

If TaskNotes is disabled or has not loaded yet, api will be unavailable. Companion plugins should handle that case and retry after plugin load if needed.

\n

TypeScript#

\n

Use the exported runtime contract for type safety:

\n
import type { TaskNotesRuntimeApiV1 } from "tasknotes/src/api/runtime-api";\n\ntype TaskNotesPluginInstance = {\n    api?: TaskNotesRuntimeApiV1;\n};\n\nconst tasknotes = app.plugins.getPlugin("tasknotes") as TaskNotesPluginInstance | null;\nconst api = tasknotes?.api;\n\nif (api?.apiVersion === 1 && api.hasCapability("tasks.write")) {\n    await api.tasks.setStatus("Tasks/example.md", "active");\n}\n

TaskNotes is still loaded by Obsidian at runtime. The TypeScript contract only gives companion plugins compile-time checking and autocomplete.

\n

Model#

\n

The runtime API exposes a small model namespace backed by @tasknotes/model:

\n
const info = api.model.info();\nconst config = api.model.config();\nconst validation = api.model.validateTask(task);\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
MethodDescription
api.model.info()Returns the model package name, TaskNotes spec version, and runtime API version.
api.model.config()Returns a resolved, Obsidian-free model configuration snapshot derived from TaskNotes settings.
api.model.validateTask(task)Validates a partial or complete task against the shared model schema and TaskNotes status rules.
api.model.validatePatch(patch)Validates a task patch before passing it to a runtime task mutation.
\n

Catalog#

\n

Use api.catalog to build companion-plugin editors without hardcoding TaskNotes values:

\n
const statuses = api.catalog.statuses();\nconst writableFields = api.catalog.writableFields();\nconst operators = api.catalog.filterOperators();\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
MethodDescription
api.catalog.statuses()Returns configured TaskNotes status definitions.
api.catalog.priorities()Returns configured TaskNotes priority definitions.
api.catalog.userFields()Returns configured user-defined field mappings.
api.catalog.fields()Returns core, computed, and user field metadata with value type, writability, and frontmatter key when available.
api.catalog.writableFields()Returns only fields that runtime task mutations may write.
api.catalog.filterProperties()Returns canonical query fields, aliases, value types, and supported operators.
api.catalog.filterOperators()Returns canonical query operators, labels, value requirements, and accepted aliases.
api.catalog.relationships()Returns relationship categories supported by api.relationships.
api.catalog.dependencyRelTypes()Returns dependency relationship types accepted by api.tasks.addDependency.
api.catalog.events()Returns the same runtime event catalogue as api.events.list().
\n

Tasks#

\n

All paths are vault-relative Markdown file paths.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
MethodDescription
api.tasks.get(path)Returns a task by path, or null when no task is cached at that path.
api.tasks.list(query?)Returns all tasks, or tasks matching a runtime task query. Prefer api.query.tasks() when count and grouping metadata matters.
api.tasks.create(taskData, context?)Creates a task using the normal TaskNotes creation service.
api.tasks.update(path, patch, context?)Updates one or more task fields using the normal TaskNotes update service.
api.tasks.delete(path, context?)Deletes the task file through TaskNotes' delete service.
api.tasks.complete(path, options?, context?)Marks a task complete.
api.tasks.uncomplete(path, options?, context?)Moves a completed task back to a non-completed status.
api.tasks.setStatus(path, status, context?)Sets task status.
api.tasks.setPriority(path, priority, context?)Sets task priority.
api.tasks.setDue(path, date, context?) / clearDue(path, context?)Sets or clears due date.
api.tasks.setScheduled(path, date, context?) / clearScheduled(path, context?)Sets or clears scheduled date.
api.tasks.archive(path, archived, context?)Archives or unarchives a task, including archive-folder movement when configured.
api.tasks.move(path, targetFolder, context?)Moves the task note and refuses to overwrite an existing file.
api.tasks.addTag/removeTagMutates task tags.
api.tasks.addProject/removeProjectMutates project links.
api.tasks.addContext/removeContextMutates contexts.
api.tasks.setReminders/addReminder/removeReminderMutates reminders.
api.tasks.addDependency/removeDependencyMutates blocking dependencies stored in blockedBy.
\n

Example:

\n
const task = await api.tasks.create(\n    {\n        title: "Review automation design",\n        status: "open",\n        priority: "normal",\n        scheduled: "2026-06-01",\n        tags: ["tasknotes"],\n    },\n    {\n        source: "my-companion-plugin",\n        correlationId: crypto.randomUUID(),\n        reason: "manual workflow command",\n    }\n);\n\nawait api.tasks.complete(task.path);\n

Relationships#

\n

Relationship methods resolve TaskNotes' project-as-parent links and blockedBy dependencies into task records where possible.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
MethodDescription
api.relationships.parents(path)Returns parent tasks referenced from the task's projects.
api.relationships.subtasks(path)Returns tasks that reference this task as a project.
api.relationships.dependencies(path)Returns blockedBy dependencies with resolved task data when available.
api.relationships.blocking(path)Returns tasks that are blocked by this task.
api.relationships.all(path)Returns the task plus parents, subtasks, dependencies, and blocking tasks.
\n

Example:

\n
const relationships = await api.relationships.all("Tasks/example.md");\n\nfor (const subtask of relationships.subtasks) {\n    await api.tasks.setPriority(subtask.path, relationships.task.priority);\n}\n

Time Tracking#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
MethodDescription
api.time.start(path, options?, context?)Starts time tracking and returns the updated task.
api.time.stop(path, context?)Stops the active time entry and returns the updated task.
api.time.active()Returns active time entries with task, path, entry, and entry index.
api.time.summary(options?)Returns aggregate time totals, top tasks, projects, and tags.
api.time.task(path)Returns one task's time summary and normalized time entries.
api.time.append(path, entry, context?)Appends a time entry.
api.time.deleteEntry(path, entryIndex, context?)Deletes a time entry through TaskNotes' service.
\n

Query, Stats, And System#

\n

The query, stats, and system namespaces expose HTTP/MCP-style support data without requiring companion plugins to reach into TaskNotes internals. Runtime queries use a stable DTO rather than TaskNotes' internal view state.

\n
const result = await api.query.tasks({\n    where: {\n        all: [\n            { field: "task.status", op: "eq", value: "active" },\n            { field: "task.due", op: "lte", value: { fn: "today" } },\n        ],\n    },\n    sort: [{ field: "task.due", direction: "asc" }],\n    group: [{ field: "task.status" }],\n    limit: 25,\n    scope: {\n        includeArchived: false,\n        folders: ["Tasks"],\n    },\n});\n

Runtime query fields are canonical IDs such as task.status, task.priority, task.due, task.projects, task.isBlocked, file.path, and user.<id-or-key>. api.catalog.filterProperties() returns the complete queryable field catalog, including aliases such as status and user:<id>.

\n

Canonical operators are eq, ne, contains, notContains, in, notIn, exists, missing, lt, lte, gt, gte, isTrue, and isFalse. Legacy operator aliases such as is, is-not, is-on-or-before, and is-not-empty are accepted and normalized.

\n

api.query.tasks() returns explicit count semantics:

\n
    \n
  • total: tasks in scope before filtering
  • \n
  • matched: tasks matching where before offset and limit
  • \n
  • returned: tasks returned after offset and limit
  • \n
  • tasks: returned task records
  • \n
  • groups: optional group details with task paths
  • \n
  • query: the normalized canonical query
  • \n
  • warnings: non-fatal normalization notes
  • \n
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
MethodDescription
api.query.tasks(query?)Validates, normalizes, and executes a runtime task query.
api.query.validate(query)Validates a query without executing it.
api.query.normalize(query)Returns the canonical normalized query, or throws a typed invalid_input API error.
api.query.explain(query)Returns validation, normalized query, count, grouping, and applied sort/limit details for dry run.
api.query.filterOptions()Returns available statuses, priorities, contexts, projects, tags, folders, and user properties.
api.stats.tasks(query?)Returns task counts, status/priority counts, archive/completion counts, and time-tracking totals.
api.system.health()Returns runtime status, API version, capabilities, vault identity, and task count.
\n

TaskNotes compiles this DTO into its internal filter engine. Companion plugins should treat the runtime DTO and the catalog metadata as the public query contract.

\n

Task Menu UI#

\n

Companion plugins can reuse the standard TaskNotes task context menu through api.ui.taskMenu. This keeps task actions, relationship actions, recurrence controls, and future menu changes behind the runtime API boundary instead of requiring companion plugins to import TaskNotes internals.

\n

This surface is only available inside Obsidian. It is not exposed through the HTTP API.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
MethodDescription
api.ui.taskMenu.show({ taskPath, event, targetDate?, onUpdate?, promoteOccurrenceControls? })Shows the standard TaskNotes task context menu at a mouse event.
api.ui.taskMenu.showAtElement({ taskPath, element, targetDate?, onUpdate?, ... })Shows the standard TaskNotes task context menu anchored to an element.
api.ui.taskMenu.populate(menu, { taskPath, targetDate?, onUpdate?, ... })Adds the standard TaskNotes task context menu items to an existing Obsidian Menu so plugins can extend it.
\n

All methods resolve taskPath through the TaskNotes task cache and throw a typed task_not_found error when the path does not point to a cached task.

\n

targetDate defaults to today and is used by date-sensitive recurring-task menu items. onUpdate is called after menu actions mutate the task; when omitted, TaskNotes refreshes its own task views. promoteOccurrenceControls moves recurring-instance controls to the top of the menu.

\n

Example context menu:

\n
nodeEl.addEventListener("contextmenu", async (event) => {\n    event.preventDefault();\n\n    await api.ui.taskMenu.show({\n        taskPath: task.path,\n        event,\n        onUpdate: () => refreshGraph(),\n    });\n});\n

Example composed menu:

\n
const menu = new Menu();\n\nawait api.ui.taskMenu.populate(menu, {\n    taskPath: task.path,\n    onUpdate: () => refreshGraph(),\n});\n\nmenu.addSeparator();\nmenu.addItem((item) =>\n    item\n        .setTitle("Focus in graph")\n        .setIcon("network")\n        .onClick(() => selectGraphNode(task.path))\n);\n\nmenu.showAtMouseEvent(event);\n

Pomodoro#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
MethodDescription
api.pomodoro.status()Returns current Pomodoro state.
api.pomodoro.start(options?, context?)Starts a Pomodoro session.
api.pomodoro.stop(context?)Stops and resets the active Pomodoro session.
api.pomodoro.pause(context?)Pauses the current session.
api.pomodoro.resume(context?)Resumes a paused session.
api.pomodoro.assignTask(pathOrNull, context?)Assigns or clears the current session task.
api.pomodoro.sessions(options?)Returns Pomodoro session history.
api.pomodoro.stats(date?)Returns Pomodoro stats for a date or today.
\n

Recurring Tasks#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
MethodDescription
api.recurring.toggleCompleteInstance(path, date?, context?)Toggles completion for a recurring task instance.
api.recurring.toggleSkippedInstance(path, date?, context?)Toggles skipped state for a recurring task instance.
api.recurring.materializeOccurrence(path, date, context?)Creates or returns an occurrence note for a recurring task date.
\n

Natural Language Parser#

\n
const parsed = api.nlp.parse("Write draft friday 2pm #writing @desk");\n

api.parseNaturalLanguage(text) remains as a compatibility alias. Parsing does not create or modify task files.

\n

See NLP API for HTTP endpoint details and parser behavior.

\n

Settings Snapshot#

\n
const settings = api.settings.snapshot();\nconsole.log(settings.defaultTaskStatus);\n

The returned object is a snapshot. Mutating it does not change TaskNotes settings. api.getSettingsSnapshot() remains available as a compatibility alias.

\n

Bases#

\n

api.bases.updateDefaultFiles() regenerates the configured default TaskNotes .base files from the current TaskNotes settings and returns the created, updated, and skipped file paths.

\n
const result = await api.bases.updateDefaultFiles();\nconsole.log(result.updated);\n

Mutation Context#

\n

Mutating methods accept an optional context object:

\n
{\n  source: "tasknotes-workflows",\n  correlationId: "run-2026-06-01T09-00-00",\n  reason: "status changed to active"\n}\n

TaskNotes attaches this context to normalized events emitted during the mutation. Use it to make workflow runs debuggable, connect multiple API calls to one run, and prevent companion plugins from responding to their own writes.

\n

Events#

\n

Subscribe with api.events.on(eventName, handler) and unsubscribe with api.events.off(ref). In an Obsidian plugin, pass the returned EventRef to this.registerEvent(ref).

\n

Use api.events.list() to discover the event catalogue for companion-plugin UIs:

\n
const events = api.events.list();\n// [{ name: "task.status.changed", label: "Task status changed", category: "task", ... }]\n

Task events:

\n
    \n
  • task.created
  • \n
  • task.updated
  • \n
  • task.deleted
  • \n
  • task.moved
  • \n
  • task.status.changed
  • \n
  • task.completed
  • \n
  • task.uncompleted
  • \n
  • task.archived
  • \n
  • task.unarchived
  • \n
  • task.scheduled.changed
  • \n
  • task.due.changed
  • \n
  • task.priority.changed
  • \n
  • task.tags.changed
  • \n
  • task.contexts.changed
  • \n
  • task.projects.changed
  • \n
  • task.reminders.changed
  • \n
  • task.dependencies.changed
  • \n
  • task.recurrence.changed
  • \n
\n

Time, Pomodoro, and recurring events:

\n
    \n
  • time.started
  • \n
  • time.stopped
  • \n
  • pomodoro.started
  • \n
  • pomodoro.completed
  • \n
  • pomodoro.interrupted
  • \n
  • recurring.instance.completed
  • \n
  • recurring.instance.skipped
  • \n
\n

Specific events are emitted in addition to task.updated. For example, changing a task from open to done emits task.updated, task.status.changed, and task.completed.

\n

Event payloads have this shape:

\n
{\n  event: "task.status.changed",\n  timestamp: "2026-06-01T09:00:00.000Z",\n  taskPath: "Tasks/Review automation design.md",\n  task: { /* current task */ },\n  before: { /* task before change */ },\n  after: { /* task after change */ },\n  deletedTask: undefined,\n  changes: {\n    status: {\n      before: "open",\n      after: "done"\n    }\n  },\n  data: undefined,\n  context: {\n    source: "tasknotes-workflows",\n    correlationId: "run-2026-06-01T09-00-00",\n    reason: "status changed to done"\n  },\n  source: "tasknotes-workflows",\n  correlationId: "run-2026-06-01T09-00-00",\n  reason: "status changed to done",\n  rawEvent: "task-updated"\n}\n

Events caused outside the runtime API may not include context, source, correlationId, or reason.

\n

Example automation-style listener:

\n
const source = "my-workflow-plugin";\n\nthis.registerEvent(\n    api.events.on("task.status.changed", async (event) => {\n        if (event.source === source) {\n            return;\n        }\n\n        if (event.after?.status !== "active") {\n            return;\n        }\n\n        await api.time.start(event.after.path, undefined, {\n            source,\n            correlationId: event.correlationId ?? crypto.randomUUID(),\n            reason: "status changed to active",\n        });\n    })\n);\n

Lifecycle#

\n

Use api.lifecycle to coordinate companion plugin startup, reload, and cache-sensitive UI state:

\n
await api.lifecycle.ready();\n\nthis.registerEvent(\n    api.lifecycle.on("settings.changed", () => {\n        refreshCompanionCatalogs();\n    })\n);\n

Lifecycle events:

\n
    \n
  • ready
  • \n
  • layout.ready
  • \n
  • settings.changed
  • \n
  • cache.changed
  • \n
  • cache.rebuilt
  • \n
  • extension.registered
  • \n
  • extension.unregistered
  • \n
  • unloading
  • \n
\n

api.lifecycle.list() returns labels, descriptions, and categories for these events.

\n

Error Handling#

\n

API methods throw TaskNotesApiError for invalid input or failed operations that the runtime API can classify. The error object includes:

\n
    \n
  • name: always TaskNotesApiError
  • \n
  • code: a stable machine-readable code
  • \n
  • message: a human-readable message for logs
  • \n
  • status: an HTTP-style status code for tools that mirror runtime calls over HTTP or MCP
  • \n
  • details: optional structured context such as the task path, extension namespace, or invalid status
  • \n
\n

Common examples:

\n
    \n
  • The task path is empty or invalid.
  • \n
  • No task exists at the requested path.
  • \n
  • A target move folder already contains a file with the same name.
  • \n
  • complete is called with a status that is not configured as completed.
  • \n
\n

Current error codes:

\n
    \n
  • invalid_input
  • \n
  • invalid_task_path
  • \n
  • invalid_status
  • \n
  • task_not_found
  • \n
  • task_file_not_found
  • \n
  • file_already_exists
  • \n
  • extension_invalid
  • \n
  • extension_namespace_reserved
  • \n
  • extension_namespace_conflict
  • \n
  • extension_not_registered
  • \n
  • operation_failed
  • \n
\n

Use api.errors when workflow engines or background listeners need consistent result objects instead of thrown exceptions:

\n
const result = await api.errors.toResult(() =>\n    api.tasks.complete("Tasks/example.md", { status: "done" })\n);\n\nif (!result.ok) {\n    console.warn(result.error.code, result.error.details);\n    return;\n}\n\nconsole.log(result.value.path);\n

api.errors.normalize(error) converts unknown thrown values into a TaskNotesApiError payload. Unknown JavaScript errors use operation_failed with status 500.

\n","text":"TaskNotes exposes an in-process runtime API on the loaded Obsidian plugin instance: const tasknotes = app.plugins.plugins.tasknotes; const api = tasknotes?.api; This API is for Obsidian companion plugins and in-vault scripting tools such as Templater, QuickAdd, and MetaBind. It runs inside Obsidian and uses the same TaskNotes services, settings, cache, and vault permissions as the plugin UI. This is separate from the HTTP API. The runtime API does not start a server, does not use bearer-token authentication, and is only available inside the running Obsidian app. For user-facing extensions built on this API, see Companion Plugins. For a concrete automation companion plugin, see TaskNotes Workflows. The TypeScript contract lives in src/api/runtime-api.ts. It is intentionally small and type-focused so it can later become a standalone @tasknotes/runtime-api package for companion plugins. Version and Capabilities# Check the API version and capabilities before using methods that may not exist in older TaskNotes versions: const tasknotes = app.plugins.plugins.tasknotes; const api = tasknotes?.api; if (!api || api.apiVersion !== 1 || !api.hasCapability(\"tasks.write\")) { throw new Error(\"This workflow requires TaskNotes runtime API v1 task writes\"); } Current capabilities: model.read model.validate catalog.read extensions.read extensions.register tasks.read tasks.write tasks.delete tasks.move tasks.events relationships.read events.list time.read time.write time.summary pomodoro.read pomodoro.write pomodoro.events recurring.write recurring.materialize recurring.events settings.snapshot bases.write nlp.parse ui.task-menu query.tasks query.validate query.explain query.filter-options stats.tasks system.health lifecycle.events errors.typed Namespaces# Prefer the namespaced API for new code: await api.tasks.update(\"Tasks/example.md\", { status: \"active\" }); const subtasks = await api.relationships.subtasks(\"Tasks/example.md\"); await api.time.start(\"Tasks/example.md\", { description: \"Deep work\" }); await api.pomodoro.start({ taskPath: \"Tasks/example.md\", duration: 25 }); The older flat methods, such as api.getTask(path) and api.parseNaturalLanguage(text), remain available as compatibility aliases. Extension Registry# Companion plugins can publish their own runtime API namespace through api.extensions. This is the preferred way to extend TaskNotes without adding arbitrary properties to the core API object. const tasknotes = this.app.plugins.getPlugin(\"tasknotes\"); const api = tasknotes?.api; if (!api?.hasCapability(\"extensions.register\")) { return; } const handle = api.extensions.register({ id: this.manifest.id, namespace: \"tasknotes-workflows\", displayName: \"TaskNotes Workflows\", version: this.manifest.version, capabilities: [\"tasknotes-workflows.run\", \"tasknotes-workflows.events\"], api: { runWorkflow: async (workflowId, input) => { // companion plugin implementation }, }, }); this.register(() => handle.unregister()); Other plugins can discover and consume extension namespaces: const workflows = api.extensions.get(\"tasknotes-workflows\"); if (api.hasCapability(\"tasknotes-workflows.run\")) { await workflows.runWorkflow(\"start-timer-on-active\", { taskPath: \"Tasks/example.md\" }); } Extension namespaces are normalized to lowercase and may use letters, numbers, dots, underscores, or dashes. Capability names are also normalized to lowercase. Prefix extension capabilities with the extension namespace to avoid collisions. Companion Plugin Access# Companion plugins can read the TaskNotes plugin instance from Obsidian's plugin registry: const tasknotes = this.app.plugins.getPlugin(\"tasknotes\"); const api = tasknotes?.api; if (!api?.hasCapability(\"tasks.events\")) { return; } this.registerEvent( api.events.on(\"task.status.changed\", (event) => { console.log(event.taskPath, event.changes.status); }) ); If TaskNotes is disabled or has not loaded yet, api will be unavailable. Companion plugins should handle that case and retry after plugin load if needed. TypeScript# Use the exported runtime contract for type safety: import type { TaskNotesRuntimeApiV1 } from \"tasknotes/src/api/runtime-api\"; type TaskNotesPluginInstance = { api?: TaskNotesRuntimeApiV1; }; const tasknotes = app.plugins.getPlugin(\"tasknotes\") as TaskNotesPluginInstance | null; const api = tasknotes?.api; if (api?.apiVersion === 1 && api.hasCapability(\"tasks.write\")) { await api.tasks.setStatus(\"Tasks/example.md\", \"active\"); } TaskNotes is still loaded by Obsidian at runtime. The TypeScript contract only gives companion plugins compile-time checking and autocomplete. Model# The runtime API exposes a small model namespace backed by @tasknotes/model: const info = api.model.info(); const config = api.model.config(); const validation = api.model.validateTask(task); Method Description api.model.info() Returns the model package name, TaskNotes spec version, and runtime API version. api.model.config() Returns a resolved, Obsidian-free model configuration snapshot derived from TaskNotes settings. api.model.validateTask(task) Validates a partial or complete task against the shared model schema and TaskNotes status rules. api.model.validatePatch(patch) Validates a task patch before passing it to a runtime task mutation. Catalog# Use api.catalog to build companion-plugin editors without hardcoding TaskNotes values: const statuses = api.catalog.statuses(); const writableFields = api.catalog.writableFields(); const operators = api.catalog.filterOperators(); Method Description api.catalog.statuses() Returns configured TaskNotes status definitions. api.catalog.priorities() Returns configured TaskNotes priority definitions. api.catalog.userFields() Returns configured user-defined field mappings. api.catalog.fields() Returns core, computed, and user field metadata with value type, writability, and frontmatter key when available. api.catalog.writableFields() Returns only fields that runtime task mutations may write. api.catalog.filterProperties() Returns canonical query fields, aliases, value types, and supported operators. api.catalog.filterOperators() Returns canonical query operators, labels, value requirements, and accepted aliases. api.catalog.relationships() Returns relationship categories supported by api.relationships. api.catalog.dependencyRelTypes() Returns dependency relationship types accepted by api.tasks.addDependency. api.catalog.events() Returns the same runtime event catalogue as api.events.list(). Tasks# All paths are vault-relative Markdown file paths. Method Description api.tasks.get(path) Returns a task by path, or null when no task is cached at that path. api.tasks.list(query?) Returns all tasks, or tasks matching a runtime task query. Prefer api.query.tasks() when count and grouping metadata matters. api.tasks.create(taskData, context?) Creates a task using the normal TaskNotes creation service. api.tasks.update(path, patch, context?) Updates one or more task fields using the normal TaskNotes update service. api.tasks.delete(path, context?) Deletes the task file through TaskNotes' delete service. api.tasks.complete(path, options?, context?) Marks a task complete. api.tasks.uncomplete(path, options?, context?) Moves a completed task back to a non-completed status. api.tasks.setStatus(path, status, context?) Sets task status. api.tasks.setPriority(path, priority, context?) Sets task priority. api.tasks.setDue(path, date, context?) / clearDue(path, context?) Sets or clears due date. api.tasks.setScheduled(path, date, context?) / clearScheduled(path, context?) Sets or clears scheduled date. api.tasks.archive(path, archived, context?) Archives or unarchives a task, including archive-folder movement when configured. api.tasks.move(path, targetFolder, context?) Moves the task note and refuses to overwrite an existing file. api.tasks.addTag/removeTag Mutates task tags. api.tasks.addProject/removeProject Mutates project links. api.tasks.addContext/removeContext Mutates contexts. api.tasks.setReminders/addReminder/removeReminder Mutates reminders. api.tasks.addDependency/removeDependency Mutates blocking dependencies stored in blockedBy. Example: const task = await api.tasks.create( { title: \"Review automation design\", status: \"open\", priority: \"normal\", scheduled: \"2026-06-01\", tags: [\"tasknotes\"], }, { source: \"my-companion-plugin\", correlationId: crypto.randomUUID(), reason: \"manual workflow command\", } ); await api.tasks.complete(task.path); Relationships# Relationship methods resolve TaskNotes' project-as-parent links and blockedBy dependencies into task records where possible. Method Description api.relationships.parents(path) Returns parent tasks referenced from the task's projects. api.relationships.subtasks(path) Returns tasks that reference this task as a project. api.relationships.dependencies(path) Returns blockedBy dependencies with resolved task data when available. api.relationships.blocking(path) Returns tasks that are blocked by this task. api.relationships.all(path) Returns the task plus parents, subtasks, dependencies, and blocking tasks. Example: const relationships = await api.relationships.all(\"Tasks/example.md\"); for (const subtask of relationships.subtasks) { await api.tasks.setPriority(subtask.path, relationships.task.priority); } Time Tracking# Method Description api.time.start(path, options?, context?) Starts time tracking and returns the updated task. api.time.stop(path, context?) Stops the active time entry and returns the updated task. api.time.active() Returns active time entries with task, path, entry, and entry index. api.time.summary(options?) Returns aggregate time totals, top tasks, projects, and tags. api.time.task(path) Returns one task's time summary and normalized time entries. api.time.append(path, entry, context?) Appends a time entry. api.time.deleteEntry(path, entryIndex, context?) Deletes a time entry through TaskNotes' service. Query, Stats, And System# The query, stats, and system namespaces expose HTTP/MCP-style support data without requiring companion plugins to reach into TaskNotes internals. Runtime queries use a stable DTO rather than TaskNotes' internal view state. const result = await api.query.tasks({ where: { all: [ { field: \"task.status\", op: \"eq\", value: \"active\" }, { field: \"task.due\", op: \"lte\", value: { fn: \"today\" } }, ], }, sort: [{ field: \"task.due\", direction: \"asc\" }], group: [{ field: \"task.status\" }], limit: 25, scope: { includeArchived: false, folders: [\"Tasks\"], }, }); Runtime query fields are canonical IDs such as task.status, task.priority, task.due, task.projects, task.isBlocked, file.path, and user.. api.catalog.filterProperties() returns the complete queryable field catalog, including aliases such as status and user:. Canonical operators are eq, ne, contains, notContains, in, notIn, exists, missing, lt, lte, gt, gte, isTrue, and isFalse. Legacy operator aliases such as is, is-not, is-on-or-before, and is-not-empty are accepted and normalized. api.query.tasks() returns explicit count semantics: total: tasks in scope before filtering matched: tasks matching where before offset and limit returned: tasks returned after offset and limit tasks: returned task records groups: optional group details with task paths query: the normalized canonical query warnings: non-fatal normalization notes Method Description api.query.tasks(query?) Validates, normalizes, and executes a runtime task query. api.query.validate(query) Validates a query without executing it. api.query.normalize(query) Returns the canonical normalized query, or throws a typed invalid_input API error. api.query.explain(query) Returns validation, normalized query, count, grouping, and applied sort/limit details for dry run. api.query.filterOptions() Returns available statuses, priorities, contexts, projects, tags, folders, and user properties. api.stats.tasks(query?) Returns task counts, status/priority counts, archive/completion counts, and time-tracking totals. api.system.health() Returns runtime status, API version, capabilities, vault identity, and task count. TaskNotes compiles this DTO into its internal filter engine. Companion plugins should treat the runtime DTO and the catalog metadata as the public query contract. Task Menu UI# Companion plugins can reuse the standard TaskNotes task context menu through api.ui.taskMenu. This keeps task actions, relationship actions, recurrence controls, and future menu changes behind the runtime API boundary instead of requiring companion plugins to import TaskNotes internals. This surface is only available inside Obsidian. It is not exposed through the HTTP API. Method Description api.ui.taskMenu.show({ taskPath, event, targetDate?, onUpdate?, promoteOccurrenceControls? }) Shows the standard TaskNotes task context menu at a mouse event. api.ui.taskMenu.showAtElement({ taskPath, element, targetDate?, onUpdate?, ... }) Shows the standard TaskNotes task context menu anchored to an element. api.ui.taskMenu.populate(menu, { taskPath, targetDate?, onUpdate?, ... }) Adds the standard TaskNotes task context menu items to an existing Obsidian Menu so plugins can extend it. All methods resolve taskPath through the TaskNotes task cache and throw a typed task_not_found error when the path does not point to a cached task. targetDate defaults to today and is used by date-sensitive recurring-task menu items. onUpdate is called after menu actions mutate the task; when omitted, TaskNotes refreshes its own task views. promoteOccurrenceControls moves recurring-instance controls to the top of the menu. Example context menu: nodeEl.addEventListener(\"contextmenu\", async (event) => { event.preventDefault(); await api.ui.taskMenu.show({ taskPath: task.path, event, onUpdate: () => refreshGraph(), }); }); Example composed menu: const menu = new Menu(); await api.ui.taskMenu.populate(menu, { taskPath: task.path, onUpdate: () => refreshGraph(), }); menu.addSeparator(); menu.addItem((item) => item .setTitle(\"Focus in graph\") .setIcon(\"network\") .onClick(() => selectGraphNode(task.path)) ); menu.showAtMouseEvent(event); Pomodoro# Method Description api.pomodoro.status() Returns current Pomodoro state. api.pomodoro.start(options?, context?) Starts a Pomodoro session. api.pomodoro.stop(context?) Stops and resets the active Pomodoro session. api.pomodoro.pause(context?) Pauses the current session. api.pomodoro.resume(context?) Resumes a paused session. api.pomodoro.assignTask(pathOrNull, context?) Assigns or clears the current session task. api.pomodoro.sessions(options?) Returns Pomodoro session history. api.pomodoro.stats(date?) Returns Pomodoro stats for a date or today. Recurring Tasks# Method Description api.recurring.toggleCompleteInstance(path, date?, context?) Toggles completion for a recurring task instance. api.recurring.toggleSkippedInstance(path, date?, context?) Toggles skipped state for a recurring task instance. api.recurring.materializeOccurrence(path, date, context?) Creates or returns an occurrence note for a recurring task date. Natural Language Parser# const parsed = api.nlp.parse(\"Write draft friday 2pm #writing @desk\"); api.parseNaturalLanguage(text) remains as a compatibility alias. Parsing does not create or modify task files. See NLP API for HTTP endpoint details and parser behavior. Settings Snapshot# const settings = api.settings.snapshot(); console.log(settings.defaultTaskStatus); The returned object is a snapshot. Mutating it does not change TaskNotes settings. api.getSettingsSnapshot() remains available as a compatibility alias. Bases# api.bases.updateDefaultFiles() regenerates the configured default TaskNotes .base files from the current TaskNotes settings and returns the created, updated, and skipped file paths. const result = await api.bases.updateDefaultFiles(); console.log(result.updated); Mutation Context# Mutating methods accept an optional context object: { source: \"tasknotes-workflows\", correlationId: \"run-2026-06-01T09-00-00\", reason: \"status chang"},{"route":"/obsidian/mdbase-tasknotes-cli/","title":"mdbase-tasknotes CLI","description":"mdbase-tasknotes (mtn) is a standalone command-line tool for managing TaskNotes tasks directly on markdown files. It uses mdbase to read and write task files and tasknotes-nlp-c...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/mdbase-tasknotes-cli.md","namespace":"obsidian","relativePath":"mdbase-tasknotes-cli.md","raw":"# mdbase-tasknotes CLI\n\n[mdbase-tasknotes](https://github.com/callumalpass/mdbase-tasknotes) (`mtn`) is a standalone command-line tool for managing TaskNotes tasks directly on markdown files. It uses [mdbase](https://mdbase.dev) to read and write task files and [tasknotes-nlp-core](https://github.com/callumalpass/tasknotes-nlp-core) for natural language parsing.\n\n\n## When to use this vs TaskNotes Obsidian CLI\n\nIf you are looking for the built-in `obsidian tasknotes:*` commands exposed by the plugin itself, see [TaskNotes Obsidian CLI](obsidian-cli.md).\n\nTaskNotes ships with [tasknotes-cli](https://github.com/callumalpass/tasknotes-cli) (`tn`), which communicates with the Obsidian plugin over its HTTP API. `mdbase-tasknotes` operates directly on the markdown files instead.\n\n| | `tn` (tasknotes-cli) | `mtn` (mdbase-tasknotes) |\n|---|---|---|\n| **Requires Obsidian** | Yes — plugin must be running with API enabled | No |\n| **Operates on** | HTTP API | Markdown files directly via mdbase |\n| **Use when** | Obsidian is open and you want live sync | Obsidian is closed, on a server, or in scripts |\n| **Time tracking** | Via plugin API | Via frontmatter `timeEntries` |\n| **Task creation** | NLP via API | NLP via bundled `tasknotes-nlp-core` |\n| **Install** | `npm install -g tasknotes-cli` | `npm install -g mdbase-tasknotes` |\n\nUse `mtn` when:\n\n- Obsidian isn't running or isn't available (headless servers, SSH sessions, CI pipelines)\n- You want to manage tasks from the terminal without any background process\n- You're scripting task creation or querying in shell workflows\n- You're on a machine where Obsidian isn't installed\n\nBoth tools read and write the same task files, so they can be used interchangeably on the same vault.\n\n## Install\n\n```\nnpm install -g mdbase-tasknotes\n```\n\n## Setup\n\n### Using an existing TaskNotes vault\n\nIf you already use TaskNotes with mdbase spec generation enabled (Settings → Integrations → Enable mdbase spec), point `mtn` at your vault root:\n\n```bash\nmtn config --set collectionPath=/path/to/your/vault\n```\n\nThe plugin generates `mdbase.yaml` and `_types/task.md` automatically — `mtn` reads these to understand your task schema, including your custom statuses and priorities.\n\n### Creating a standalone collection\n\nTo create a new collection without Obsidian:\n\n```bash\nmtn init ~/tasks\nmtn config --set collectionPath=~/tasks\n```\n\nThis generates `mdbase.yaml`, `_types/task.md`, and a `tasks/` folder with sensible defaults (statuses: open, in-progress, done, cancelled; priorities: low, normal, high, urgent).\n\n## Creating tasks\n\nCreate tasks using natural language. Tags, contexts, projects, dates, priorities, and recurrence are extracted automatically:\n\n```bash\nmtn create \"Buy groceries tomorrow #shopping @errands\"\nmtn create \"Write quarterly report due friday #work +quarterly-review\"\nmtn create \"Call dentist high priority @phone\"\nmtn create \"Water plants every monday #home\"\n```\n\n### Supported patterns\n\n| Pattern | Example | Extracted as |\n|---|---|---|\n| `#tag` | `#shopping` | Tag |\n| `@context` | `@errands` | Context |\n| `+project` | `+quarterly-review` | Project (stored as wikilink) |\n| Date words | `tomorrow`, `friday`, `next week` | Due date |\n| Priority words | `high priority`, `urgent` | Priority |\n| Recurrence | `every day`, `weekly`, `every monday` | Recurrence rule |\n| Estimate | `~30m`, `~2h` | Time estimate |\n\nThe NLP parser reads your collection's status and priority enum values from `_types/task.md`, so any custom values you define there are automatically recognized.\n\n## Querying tasks\n\n### List tasks\n\n```bash\n# Default: open tasks ordered by due date\nmtn list\n\n# Filter by status, priority, or tag\nmtn list --status in-progress\nmtn list --priority high\nmtn list --tag work\n\n# Show overdue tasks\nmtn list --overdue\n\n# Raw mdbase where expression\nmtn list --where 'due < \"2026-03-01\" && priority == \"urgent\"'\n\n# JSON output for scripting\nmtn list --json\n```\n\n### Show task detail\n\n```bash\nmtn show \"Buy groceries\"\nmtn show tasks/Buy\\ groceries.md\n```\n\nTasks can be referenced by title or file path. Title matching tries exact match first, then substring.\n\n### Search\n\nFull-text search across titles, body content, tags, contexts, and projects:\n\n```bash\nmtn search quarterly\n```\n\n## Updating tasks\n\n### Complete a task\n\n```bash\nmtn complete \"Buy groceries\"\n```\n\nSets status to `done` and records the completion date.\n\n### Update fields\n\n```bash\nmtn update \"Write report\" --status in-progress\nmtn update \"Write report\" --priority urgent --due 2026-03-01\nmtn update \"Write report\" --add-tag important --remove-tag draft\nmtn update \"Write report\" --add-context office\n```\n\n### Archive and delete\n\n```bash\nmtn archive \"Write report\" # Adds \"archive\" tag\nmtn delete \"Old task\" # Checks for backlinks first\nmtn delete \"Old task\" --force # Skip backlink check\n```\n\n## Time tracking\n\nTrack time spent on tasks via the `timeEntries` frontmatter field — the same format TaskNotes uses.\n\n```bash\n# Start a timer\nmtn timer start \"Write report\"\nmtn timer start \"Write report\" -d \"Drafting introduction\"\n\n# Check active timers\nmtn timer status\n\n# Stop the running timer\nmtn timer stop\n\n# View time log\nmtn timer log\nmtn timer log --period today\nmtn timer log --period week\nmtn timer log --from 2026-02-01 --to 2026-02-28\n```\n\n## Projects and statistics\n\n### Projects\n\n```bash\n# List all projects\nmtn projects list\nmtn projects list --stats # With completion percentages\n\n# Show tasks for a project\nmtn projects show quarterly-review\n```\n\n### Statistics\n\n```bash\nmtn stats\n```\n\nShows total tasks, completion rate, overdue count, breakdown by status and priority, and total time tracked.\n\n## Interactive mode\n\nLaunch a REPL with live NLP preview that updates as you type:\n\n```bash\nmtn interactive\n# or\nmtn i\n```\n\nType a task description and the preview line shows how it will be parsed (title, tags, dates, priority). Press Enter to create the task.\n\n## Configuration\n\nConfiguration is stored at `~/.config/mdbase-tasknotes/config.json`.\n\n```bash\nmtn config --list # Show all settings\nmtn config --set collectionPath=/path/to/vault # Set collection path\nmtn config --get collectionPath # Get a setting\n```\n\n### Collection path resolution\n\nThe collection path is resolved in order:\n\n1. `--path` / `-p` flag on any command\n2. `MDBASE_TASKNOTES_PATH` environment variable\n3. `collectionPath` in config file\n4. Current working directory\n\n## Command reference\n\n| Command | Alias | Description |\n|---|---|---|\n| `mtn init [path]` | | Initialize a new collection |\n| `mtn create ` | | Create a task from natural language |\n| `mtn list [options]` | `ls` | List tasks with filters |\n| `mtn show ` | | Show full task detail |\n| `mtn complete ` | `done` | Mark task as completed |\n| `mtn update [options]` | | Update task fields |\n| `mtn delete ` | `rm` | Delete a task |\n| `mtn archive ` | | Add archive tag |\n| `mtn search ` | | Full-text search |\n| `mtn timer start ` | | Start time tracking |\n| `mtn timer stop` | | Stop running timer |\n| `mtn timer status` | | Show active timers |\n| `mtn timer log` | | Show time entry log |\n| `mtn projects list` | | List projects |\n| `mtn projects show ` | | Show project tasks |\n| `mtn stats` | | Show task statistics |\n| `mtn interactive` | `i` | Interactive REPL |\n| `mtn config [options]` | | Manage configuration |\n","aliases":["/mdbase-tasknotes-cli/"],"toc":[{"level":2,"id":"when-to-use-this-vs-tasknotes-obsidian-cli","text":"When to use this vs TaskNotes Obsidian CLI"},{"level":2,"id":"install","text":"Install"},{"level":2,"id":"setup","text":"Setup"},{"level":3,"id":"using-an-existing-tasknotes-vault","text":"Using an existing TaskNotes vault"},{"level":3,"id":"creating-a-standalone-collection","text":"Creating a standalone collection"},{"level":2,"id":"creating-tasks","text":"Creating tasks"},{"level":3,"id":"supported-patterns","text":"Supported patterns"},{"level":2,"id":"querying-tasks","text":"Querying tasks"},{"level":3,"id":"list-tasks","text":"List tasks"},{"level":3,"id":"show-task-detail","text":"Show task detail"},{"level":3,"id":"search","text":"Search"},{"level":2,"id":"updating-tasks","text":"Updating tasks"},{"level":3,"id":"complete-a-task","text":"Complete a task"},{"level":3,"id":"update-fields","text":"Update fields"},{"level":3,"id":"archive-and-delete","text":"Archive and delete"},{"level":2,"id":"time-tracking","text":"Time tracking"},{"level":2,"id":"projects-and-statistics","text":"Projects and statistics"},{"level":3,"id":"projects","text":"Projects"},{"level":3,"id":"statistics","text":"Statistics"},{"level":2,"id":"interactive-mode","text":"Interactive mode"},{"level":2,"id":"configuration","text":"Configuration"},{"level":3,"id":"collection-path-resolution","text":"Collection path resolution"},{"level":2,"id":"command-reference","text":"Command reference"}],"html":"

mdbase-tasknotes (mtn) is a standalone command-line tool for managing TaskNotes tasks directly on markdown files. It uses mdbase to read and write task files and tasknotes-nlp-core for natural language parsing.

\n

When to use this vs TaskNotes Obsidian CLI#

\n

If you are looking for the built-in obsidian tasknotes:* commands exposed by the plugin itself, see TaskNotes Obsidian CLI.

\n

TaskNotes ships with tasknotes-cli (tn), which communicates with the Obsidian plugin over its HTTP API. mdbase-tasknotes operates directly on the markdown files instead.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
tn (tasknotes-cli)mtn (mdbase-tasknotes)
Requires ObsidianYes — plugin must be running with API enabledNo
Operates onHTTP APIMarkdown files directly via mdbase
Use whenObsidian is open and you want live syncObsidian is closed, on a server, or in scripts
Time trackingVia plugin APIVia frontmatter timeEntries
Task creationNLP via APINLP via bundled tasknotes-nlp-core
Installnpm install -g tasknotes-clinpm install -g mdbase-tasknotes
\n

Use mtn when:

\n
    \n
  • Obsidian isn't running or isn't available (headless servers, SSH sessions, CI pipelines)
  • \n
  • You want to manage tasks from the terminal without any background process
  • \n
  • You're scripting task creation or querying in shell workflows
  • \n
  • You're on a machine where Obsidian isn't installed
  • \n
\n

Both tools read and write the same task files, so they can be used interchangeably on the same vault.

\n

Install#

\n
npm install -g mdbase-tasknotes\n

Setup#

\n

Using an existing TaskNotes vault#

\n

If you already use TaskNotes with mdbase spec generation enabled (Settings → Integrations → Enable mdbase spec), point mtn at your vault root:

\n
mtn config --set collectionPath=/path/to/your/vault\n

The plugin generates mdbase.yaml and _types/task.md automatically — mtn reads these to understand your task schema, including your custom statuses and priorities.

\n

Creating a standalone collection#

\n

To create a new collection without Obsidian:

\n
mtn init ~/tasks\nmtn config --set collectionPath=~/tasks\n

This generates mdbase.yaml, _types/task.md, and a tasks/ folder with sensible defaults (statuses: open, in-progress, done, cancelled; priorities: low, normal, high, urgent).

\n

Creating tasks#

\n

Create tasks using natural language. Tags, contexts, projects, dates, priorities, and recurrence are extracted automatically:

\n
mtn create "Buy groceries tomorrow #shopping @errands"\nmtn create "Write quarterly report due friday #work +quarterly-review"\nmtn create "Call dentist high priority @phone"\nmtn create "Water plants every monday #home"\n

Supported patterns#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
PatternExampleExtracted as
#tag#shoppingTag
@context@errandsContext
+project+quarterly-reviewProject (stored as wikilink)
Date wordstomorrow, friday, next weekDue date
Priority wordshigh priority, urgentPriority
Recurrenceevery day, weekly, every mondayRecurrence rule
Estimate~30m, ~2hTime estimate
\n

The NLP parser reads your collection's status and priority enum values from _types/task.md, so any custom values you define there are automatically recognized.

\n

Querying tasks#

\n

List tasks#

\n
# Default: open tasks ordered by due date\nmtn list\n\n# Filter by status, priority, or tag\nmtn list --status in-progress\nmtn list --priority high\nmtn list --tag work\n\n# Show overdue tasks\nmtn list --overdue\n\n# Raw mdbase where expression\nmtn list --where 'due < "2026-03-01" && priority == "urgent"'\n\n# JSON output for scripting\nmtn list --json\n

Show task detail#

\n
mtn show "Buy groceries"\nmtn show tasks/Buy\\ groceries.md\n

Tasks can be referenced by title or file path. Title matching tries exact match first, then substring.

\n

Search#

\n

Full-text search across titles, body content, tags, contexts, and projects:

\n
mtn search quarterly\n

Updating tasks#

\n

Complete a task#

\n
mtn complete "Buy groceries"\n

Sets status to done and records the completion date.

\n

Update fields#

\n
mtn update "Write report" --status in-progress\nmtn update "Write report" --priority urgent --due 2026-03-01\nmtn update "Write report" --add-tag important --remove-tag draft\nmtn update "Write report" --add-context office\n

Archive and delete#

\n
mtn archive "Write report"     # Adds "archive" tag\nmtn delete "Old task"           # Checks for backlinks first\nmtn delete "Old task" --force   # Skip backlink check\n

Time tracking#

\n

Track time spent on tasks via the timeEntries frontmatter field — the same format TaskNotes uses.

\n
# Start a timer\nmtn timer start "Write report"\nmtn timer start "Write report" -d "Drafting introduction"\n\n# Check active timers\nmtn timer status\n\n# Stop the running timer\nmtn timer stop\n\n# View time log\nmtn timer log\nmtn timer log --period today\nmtn timer log --period week\nmtn timer log --from 2026-02-01 --to 2026-02-28\n

Projects and statistics#

\n

Projects#

\n
# List all projects\nmtn projects list\nmtn projects list --stats    # With completion percentages\n\n# Show tasks for a project\nmtn projects show quarterly-review\n

Statistics#

\n
mtn stats\n

Shows total tasks, completion rate, overdue count, breakdown by status and priority, and total time tracked.

\n

Interactive mode#

\n

Launch a REPL with live NLP preview that updates as you type:

\n
mtn interactive\n# or\nmtn i\n

Type a task description and the preview line shows how it will be parsed (title, tags, dates, priority). Press Enter to create the task.

\n

Configuration#

\n

Configuration is stored at ~/.config/mdbase-tasknotes/config.json.

\n
mtn config --list                              # Show all settings\nmtn config --set collectionPath=/path/to/vault  # Set collection path\nmtn config --get collectionPath                 # Get a setting\n

Collection path resolution#

\n

The collection path is resolved in order:

\n
    \n
  1. --path / -p flag on any command
  2. \n
  3. MDBASE_TASKNOTES_PATH environment variable
  4. \n
  5. collectionPath in config file
  6. \n
  7. Current working directory
  8. \n
\n

Command reference#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
CommandAliasDescription
mtn init [path]Initialize a new collection
mtn create <text...>Create a task from natural language
mtn list [options]lsList tasks with filters
mtn show <task>Show full task detail
mtn complete <task>doneMark task as completed
mtn update <task> [options]Update task fields
mtn delete <task>rmDelete a task
mtn archive <task>Add archive tag
mtn search <query>Full-text search
mtn timer start <task>Start time tracking
mtn timer stopStop running timer
mtn timer statusShow active timers
mtn timer logShow time entry log
mtn projects listList projects
mtn projects show <name>Show project tasks
mtn statsShow task statistics
mtn interactiveiInteractive REPL
mtn config [options]Manage configuration
\n","text":"mdbase-tasknotes (mtn) is a standalone command-line tool for managing TaskNotes tasks directly on markdown files. It uses mdbase to read and write task files and tasknotes-nlp-core for natural language parsing. When to use this vs TaskNotes Obsidian CLI# If you are looking for the built-in obsidian tasknotes:* commands exposed by the plugin itself, see TaskNotes Obsidian CLI. TaskNotes ships with tasknotes-cli (tn), which communicates with the Obsidian plugin over its HTTP API. mdbase-tasknotes operates directly on the markdown files instead. tn (tasknotes-cli) mtn (mdbase-tasknotes) Requires Obsidian Yes — plugin must be running with API enabled No Operates on HTTP API Markdown files directly via mdbase Use when Obsidian is open and you want live sync Obsidian is closed, on a server, or in scripts Time tracking Via plugin API Via frontmatter timeEntries Task creation NLP via API NLP via bundled tasknotes-nlp-core Install npm install -g tasknotes-cli npm install -g mdbase-tasknotes Use mtn when: Obsidian isn't running or isn't available (headless servers, SSH sessions, CI pipelines) You want to manage tasks from the terminal without any background process You're scripting task creation or querying in shell workflows You're on a machine where Obsidian isn't installed Both tools read and write the same task files, so they can be used interchangeably on the same vault. Install# npm install -g mdbase-tasknotes Setup# Using an existing TaskNotes vault# If you already use TaskNotes with mdbase spec generation enabled (Settings → Integrations → Enable mdbase spec), point mtn at your vault root: mtn config --set collectionPath=/path/to/your/vault The plugin generates mdbase.yaml and _types/task.md automatically — mtn reads these to understand your task schema, including your custom statuses and priorities. Creating a standalone collection# To create a new collection without Obsidian: mtn init ~/tasks mtn config --set collectionPath=~/tasks This generates mdbase.yaml, _types/task.md, and a tasks/ folder with sensible defaults (statuses: open, in-progress, done, cancelled; priorities: low, normal, high, urgent). Creating tasks# Create tasks using natural language. Tags, contexts, projects, dates, priorities, and recurrence are extracted automatically: mtn create \"Buy groceries tomorrow #shopping @errands\" mtn create \"Write quarterly report due friday #work +quarterly-review\" mtn create \"Call dentist high priority @phone\" mtn create \"Water plants every monday #home\" Supported patterns# Pattern Example Extracted as #tag #shopping Tag @context @errands Context +project +quarterly-review Project (stored as wikilink) Date words tomorrow, friday, next week Due date Priority words high priority, urgent Priority Recurrence every day, weekly, every monday Recurrence rule Estimate ~30m, ~2h Time estimate The NLP parser reads your collection's status and priority enum values from _types/task.md, so any custom values you define there are automatically recognized. Querying tasks# List tasks# # Default: open tasks ordered by due date mtn list # Filter by status, priority, or tag mtn list --status in-progress mtn list --priority high mtn list --tag work # Show overdue tasks mtn list --overdue # Raw mdbase where expression mtn list --where 'due < \"2026-03-01\" && priority == \"urgent\"' # JSON output for scripting mtn list --json Show task detail# mtn show \"Buy groceries\" mtn show tasks/Buy\\ groceries.md Tasks can be referenced by title or file path. Title matching tries exact match first, then substring. Search# Full-text search across titles, body content, tags, contexts, and projects: mtn search quarterly Updating tasks# Complete a task# mtn complete \"Buy groceries\" Sets status to done and records the completion date. Update fields# mtn update \"Write report\" --status in-progress mtn update \"Write report\" --priority urgent --due 2026-03-01 mtn update \"Write report\" --add-tag important --remove-tag draft mtn update \"Write report\" --add-context office Archive and delete# mtn archive \"Write report\" # Adds \"archive\" tag mtn delete \"Old task\" # Checks for backlinks first mtn delete \"Old task\" --force # Skip backlink check Time tracking# Track time spent on tasks via the timeEntries frontmatter field — the same format TaskNotes uses. # Start a timer mtn timer start \"Write report\" mtn timer start \"Write report\" -d \"Drafting introduction\" # Check active timers mtn timer status # Stop the running timer mtn timer stop # View time log mtn timer log mtn timer log --period today mtn timer log --period week mtn timer log --from 2026-02-01 --to 2026-02-28 Projects and statistics# Projects# # List all projects mtn projects list mtn projects list --stats # With completion percentages # Show tasks for a project mtn projects show quarterly-review Statistics# mtn stats Shows total tasks, completion rate, overdue count, breakdown by status and priority, and total time tracked. Interactive mode# Launch a REPL with live NLP preview that updates as you type: mtn interactive # or mtn i Type a task description and the preview line shows how it will be parsed (title, tags, dates, priority). Press Enter to create the task. Configuration# Configuration is stored at ~/.config/mdbase-tasknotes/config.json. mtn config --list # Show all settings mtn config --set collectionPath=/path/to/vault # Set collection path mtn config --get collectionPath # Get a setting Collection path resolution# The collection path is resolved in order: --path / -p flag on any command MDBASE_TASKNOTES_PATH environment variable collectionPath in config file Current working directory Command reference# Command Alias Description mtn init [path] Initialize a new collection mtn create Create a task from natural language mtn list [options] ls List tasks with filters mtn show Show full task detail mtn complete done Mark task as completed mtn update [options] Update task fields mtn delete rm Delete a task mtn archive Add archive tag mtn search Full-text search mtn timer start Start time tracking mtn timer stop Stop running timer mtn timer status Show active timers mtn timer log Show time entry log mtn projects list List projects mtn projects show Show project tasks mtn stats Show task statistics mtn interactive i Interactive REPL mtn config [options] Manage configuration"},{"route":"/obsidian/migration-v3-to-v4/","title":"Migrating from v3 to v4","description":"TaskNotes v4 migrates all views to the Bases system. This guide covers what changed and how to update your setup.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/migration-v3-to-v4.md","namespace":"obsidian","relativePath":"migration-v3-to-v4.md","raw":"# Migrating from v3 to v4\n\nTaskNotes v4 migrates all views to the Bases system. This guide covers what changed and how to update your setup.\n\n!!! warning \"Back up before migrating\"\n Back up the complete vault, including the hidden `.obsidian` directory, before changing views or plugin data.\n\n## Requirements\n\n- **Obsidian 1.10.1 or later** for early TaskNotes v4 releases\n- **Obsidian 1.12.2 or later** for the current TaskNotes 4.12.3 release\n- **Bases core plugin enabled** (Settings → Core Plugins → Bases)\n\n## What Changed\n\n### Views are Now Bases Files\n\nAll task views (Task List, Kanban, Calendar, Agenda) are now `.base` files stored in `TaskNotes/Views/`. This replaces the custom view system in v3.\n\n| v3 | v4 |\n|----|-----|\n| Views stored in plugin settings | Views stored as `.base` files |\n| Custom filter UI | Bases filter syntax |\n| Saved views in settings | Default views are separate files; exported v3 saved views share one multi-view file |\n\n### Automatic Migration on First Launch\n\nWhen you first open TaskNotes v4:\n\n1. Default `.base` files are created in `TaskNotes/Views/`\n2. Ribbon icons and commands now open these `.base` files\n3. Your existing task files are unchanged\n\n### Converting Saved Filter Views\n\nIf you had saved filter views in v3, you can export them to one `.base` file:\n\n1. Go to **Settings → TaskNotes → General → Views & base files**.\n2. Find **Export v3 saved views to Bases**.\n3. Run the export.\n4. TaskNotes creates `TaskNotes/Views/all-saved-views.base` with one Base view for each saved v3 view.\n\nThis is a one-way conversion. The original saved views remain in settings until you delete them.\n\n## Breaking Changes\n\n### View Configuration\n\nv3 saved views with custom filters need manual conversion to Bases filter syntax. Simple filters (status, priority, due date) convert automatically. Complex filters may need adjustment.\n\n**v3 Filter Example:**\n```\nstatus: in-progress\npriority: high\n```\n\n**v4 Bases Syntax:**\n```yaml\nfilters:\n and:\n - status == \"in-progress\"\n - priority == \"high\"\n```\n\nSee the [Obsidian Bases documentation](https://help.obsidian.md/Bases/Introduction+to+Bases) for filter syntax details.\n\n### Minimum Obsidian Version\n\nEarly v4 releases required Obsidian 1.10.1. The current release requirement is generated on the [version compatibility](reference/compatibility.md) page. Use the manifest requirement for the exact TaskNotes version you install.\n\n## New Features in v4\n\n### OAuth Calendar Integration\n\nv4 adds Google Calendar and Microsoft Outlook integration:\n\n- View external calendar events alongside tasks\n- Drag events to reschedule (syncs back to calendar provider)\n- Events sync every 15 minutes\n\nSee [Calendar Setup](calendar-setup.md) for configuration.\n\n### Kanban Swimlanes\n\nThe Kanban view now supports horizontal swimlane grouping:\n\n```yaml\nviews:\n - type: tasknotesKanban\n groupBy:\n property: status\n config:\n swimLane: priority\n```\n\n### Time Entry Editor\n\nA dedicated modal for managing time entries:\n\n- Alt-drag on calendar to create time entries\n- View total tracked time per task\n- Edit and delete time entries\n\n## Troubleshooting\n\n### Views Not Loading\n\n1. Verify Bases core plugin is enabled (Settings → Core Plugins)\n2. Check that `.base` files exist in `TaskNotes/Views/`\n3. Restart Obsidian\n\n### Missing Saved Views After Upgrade\n\nSaved views from v3 are preserved in settings. Use **Export v3 saved views to Bases** in **Settings → TaskNotes → General → Views & base files** to create the multi-view `.base` file.\n\n### Filter Syntax Errors\n\nBases uses different filter syntax than v3. Common issues:\n\n| Problem | Solution |\n|---------|----------|\n| `status: done` | Use `status == \"done\"` |\n| Multiple conditions | Wrap in `and:` or `or:` block |\n| Date comparisons | Use `date(due) < today()` |\n\n### Downgrading to v3\n\nMigration is one-way. If you need to downgrade:\n\n1. Uninstall TaskNotes v4\n2. Install TaskNotes v3 from releases\n3. Reconfigure your saved views manually\n\nYour task files are unaffected—only view configurations change.\n\n## View Templates\n\nFor complete `.base` file examples, see [Default Base Templates](views/default-base-templates.md).\n","aliases":["/migration-v3-to-v4/"],"toc":[{"level":2,"id":"requirements","text":"Requirements"},{"level":2,"id":"what-changed","text":"What Changed"},{"level":3,"id":"views-are-now-bases-files","text":"Views are Now Bases Files"},{"level":3,"id":"automatic-migration-on-first-launch","text":"Automatic Migration on First Launch"},{"level":3,"id":"converting-saved-filter-views","text":"Converting Saved Filter Views"},{"level":2,"id":"breaking-changes","text":"Breaking Changes"},{"level":3,"id":"view-configuration","text":"View Configuration"},{"level":3,"id":"minimum-obsidian-version","text":"Minimum Obsidian Version"},{"level":2,"id":"new-features-in-v4","text":"New Features in v4"},{"level":3,"id":"oauth-calendar-integration","text":"OAuth Calendar Integration"},{"level":3,"id":"kanban-swimlanes","text":"Kanban Swimlanes"},{"level":3,"id":"time-entry-editor","text":"Time Entry Editor"},{"level":2,"id":"troubleshooting","text":"Troubleshooting"},{"level":3,"id":"views-not-loading","text":"Views Not Loading"},{"level":3,"id":"missing-saved-views-after-upgrade","text":"Missing Saved Views After Upgrade"},{"level":3,"id":"filter-syntax-errors","text":"Filter Syntax Errors"},{"level":3,"id":"downgrading-to-v3","text":"Downgrading to v3"},{"level":2,"id":"view-templates","text":"View Templates"}],"html":"

TaskNotes v4 migrates all views to the Bases system. This guide covers what changed and how to update your setup.

\n\n

Requirements#

\n
    \n
  • Obsidian 1.10.1 or later for early TaskNotes v4 releases
  • \n
  • Obsidian 1.12.2 or later for the current TaskNotes 4.12.3 release
  • \n
  • Bases core plugin enabled (Settings → Core Plugins → Bases)
  • \n
\n

What Changed#

\n

Views are Now Bases Files#

\n

All task views (Task List, Kanban, Calendar, Agenda) are now .base files stored in TaskNotes/Views/. This replaces the custom view system in v3.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
v3v4
Views stored in plugin settingsViews stored as .base files
Custom filter UIBases filter syntax
Saved views in settingsDefault views are separate files; exported v3 saved views share one multi-view file
\n

Automatic Migration on First Launch#

\n

When you first open TaskNotes v4:

\n
    \n
  1. Default .base files are created in TaskNotes/Views/
  2. \n
  3. Ribbon icons and commands now open these .base files
  4. \n
  5. Your existing task files are unchanged
  6. \n
\n

Converting Saved Filter Views#

\n

If you had saved filter views in v3, you can export them to one .base file:

\n
    \n
  1. Go to Settings → TaskNotes → General → Views & base files.
  2. \n
  3. Find Export v3 saved views to Bases.
  4. \n
  5. Run the export.
  6. \n
  7. TaskNotes creates TaskNotes/Views/all-saved-views.base with one Base view for each saved v3 view.
  8. \n
\n

This is a one-way conversion. The original saved views remain in settings until you delete them.

\n

Breaking Changes#

\n

View Configuration#

\n

v3 saved views with custom filters need manual conversion to Bases filter syntax. Simple filters (status, priority, due date) convert automatically. Complex filters may need adjustment.

\n

v3 Filter Example:

\n
status: in-progress\npriority: high\n

v4 Bases Syntax:

\n
filters:\n  and:\n    - status == "in-progress"\n    - priority == "high"\n

See the Obsidian Bases documentation for filter syntax details.

\n

Minimum Obsidian Version#

\n

Early v4 releases required Obsidian 1.10.1. The current release requirement is generated on the version compatibility page. Use the manifest requirement for the exact TaskNotes version you install.

\n

New Features in v4#

\n

OAuth Calendar Integration#

\n

v4 adds Google Calendar and Microsoft Outlook integration:

\n
    \n
  • View external calendar events alongside tasks
  • \n
  • Drag events to reschedule (syncs back to calendar provider)
  • \n
  • Events sync every 15 minutes
  • \n
\n

See Calendar Setup for configuration.

\n

Kanban Swimlanes#

\n

The Kanban view now supports horizontal swimlane grouping:

\n
views:\n  - type: tasknotesKanban\n    groupBy:\n      property: status\n    config:\n      swimLane: priority\n

Time Entry Editor#

\n

A dedicated modal for managing time entries:

\n
    \n
  • Alt-drag on calendar to create time entries
  • \n
  • View total tracked time per task
  • \n
  • Edit and delete time entries
  • \n
\n

Troubleshooting#

\n

Views Not Loading#

\n
    \n
  1. Verify Bases core plugin is enabled (Settings → Core Plugins)
  2. \n
  3. Check that .base files exist in TaskNotes/Views/
  4. \n
  5. Restart Obsidian
  6. \n
\n

Missing Saved Views After Upgrade#

\n

Saved views from v3 are preserved in settings. Use Export v3 saved views to Bases in Settings → TaskNotes → General → Views & base files to create the multi-view .base file.

\n

Filter Syntax Errors#

\n

Bases uses different filter syntax than v3. Common issues:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
ProblemSolution
status: doneUse status == "done"
Multiple conditionsWrap in and: or or: block
Date comparisonsUse date(due) < today()
\n

Downgrading to v3#

\n

Migration is one-way. If you need to downgrade:

\n
    \n
  1. Uninstall TaskNotes v4
  2. \n
  3. Install TaskNotes v3 from releases
  4. \n
  5. Reconfigure your saved views manually
  6. \n
\n

Your task files are unaffected—only view configurations change.

\n

View Templates#

\n

For complete .base file examples, see Default Base Templates.

\n","text":"TaskNotes v4 migrates all views to the Bases system. This guide covers what changed and how to update your setup. Back up before migratingBack up the complete vault, including the hidden .obsidian directory, before changing views or plugin data. Requirements# Obsidian 1.10.1 or later for early TaskNotes v4 releases Obsidian 1.12.2 or later for the current TaskNotes 4.12.3 release Bases core plugin enabled (Settings → Core Plugins → Bases) What Changed# Views are Now Bases Files# All task views (Task List, Kanban, Calendar, Agenda) are now .base files stored in TaskNotes/Views/. This replaces the custom view system in v3. v3 v4 Views stored in plugin settings Views stored as .base files Custom filter UI Bases filter syntax Saved views in settings Default views are separate files; exported v3 saved views share one multi-view file Automatic Migration on First Launch# When you first open TaskNotes v4: Default .base files are created in TaskNotes/Views/ Ribbon icons and commands now open these .base files Your existing task files are unchanged Converting Saved Filter Views# If you had saved filter views in v3, you can export them to one .base file: Go to Settings → TaskNotes → General → Views & base files. Find Export v3 saved views to Bases. Run the export. TaskNotes creates TaskNotes/Views/all-saved-views.base with one Base view for each saved v3 view. This is a one-way conversion. The original saved views remain in settings until you delete them. Breaking Changes# View Configuration# v3 saved views with custom filters need manual conversion to Bases filter syntax. Simple filters (status, priority, due date) convert automatically. Complex filters may need adjustment. v3 Filter Example: status: in-progress priority: high v4 Bases Syntax: filters: and: - status == \"in-progress\" - priority == \"high\" See the Obsidian Bases documentation for filter syntax details. Minimum Obsidian Version# Early v4 releases required Obsidian 1.10.1. The current release requirement is generated on the version compatibility page. Use the manifest requirement for the exact TaskNotes version you install. New Features in v4# OAuth Calendar Integration# v4 adds Google Calendar and Microsoft Outlook integration: View external calendar events alongside tasks Drag events to reschedule (syncs back to calendar provider) Events sync every 15 minutes See Calendar Setup for configuration. Kanban Swimlanes# The Kanban view now supports horizontal swimlane grouping: views: - type: tasknotesKanban groupBy: property: status config: swimLane: priority Time Entry Editor# A dedicated modal for managing time entries: Alt-drag on calendar to create time entries View total tracked time per task Edit and delete time entries Troubleshooting# Views Not Loading# Verify Bases core plugin is enabled (Settings → Core Plugins) Check that .base files exist in TaskNotes/Views/ Restart Obsidian Missing Saved Views After Upgrade# Saved views from v3 are preserved in settings. Use Export v3 saved views to Bases in Settings → TaskNotes → General → Views & base files to create the multi-view .base file. Filter Syntax Errors# Bases uses different filter syntax than v3. Common issues: Problem Solution status: done Use status == \"done\" Multiple conditions Wrap in and: or or: block Date comparisons Use date(due) < today() Downgrading to v3# Migration is one-way. If you need to downgrade: Uninstall TaskNotes v4 Install TaskNotes v3 from releases Reconfigure your saved views manually Your task files are unaffected—only view configurations change. View Templates# For complete .base file examples, see Default Base Templates."},{"route":"/obsidian/nlp-api/","title":"TaskNotes NLP API","description":"The NLP API parses natural-language task text and optionally creates a task.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/nlp-api.md","namespace":"obsidian","relativePath":"nlp-api.md","raw":"# TaskNotes NLP API\n\nThe NLP API parses natural-language task text and optionally creates a task.\n\nIn-vault scripts can also call the parser directly from the loaded plugin:\n\n```javascript\nconst tasknotes = app.plugins.plugins.tasknotes;\nconst parsed = tasknotes.api.parseNaturalLanguage(\"Review PR tomorrow #code @work\");\n```\n\nFor the full in-process API exposed at `tasknotes.api`, including task updates, time tracking, settings snapshots, and events, see [TaskNotes JavaScript API](javascript-api.md).\n\n## Endpoints\n\n- `POST /api/nlp/parse`\n- `POST /api/nlp/create`\n\nBoth endpoints require a JSON body with `text`.\n\n## Request Format\n\n```json\n{\n \"text\": \"Review PR #123 tomorrow high priority @work\"\n}\n```\n\nNotes:\n\n- `text` is required and must be a string.\n- Per-request `locale` is not currently supported.\n- Parser language comes from TaskNotes settings (`nlpLanguage`).\n\n## `POST /api/nlp/parse`\n\nParses text and returns two objects:\n\n- `parsed`: direct parser output\n- `taskData`: normalized task payload that would be used for creation\n\nExample response (shape):\n\n```json\n{\n \"success\": true,\n \"data\": {\n \"parsed\": {\n \"title\": \"Review PR\",\n \"tags\": [\"123\"],\n \"contexts\": [\"work\"],\n \"projects\": [],\n \"priority\": \"high\",\n \"status\": null,\n \"dueDate\": \"2026-02-22\",\n \"scheduledDate\": null,\n \"dueTime\": null,\n \"scheduledTime\": null,\n \"recurrence\": null,\n \"estimate\": null,\n \"isCompleted\": false\n },\n \"taskData\": {\n \"title\": \"Review PR\",\n \"priority\": \"high\",\n \"status\": \"open\",\n \"tags\": [\"123\"],\n \"contexts\": [\"work\"],\n \"due\": \"2026-02-22\",\n \"dateCreated\": \"2026-02-22T09:00:00.000Z\",\n \"dateModified\": \"2026-02-22T09:00:00.000Z\"\n }\n }\n}\n```\n\nIf parser does not detect status, `taskData.status` falls back to your configured default task status. Parsed due and scheduled date-times in `taskData` use the same `YYYY-MM-DDTHH:mm` format as created tasks, and NLP trigger values for user-defined fields are returned under `customFrontmatter`.\n\n## `POST /api/nlp/create`\n\nParses text and creates a task in one call.\n\nReturns HTTP `201` on success.\n\nExample:\n\n```bash\ncurl -X POST http://localhost:8080/api/nlp/create \\\n -H \"Content-Type: application/json\" \\\n -d '{\"text\":\"Call mom due friday 2pm #personal\"}'\n```\n\nResponse fields:\n\n- `data.task` (created task)\n- `data.parsed` (parser output)\n\n## What the Parser Extracts\n\nThe parser can extract:\n\n- Dates and times (`tomorrow`, `friday 2pm`, ISO dates)\n- Priority terms (`high priority`, `urgent`, symbol patterns)\n- Status terms (mapped to your configured statuses)\n- Tags (`#tag`)\n- Contexts (`@context`)\n- Projects (`+project`)\n- Time estimates (`2h`, `30min`, `estimate 45m`)\n- Recurrence (`daily`, `weekly`, `every monday`)\n\nExact parsing behavior depends on your TaskNotes NLP settings and trigger configuration.\n\n## In-Vault Parser Method\n\nTemplater, QuickAdd, MetaBind, and other in-vault scripts can use the loaded plugin instance directly:\n\n```javascript\nconst tasknotes = app.plugins.plugins.tasknotes;\nconst parsed = tasknotes.api.parseNaturalLanguage(\"Write draft friday 2pm #writing @desk\");\n```\n\n`parseNaturalLanguage(text)` returns the same parser output shape as `data.parsed` from `POST /api/nlp/parse`. It uses your current TaskNotes settings, including custom status values, priority values, NLP language, NLP trigger configuration, user fields, and calendar locale.\n\nThis method only parses text. It does not create or modify task files.\n\nFor task creation and updates from in-vault scripts or companion plugins, use the broader [TaskNotes JavaScript API](javascript-api.md).\n\nExample Templater use:\n\n```javascript\n<%*\nconst tasknotes = app.plugins.plugins.tasknotes;\nconst text = await tp.system.prompt(\"Task\");\nconst parsed = tasknotes.api.parseNaturalLanguage(text);\ntR += `title: ${parsed.title}`;\n%>\n```\n\n## Error Responses\n\nCommon errors:\n\n- `400`: missing/invalid `text`\n- `401`: auth required (if API token is enabled)\n- `500`: parse/processing error\n\nError shape:\n\n```json\n{\n \"success\": false,\n \"error\": \"Text field is required and must be a string\"\n}\n```\n\n## Client Examples\n\n### JavaScript\n\n```javascript\nasync function parseTask(text) {\n const response = await fetch(\"http://localhost:8080/api/nlp/parse\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ text })\n });\n return response.json();\n}\n\nasync function createTaskFromText(text) {\n const response = await fetch(\"http://localhost:8080/api/nlp/create\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ text })\n });\n return response.json();\n}\n```\n\n### Python\n\n```python\nimport requests\n\n\ndef parse_task(text):\n response = requests.post(\n \"http://localhost:8080/api/nlp/parse\",\n json={\"text\": text},\n )\n return response.json()\n\n\ndef create_task_from_text(text):\n response = requests.post(\n \"http://localhost:8080/api/nlp/create\",\n json={\"text\": text},\n )\n return response.json()\n```\n\n## Authentication\n\nIf API auth token is enabled, include bearer token:\n\n```http\nAuthorization: Bearer YOUR_TOKEN\n```\n","aliases":["/nlp-api/"],"toc":[{"level":2,"id":"endpoints","text":"Endpoints"},{"level":2,"id":"request-format","text":"Request Format"},{"level":2,"id":"post-apinlpparse","text":"POST /api/nlp/parse"},{"level":2,"id":"post-apinlpcreate","text":"POST /api/nlp/create"},{"level":2,"id":"what-the-parser-extracts","text":"What the Parser Extracts"},{"level":2,"id":"in-vault-parser-method","text":"In-Vault Parser Method"},{"level":2,"id":"error-responses","text":"Error Responses"},{"level":2,"id":"client-examples","text":"Client Examples"},{"level":3,"id":"javascript","text":"JavaScript"},{"level":3,"id":"python","text":"Python"},{"level":2,"id":"authentication","text":"Authentication"}],"html":"

The NLP API parses natural-language task text and optionally creates a task.

\n

In-vault scripts can also call the parser directly from the loaded plugin:

\n
const tasknotes = app.plugins.plugins.tasknotes;\nconst parsed = tasknotes.api.parseNaturalLanguage("Review PR tomorrow #code @work");\n

For the full in-process API exposed at tasknotes.api, including task updates, time tracking, settings snapshots, and events, see TaskNotes JavaScript API.

\n

Endpoints#

\n
    \n
  • POST /api/nlp/parse
  • \n
  • POST /api/nlp/create
  • \n
\n

Both endpoints require a JSON body with text.

\n

Request Format#

\n
{\n  "text": "Review PR #123 tomorrow high priority @work"\n}\n

Notes:

\n
    \n
  • text is required and must be a string.
  • \n
  • Per-request locale is not currently supported.
  • \n
  • Parser language comes from TaskNotes settings (nlpLanguage).
  • \n
\n

POST /api/nlp/parse#

\n

Parses text and returns two objects:

\n
    \n
  • parsed: direct parser output
  • \n
  • taskData: normalized task payload that would be used for creation
  • \n
\n

Example response (shape):

\n
{\n  "success": true,\n  "data": {\n    "parsed": {\n      "title": "Review PR",\n      "tags": ["123"],\n      "contexts": ["work"],\n      "projects": [],\n      "priority": "high",\n      "status": null,\n      "dueDate": "2026-02-22",\n      "scheduledDate": null,\n      "dueTime": null,\n      "scheduledTime": null,\n      "recurrence": null,\n      "estimate": null,\n      "isCompleted": false\n    },\n    "taskData": {\n      "title": "Review PR",\n      "priority": "high",\n      "status": "open",\n      "tags": ["123"],\n      "contexts": ["work"],\n      "due": "2026-02-22",\n      "dateCreated": "2026-02-22T09:00:00.000Z",\n      "dateModified": "2026-02-22T09:00:00.000Z"\n    }\n  }\n}\n

If parser does not detect status, taskData.status falls back to your configured default task status. Parsed due and scheduled date-times in taskData use the same YYYY-MM-DDTHH:mm format as created tasks, and NLP trigger values for user-defined fields are returned under customFrontmatter.

\n

POST /api/nlp/create#

\n

Parses text and creates a task in one call.

\n

Returns HTTP 201 on success.

\n

Example:

\n
curl -X POST http://localhost:8080/api/nlp/create \\\n  -H "Content-Type: application/json" \\\n  -d '{"text":"Call mom due friday 2pm #personal"}'\n

Response fields:

\n
    \n
  • data.task (created task)
  • \n
  • data.parsed (parser output)
  • \n
\n

What the Parser Extracts#

\n

The parser can extract:

\n
    \n
  • Dates and times (tomorrow, friday 2pm, ISO dates)
  • \n
  • Priority terms (high priority, urgent, symbol patterns)
  • \n
  • Status terms (mapped to your configured statuses)
  • \n
  • Tags (#tag)
  • \n
  • Contexts (@context)
  • \n
  • Projects (+project)
  • \n
  • Time estimates (2h, 30min, estimate 45m)
  • \n
  • Recurrence (daily, weekly, every monday)
  • \n
\n

Exact parsing behavior depends on your TaskNotes NLP settings and trigger configuration.

\n

In-Vault Parser Method#

\n

Templater, QuickAdd, MetaBind, and other in-vault scripts can use the loaded plugin instance directly:

\n
const tasknotes = app.plugins.plugins.tasknotes;\nconst parsed = tasknotes.api.parseNaturalLanguage("Write draft friday 2pm #writing @desk");\n

parseNaturalLanguage(text) returns the same parser output shape as data.parsed from POST /api/nlp/parse. It uses your current TaskNotes settings, including custom status values, priority values, NLP language, NLP trigger configuration, user fields, and calendar locale.

\n

This method only parses text. It does not create or modify task files.

\n

For task creation and updates from in-vault scripts or companion plugins, use the broader TaskNotes JavaScript API.

\n

Example Templater use:

\n
<%*\nconst tasknotes = app.plugins.plugins.tasknotes;\nconst text = await tp.system.prompt("Task");\nconst parsed = tasknotes.api.parseNaturalLanguage(text);\ntR += `title: ${parsed.title}`;\n%>\n

Error Responses#

\n

Common errors:

\n
    \n
  • 400: missing/invalid text
  • \n
  • 401: auth required (if API token is enabled)
  • \n
  • 500: parse/processing error
  • \n
\n

Error shape:

\n
{\n  "success": false,\n  "error": "Text field is required and must be a string"\n}\n

Client Examples#

\n

JavaScript#

\n
async function parseTask(text) {\n  const response = await fetch("http://localhost:8080/api/nlp/parse", {\n    method: "POST",\n    headers: { "Content-Type": "application/json" },\n    body: JSON.stringify({ text })\n  });\n  return response.json();\n}\n\nasync function createTaskFromText(text) {\n  const response = await fetch("http://localhost:8080/api/nlp/create", {\n    method: "POST",\n    headers: { "Content-Type": "application/json" },\n    body: JSON.stringify({ text })\n  });\n  return response.json();\n}\n

Python#

\n
import requests\n\n\ndef parse_task(text):\n    response = requests.post(\n        "http://localhost:8080/api/nlp/parse",\n        json={"text": text},\n    )\n    return response.json()\n\n\ndef create_task_from_text(text):\n    response = requests.post(\n        "http://localhost:8080/api/nlp/create",\n        json={"text": text},\n    )\n    return response.json()\n

Authentication#

\n

If API auth token is enabled, include bearer token:

\n
Authorization: Bearer YOUR_TOKEN\n
","text":"The NLP API parses natural-language task text and optionally creates a task. In-vault scripts can also call the parser directly from the loaded plugin: const tasknotes = app.plugins.plugins.tasknotes; const parsed = tasknotes.api.parseNaturalLanguage(\"Review PR tomorrow #code @work\"); For the full in-process API exposed at tasknotes.api, including task updates, time tracking, settings snapshots, and events, see TaskNotes JavaScript API. Endpoints# POST /api/nlp/parse POST /api/nlp/create Both endpoints require a JSON body with text. Request Format# { \"text\": \"Review PR #123 tomorrow high priority @work\" } Notes: text is required and must be a string. Per-request locale is not currently supported. Parser language comes from TaskNotes settings (nlpLanguage). POST /api/nlp/parse# Parses text and returns two objects: parsed: direct parser output taskData: normalized task payload that would be used for creation Example response (shape): { \"success\": true, \"data\": { \"parsed\": { \"title\": \"Review PR\", \"tags\": [\"123\"], \"contexts\": [\"work\"], \"projects\": [], \"priority\": \"high\", \"status\": null, \"dueDate\": \"2026-02-22\", \"scheduledDate\": null, \"dueTime\": null, \"scheduledTime\": null, \"recurrence\": null, \"estimate\": null, \"isCompleted\": false }, \"taskData\": { \"title\": \"Review PR\", \"priority\": \"high\", \"status\": \"open\", \"tags\": [\"123\"], \"contexts\": [\"work\"], \"due\": \"2026-02-22\", \"dateCreated\": \"2026-02-22T09:00:00.000Z\", \"dateModified\": \"2026-02-22T09:00:00.000Z\" } } } If parser does not detect status, taskData.status falls back to your configured default task status. Parsed due and scheduled date-times in taskData use the same YYYY-MM-DDTHH:mm format as created tasks, and NLP trigger values for user-defined fields are returned under customFrontmatter. POST /api/nlp/create# Parses text and creates a task in one call. Returns HTTP 201 on success. Example: curl -X POST http://localhost:8080/api/nlp/create \\ -H \"Content-Type: application/json\" \\ -d '{\"text\":\"Call mom due friday 2pm #personal\"}' Response fields: data.task (created task) data.parsed (parser output) What the Parser Extracts# The parser can extract: Dates and times (tomorrow, friday 2pm, ISO dates) Priority terms (high priority, urgent, symbol patterns) Status terms (mapped to your configured statuses) Tags (#tag) Contexts (@context) Projects (+project) Time estimates (2h, 30min, estimate 45m) Recurrence (daily, weekly, every monday) Exact parsing behavior depends on your TaskNotes NLP settings and trigger configuration. In-Vault Parser Method# Templater, QuickAdd, MetaBind, and other in-vault scripts can use the loaded plugin instance directly: const tasknotes = app.plugins.plugins.tasknotes; const parsed = tasknotes.api.parseNaturalLanguage(\"Write draft friday 2pm #writing @desk\"); parseNaturalLanguage(text) returns the same parser output shape as data.parsed from POST /api/nlp/parse. It uses your current TaskNotes settings, including custom status values, priority values, NLP language, NLP trigger configuration, user fields, and calendar locale. This method only parses text. It does not create or modify task files. For task creation and updates from in-vault scripts or companion plugins, use the broader TaskNotes JavaScript API. Example Templater use: <%* const tasknotes = app.plugins.plugins.tasknotes; const text = await tp.system.prompt(\"Task\"); const parsed = tasknotes.api.parseNaturalLanguage(text); tR += `title: ${parsed.title}`; %> Error Responses# Common errors: 400: missing/invalid text 401: auth required (if API token is enabled) 500: parse/processing error Error shape: { \"success\": false, \"error\": \"Text field is required and must be a string\" } Client Examples# JavaScript# async function parseTask(text) { const response = await fetch(\"http://localhost:8080/api/nlp/parse\", { method: \"POST\", headers: { \"Content-Type\": \"application/json\" }, body: JSON.stringify({ text }) }); return response.json(); } async function createTaskFromText(text) { const response = await fetch(\"http://localhost:8080/api/nlp/create\", { method: \"POST\", headers: { \"Content-Type\": \"application/json\" }, body: JSON.stringify({ text }) }); return response.json(); } Python# import requests def parse_task(text): response = requests.post( \"http://localhost:8080/api/nlp/parse\", json={\"text\": text}, ) return response.json() def create_task_from_text(text): response = requests.post( \"http://localhost:8080/api/nlp/create\", json={\"text\": text}, ) return response.json() Authentication# If API auth token is enabled, include bearer token: Authorization: Bearer YOUR_TOKEN"},{"route":"/obsidian/obsidian-cli/","title":"TaskNotes Obsidian CLI","description":"TaskNotes can register commands directly with the Obsidian desktop CLI. This is useful when Obsidian is already running and you want shell access to task creation, time tracking...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/obsidian-cli.md","namespace":"obsidian","relativePath":"obsidian-cli.md","raw":"# TaskNotes Obsidian CLI\n\nTaskNotes can register commands directly with the Obsidian desktop CLI. This is useful when Obsidian is already running and you want shell access to task creation, time tracking, or Pomodoro control without going through the HTTP API.\n\nUse this page for the built-in `obsidian ...` commands exposed by the plugin itself. If you want a standalone terminal tool that works directly on Markdown files without Obsidian running, see [mdbase-tasknotes CLI](mdbase-tasknotes-cli.md).\n\n## Requirements\n\n- Obsidian desktop `1.12.2` or newer\n- TaskNotes installed and enabled in the target vault\n- Obsidian running when you invoke the CLI\n\nThe Obsidian CLI resolves commands against a vault context. In practice, it is safer to pass `vault=` explicitly instead of relying on the default vault.\n\n## Discovering commands\n\nList available TaskNotes commands:\n\n```bash\nobsidian help | rg 'tasknotes:'\n```\n\nYou should see:\n\n- `tasknotes:capture`\n- `tasknotes:start-time`\n- `tasknotes:stop-time`\n- `tasknotes:time-status`\n- `tasknotes:pomodoro`\n\n## `tasknotes:capture`\n\nCreate a task from free text, explicit flags, or both.\n\n```bash\nobsidian tasknotes:capture vault=test text=\"Review PR tomorrow #work @desk\"\n```\n\nBy default, `text=` is parsed with TaskNotes NLP. Explicit flags override parsed values.\n\n### Literal title mode\n\nUse `literal` when you want the text treated as an exact title instead of being parsed.\n\n```bash\nobsidian tasknotes:capture vault=test text=\"Fix parser edge case\" literal\n```\n\n### Explicit fields\n\nSupported override flags:\n\n- `title`\n- `details`\n- `status`\n- `priority`\n- `due`\n- `scheduled`\n- `tags`\n- `contexts`\n- `projects`\n- `recurrence`\n- `recurrence-anchor`\n- `reminders`\n- `estimate`\n\nExample:\n\n```bash\nobsidian tasknotes:capture vault=test \\\n text=\"Write release notes tomorrow #docs\" \\\n priority=high \\\n status=in-progress \\\n reminders='due:-PT1H'\n```\n\n### Reminder format\n\n`reminders=` accepts either:\n\n- a semicolon-separated shorthand such as `due:-PT1H;scheduled:-PT30M;at:2026-04-02T09:00`\n- a JSON array in the same shape TaskNotes stores internally\n\n### Recurrence anchor\n\nUse `recurrence-anchor=scheduled` or `recurrence-anchor=completion` to control how recurring tasks advance.\n\n## `tasknotes:start-time`\n\nStart time tracking for a task.\n\nYou can target a task by:\n\n- `path`\n- exact `title`\n- fuzzy `query`\n\nExamples:\n\n```bash\nobsidian tasknotes:start-time vault=test title=\"Write release notes\"\nobsidian tasknotes:start-time vault=test query=\"release notes\" description=\"Drafting first pass\"\nobsidian tasknotes:start-time vault=test path=\"TaskNotes/Write release notes.md\"\n```\n\n## `tasknotes:stop-time`\n\nStop time tracking for a task.\n\nExamples:\n\n```bash\nobsidian tasknotes:stop-time vault=test title=\"Write release notes\"\nobsidian tasknotes:stop-time vault=test path=\"TaskNotes/Write release notes.md\"\n```\n\nIf you omit task lookup flags, TaskNotes will stop the only active session when that is unambiguous.\n\n## `tasknotes:time-status`\n\nShow time-tracking status for either:\n\n- all active sessions\n- one resolved task\n\nExamples:\n\n```bash\nobsidian tasknotes:time-status vault=test\nobsidian tasknotes:time-status vault=test title=\"Write release notes\"\nobsidian tasknotes:time-status vault=test path=\"TaskNotes/Write release notes.md\"\n```\n\nWhen a task is targeted, the command returns that task's summary, active session, and time entries. With no lookup flags, it returns the currently active sessions across the vault.\n\n## `tasknotes:pomodoro`\n\nControl Pomodoro state from the CLI.\n\nSupported actions:\n\n- `status`\n- `start`\n- `pause`\n- `resume`\n- `stop`\n- `short-break`\n- `long-break`\n\n### Inspect state\n\n```bash\nobsidian tasknotes:pomodoro vault=test action=status\n```\n\n### Start a work session\n\nYou can start a Pomodoro with or without a linked task.\n\n```bash\nobsidian tasknotes:pomodoro vault=test action=start duration=25\nobsidian tasknotes:pomodoro vault=test action=start title=\"Write release notes\" duration=25\n```\n\nTask lookup for `action=start` supports the same selectors as time tracking:\n\n- `path`\n- exact `title`\n- fuzzy `query`\n\n### Pause, resume, and stop\n\n```bash\nobsidian tasknotes:pomodoro vault=test action=pause\nobsidian tasknotes:pomodoro vault=test action=resume\nobsidian tasknotes:pomodoro vault=test action=stop\n```\n\n### Breaks\n\n```bash\nobsidian tasknotes:pomodoro vault=test action=short-break\nobsidian tasknotes:pomodoro vault=test action=long-break\n```\n\n## Choosing between CLI surfaces\n\nUse the built-in Obsidian CLI when:\n\n- Obsidian is already open\n- you want plugin-aware behavior, including current cache, defaults, templates, time tracking, and Pomodoro state\n- you are scripting on the same machine as the running vault\n\nUse [mdbase-tasknotes CLI](mdbase-tasknotes-cli.md) when:\n\n- Obsidian is not running\n- you need headless/server workflows\n- you want direct file-level automation over a task collection\n\n## Notes\n\n- `path` is the most reliable task selector for automation.\n- Immediately after creating a task, exact title lookup can lag briefly until the in-memory cache catches up.\n- These commands are desktop-only because they depend on the Obsidian desktop CLI.\n","aliases":["/obsidian-cli/"],"toc":[{"level":2,"id":"requirements","text":"Requirements"},{"level":2,"id":"discovering-commands","text":"Discovering commands"},{"level":2,"id":"tasknotescapture","text":"tasknotes:capture"},{"level":3,"id":"literal-title-mode","text":"Literal title mode"},{"level":3,"id":"explicit-fields","text":"Explicit fields"},{"level":3,"id":"reminder-format","text":"Reminder format"},{"level":3,"id":"recurrence-anchor","text":"Recurrence anchor"},{"level":2,"id":"tasknotesstart-time","text":"tasknotes:start-time"},{"level":2,"id":"tasknotesstop-time","text":"tasknotes:stop-time"},{"level":2,"id":"tasknotestime-status","text":"tasknotes:time-status"},{"level":2,"id":"tasknotespomodoro","text":"tasknotes:pomodoro"},{"level":3,"id":"inspect-state","text":"Inspect state"},{"level":3,"id":"start-a-work-session","text":"Start a work session"},{"level":3,"id":"pause-resume-and-stop","text":"Pause, resume, and stop"},{"level":3,"id":"breaks","text":"Breaks"},{"level":2,"id":"choosing-between-cli-surfaces","text":"Choosing between CLI surfaces"},{"level":2,"id":"notes","text":"Notes"}],"html":"

TaskNotes can register commands directly with the Obsidian desktop CLI. This is useful when Obsidian is already running and you want shell access to task creation, time tracking, or Pomodoro control without going through the HTTP API.

\n

Use this page for the built-in obsidian ... commands exposed by the plugin itself. If you want a standalone terminal tool that works directly on Markdown files without Obsidian running, see mdbase-tasknotes CLI.

\n

Requirements#

\n
    \n
  • Obsidian desktop 1.12.2 or newer
  • \n
  • TaskNotes installed and enabled in the target vault
  • \n
  • Obsidian running when you invoke the CLI
  • \n
\n

The Obsidian CLI resolves commands against a vault context. In practice, it is safer to pass vault=<name> explicitly instead of relying on the default vault.

\n

Discovering commands#

\n

List available TaskNotes commands:

\n
obsidian help | rg 'tasknotes:'\n

You should see:

\n
    \n
  • tasknotes:capture
  • \n
  • tasknotes:start-time
  • \n
  • tasknotes:stop-time
  • \n
  • tasknotes:time-status
  • \n
  • tasknotes:pomodoro
  • \n
\n

tasknotes:capture#

\n

Create a task from free text, explicit flags, or both.

\n
obsidian tasknotes:capture vault=test text="Review PR tomorrow #work @desk"\n

By default, text= is parsed with TaskNotes NLP. Explicit flags override parsed values.

\n

Literal title mode#

\n

Use literal when you want the text treated as an exact title instead of being parsed.

\n
obsidian tasknotes:capture vault=test text="Fix parser edge case" literal\n

Explicit fields#

\n

Supported override flags:

\n
    \n
  • title
  • \n
  • details
  • \n
  • status
  • \n
  • priority
  • \n
  • due
  • \n
  • scheduled
  • \n
  • tags
  • \n
  • contexts
  • \n
  • projects
  • \n
  • recurrence
  • \n
  • recurrence-anchor
  • \n
  • reminders
  • \n
  • estimate
  • \n
\n

Example:

\n
obsidian tasknotes:capture vault=test \\\n  text="Write release notes tomorrow #docs" \\\n  priority=high \\\n  status=in-progress \\\n  reminders='due:-PT1H'\n

Reminder format#

\n

reminders= accepts either:

\n
    \n
  • a semicolon-separated shorthand such as due:-PT1H;scheduled:-PT30M;at:2026-04-02T09:00
  • \n
  • a JSON array in the same shape TaskNotes stores internally
  • \n
\n

Recurrence anchor#

\n

Use recurrence-anchor=scheduled or recurrence-anchor=completion to control how recurring tasks advance.

\n

tasknotes:start-time#

\n

Start time tracking for a task.

\n

You can target a task by:

\n
    \n
  • path
  • \n
  • exact title
  • \n
  • fuzzy query
  • \n
\n

Examples:

\n
obsidian tasknotes:start-time vault=test title="Write release notes"\nobsidian tasknotes:start-time vault=test query="release notes" description="Drafting first pass"\nobsidian tasknotes:start-time vault=test path="TaskNotes/Write release notes.md"\n

tasknotes:stop-time#

\n

Stop time tracking for a task.

\n

Examples:

\n
obsidian tasknotes:stop-time vault=test title="Write release notes"\nobsidian tasknotes:stop-time vault=test path="TaskNotes/Write release notes.md"\n

If you omit task lookup flags, TaskNotes will stop the only active session when that is unambiguous.

\n

tasknotes:time-status#

\n

Show time-tracking status for either:

\n
    \n
  • all active sessions
  • \n
  • one resolved task
  • \n
\n

Examples:

\n
obsidian tasknotes:time-status vault=test\nobsidian tasknotes:time-status vault=test title="Write release notes"\nobsidian tasknotes:time-status vault=test path="TaskNotes/Write release notes.md"\n

When a task is targeted, the command returns that task's summary, active session, and time entries. With no lookup flags, it returns the currently active sessions across the vault.

\n

tasknotes:pomodoro#

\n

Control Pomodoro state from the CLI.

\n

Supported actions:

\n
    \n
  • status
  • \n
  • start
  • \n
  • pause
  • \n
  • resume
  • \n
  • stop
  • \n
  • short-break
  • \n
  • long-break
  • \n
\n

Inspect state#

\n
obsidian tasknotes:pomodoro vault=test action=status\n

Start a work session#

\n

You can start a Pomodoro with or without a linked task.

\n
obsidian tasknotes:pomodoro vault=test action=start duration=25\nobsidian tasknotes:pomodoro vault=test action=start title="Write release notes" duration=25\n

Task lookup for action=start supports the same selectors as time tracking:

\n
    \n
  • path
  • \n
  • exact title
  • \n
  • fuzzy query
  • \n
\n

Pause, resume, and stop#

\n
obsidian tasknotes:pomodoro vault=test action=pause\nobsidian tasknotes:pomodoro vault=test action=resume\nobsidian tasknotes:pomodoro vault=test action=stop\n

Breaks#

\n
obsidian tasknotes:pomodoro vault=test action=short-break\nobsidian tasknotes:pomodoro vault=test action=long-break\n

Choosing between CLI surfaces#

\n

Use the built-in Obsidian CLI when:

\n
    \n
  • Obsidian is already open
  • \n
  • you want plugin-aware behavior, including current cache, defaults, templates, time tracking, and Pomodoro state
  • \n
  • you are scripting on the same machine as the running vault
  • \n
\n

Use mdbase-tasknotes CLI when:

\n
    \n
  • Obsidian is not running
  • \n
  • you need headless/server workflows
  • \n
  • you want direct file-level automation over a task collection
  • \n
\n

Notes#

\n
    \n
  • path is the most reliable task selector for automation.
  • \n
  • Immediately after creating a task, exact title lookup can lag briefly until the in-memory cache catches up.
  • \n
  • These commands are desktop-only because they depend on the Obsidian desktop CLI.
  • \n
\n","text":"TaskNotes can register commands directly with the Obsidian desktop CLI. This is useful when Obsidian is already running and you want shell access to task creation, time tracking, or Pomodoro control without going through the HTTP API. Use this page for the built-in obsidian ... commands exposed by the plugin itself. If you want a standalone terminal tool that works directly on Markdown files without Obsidian running, see mdbase-tasknotes CLI. Requirements# Obsidian desktop 1.12.2 or newer TaskNotes installed and enabled in the target vault Obsidian running when you invoke the CLI The Obsidian CLI resolves commands against a vault context. In practice, it is safer to pass vault= explicitly instead of relying on the default vault. Discovering commands# List available TaskNotes commands: obsidian help | rg 'tasknotes:' You should see: tasknotes:capture tasknotes:start-time tasknotes:stop-time tasknotes:time-status tasknotes:pomodoro tasknotes:capture# Create a task from free text, explicit flags, or both. obsidian tasknotes:capture vault=test text=\"Review PR tomorrow #work @desk\" By default, text= is parsed with TaskNotes NLP. Explicit flags override parsed values. Literal title mode# Use literal when you want the text treated as an exact title instead of being parsed. obsidian tasknotes:capture vault=test text=\"Fix parser edge case\" literal Explicit fields# Supported override flags: title details status priority due scheduled tags contexts projects recurrence recurrence-anchor reminders estimate Example: obsidian tasknotes:capture vault=test \\ text=\"Write release notes tomorrow #docs\" \\ priority=high \\ status=in-progress \\ reminders='due:-PT1H' Reminder format# reminders= accepts either: a semicolon-separated shorthand such as due:-PT1H;scheduled:-PT30M;at:2026-04-02T09:00 a JSON array in the same shape TaskNotes stores internally Recurrence anchor# Use recurrence-anchor=scheduled or recurrence-anchor=completion to control how recurring tasks advance. tasknotes:start-time# Start time tracking for a task. You can target a task by: path exact title fuzzy query Examples: obsidian tasknotes:start-time vault=test title=\"Write release notes\" obsidian tasknotes:start-time vault=test query=\"release notes\" description=\"Drafting first pass\" obsidian tasknotes:start-time vault=test path=\"TaskNotes/Write release notes.md\" tasknotes:stop-time# Stop time tracking for a task. Examples: obsidian tasknotes:stop-time vault=test title=\"Write release notes\" obsidian tasknotes:stop-time vault=test path=\"TaskNotes/Write release notes.md\" If you omit task lookup flags, TaskNotes will stop the only active session when that is unambiguous. tasknotes:time-status# Show time-tracking status for either: all active sessions one resolved task Examples: obsidian tasknotes:time-status vault=test obsidian tasknotes:time-status vault=test title=\"Write release notes\" obsidian tasknotes:time-status vault=test path=\"TaskNotes/Write release notes.md\" When a task is targeted, the command returns that task's summary, active session, and time entries. With no lookup flags, it returns the currently active sessions across the vault. tasknotes:pomodoro# Control Pomodoro state from the CLI. Supported actions: status start pause resume stop short-break long-break Inspect state# obsidian tasknotes:pomodoro vault=test action=status Start a work session# You can start a Pomodoro with or without a linked task. obsidian tasknotes:pomodoro vault=test action=start duration=25 obsidian tasknotes:pomodoro vault=test action=start title=\"Write release notes\" duration=25 Task lookup for action=start supports the same selectors as time tracking: path exact title fuzzy query Pause, resume, and stop# obsidian tasknotes:pomodoro vault=test action=pause obsidian tasknotes:pomodoro vault=test action=resume obsidian tasknotes:pomodoro vault=test action=stop Breaks# obsidian tasknotes:pomodoro vault=test action=short-break obsidian tasknotes:pomodoro vault=test action=long-break Choosing between CLI surfaces# Use the built-in Obsidian CLI when: Obsidian is already open you want plugin-aware behavior, including current cache, defaults, templates, time tracking, and Pomodoro state you are scripting on the same machine as the running vault Use mdbase-tasknotes CLI when: Obsidian is not running you need headless/server workflows you want direct file-level automation over a task collection Notes# path is the most reliable task selector for automation. Immediately after creating a task, exact title lookup can lag briefly until the in-memory cache catches up. These commands are desktop-only because they depend on the Obsidian desktop CLI."},{"route":"/obsidian/reference/commands/","title":"Command reference","description":"Every TaskNotes command registered with Obsidian, generated from the plugin command definitions.","product":"obsidian","platforms":[],"version":"4.12.3","generated":true,"noIndex":false,"hideToc":false,"source":"tasknotes:docs-builder/src/generated-pages.js","namespace":"obsidian","relativePath":"reference/commands.md","raw":"---\ntitle: \"Command reference\"\ndescription: \"Every TaskNotes command registered with Obsidian, generated from the plugin command definitions.\"\ngenerated: true\nsource: [\"src/commands/taskNotesCommands.ts\",\"src/i18n/resources/en.ts\"]\n---\n# Command reference\n\nThis page is generated from the commands registered by TaskNotes. Command IDs are stable integration identifiers; names are the English labels shown in Obsidian.\n\n| Command | ID | Available in |\n| --- | --- | --- |\n| Open mini calendar view | `open-calendar-view` | Global |\n| Open calendar view | `open-advanced-calendar-view` | Global |\n| Open tasks view | `open-tasks-view` | Global |\n| Open agenda view | `open-agenda-view` | Global |\n| Open Pomodoro timer | `open-pomodoro-view` | Global |\n| Open Kanban board | `open-kanban-view` | Global |\n| Update default base files | `update-default-base-files` | Global |\n| Open Pomodoro statistics | `open-pomodoro-stats` | Global |\n| Open task & project statistics | `open-statistics` | Global |\n| Create new task | `create-new-task` | Global |\n| Convert current note to task | `convert-current-note-to-task` | Global |\n| Convert checkbox task to TaskNote | `convert-to-tasknote` | Editor |\n| Convert all tasks in note | `batch-convert-all-tasks` | Editor |\n| Insert tasknote link | `insert-tasknote-link` | Editor |\n| Create new inline task | `create-inline-task` | Editor |\n| Quick actions for current task | `quick-actions-current-task` | Global |\n| Quick actions for task under cursor | `quick-actions-task-under-cursor` | Editor |\n| Edit current task | `edit-current-task` | Global |\n| Cycle current task status | `cycle-current-task-status` | Global |\n| Cycle current task priority | `cycle-current-task-priority` | Global |\n| Add project to current task | `add-project-to-current-task` | Global |\n| Add subtask to current note | `add-subtask-to-current-note` | Global |\n| Go to today's note | `go-to-today` | Global |\n| Start Pomodoro timer | `start-pomodoro` | Global |\n| Stop Pomodoro timer | `stop-pomodoro` | Global |\n| Pause/resume Pomodoro timer | `pause-pomodoro` | Global |\n| Refresh cache | `refresh-cache` | Global |\n| Export all tasks as ICS file | `export-all-tasks-ics` | Global |\n| Sync all tasks to Google Calendar | `sync-all-tasks-google-calendar` | Global |\n| Sync current task to Google Calendar | `sync-current-task-google-calendar` | Global |\n| View release notes | `view-release-notes` | Global |\n| Start time tracking (select task) | `start-time-tracking-with-selector` | Global |\n| Edit time entries (select task) | `edit-time-entries` | Global |\n| Create or open task | `create-or-open-task` | Global |\n| Create or open task and start time tracking | `create-or-open-task-with-time-tracking` | Global |\n| Postpone overdue scheduled tasks to today | `rollover-overdue-scheduled-tasks` | Global |\n\n_Generated from 36 registered commands._\n","aliases":["/reference/commands/","/reference/commands/"],"toc":[],"html":"

This page is generated from the commands registered by TaskNotes. Command IDs are stable integration identifiers; names are the English labels shown in Obsidian.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
CommandIDAvailable in
Open mini calendar viewopen-calendar-viewGlobal
Open calendar viewopen-advanced-calendar-viewGlobal
Open tasks viewopen-tasks-viewGlobal
Open agenda viewopen-agenda-viewGlobal
Open Pomodoro timeropen-pomodoro-viewGlobal
Open Kanban boardopen-kanban-viewGlobal
Update default base filesupdate-default-base-filesGlobal
Open Pomodoro statisticsopen-pomodoro-statsGlobal
Open task & project statisticsopen-statisticsGlobal
Create new taskcreate-new-taskGlobal
Convert current note to taskconvert-current-note-to-taskGlobal
Convert checkbox task to TaskNoteconvert-to-tasknoteEditor
Convert all tasks in notebatch-convert-all-tasksEditor
Insert tasknote linkinsert-tasknote-linkEditor
Create new inline taskcreate-inline-taskEditor
Quick actions for current taskquick-actions-current-taskGlobal
Quick actions for task under cursorquick-actions-task-under-cursorEditor
Edit current taskedit-current-taskGlobal
Cycle current task statuscycle-current-task-statusGlobal
Cycle current task prioritycycle-current-task-priorityGlobal
Add project to current taskadd-project-to-current-taskGlobal
Add subtask to current noteadd-subtask-to-current-noteGlobal
Go to today's notego-to-todayGlobal
Start Pomodoro timerstart-pomodoroGlobal
Stop Pomodoro timerstop-pomodoroGlobal
Pause/resume Pomodoro timerpause-pomodoroGlobal
Refresh cacherefresh-cacheGlobal
Export all tasks as ICS fileexport-all-tasks-icsGlobal
Sync all tasks to Google Calendarsync-all-tasks-google-calendarGlobal
Sync current task to Google Calendarsync-current-task-google-calendarGlobal
View release notesview-release-notesGlobal
Start time tracking (select task)start-time-tracking-with-selectorGlobal
Edit time entries (select task)edit-time-entriesGlobal
Create or open taskcreate-or-open-taskGlobal
Create or open task and start time trackingcreate-or-open-task-with-time-trackingGlobal
Postpone overdue scheduled tasks to todayrollover-overdue-scheduled-tasksGlobal
\n

Generated from 36 registered commands.

\n","text":"This page is generated from the commands registered by TaskNotes. Command IDs are stable integration identifiers; names are the English labels shown in Obsidian. Command ID Available in Open mini calendar view open-calendar-view Global Open calendar view open-advanced-calendar-view Global Open tasks view open-tasks-view Global Open agenda view open-agenda-view Global Open Pomodoro timer open-pomodoro-view Global Open Kanban board open-kanban-view Global Update default base files update-default-base-files Global Open Pomodoro statistics open-pomodoro-stats Global Open task & project statistics open-statistics Global Create new task create-new-task Global Convert current note to task convert-current-note-to-task Global Convert checkbox task to TaskNote convert-to-tasknote Editor Convert all tasks in note batch-convert-all-tasks Editor Insert tasknote link insert-tasknote-link Editor Create new inline task create-inline-task Editor Quick actions for current task quick-actions-current-task Global Quick actions for task under cursor quick-actions-task-under-cursor Editor Edit current task edit-current-task Global Cycle current task status cycle-current-task-status Global Cycle current task priority cycle-current-task-priority Global Add project to current task add-project-to-current-task Global Add subtask to current note add-subtask-to-current-note Global Go to today's note go-to-today Global Start Pomodoro timer start-pomodoro Global Stop Pomodoro timer stop-pomodoro Global Pause/resume Pomodoro timer pause-pomodoro Global Refresh cache refresh-cache Global Export all tasks as ICS file export-all-tasks-ics Global Sync all tasks to Google Calendar sync-all-tasks-google-calendar Global Sync current task to Google Calendar sync-current-task-google-calendar Global View release notes view-release-notes Global Start time tracking (select task) start-time-tracking-with-selector Global Edit time entries (select task) edit-time-entries Global Create or open task create-or-open-task Global Create or open task and start time tracking create-or-open-task-with-time-tracking Global Postpone overdue scheduled tasks to today rollover-overdue-scheduled-tasks Global Generated from 36 registered commands."},{"route":"/obsidian/reference/compatibility/","title":"Version compatibility","description":"Current TaskNotes and Obsidian compatibility requirements, generated from the plugin manifest.","product":"obsidian","platforms":[],"version":"4.12.3","generated":true,"noIndex":false,"hideToc":false,"source":"tasknotes:docs-builder/src/generated-pages.js","namespace":"obsidian","relativePath":"reference/compatibility.md","raw":"---\ntitle: \"Version compatibility\"\ndescription: \"Current TaskNotes and Obsidian compatibility requirements, generated from the plugin manifest.\"\ngenerated: true\nsource: [\"manifest.json\",\"versions.json\"]\n---\n# Version compatibility\n\n## Current release\n\n| Item | Value |\n| --- | --- |\n| TaskNotes | `4.12.3` |\n| Minimum Obsidian version | `1.12.2` |\n| Desktop only | No |\n| Bases core plugin | Required |\n\nThe minimum version above applies to the current TaskNotes release. Older releases had different requirements; consult `versions.json` or the relevant [release note](/releases/) when maintaining an older installation.\n","aliases":["/reference/compatibility/","/reference/compatibility/"],"toc":[{"level":2,"id":"current-release","text":"Current release"}],"html":"

Current release#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
ItemValue
TaskNotes4.12.3
Minimum Obsidian version1.12.2
Desktop onlyNo
Bases core pluginRequired
\n

The minimum version above applies to the current TaskNotes release. Older releases had different requirements; consult versions.json or the relevant release note when maintaining an older installation.

\n","text":"Current release# Item Value TaskNotes 4.12.3 Minimum Obsidian version 1.12.2 Desktop only No Bases core plugin Required The minimum version above applies to the current TaskNotes release. Older releases had different requirements; consult versions.json or the relevant release note when maintaining an older installation."},{"route":"/obsidian/reference/default-base-templates/","title":"Generated default Base templates","description":"Exact default Obsidian Base files generated by the current TaskNotes source and default settings.","product":"obsidian","platforms":[],"version":"4.12.3","generated":true,"noIndex":false,"hideToc":false,"source":"tasknotes:docs-builder/src/generated-pages.js","namespace":"obsidian","relativePath":"reference/default-base-templates.md","raw":"---\ntitle: \"Generated default Base templates\"\ndescription: \"Exact default Obsidian Base files generated by the current TaskNotes source and default settings.\"\ngenerated: true\nsource: [\"src/templates/defaultBasesFiles.ts\",\"src/settings/defaults.ts\",\"src/core/FieldMapper.ts\"]\n---\n# Generated default Base templates\n\nThese are the exact templates TaskNotes 4.12.3 produces with default settings. Your generated files reflect your own field mapping and other settings, so customized output can differ.\n\nRegenerating with **Update files** overwrites configured default Base files. Copy a customized file to a new path before updating it.\n\n## mini-calendar-default.base\n\nCommand/template ID: `open-calendar-view`\n\n```yaml\n# Mini Calendar\n# Generated with your TaskNotes settings\n\nfilters:\n and:\n - file.hasTag(\"task\")\n\nformulas:\n priorityWeight: 'if(priority==\"none\",0,if(priority==\"low\",1,if(priority==\"normal\",2,if(priority==\"high\",3,999))))'\n daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n dueIn: 'if(due.isEmpty(), \"\", if(formula.daysUntilDue == 0, \"Today\", if(formula.daysUntilDue == 1, \"1 day\", if(formula.daysUntilDue > 1, formula.daysUntilDue + \" days\", if(formula.daysUntilDue == -1, \"1 day overdue\", formula.daysUntilDue * -1 + \" days overdue\")))))'\n daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != \"done\"'\n isDueToday: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isDueThisWeek: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")'\n isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isRecurring: 'recurrence && !recurrence.isEmpty()'\n hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - \"7d\").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n dueMonth: 'if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), \"No due date\")'\n dueWeek: 'if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), \"No due date\")'\n scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"Not scheduled\")'\n scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"Not scheduled\")'\n dueDateCategory: 'if(due.isEmpty(), \"No due date\", if(date(due) < today(), \"Overdue\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), \"This week\", \"Later\")))))'\n timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(timeEstimate < 30, \"Quick (<30m)\", if(timeEstimate <= 120, \"Medium (30m-2h)\", \"Long (>2h)\")))'\n ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, \"Today\", if(((number(now()) - number(file.ctime)) / 86400000) < 7, \"This week\", if(((number(now()) - number(file.ctime)) / 86400000) < 30, \"This month\", \"Older\")))'\n createdMonth: 'file.ctime.format(\"YYYY-MM\")'\n modifiedMonth: 'file.mtime.format(\"YYYY-MM\")'\n priorityCategory: 'if(priority==\"none\",\"None\",if(priority==\"low\",\"Low\",if(priority==\"normal\",\"Normal\",if(priority==\"high\",\"High\",\"No priority\"))))'\n projectCount: 'if(!projects || list(projects).length == 0, \"No projects\", if(list(projects).length == 1, \"Single project\", \"Multiple projects\"))'\n contextCount: 'if(!contexts || list(contexts).length == 0, \"No contexts\", if(list(contexts).length == 1, \"Single context\", \"Multiple contexts\"))'\n trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(!timeEntries || list(timeEntries).length == 0, \"Not started\", if(formula.efficiencyRatio < 100, \"Under estimate\", \"Over estimate\")))'\n nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n isToday: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"))'\n isThisWeek: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"))'\n nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), \"No date\", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), \"Overdue/Past\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")), \"Today\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")), \"Tomorrow\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")), \"This week\", \"Later\")))))'\n nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-MM\"), date(scheduled).format(\"YYYY-MM\")), if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"No date\")))'\n nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-[W]WW\"), date(scheduled).format(\"YYYY-[W]WW\")), if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"No date\")))'\n urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format(\"YYYY-MM-DD\")))) / 86400000)))'\n timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + \"h \" + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + \"m\", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + \"m\"), \"0m\")'\n dueDateDisplay: 'if(due.isEmpty(), \"\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") == (today() - \"1 day\").format(\"YYYY-MM-DD\"), \"Yesterday\", if(date(due) < today(), formula.daysUntilDue * -1 + \"d ago\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), date(due).format(\"ddd\"), date(due).format(\"MMM D\")))))))'\n\nviews:\n - type: tasknotesMiniCalendar\n name: \"Due\"\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - property: due\n direction: ASC\n dateProperty: due\n - type: tasknotesMiniCalendar\n name: \"Scheduled\"\n order: []\n dateProperty: scheduled\n - type: tasknotesMiniCalendar\n name: \"Created\"\n dateProperty: file.ctime\n - type: tasknotesMiniCalendar\n name: \"Modified\"\n dateProperty: file.mtime\n```\n\n## kanban-default.base\n\nCommand/template ID: `open-kanban-view`\n\n```yaml\n# Kanban Board\n\nfilters:\n and:\n - file.hasTag(\"task\")\n\nformulas:\n priorityWeight: 'if(priority==\"none\",0,if(priority==\"low\",1,if(priority==\"normal\",2,if(priority==\"high\",3,999))))'\n daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n dueIn: 'if(due.isEmpty(), \"\", if(formula.daysUntilDue == 0, \"Today\", if(formula.daysUntilDue == 1, \"1 day\", if(formula.daysUntilDue > 1, formula.daysUntilDue + \" days\", if(formula.daysUntilDue == -1, \"1 day overdue\", formula.daysUntilDue * -1 + \" days overdue\")))))'\n daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != \"done\"'\n isDueToday: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isDueThisWeek: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")'\n isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isRecurring: 'recurrence && !recurrence.isEmpty()'\n hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - \"7d\").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n dueMonth: 'if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), \"No due date\")'\n dueWeek: 'if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), \"No due date\")'\n scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"Not scheduled\")'\n scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"Not scheduled\")'\n dueDateCategory: 'if(due.isEmpty(), \"No due date\", if(date(due) < today(), \"Overdue\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), \"This week\", \"Later\")))))'\n timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(timeEstimate < 30, \"Quick (<30m)\", if(timeEstimate <= 120, \"Medium (30m-2h)\", \"Long (>2h)\")))'\n ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, \"Today\", if(((number(now()) - number(file.ctime)) / 86400000) < 7, \"This week\", if(((number(now()) - number(file.ctime)) / 86400000) < 30, \"This month\", \"Older\")))'\n createdMonth: 'file.ctime.format(\"YYYY-MM\")'\n modifiedMonth: 'file.mtime.format(\"YYYY-MM\")'\n priorityCategory: 'if(priority==\"none\",\"None\",if(priority==\"low\",\"Low\",if(priority==\"normal\",\"Normal\",if(priority==\"high\",\"High\",\"No priority\"))))'\n projectCount: 'if(!projects || list(projects).length == 0, \"No projects\", if(list(projects).length == 1, \"Single project\", \"Multiple projects\"))'\n contextCount: 'if(!contexts || list(contexts).length == 0, \"No contexts\", if(list(contexts).length == 1, \"Single context\", \"Multiple contexts\"))'\n trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(!timeEntries || list(timeEntries).length == 0, \"Not started\", if(formula.efficiencyRatio < 100, \"Under estimate\", \"Over estimate\")))'\n nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n isToday: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"))'\n isThisWeek: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"))'\n nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), \"No date\", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), \"Overdue/Past\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")), \"Today\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")), \"Tomorrow\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")), \"This week\", \"Later\")))))'\n nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-MM\"), date(scheduled).format(\"YYYY-MM\")), if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"No date\")))'\n nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-[W]WW\"), date(scheduled).format(\"YYYY-[W]WW\")), if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"No date\")))'\n urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format(\"YYYY-MM-DD\")))) / 86400000)))'\n timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + \"h \" + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + \"m\", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + \"m\"), \"0m\")'\n dueDateDisplay: 'if(due.isEmpty(), \"\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") == (today() - \"1 day\").format(\"YYYY-MM-DD\"), \"Yesterday\", if(date(due) < today(), formula.daysUntilDue * -1 + \"d ago\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), date(due).format(\"ddd\"), date(due).format(\"MMM D\")))))))'\n\nviews:\n - type: tasknotesKanban\n name: \"Kanban Board\"\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: tasknotes_manual_order\n direction: DESC\n groupBy:\n property: status\n direction: ASC\n config:\n columnWidth: 280\n hideEmptyColumns: false\n```\n\n## tasks-default.base\n\nCommand/template ID: `open-tasks-view`\n\n```yaml\n# All Tasks\n\nfilters:\n and:\n - file.hasTag(\"task\")\n\nformulas:\n priorityWeight: 'if(priority==\"none\",0,if(priority==\"low\",1,if(priority==\"normal\",2,if(priority==\"high\",3,999))))'\n daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n dueIn: 'if(due.isEmpty(), \"\", if(formula.daysUntilDue == 0, \"Today\", if(formula.daysUntilDue == 1, \"1 day\", if(formula.daysUntilDue > 1, formula.daysUntilDue + \" days\", if(formula.daysUntilDue == -1, \"1 day overdue\", formula.daysUntilDue * -1 + \" days overdue\")))))'\n daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != \"done\"'\n isDueToday: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isDueThisWeek: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")'\n isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isRecurring: 'recurrence && !recurrence.isEmpty()'\n hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - \"7d\").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n dueMonth: 'if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), \"No due date\")'\n dueWeek: 'if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), \"No due date\")'\n scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"Not scheduled\")'\n scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"Not scheduled\")'\n dueDateCategory: 'if(due.isEmpty(), \"No due date\", if(date(due) < today(), \"Overdue\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), \"This week\", \"Later\")))))'\n timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(timeEstimate < 30, \"Quick (<30m)\", if(timeEstimate <= 120, \"Medium (30m-2h)\", \"Long (>2h)\")))'\n ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, \"Today\", if(((number(now()) - number(file.ctime)) / 86400000) < 7, \"This week\", if(((number(now()) - number(file.ctime)) / 86400000) < 30, \"This month\", \"Older\")))'\n createdMonth: 'file.ctime.format(\"YYYY-MM\")'\n modifiedMonth: 'file.mtime.format(\"YYYY-MM\")'\n priorityCategory: 'if(priority==\"none\",\"None\",if(priority==\"low\",\"Low\",if(priority==\"normal\",\"Normal\",if(priority==\"high\",\"High\",\"No priority\"))))'\n projectCount: 'if(!projects || list(projects).length == 0, \"No projects\", if(list(projects).length == 1, \"Single project\", \"Multiple projects\"))'\n contextCount: 'if(!contexts || list(contexts).length == 0, \"No contexts\", if(list(contexts).length == 1, \"Single context\", \"Multiple contexts\"))'\n trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(!timeEntries || list(timeEntries).length == 0, \"Not started\", if(formula.efficiencyRatio < 100, \"Under estimate\", \"Over estimate\")))'\n nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n isToday: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"))'\n isThisWeek: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"))'\n nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), \"No date\", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), \"Overdue/Past\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")), \"Today\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")), \"Tomorrow\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")), \"This week\", \"Later\")))))'\n nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-MM\"), date(scheduled).format(\"YYYY-MM\")), if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"No date\")))'\n nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-[W]WW\"), date(scheduled).format(\"YYYY-[W]WW\")), if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"No date\")))'\n urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format(\"YYYY-MM-DD\")))) / 86400000)))'\n timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + \"h \" + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + \"m\", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + \"m\"), \"0m\")'\n dueDateDisplay: 'if(due.isEmpty(), \"\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") == (today() - \"1 day\").format(\"YYYY-MM-DD\"), \"Yesterday\", if(date(due) < today(), formula.daysUntilDue * -1 + \"d ago\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), date(due).format(\"ddd\"), date(due).format(\"MMM D\")))))))'\n\nviews:\n - type: tasknotesTaskList\n name: \"Manual Order\"\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: tasknotes_manual_order\n direction: DESC\n groupBy:\n property: status\n direction: ASC\n - type: tasknotesTaskList\n name: \"All Tasks\"\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: due\n direction: ASC\n - type: tasknotesTaskList\n name: \"Not Blocked\"\n filters:\n and:\n # Incomplete tasks\n - or:\n # Non-recurring task that's not in any completed status\n - and:\n - recurrence.isEmpty()\n - status != \"done\"\n # Recurring task where today is not in complete_instances\n - and:\n - recurrence.isEmpty() == false\n - complete_instances.map(date(value).format(\"YYYY-MM-DD\")).contains(today().format(\"YYYY-MM-DD\")) != true\n # Not blocked by any incomplete tasks\n - or:\n # No blocking dependencies at all\n - blockedBy.isEmpty()\n # All blocking tasks are completed (filter returns only incomplete, then check if empty)\n - 'list(blockedBy).filter(file(if(value.isType(\"object\"), value.uid, value)).properties.status != \"done\").isEmpty()'\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: formula.urgencyScore\n direction: DESC\n - type: tasknotesTaskList\n name: \"Today\"\n filters:\n and:\n # Incomplete tasks (handles both recurring and non-recurring)\n - or:\n # Non-recurring task that's not in any completed status\n - and:\n - recurrence.isEmpty()\n - status != \"done\"\n # Recurring task where today is not in complete_instances\n - and:\n - recurrence.isEmpty() == false\n - complete_instances.map(date(value).format(\"YYYY-MM-DD\")).contains(today().format(\"YYYY-MM-DD\")) != true\n # Due or scheduled today\n - or:\n - and:\n - due.isEmpty() == false\n - date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")\n - and:\n - scheduled.isEmpty() == false\n - date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: formula.urgencyScore\n direction: DESC\n - type: tasknotesTaskList\n name: \"Overdue\"\n filters:\n and:\n # Incomplete tasks\n - or:\n # Non-recurring task that's not in any completed status\n - and:\n - recurrence.isEmpty()\n - status != \"done\"\n # Recurring task where today is not in complete_instances\n - and:\n - recurrence.isEmpty() == false\n - complete_instances.map(date(value).format(\"YYYY-MM-DD\")).contains(today().format(\"YYYY-MM-DD\")) != true\n # Due or scheduled in the past\n - or:\n - and:\n - due.isEmpty() == false\n - date(due) < today()\n - and:\n - scheduled.isEmpty() == false\n - date(scheduled) < today()\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: formula.urgencyScore\n direction: DESC\n - type: tasknotesTaskList\n name: \"This Week\"\n filters:\n and:\n # Incomplete tasks\n - or:\n # Non-recurring task that's not in any completed status\n - and:\n - recurrence.isEmpty()\n - status != \"done\"\n # Recurring task where today is not in complete_instances\n - and:\n - recurrence.isEmpty() == false\n - complete_instances.map(date(value).format(\"YYYY-MM-DD\")).contains(today().format(\"YYYY-MM-DD\")) != true\n # Due or scheduled this week\n - or:\n - and:\n - due.isEmpty() == false\n - date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\")\n - date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")\n - and:\n - scheduled.isEmpty() == false\n - date(scheduled).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\")\n - date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: formula.urgencyScore\n direction: DESC\n - type: tasknotesTaskList\n name: \"Unscheduled\"\n filters:\n and:\n # Incomplete tasks\n - or:\n # Non-recurring task that's not in any completed status\n - and:\n - recurrence.isEmpty()\n - status != \"done\"\n # Recurring task where today is not in complete_instances\n - and:\n - recurrence.isEmpty() == false\n - complete_instances.map(date(value).format(\"YYYY-MM-DD\")).contains(today().format(\"YYYY-MM-DD\")) != true\n # No due date and no scheduled date\n - date(due).isEmpty()\n - date(scheduled).isEmpty()\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: status\n direction: ASC\n```\n\n## calendar-default.base\n\nCommand/template ID: `open-advanced-calendar-view`\n\n```yaml\n# Calendar\n\nfilters:\n and:\n - file.hasTag(\"task\")\n\nformulas:\n priorityWeight: 'if(priority==\"none\",0,if(priority==\"low\",1,if(priority==\"normal\",2,if(priority==\"high\",3,999))))'\n daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n dueIn: 'if(due.isEmpty(), \"\", if(formula.daysUntilDue == 0, \"Today\", if(formula.daysUntilDue == 1, \"1 day\", if(formula.daysUntilDue > 1, formula.daysUntilDue + \" days\", if(formula.daysUntilDue == -1, \"1 day overdue\", formula.daysUntilDue * -1 + \" days overdue\")))))'\n daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != \"done\"'\n isDueToday: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isDueThisWeek: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")'\n isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isRecurring: 'recurrence && !recurrence.isEmpty()'\n hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - \"7d\").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n dueMonth: 'if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), \"No due date\")'\n dueWeek: 'if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), \"No due date\")'\n scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"Not scheduled\")'\n scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"Not scheduled\")'\n dueDateCategory: 'if(due.isEmpty(), \"No due date\", if(date(due) < today(), \"Overdue\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), \"This week\", \"Later\")))))'\n timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(timeEstimate < 30, \"Quick (<30m)\", if(timeEstimate <= 120, \"Medium (30m-2h)\", \"Long (>2h)\")))'\n ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, \"Today\", if(((number(now()) - number(file.ctime)) / 86400000) < 7, \"This week\", if(((number(now()) - number(file.ctime)) / 86400000) < 30, \"This month\", \"Older\")))'\n createdMonth: 'file.ctime.format(\"YYYY-MM\")'\n modifiedMonth: 'file.mtime.format(\"YYYY-MM\")'\n priorityCategory: 'if(priority==\"none\",\"None\",if(priority==\"low\",\"Low\",if(priority==\"normal\",\"Normal\",if(priority==\"high\",\"High\",\"No priority\"))))'\n projectCount: 'if(!projects || list(projects).length == 0, \"No projects\", if(list(projects).length == 1, \"Single project\", \"Multiple projects\"))'\n contextCount: 'if(!contexts || list(contexts).length == 0, \"No contexts\", if(list(contexts).length == 1, \"Single context\", \"Multiple contexts\"))'\n trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(!timeEntries || list(timeEntries).length == 0, \"Not started\", if(formula.efficiencyRatio < 100, \"Under estimate\", \"Over estimate\")))'\n nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n isToday: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"))'\n isThisWeek: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"))'\n nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), \"No date\", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), \"Overdue/Past\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")), \"Today\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")), \"Tomorrow\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")), \"This week\", \"Later\")))))'\n nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-MM\"), date(scheduled).format(\"YYYY-MM\")), if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"No date\")))'\n nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-[W]WW\"), date(scheduled).format(\"YYYY-[W]WW\")), if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"No date\")))'\n urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format(\"YYYY-MM-DD\")))) / 86400000)))'\n timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + \"h \" + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + \"m\", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + \"m\"), \"0m\")'\n dueDateDisplay: 'if(due.isEmpty(), \"\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") == (today() - \"1 day\").format(\"YYYY-MM-DD\"), \"Yesterday\", if(date(due) < today(), formula.daysUntilDue * -1 + \"d ago\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), date(due).format(\"ddd\"), date(due).format(\"MMM D\")))))))'\n\nviews:\n - type: tasknotesCalendar\n name: \"Calendar\"\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n options:\n showScheduled: true\n showDue: true\n showRecurring: true\n showTimeEntries: true\n showTimeblocks: true\n showPropertyBasedEvents: true\n createDailyNotesFromDateLinks: true\n calendarView: \"timeGridWeek\"\n customDayCount: 3\n firstDay: 1\n```\n\n## agenda-default.base\n\nCommand/template ID: `open-agenda-view`\n\n```yaml\n# Agenda\n\nfilters:\n and:\n - file.hasTag(\"task\")\n\nformulas:\n priorityWeight: 'if(priority==\"none\",0,if(priority==\"low\",1,if(priority==\"normal\",2,if(priority==\"high\",3,999))))'\n daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n dueIn: 'if(due.isEmpty(), \"\", if(formula.daysUntilDue == 0, \"Today\", if(formula.daysUntilDue == 1, \"1 day\", if(formula.daysUntilDue > 1, formula.daysUntilDue + \" days\", if(formula.daysUntilDue == -1, \"1 day overdue\", formula.daysUntilDue * -1 + \" days overdue\")))))'\n daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != \"done\"'\n isDueToday: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isDueThisWeek: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")'\n isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isRecurring: 'recurrence && !recurrence.isEmpty()'\n hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - \"7d\").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n dueMonth: 'if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), \"No due date\")'\n dueWeek: 'if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), \"No due date\")'\n scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"Not scheduled\")'\n scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"Not scheduled\")'\n dueDateCategory: 'if(due.isEmpty(), \"No due date\", if(date(due) < today(), \"Overdue\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), \"This week\", \"Later\")))))'\n timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(timeEstimate < 30, \"Quick (<30m)\", if(timeEstimate <= 120, \"Medium (30m-2h)\", \"Long (>2h)\")))'\n ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, \"Today\", if(((number(now()) - number(file.ctime)) / 86400000) < 7, \"This week\", if(((number(now()) - number(file.ctime)) / 86400000) < 30, \"This month\", \"Older\")))'\n createdMonth: 'file.ctime.format(\"YYYY-MM\")'\n modifiedMonth: 'file.mtime.format(\"YYYY-MM\")'\n priorityCategory: 'if(priority==\"none\",\"None\",if(priority==\"low\",\"Low\",if(priority==\"normal\",\"Normal\",if(priority==\"high\",\"High\",\"No priority\"))))'\n projectCount: 'if(!projects || list(projects).length == 0, \"No projects\", if(list(projects).length == 1, \"Single project\", \"Multiple projects\"))'\n contextCount: 'if(!contexts || list(contexts).length == 0, \"No contexts\", if(list(contexts).length == 1, \"Single context\", \"Multiple contexts\"))'\n trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(!timeEntries || list(timeEntries).length == 0, \"Not started\", if(formula.efficiencyRatio < 100, \"Under estimate\", \"Over estimate\")))'\n nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n isToday: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"))'\n isThisWeek: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"))'\n nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), \"No date\", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), \"Overdue/Past\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")), \"Today\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")), \"Tomorrow\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")), \"This week\", \"Later\")))))'\n nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-MM\"), date(scheduled).format(\"YYYY-MM\")), if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"No date\")))'\n nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-[W]WW\"), date(scheduled).format(\"YYYY-[W]WW\")), if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"No date\")))'\n urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format(\"YYYY-MM-DD\")))) / 86400000)))'\n timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + \"h \" + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + \"m\", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + \"m\"), \"0m\")'\n dueDateDisplay: 'if(due.isEmpty(), \"\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") == (today() - \"1 day\").format(\"YYYY-MM-DD\"), \"Yesterday\", if(date(due) < today(), formula.daysUntilDue * -1 + \"d ago\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), date(due).format(\"ddd\"), date(due).format(\"MMM D\")))))))'\n\nproperties:\n formula.dueIn:\n displayName: Due in\n\n\nviews:\n - type: tasknotesCalendar\n name: \"Agenda\"\n order:\n - status\n - priority\n - due\n - formula.dueIn\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n options:\n showPropertyBasedEvents: false\n showOverdueOnToday: true\n createDailyNotesFromDateLinks: true\n calendarView: \"listWeek\"\n startDateProperty: file.ctime\n listDayCount: 7\n titleProperty: file.basename\n```\n\n## pomodoro-stats.base\n\nCommand/template ID: `pomodoro-stats-base`\n\n```yaml\n# Pomodoro statistics\n# Generated with your TaskNotes settings\n# Requires Pomodoro data storage to be set to Daily notes.\n\nfilters:\n and:\n - file.hasProperty(\"pomodoros\")\n - list(note[\"pomodoros\"]).filter(value.startTime).isEmpty() == false\n\nformulas:\n pomodoroDate: 'if(note[\"pomodoros\"], list(note[\"pomodoros\"]).filter(value.startTime).map(date(value.startTime).format(\"YYYY-MM-DD\")).unique().join(\", \"), file.basename)'\n pomodoroMonth: 'if(note[\"pomodoros\"], list(note[\"pomodoros\"]).filter(value.startTime).map(date(value.startTime).format(\"YYYY-MM\")).unique().join(\", \"), \"\")'\n completedPomos: 'if(note[\"pomodoros\"], list(note[\"pomodoros\"]).filter(value.type == \"work\" && value.completed == true).length, 0)'\n attemptedPomos: 'if(note[\"pomodoros\"], list(note[\"pomodoros\"]).filter(value.type == \"work\").length, 0)'\n interruptedPomos: 'if(note[\"pomodoros\"], list(note[\"pomodoros\"]).filter(value.type == \"work\" && value.completed == false).length, 0)'\n focusMinutes: 'if(note[\"pomodoros\"], list(note[\"pomodoros\"]).filter(value.type == \"work\" && value.completed == true).map(if(value.plannedDuration && value.plannedDuration > 0, value.plannedDuration, if(value.startTime && value.endTime, ((number(date(value.endTime)) - number(date(value.startTime))) / 60000).round(), 0))).reduce(acc + value, 0).round(), 0)'\n focusTime: 'if(formula.focusMinutes >= 60, (formula.focusMinutes / 60).floor() + \"h \" + (formula.focusMinutes % 60).round() + \"m\", formula.focusMinutes + \"m\")'\n completionRate: 'if(formula.attemptedPomos > 0, (formula.completedPomos / formula.attemptedPomos * 100).round() + \"%\", \"0%\")'\n shortBreaks: 'if(note[\"pomodoros\"], list(note[\"pomodoros\"]).filter(value.type == \"short-break\").length, 0)'\n longBreaks: 'if(note[\"pomodoros\"], list(note[\"pomodoros\"]).filter(value.type == \"long-break\").length, 0)'\n\nproperties:\n formula.pomodoroDate:\n displayName: Date\n formula.pomodoroMonth:\n displayName: Month\n formula.completedPomos:\n displayName: Completed\n formula.attemptedPomos:\n displayName: Attempted\n formula.interruptedPomos:\n displayName: Interrupted\n formula.focusMinutes:\n displayName: Focus minutes\n formula.focusTime:\n displayName: Focus time\n formula.completionRate:\n displayName: Completion\n formula.shortBreaks:\n displayName: Short breaks\n formula.longBreaks:\n displayName: Long breaks\n\nviews:\n - type: table\n name: \"Daily\"\n order:\n - formula.pomodoroDate\n - formula.completedPomos\n - formula.focusTime\n - formula.attemptedPomos\n - formula.completionRate\n - formula.interruptedPomos\n - formula.shortBreaks\n - formula.longBreaks\n - file.name\n sort:\n - column: formula.pomodoroDate\n direction: DESC\n - type: table\n name: \"Monthly\"\n groupBy:\n property: formula.pomodoroMonth\n direction: DESC\n order:\n - formula.pomodoroDate\n - formula.completedPomos\n - formula.focusMinutes\n - formula.focusTime\n - formula.attemptedPomos\n - formula.completionRate\n - formula.interruptedPomos\n - formula.shortBreaks\n - formula.longBreaks\n - file.name\n summaries:\n formula.completedPomos: Sum\n formula.focusMinutes: Sum\n formula.attemptedPomos: Sum\n formula.interruptedPomos: Sum\n formula.shortBreaks: Sum\n formula.longBreaks: Sum\n sort:\n - column: formula.pomodoroDate\n direction: DESC\n```\n\n## relationships.base\n\nCommand/template ID: `relationships`\n\n```yaml\n# Relationships\n# This view shows all relationships for the current file\n# Dynamically shows/hides tabs based on available data\n\nformulas:\n priorityWeight: 'if(priority==\"none\",0,if(priority==\"low\",1,if(priority==\"normal\",2,if(priority==\"high\",3,999))))'\n daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n dueIn: 'if(due.isEmpty(), \"\", if(formula.daysUntilDue == 0, \"Today\", if(formula.daysUntilDue == 1, \"1 day\", if(formula.daysUntilDue > 1, formula.daysUntilDue + \" days\", if(formula.daysUntilDue == -1, \"1 day overdue\", formula.daysUntilDue * -1 + \" days overdue\")))))'\n daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != \"done\"'\n isDueToday: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isDueThisWeek: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")'\n isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isRecurring: 'recurrence && !recurrence.isEmpty()'\n hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - \"7d\").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n dueMonth: 'if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), \"No due date\")'\n dueWeek: 'if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), \"No due date\")'\n scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"Not scheduled\")'\n scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"Not scheduled\")'\n dueDateCategory: 'if(due.isEmpty(), \"No due date\", if(date(due) < today(), \"Overdue\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), \"This week\", \"Later\")))))'\n timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(timeEstimate < 30, \"Quick (<30m)\", if(timeEstimate <= 120, \"Medium (30m-2h)\", \"Long (>2h)\")))'\n ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, \"Today\", if(((number(now()) - number(file.ctime)) / 86400000) < 7, \"This week\", if(((number(now()) - number(file.ctime)) / 86400000) < 30, \"This month\", \"Older\")))'\n createdMonth: 'file.ctime.format(\"YYYY-MM\")'\n modifiedMonth: 'file.mtime.format(\"YYYY-MM\")'\n priorityCategory: 'if(priority==\"none\",\"None\",if(priority==\"low\",\"Low\",if(priority==\"normal\",\"Normal\",if(priority==\"high\",\"High\",\"No priority\"))))'\n projectCount: 'if(!projects || list(projects).length == 0, \"No projects\", if(list(projects).length == 1, \"Single project\", \"Multiple projects\"))'\n contextCount: 'if(!contexts || list(contexts).length == 0, \"No contexts\", if(list(contexts).length == 1, \"Single context\", \"Multiple contexts\"))'\n trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(!timeEntries || list(timeEntries).length == 0, \"Not started\", if(formula.efficiencyRatio < 100, \"Under estimate\", \"Over estimate\")))'\n nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n isToday: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"))'\n isThisWeek: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"))'\n nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), \"No date\", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), \"Overdue/Past\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")), \"Today\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")), \"Tomorrow\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")), \"This week\", \"Later\")))))'\n nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-MM\"), date(scheduled).format(\"YYYY-MM\")), if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"No date\")))'\n nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-[W]WW\"), date(scheduled).format(\"YYYY-[W]WW\")), if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"No date\")))'\n urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format(\"YYYY-MM-DD\")))) / 86400000)))'\n timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + \"h \" + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + \"m\", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + \"m\"), \"0m\")'\n dueDateDisplay: 'if(due.isEmpty(), \"\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") == (today() - \"1 day\").format(\"YYYY-MM-DD\"), \"Yesterday\", if(date(due) < today(), formula.daysUntilDue * -1 + \"d ago\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), date(due).format(\"ddd\"), date(due).format(\"MMM D\")))))))'\n\nviews:\n - type: tasknotesKanban\n name: \"Subtasks\"\n filters:\n and:\n - file.hasTag(\"task\")\n - file.hasLink(this.file) && list(note.projects).map(file(value.replace(/^\\[[^\\]]+\\]\\((.*)\\)$/, \"$1\").replace(/%20/g, \" \")).asLink()).contains(this.file.asLink())\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: tasknotes_manual_order\n direction: DESC\n groupBy:\n property: status\n direction: ASC\n - type: tasknotesTaskList\n name: \"Occurrences\"\n filters:\n and:\n - file.hasTag(\"task\")\n - file.hasLink(this.file) && note.recurrence_parent && file(note.recurrence_parent.replace(/^\\[[^\\]]+\\]\\((.*)\\)$/, \"$1\").replace(/%20/g, \" \")).asLink() == this.file.asLink()\n order:\n - status\n - priority\n - due\n - scheduled\n - occurrence_date\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: occurrence_date\n direction: ASC\n - type: tasknotesTaskList\n name: \"Projects\"\n filters:\n and:\n - list(this.projects).map(file(value.replace(/^\\[[^\\]]+\\]\\((.*)\\)$/, \"$1\").replace(/%20/g, \" \")).asLink()).contains(file.asLink())\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n - type: tasknotesTaskList\n name: \"Blocked By\"\n filters:\n and:\n - file.hasTag(\"task\")\n - list(this.note.blockedBy).map(file(if(value.isType(\"object\"), value.uid, value)).asLink()).contains(file.asLink())\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: tasknotes_manual_order\n direction: DESC\n - type: tasknotesKanban\n name: \"Blocking\"\n filters:\n and:\n - file.hasTag(\"task\")\n - list(note.blockedBy).map(file(if(value.isType(\"object\"), value.uid, value)).asLink()).contains(this.file.asLink())\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: tasknotes_manual_order\n direction: DESC\n groupBy:\n property: status\n direction: ASC\n```\n","aliases":["/reference/default-base-templates/","/reference/default-base-templates/"],"toc":[{"level":2,"id":"mini-calendar-defaultbase","text":"mini-calendar-default.base"},{"level":2,"id":"kanban-defaultbase","text":"kanban-default.base"},{"level":2,"id":"tasks-defaultbase","text":"tasks-default.base"},{"level":2,"id":"calendar-defaultbase","text":"calendar-default.base"},{"level":2,"id":"agenda-defaultbase","text":"agenda-default.base"},{"level":2,"id":"pomodoro-statsbase","text":"pomodoro-stats.base"},{"level":2,"id":"relationshipsbase","text":"relationships.base"}],"html":"

These are the exact templates TaskNotes 4.12.3 produces with default settings. Your generated files reflect your own field mapping and other settings, so customized output can differ.

\n

Regenerating with Update files overwrites configured default Base files. Copy a customized file to a new path before updating it.

\n

mini-calendar-default.base#

\n

Command/template ID: open-calendar-view

\n
# Mini Calendar\n# Generated with your TaskNotes settings\n\nfilters:\n  and:\n    - file.hasTag("task")\n\nformulas:\n  priorityWeight: 'if(priority=="none",0,if(priority=="low",1,if(priority=="normal",2,if(priority=="high",3,999))))'\n  daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n  dueIn: 'if(due.isEmpty(), "", if(formula.daysUntilDue == 0, "Today", if(formula.daysUntilDue == 1, "1 day", if(formula.daysUntilDue > 1, formula.daysUntilDue + " days", if(formula.daysUntilDue == -1, "1 day overdue", formula.daysUntilDue * -1 + " days overdue")))))'\n  daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n  daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n  daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n  isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != "done"'\n  isDueToday: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isDueThisWeek: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")'\n  isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isRecurring: 'recurrence && !recurrence.isEmpty()'\n  hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n  timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n  efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n  timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - "7d").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  dueMonth: 'if((due.isEmpty() == false), date(due).format("YYYY-MM"), "No due date")'\n  dueWeek: 'if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), "No due date")'\n  scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "Not scheduled")'\n  scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "Not scheduled")'\n  dueDateCategory: 'if(due.isEmpty(), "No due date", if(date(due) < today(), "Overdue", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), "This week", "Later")))))'\n  timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(timeEstimate < 30, "Quick (<30m)", if(timeEstimate <= 120, "Medium (30m-2h)", "Long (>2h)")))'\n  ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, "Today", if(((number(now()) - number(file.ctime)) / 86400000) < 7, "This week", if(((number(now()) - number(file.ctime)) / 86400000) < 30, "This month", "Older")))'\n  createdMonth: 'file.ctime.format("YYYY-MM")'\n  modifiedMonth: 'file.mtime.format("YYYY-MM")'\n  priorityCategory: 'if(priority=="none","None",if(priority=="low","Low",if(priority=="normal","Normal",if(priority=="high","High","No priority"))))'\n  projectCount: 'if(!projects || list(projects).length == 0, "No projects", if(list(projects).length == 1, "Single project", "Multiple projects"))'\n  contextCount: 'if(!contexts || list(contexts).length == 0, "No contexts", if(list(contexts).length == 1, "Single context", "Multiple contexts"))'\n  trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(!timeEntries || list(timeEntries).length == 0, "Not started", if(formula.efficiencyRatio < 100, "Under estimate", "Over estimate")))'\n  nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n  daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n  hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n  isToday: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"))'\n  isThisWeek: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"))'\n  nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), "No date", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), "Overdue/Past", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")), "Today", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")), "Tomorrow", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")), "This week", "Later")))))'\n  nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-MM"), date(scheduled).format("YYYY-MM")), if((due.isEmpty() == false), date(due).format("YYYY-MM"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "No date")))'\n  nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-[W]WW"), date(scheduled).format("YYYY-[W]WW")), if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "No date")))'\n  urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format("YYYY-MM-DD")))) / 86400000)))'\n  timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + "h " + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + "m", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + "m"), "0m")'\n  dueDateDisplay: 'if(due.isEmpty(), "", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") == (today() - "1 day").format("YYYY-MM-DD"), "Yesterday", if(date(due) < today(), formula.daysUntilDue * -1 + "d ago", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), date(due).format("ddd"), date(due).format("MMM D")))))))'\n\nviews:\n  - type: tasknotesMiniCalendar\n    name: "Due"\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - property: due\n        direction: ASC\n    dateProperty: due\n  - type: tasknotesMiniCalendar\n    name: "Scheduled"\n    order: []\n    dateProperty: scheduled\n  - type: tasknotesMiniCalendar\n    name: "Created"\n    dateProperty: file.ctime\n  - type: tasknotesMiniCalendar\n    name: "Modified"\n    dateProperty: file.mtime\n

kanban-default.base#

\n

Command/template ID: open-kanban-view

\n
# Kanban Board\n\nfilters:\n  and:\n    - file.hasTag("task")\n\nformulas:\n  priorityWeight: 'if(priority=="none",0,if(priority=="low",1,if(priority=="normal",2,if(priority=="high",3,999))))'\n  daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n  dueIn: 'if(due.isEmpty(), "", if(formula.daysUntilDue == 0, "Today", if(formula.daysUntilDue == 1, "1 day", if(formula.daysUntilDue > 1, formula.daysUntilDue + " days", if(formula.daysUntilDue == -1, "1 day overdue", formula.daysUntilDue * -1 + " days overdue")))))'\n  daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n  daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n  daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n  isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != "done"'\n  isDueToday: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isDueThisWeek: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")'\n  isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isRecurring: 'recurrence && !recurrence.isEmpty()'\n  hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n  timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n  efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n  timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - "7d").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  dueMonth: 'if((due.isEmpty() == false), date(due).format("YYYY-MM"), "No due date")'\n  dueWeek: 'if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), "No due date")'\n  scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "Not scheduled")'\n  scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "Not scheduled")'\n  dueDateCategory: 'if(due.isEmpty(), "No due date", if(date(due) < today(), "Overdue", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), "This week", "Later")))))'\n  timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(timeEstimate < 30, "Quick (<30m)", if(timeEstimate <= 120, "Medium (30m-2h)", "Long (>2h)")))'\n  ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, "Today", if(((number(now()) - number(file.ctime)) / 86400000) < 7, "This week", if(((number(now()) - number(file.ctime)) / 86400000) < 30, "This month", "Older")))'\n  createdMonth: 'file.ctime.format("YYYY-MM")'\n  modifiedMonth: 'file.mtime.format("YYYY-MM")'\n  priorityCategory: 'if(priority=="none","None",if(priority=="low","Low",if(priority=="normal","Normal",if(priority=="high","High","No priority"))))'\n  projectCount: 'if(!projects || list(projects).length == 0, "No projects", if(list(projects).length == 1, "Single project", "Multiple projects"))'\n  contextCount: 'if(!contexts || list(contexts).length == 0, "No contexts", if(list(contexts).length == 1, "Single context", "Multiple contexts"))'\n  trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(!timeEntries || list(timeEntries).length == 0, "Not started", if(formula.efficiencyRatio < 100, "Under estimate", "Over estimate")))'\n  nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n  daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n  hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n  isToday: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"))'\n  isThisWeek: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"))'\n  nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), "No date", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), "Overdue/Past", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")), "Today", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")), "Tomorrow", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")), "This week", "Later")))))'\n  nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-MM"), date(scheduled).format("YYYY-MM")), if((due.isEmpty() == false), date(due).format("YYYY-MM"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "No date")))'\n  nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-[W]WW"), date(scheduled).format("YYYY-[W]WW")), if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "No date")))'\n  urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format("YYYY-MM-DD")))) / 86400000)))'\n  timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + "h " + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + "m", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + "m"), "0m")'\n  dueDateDisplay: 'if(due.isEmpty(), "", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") == (today() - "1 day").format("YYYY-MM-DD"), "Yesterday", if(date(due) < today(), formula.daysUntilDue * -1 + "d ago", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), date(due).format("ddd"), date(due).format("MMM D")))))))'\n\nviews:\n  - type: tasknotesKanban\n    name: "Kanban Board"\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: tasknotes_manual_order\n        direction: DESC\n    groupBy:\n      property: status\n      direction: ASC\n    config:\n      columnWidth: 280\n      hideEmptyColumns: false\n

tasks-default.base#

\n

Command/template ID: open-tasks-view

\n
# All Tasks\n\nfilters:\n  and:\n    - file.hasTag("task")\n\nformulas:\n  priorityWeight: 'if(priority=="none",0,if(priority=="low",1,if(priority=="normal",2,if(priority=="high",3,999))))'\n  daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n  dueIn: 'if(due.isEmpty(), "", if(formula.daysUntilDue == 0, "Today", if(formula.daysUntilDue == 1, "1 day", if(formula.daysUntilDue > 1, formula.daysUntilDue + " days", if(formula.daysUntilDue == -1, "1 day overdue", formula.daysUntilDue * -1 + " days overdue")))))'\n  daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n  daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n  daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n  isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != "done"'\n  isDueToday: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isDueThisWeek: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")'\n  isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isRecurring: 'recurrence && !recurrence.isEmpty()'\n  hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n  timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n  efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n  timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - "7d").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  dueMonth: 'if((due.isEmpty() == false), date(due).format("YYYY-MM"), "No due date")'\n  dueWeek: 'if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), "No due date")'\n  scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "Not scheduled")'\n  scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "Not scheduled")'\n  dueDateCategory: 'if(due.isEmpty(), "No due date", if(date(due) < today(), "Overdue", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), "This week", "Later")))))'\n  timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(timeEstimate < 30, "Quick (<30m)", if(timeEstimate <= 120, "Medium (30m-2h)", "Long (>2h)")))'\n  ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, "Today", if(((number(now()) - number(file.ctime)) / 86400000) < 7, "This week", if(((number(now()) - number(file.ctime)) / 86400000) < 30, "This month", "Older")))'\n  createdMonth: 'file.ctime.format("YYYY-MM")'\n  modifiedMonth: 'file.mtime.format("YYYY-MM")'\n  priorityCategory: 'if(priority=="none","None",if(priority=="low","Low",if(priority=="normal","Normal",if(priority=="high","High","No priority"))))'\n  projectCount: 'if(!projects || list(projects).length == 0, "No projects", if(list(projects).length == 1, "Single project", "Multiple projects"))'\n  contextCount: 'if(!contexts || list(contexts).length == 0, "No contexts", if(list(contexts).length == 1, "Single context", "Multiple contexts"))'\n  trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(!timeEntries || list(timeEntries).length == 0, "Not started", if(formula.efficiencyRatio < 100, "Under estimate", "Over estimate")))'\n  nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n  daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n  hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n  isToday: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"))'\n  isThisWeek: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"))'\n  nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), "No date", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), "Overdue/Past", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")), "Today", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")), "Tomorrow", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")), "This week", "Later")))))'\n  nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-MM"), date(scheduled).format("YYYY-MM")), if((due.isEmpty() == false), date(due).format("YYYY-MM"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "No date")))'\n  nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-[W]WW"), date(scheduled).format("YYYY-[W]WW")), if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "No date")))'\n  urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format("YYYY-MM-DD")))) / 86400000)))'\n  timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + "h " + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + "m", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + "m"), "0m")'\n  dueDateDisplay: 'if(due.isEmpty(), "", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") == (today() - "1 day").format("YYYY-MM-DD"), "Yesterday", if(date(due) < today(), formula.daysUntilDue * -1 + "d ago", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), date(due).format("ddd"), date(due).format("MMM D")))))))'\n\nviews:\n  - type: tasknotesTaskList\n    name: "Manual Order"\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: tasknotes_manual_order\n        direction: DESC\n    groupBy:\n      property: status\n      direction: ASC\n  - type: tasknotesTaskList\n    name: "All Tasks"\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: due\n        direction: ASC\n  - type: tasknotesTaskList\n    name: "Not Blocked"\n    filters:\n      and:\n        # Incomplete tasks\n        - or:\n          # Non-recurring task that's not in any completed status\n          - and:\n            - recurrence.isEmpty()\n            - status != "done"\n          # Recurring task where today is not in complete_instances\n          - and:\n            - recurrence.isEmpty() == false\n            - complete_instances.map(date(value).format("YYYY-MM-DD")).contains(today().format("YYYY-MM-DD")) != true\n        # Not blocked by any incomplete tasks\n        - or:\n          # No blocking dependencies at all\n          - blockedBy.isEmpty()\n          # All blocking tasks are completed (filter returns only incomplete, then check if empty)\n          - 'list(blockedBy).filter(file(if(value.isType("object"), value.uid, value)).properties.status != "done").isEmpty()'\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: formula.urgencyScore\n        direction: DESC\n  - type: tasknotesTaskList\n    name: "Today"\n    filters:\n      and:\n        # Incomplete tasks (handles both recurring and non-recurring)\n        - or:\n          # Non-recurring task that's not in any completed status\n          - and:\n            - recurrence.isEmpty()\n            - status != "done"\n          # Recurring task where today is not in complete_instances\n          - and:\n            - recurrence.isEmpty() == false\n            - complete_instances.map(date(value).format("YYYY-MM-DD")).contains(today().format("YYYY-MM-DD")) != true\n        # Due or scheduled today\n        - or:\n          - and:\n            - due.isEmpty() == false\n            - date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")\n          - and:\n            - scheduled.isEmpty() == false\n            - date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: formula.urgencyScore\n        direction: DESC\n  - type: tasknotesTaskList\n    name: "Overdue"\n    filters:\n      and:\n        # Incomplete tasks\n        - or:\n          # Non-recurring task that's not in any completed status\n          - and:\n            - recurrence.isEmpty()\n            - status != "done"\n          # Recurring task where today is not in complete_instances\n          - and:\n            - recurrence.isEmpty() == false\n            - complete_instances.map(date(value).format("YYYY-MM-DD")).contains(today().format("YYYY-MM-DD")) != true\n        # Due or scheduled in the past\n        - or:\n          - and:\n            - due.isEmpty() == false\n            - date(due) < today()\n          - and:\n            - scheduled.isEmpty() == false\n            - date(scheduled) < today()\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: formula.urgencyScore\n        direction: DESC\n  - type: tasknotesTaskList\n    name: "This Week"\n    filters:\n      and:\n        # Incomplete tasks\n        - or:\n          # Non-recurring task that's not in any completed status\n          - and:\n            - recurrence.isEmpty()\n            - status != "done"\n          # Recurring task where today is not in complete_instances\n          - and:\n            - recurrence.isEmpty() == false\n            - complete_instances.map(date(value).format("YYYY-MM-DD")).contains(today().format("YYYY-MM-DD")) != true\n        # Due or scheduled this week\n        - or:\n          - and:\n            - due.isEmpty() == false\n            - date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD")\n            - date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")\n          - and:\n            - scheduled.isEmpty() == false\n            - date(scheduled).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD")\n            - date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: formula.urgencyScore\n        direction: DESC\n  - type: tasknotesTaskList\n    name: "Unscheduled"\n    filters:\n      and:\n        # Incomplete tasks\n        - or:\n          # Non-recurring task that's not in any completed status\n          - and:\n            - recurrence.isEmpty()\n            - status != "done"\n          # Recurring task where today is not in complete_instances\n          - and:\n            - recurrence.isEmpty() == false\n            - complete_instances.map(date(value).format("YYYY-MM-DD")).contains(today().format("YYYY-MM-DD")) != true\n        # No due date and no scheduled date\n        - date(due).isEmpty()\n        - date(scheduled).isEmpty()\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: status\n        direction: ASC\n

calendar-default.base#

\n

Command/template ID: open-advanced-calendar-view

\n
# Calendar\n\nfilters:\n  and:\n    - file.hasTag("task")\n\nformulas:\n  priorityWeight: 'if(priority=="none",0,if(priority=="low",1,if(priority=="normal",2,if(priority=="high",3,999))))'\n  daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n  dueIn: 'if(due.isEmpty(), "", if(formula.daysUntilDue == 0, "Today", if(formula.daysUntilDue == 1, "1 day", if(formula.daysUntilDue > 1, formula.daysUntilDue + " days", if(formula.daysUntilDue == -1, "1 day overdue", formula.daysUntilDue * -1 + " days overdue")))))'\n  daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n  daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n  daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n  isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != "done"'\n  isDueToday: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isDueThisWeek: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")'\n  isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isRecurring: 'recurrence && !recurrence.isEmpty()'\n  hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n  timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n  efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n  timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - "7d").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  dueMonth: 'if((due.isEmpty() == false), date(due).format("YYYY-MM"), "No due date")'\n  dueWeek: 'if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), "No due date")'\n  scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "Not scheduled")'\n  scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "Not scheduled")'\n  dueDateCategory: 'if(due.isEmpty(), "No due date", if(date(due) < today(), "Overdue", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), "This week", "Later")))))'\n  timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(timeEstimate < 30, "Quick (<30m)", if(timeEstimate <= 120, "Medium (30m-2h)", "Long (>2h)")))'\n  ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, "Today", if(((number(now()) - number(file.ctime)) / 86400000) < 7, "This week", if(((number(now()) - number(file.ctime)) / 86400000) < 30, "This month", "Older")))'\n  createdMonth: 'file.ctime.format("YYYY-MM")'\n  modifiedMonth: 'file.mtime.format("YYYY-MM")'\n  priorityCategory: 'if(priority=="none","None",if(priority=="low","Low",if(priority=="normal","Normal",if(priority=="high","High","No priority"))))'\n  projectCount: 'if(!projects || list(projects).length == 0, "No projects", if(list(projects).length == 1, "Single project", "Multiple projects"))'\n  contextCount: 'if(!contexts || list(contexts).length == 0, "No contexts", if(list(contexts).length == 1, "Single context", "Multiple contexts"))'\n  trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(!timeEntries || list(timeEntries).length == 0, "Not started", if(formula.efficiencyRatio < 100, "Under estimate", "Over estimate")))'\n  nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n  daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n  hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n  isToday: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"))'\n  isThisWeek: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"))'\n  nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), "No date", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), "Overdue/Past", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")), "Today", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")), "Tomorrow", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")), "This week", "Later")))))'\n  nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-MM"), date(scheduled).format("YYYY-MM")), if((due.isEmpty() == false), date(due).format("YYYY-MM"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "No date")))'\n  nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-[W]WW"), date(scheduled).format("YYYY-[W]WW")), if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "No date")))'\n  urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format("YYYY-MM-DD")))) / 86400000)))'\n  timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + "h " + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + "m", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + "m"), "0m")'\n  dueDateDisplay: 'if(due.isEmpty(), "", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") == (today() - "1 day").format("YYYY-MM-DD"), "Yesterday", if(date(due) < today(), formula.daysUntilDue * -1 + "d ago", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), date(due).format("ddd"), date(due).format("MMM D")))))))'\n\nviews:\n  - type: tasknotesCalendar\n    name: "Calendar"\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    options:\n      showScheduled: true\n      showDue: true\n      showRecurring: true\n      showTimeEntries: true\n      showTimeblocks: true\n      showPropertyBasedEvents: true\n      createDailyNotesFromDateLinks: true\n      calendarView: "timeGridWeek"\n      customDayCount: 3\n      firstDay: 1\n

agenda-default.base#

\n

Command/template ID: open-agenda-view

\n
# Agenda\n\nfilters:\n  and:\n    - file.hasTag("task")\n\nformulas:\n  priorityWeight: 'if(priority=="none",0,if(priority=="low",1,if(priority=="normal",2,if(priority=="high",3,999))))'\n  daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n  dueIn: 'if(due.isEmpty(), "", if(formula.daysUntilDue == 0, "Today", if(formula.daysUntilDue == 1, "1 day", if(formula.daysUntilDue > 1, formula.daysUntilDue + " days", if(formula.daysUntilDue == -1, "1 day overdue", formula.daysUntilDue * -1 + " days overdue")))))'\n  daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n  daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n  daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n  isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != "done"'\n  isDueToday: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isDueThisWeek: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")'\n  isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isRecurring: 'recurrence && !recurrence.isEmpty()'\n  hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n  timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n  efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n  timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - "7d").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  dueMonth: 'if((due.isEmpty() == false), date(due).format("YYYY-MM"), "No due date")'\n  dueWeek: 'if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), "No due date")'\n  scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "Not scheduled")'\n  scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "Not scheduled")'\n  dueDateCategory: 'if(due.isEmpty(), "No due date", if(date(due) < today(), "Overdue", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), "This week", "Later")))))'\n  timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(timeEstimate < 30, "Quick (<30m)", if(timeEstimate <= 120, "Medium (30m-2h)", "Long (>2h)")))'\n  ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, "Today", if(((number(now()) - number(file.ctime)) / 86400000) < 7, "This week", if(((number(now()) - number(file.ctime)) / 86400000) < 30, "This month", "Older")))'\n  createdMonth: 'file.ctime.format("YYYY-MM")'\n  modifiedMonth: 'file.mtime.format("YYYY-MM")'\n  priorityCategory: 'if(priority=="none","None",if(priority=="low","Low",if(priority=="normal","Normal",if(priority=="high","High","No priority"))))'\n  projectCount: 'if(!projects || list(projects).length == 0, "No projects", if(list(projects).length == 1, "Single project", "Multiple projects"))'\n  contextCount: 'if(!contexts || list(contexts).length == 0, "No contexts", if(list(contexts).length == 1, "Single context", "Multiple contexts"))'\n  trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(!timeEntries || list(timeEntries).length == 0, "Not started", if(formula.efficiencyRatio < 100, "Under estimate", "Over estimate")))'\n  nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n  daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n  hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n  isToday: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"))'\n  isThisWeek: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"))'\n  nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), "No date", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), "Overdue/Past", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")), "Today", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")), "Tomorrow", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")), "This week", "Later")))))'\n  nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-MM"), date(scheduled).format("YYYY-MM")), if((due.isEmpty() == false), date(due).format("YYYY-MM"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "No date")))'\n  nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-[W]WW"), date(scheduled).format("YYYY-[W]WW")), if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "No date")))'\n  urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format("YYYY-MM-DD")))) / 86400000)))'\n  timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + "h " + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + "m", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + "m"), "0m")'\n  dueDateDisplay: 'if(due.isEmpty(), "", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") == (today() - "1 day").format("YYYY-MM-DD"), "Yesterday", if(date(due) < today(), formula.daysUntilDue * -1 + "d ago", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), date(due).format("ddd"), date(due).format("MMM D")))))))'\n\nproperties:\n  formula.dueIn:\n    displayName: Due in\n\n\nviews:\n  - type: tasknotesCalendar\n    name: "Agenda"\n    order:\n      - status\n      - priority\n      - due\n      - formula.dueIn\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    options:\n      showPropertyBasedEvents: false\n      showOverdueOnToday: true\n      createDailyNotesFromDateLinks: true\n    calendarView: "listWeek"\n    startDateProperty: file.ctime\n    listDayCount: 7\n    titleProperty: file.basename\n

pomodoro-stats.base#

\n

Command/template ID: pomodoro-stats-base

\n
# Pomodoro statistics\n# Generated with your TaskNotes settings\n# Requires Pomodoro data storage to be set to Daily notes.\n\nfilters:\n  and:\n    - file.hasProperty("pomodoros")\n    - list(note["pomodoros"]).filter(value.startTime).isEmpty() == false\n\nformulas:\n  pomodoroDate: 'if(note["pomodoros"], list(note["pomodoros"]).filter(value.startTime).map(date(value.startTime).format("YYYY-MM-DD")).unique().join(", "), file.basename)'\n  pomodoroMonth: 'if(note["pomodoros"], list(note["pomodoros"]).filter(value.startTime).map(date(value.startTime).format("YYYY-MM")).unique().join(", "), "")'\n  completedPomos: 'if(note["pomodoros"], list(note["pomodoros"]).filter(value.type == "work" && value.completed == true).length, 0)'\n  attemptedPomos: 'if(note["pomodoros"], list(note["pomodoros"]).filter(value.type == "work").length, 0)'\n  interruptedPomos: 'if(note["pomodoros"], list(note["pomodoros"]).filter(value.type == "work" && value.completed == false).length, 0)'\n  focusMinutes: 'if(note["pomodoros"], list(note["pomodoros"]).filter(value.type == "work" && value.completed == true).map(if(value.plannedDuration && value.plannedDuration > 0, value.plannedDuration, if(value.startTime && value.endTime, ((number(date(value.endTime)) - number(date(value.startTime))) / 60000).round(), 0))).reduce(acc + value, 0).round(), 0)'\n  focusTime: 'if(formula.focusMinutes >= 60, (formula.focusMinutes / 60).floor() + "h " + (formula.focusMinutes % 60).round() + "m", formula.focusMinutes + "m")'\n  completionRate: 'if(formula.attemptedPomos > 0, (formula.completedPomos / formula.attemptedPomos * 100).round() + "%", "0%")'\n  shortBreaks: 'if(note["pomodoros"], list(note["pomodoros"]).filter(value.type == "short-break").length, 0)'\n  longBreaks: 'if(note["pomodoros"], list(note["pomodoros"]).filter(value.type == "long-break").length, 0)'\n\nproperties:\n  formula.pomodoroDate:\n    displayName: Date\n  formula.pomodoroMonth:\n    displayName: Month\n  formula.completedPomos:\n    displayName: Completed\n  formula.attemptedPomos:\n    displayName: Attempted\n  formula.interruptedPomos:\n    displayName: Interrupted\n  formula.focusMinutes:\n    displayName: Focus minutes\n  formula.focusTime:\n    displayName: Focus time\n  formula.completionRate:\n    displayName: Completion\n  formula.shortBreaks:\n    displayName: Short breaks\n  formula.longBreaks:\n    displayName: Long breaks\n\nviews:\n  - type: table\n    name: "Daily"\n    order:\n      - formula.pomodoroDate\n      - formula.completedPomos\n      - formula.focusTime\n      - formula.attemptedPomos\n      - formula.completionRate\n      - formula.interruptedPomos\n      - formula.shortBreaks\n      - formula.longBreaks\n      - file.name\n    sort:\n      - column: formula.pomodoroDate\n        direction: DESC\n  - type: table\n    name: "Monthly"\n    groupBy:\n      property: formula.pomodoroMonth\n      direction: DESC\n    order:\n      - formula.pomodoroDate\n      - formula.completedPomos\n      - formula.focusMinutes\n      - formula.focusTime\n      - formula.attemptedPomos\n      - formula.completionRate\n      - formula.interruptedPomos\n      - formula.shortBreaks\n      - formula.longBreaks\n      - file.name\n    summaries:\n      formula.completedPomos: Sum\n      formula.focusMinutes: Sum\n      formula.attemptedPomos: Sum\n      formula.interruptedPomos: Sum\n      formula.shortBreaks: Sum\n      formula.longBreaks: Sum\n    sort:\n      - column: formula.pomodoroDate\n        direction: DESC\n

relationships.base#

\n

Command/template ID: relationships

\n
# Relationships\n# This view shows all relationships for the current file\n# Dynamically shows/hides tabs based on available data\n\nformulas:\n  priorityWeight: 'if(priority=="none",0,if(priority=="low",1,if(priority=="normal",2,if(priority=="high",3,999))))'\n  daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n  dueIn: 'if(due.isEmpty(), "", if(formula.daysUntilDue == 0, "Today", if(formula.daysUntilDue == 1, "1 day", if(formula.daysUntilDue > 1, formula.daysUntilDue + " days", if(formula.daysUntilDue == -1, "1 day overdue", formula.daysUntilDue * -1 + " days overdue")))))'\n  daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n  daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n  daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n  isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != "done"'\n  isDueToday: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isDueThisWeek: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")'\n  isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isRecurring: 'recurrence && !recurrence.isEmpty()'\n  hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n  timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n  efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n  timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - "7d").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  dueMonth: 'if((due.isEmpty() == false), date(due).format("YYYY-MM"), "No due date")'\n  dueWeek: 'if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), "No due date")'\n  scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "Not scheduled")'\n  scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "Not scheduled")'\n  dueDateCategory: 'if(due.isEmpty(), "No due date", if(date(due) < today(), "Overdue", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), "This week", "Later")))))'\n  timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(timeEstimate < 30, "Quick (<30m)", if(timeEstimate <= 120, "Medium (30m-2h)", "Long (>2h)")))'\n  ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, "Today", if(((number(now()) - number(file.ctime)) / 86400000) < 7, "This week", if(((number(now()) - number(file.ctime)) / 86400000) < 30, "This month", "Older")))'\n  createdMonth: 'file.ctime.format("YYYY-MM")'\n  modifiedMonth: 'file.mtime.format("YYYY-MM")'\n  priorityCategory: 'if(priority=="none","None",if(priority=="low","Low",if(priority=="normal","Normal",if(priority=="high","High","No priority"))))'\n  projectCount: 'if(!projects || list(projects).length == 0, "No projects", if(list(projects).length == 1, "Single project", "Multiple projects"))'\n  contextCount: 'if(!contexts || list(contexts).length == 0, "No contexts", if(list(contexts).length == 1, "Single context", "Multiple contexts"))'\n  trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(!timeEntries || list(timeEntries).length == 0, "Not started", if(formula.efficiencyRatio < 100, "Under estimate", "Over estimate")))'\n  nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n  daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n  hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n  isToday: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"))'\n  isThisWeek: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"))'\n  nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), "No date", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), "Overdue/Past", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")), "Today", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")), "Tomorrow", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")), "This week", "Later")))))'\n  nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-MM"), date(scheduled).format("YYYY-MM")), if((due.isEmpty() == false), date(due).format("YYYY-MM"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "No date")))'\n  nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-[W]WW"), date(scheduled).format("YYYY-[W]WW")), if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "No date")))'\n  urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format("YYYY-MM-DD")))) / 86400000)))'\n  timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + "h " + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + "m", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + "m"), "0m")'\n  dueDateDisplay: 'if(due.isEmpty(), "", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") == (today() - "1 day").format("YYYY-MM-DD"), "Yesterday", if(date(due) < today(), formula.daysUntilDue * -1 + "d ago", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), date(due).format("ddd"), date(due).format("MMM D")))))))'\n\nviews:\n  - type: tasknotesKanban\n    name: "Subtasks"\n    filters:\n      and:\n        - file.hasTag("task")\n        - file.hasLink(this.file) && list(note.projects).map(file(value.replace(/^\\[[^\\]]+\\]\\((.*)\\)$/, "$1").replace(/%20/g, " ")).asLink()).contains(this.file.asLink())\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: tasknotes_manual_order\n        direction: DESC\n    groupBy:\n      property: status\n      direction: ASC\n  - type: tasknotesTaskList\n    name: "Occurrences"\n    filters:\n      and:\n        - file.hasTag("task")\n        - file.hasLink(this.file) && note.recurrence_parent && file(note.recurrence_parent.replace(/^\\[[^\\]]+\\]\\((.*)\\)$/, "$1").replace(/%20/g, " ")).asLink() == this.file.asLink()\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - occurrence_date\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: occurrence_date\n        direction: ASC\n  - type: tasknotesTaskList\n    name: "Projects"\n    filters:\n      and:\n        - list(this.projects).map(file(value.replace(/^\\[[^\\]]+\\]\\((.*)\\)$/, "$1").replace(/%20/g, " ")).asLink()).contains(file.asLink())\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n  - type: tasknotesTaskList\n    name: "Blocked By"\n    filters:\n      and:\n        - file.hasTag("task")\n        - list(this.note.blockedBy).map(file(if(value.isType("object"), value.uid, value)).asLink()).contains(file.asLink())\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: tasknotes_manual_order\n        direction: DESC\n  - type: tasknotesKanban\n    name: "Blocking"\n    filters:\n      and:\n        - file.hasTag("task")\n        - list(note.blockedBy).map(file(if(value.isType("object"), value.uid, value)).asLink()).contains(this.file.asLink())\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: tasknotes_manual_order\n        direction: DESC\n    groupBy:\n      property: status\n      direction: ASC\n
","text":"These are the exact templates TaskNotes 4.12.3 produces with default settings. Your generated files reflect your own field mapping and other settings, so customized output can differ. Regenerating with Update files overwrites configured default Base files. Copy a customized file to a new path before updating it. mini-calendar-default.base# Command/template ID: open-calendar-view # Mini Calendar # Generated with your TaskNotes settings filters: and: - file.hasTag(\"task\") formulas: priorityWeight: 'if(priority==\"none\",0,if(priority==\"low\",1,if(priority==\"normal\",2,if(priority==\"high\",3,999))))' daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)' dueIn: 'if(due.isEmpty(), \"\", if(formula.daysUntilDue == 0, \"Today\", if(formula.daysUntilDue == 1, \"1 day\", if(formula.daysUntilDue > 1, formula.daysUntilDue + \" days\", if(formula.daysUntilDue == -1, \"1 day overdue\", formula.daysUntilDue * -1 + \" days overdue\")))))' daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)' daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()' daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()' isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != \"done\"' isDueToday: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")' isDueThisWeek: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")' isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")' isRecurring: 'recurrence && !recurrence.isEmpty()' hasTimeEstimate: 'timeEstimate && timeEstimate > 0' timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)' efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)' timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - \"7d\").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)' timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)' dueMonth: 'if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), \"No due date\")' dueWeek: 'if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), \"No due date\")' scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"Not scheduled\")' scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"Not scheduled\")' dueDateCategory: 'if(due.isEmpty(), \"No due date\", if(date(due) < today(), \"Overdue\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), \"This week\", \"Later\")))))' timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(timeEstimate < 30, \"Quick (<30m)\", if(timeEstimate <= 120, \"Medium (30m-2h)\", \"Long (>2h)\")))' ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, \"Today\", if(((number(now()) - number(file.ctime)) / 86400000) < 7, \"This week\", if(((number(now()) - number(file.ctime)) / 86400000) < 30, \"This month\", \"Older\")))' createdMonth: 'file.ctime.format(\"YYYY-MM\")' modifiedMonth: 'file.mtime.format(\"YYYY-MM\")' priorityCategory: 'if(priority==\"none\",\"None\",if(priority==\"low\",\"Low\",if(priority==\"normal\",\"Normal\",if(priority==\"high\",\"High\",\"No priority\"))))' projectCount: 'if(!projects || list(projects).length == 0, \"No projects\", if(list(projects).length == 1, \"Single project\", \"Multiple projects\"))' contextCount: 'if(!contexts || list(contexts).length == 0, \"No contexts\", if(list(contexts).length == 1, \"Single context\", \"Multiple contexts\"))' trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(!timeEntries || list(timeEntries).length == 0, \"Not started\", if(formula.efficiencyRatio < 100, \"Under estimate\", \"Over estimate\")))' nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))' daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))' hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)' isToday: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"))' isThisWeek: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"))' nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), \"No date\", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), \"Overdue/Past\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")), \"Today\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")), \"Tomorrow\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")), \"This week\", \"Later\")))))' nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-MM\"), date(scheduled).format(\"YYYY-MM\")), if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"No date\")))' nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-[W]WW\"), date(scheduled).format(\"YYYY-[W]WW\")), if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"No date\")))' urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format(\"YYYY-MM-DD\")))) / 86400000)))' timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + \"h \" + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + \"m\", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + \"m\"), \"0m\")' dueDateDisplay: 'if(due.isEmpty(), \"\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") == (today() - \"1 day\").format(\"YYYY-MM-DD\"), \"Yesterday\", if(date(due) < today(), formula.daysUntilDue * -1 + \"d ago\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), date(due).format(\"ddd\"), date(due).format(\"MMM D\")))))))' views: - type: tasknotesMiniCalendar name: \"Due\" order: - status - priority - due - scheduled - projects - contexts - file.tags - blockedBy - file.name - recurrence - complete_instances - file.tasks sort: - property: due direction: ASC dateProperty: due - type: tasknotesMiniCalendar name: \"Scheduled\" order: [] dateProperty: scheduled - type: tasknotesMiniCalendar name: \"Created\" dateProperty: file.ctime - type: tasknotesMiniCalendar name: \"Modified\" dateProperty: file.mtime kanban-default.base# Command/template ID: open-kanban-view # Kanban Board filters: and: - file.hasTag(\"task\") formulas: priorityWeight: 'if(priority==\"none\",0,if(priority==\"low\",1,if(priority==\"normal\",2,if(priority==\"high\",3,999))))' daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)' dueIn: 'if(due.isEmpty(), \"\", if(formula.daysUntilDue == 0, \"Today\", if(formula.daysUntilDue == 1, \"1 day\", if(formula.daysUntilDue > 1, formula.daysUntilDue + \" days\", if(formula.daysUntilDue == -1, \"1 day overdue\", formula.daysUntilDue * -1 + \" days overdue\")))))' daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)' daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()' daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()' isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != \"done\"' isDueToday: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")' isDueThisWeek: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")' isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")' isRecurring: 'recurrence && !recurrence.isEmpty()' hasTimeEstimate: 'timeEstimate && timeEstimate > 0' timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)' efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)' timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - \"7d\").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)' timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)' dueMonth: 'if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), \"No due date\")' dueWeek: 'if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), \"No due date\")' scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"Not scheduled\")' scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"Not scheduled\")' dueDateCategory: 'if(due.isEmpty(), \"No due date\", if(date(due) < today(), \"Overdue\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), \"This week\", \"Later\")))))' timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(timeEstimate < 30, \"Quick (<30m)\", if(timeEstimate <= 120, \"Medium (30m-2h)\", \"Long (>2h)\")))' ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, \"Today\", if(((number(now()) - number(file.ctime)) / 86400000) < 7, \"This week\", if(((number(now()) - number(file.ctime)) / 86400000) < 30, \"This month\", \"Older\")))' createdMonth: 'file.ctime.format(\"YYYY-MM\")' modifiedMonth: 'file.mtime.format(\"YYYY-MM\")' priorityCategory: 'if(priority==\"none\",\"None\",if(priority==\"low\",\"Low\",if(priority==\"normal\",\"Normal\",if(priority==\"high\",\"High\",\"No priority\"))))' projectCount: 'if(!projects || list(projects).length == 0, \"No projects\", if(list(projects).length == 1, \"Single project\", \"Multiple projects\"))' contextCount: 'if(!contexts || list(contexts).length == 0, \"No contexts\", if(list(contexts).length == 1, \"Single context\", \"Multiple contexts\"))' trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(!timeEntries || list(timeEntries).length == 0, \"Not started\", if(formula.efficiencyRatio < 100, \"Under estimate\", \"Over estimate\")))' nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))' daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))' hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)' isToday: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"))' isThisWeek: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"))' nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), \"No date\", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), \"Overdue/Past\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")), \"Today\", if(((due.isEmpty() == false) && date(due).fo"},{"route":"/obsidian/reference/http-routes/","title":"HTTP route index","description":"Implemented TaskNotes HTTP API routes generated from controller decorators.","product":"obsidian","platforms":[],"version":"4.12.3","generated":true,"noIndex":false,"hideToc":false,"source":"tasknotes:docs-builder/src/generated-pages.js","namespace":"obsidian","relativePath":"reference/http-routes.md","raw":"---\ntitle: \"HTTP route index\"\ndescription: \"Implemented TaskNotes HTTP API routes generated from controller decorators.\"\ngenerated: true\nsource: [\"src/api/*Controller.ts\",\"docs/HTTP_API.md\",\"docs/nlp-api.md\"]\n---\n# HTTP route index\n\nThis index is generated from controller route decorators. The build fails if an implemented route is absent from the narrative [HTTP API guide](/HTTP_API/) or [NLP API guide](/nlp-api/).\n\n| Method | Path | Controller |\n| --- | --- | --- |\n| `POST` | `/api/bases/default-files/update` | `BasesController` |\n| `GET` | `/api/calendars` | `CalendarsController` |\n| `GET` | `/api/calendars/events` | `CalendarsController` |\n| `GET` | `/api/calendars/google` | `CalendarsController` |\n| `GET` | `/api/calendars/microsoft` | `CalendarsController` |\n| `GET` | `/api/calendars/subscriptions` | `CalendarsController` |\n| `GET` | `/api/docs` | `SystemController` |\n| `GET` | `/api/docs/ui` | `SystemController` |\n| `GET` | `/api/filter-options` | `TasksController` |\n| `GET` | `/api/health` | `SystemController` |\n| `POST` | `/api/nlp/create` | `SystemController` |\n| `POST` | `/api/nlp/parse` | `SystemController` |\n| `POST` | `/api/pomodoro/pause` | `PomodoroController` |\n| `POST` | `/api/pomodoro/resume` | `PomodoroController` |\n| `GET` | `/api/pomodoro/sessions` | `PomodoroController` |\n| `POST` | `/api/pomodoro/start` | `PomodoroController` |\n| `GET` | `/api/pomodoro/stats` | `PomodoroController` |\n| `GET` | `/api/pomodoro/status` | `PomodoroController` |\n| `POST` | `/api/pomodoro/stop` | `PomodoroController` |\n| `GET` | `/api/stats` | `TasksController` |\n| `GET` | `/api/tasks` | `TasksController` |\n| `POST` | `/api/tasks` | `TasksController` |\n| `DELETE` | `/api/tasks/:id` | `TasksController` |\n| `GET` | `/api/tasks/:id` | `TasksController` |\n| `PUT` | `/api/tasks/:id` | `TasksController` |\n| `POST` | `/api/tasks/:id/archive` | `TasksController` |\n| `POST` | `/api/tasks/:id/complete-instance` | `TasksController` |\n| `POST` | `/api/tasks/:id/materialize-occurrence` | `TasksController` |\n| `GET` | `/api/tasks/:id/time` | `TimeTrackingController` |\n| `POST` | `/api/tasks/:id/time/start` | `TimeTrackingController` |\n| `POST` | `/api/tasks/:id/time/start-with-description` | `TimeTrackingController` |\n| `POST` | `/api/tasks/:id/time/stop` | `TimeTrackingController` |\n| `POST` | `/api/tasks/:id/toggle-status` | `TasksController` |\n| `POST` | `/api/tasks/query` | `TasksController` |\n| `GET` | `/api/time/active` | `TimeTrackingController` |\n| `GET` | `/api/time/summary` | `TimeTrackingController` |\n| `GET` | `/api/webhooks` | `WebhookController` |\n| `POST` | `/api/webhooks` | `WebhookController` |\n| `DELETE` | `/api/webhooks/:id` | `WebhookController` |\n| `GET` | `/api/webhooks/deliveries` | `WebhookController` |\n\n_Generated from 40 implemented routes._\n","aliases":["/reference/http-routes/","/reference/http-routes/"],"toc":[],"html":"

This index is generated from controller route decorators. The build fails if an implemented route is absent from the narrative HTTP API guide or NLP API guide.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
MethodPathController
POST/api/bases/default-files/updateBasesController
GET/api/calendarsCalendarsController
GET/api/calendars/eventsCalendarsController
GET/api/calendars/googleCalendarsController
GET/api/calendars/microsoftCalendarsController
GET/api/calendars/subscriptionsCalendarsController
GET/api/docsSystemController
GET/api/docs/uiSystemController
GET/api/filter-optionsTasksController
GET/api/healthSystemController
POST/api/nlp/createSystemController
POST/api/nlp/parseSystemController
POST/api/pomodoro/pausePomodoroController
POST/api/pomodoro/resumePomodoroController
GET/api/pomodoro/sessionsPomodoroController
POST/api/pomodoro/startPomodoroController
GET/api/pomodoro/statsPomodoroController
GET/api/pomodoro/statusPomodoroController
POST/api/pomodoro/stopPomodoroController
GET/api/statsTasksController
GET/api/tasksTasksController
POST/api/tasksTasksController
DELETE/api/tasks/:idTasksController
GET/api/tasks/:idTasksController
PUT/api/tasks/:idTasksController
POST/api/tasks/:id/archiveTasksController
POST/api/tasks/:id/complete-instanceTasksController
POST/api/tasks/:id/materialize-occurrenceTasksController
GET/api/tasks/:id/timeTimeTrackingController
POST/api/tasks/:id/time/startTimeTrackingController
POST/api/tasks/:id/time/start-with-descriptionTimeTrackingController
POST/api/tasks/:id/time/stopTimeTrackingController
POST/api/tasks/:id/toggle-statusTasksController
POST/api/tasks/queryTasksController
GET/api/time/activeTimeTrackingController
GET/api/time/summaryTimeTrackingController
GET/api/webhooksWebhookController
POST/api/webhooksWebhookController
DELETE/api/webhooks/:idWebhookController
GET/api/webhooks/deliveriesWebhookController
\n

Generated from 40 implemented routes.

\n","text":"This index is generated from controller route decorators. The build fails if an implemented route is absent from the narrative HTTP API guide or NLP API guide. Method Path Controller POST /api/bases/default-files/update BasesController GET /api/calendars CalendarsController GET /api/calendars/events CalendarsController GET /api/calendars/google CalendarsController GET /api/calendars/microsoft CalendarsController GET /api/calendars/subscriptions CalendarsController GET /api/docs SystemController GET /api/docs/ui SystemController GET /api/filter-options TasksController GET /api/health SystemController POST /api/nlp/create SystemController POST /api/nlp/parse SystemController POST /api/pomodoro/pause PomodoroController POST /api/pomodoro/resume PomodoroController GET /api/pomodoro/sessions PomodoroController POST /api/pomodoro/start PomodoroController GET /api/pomodoro/stats PomodoroController GET /api/pomodoro/status PomodoroController POST /api/pomodoro/stop PomodoroController GET /api/stats TasksController GET /api/tasks TasksController POST /api/tasks TasksController DELETE /api/tasks/:id TasksController GET /api/tasks/:id TasksController PUT /api/tasks/:id TasksController POST /api/tasks/:id/archive TasksController POST /api/tasks/:id/complete-instance TasksController POST /api/tasks/:id/materialize-occurrence TasksController GET /api/tasks/:id/time TimeTrackingController POST /api/tasks/:id/time/start TimeTrackingController POST /api/tasks/:id/time/start-with-description TimeTrackingController POST /api/tasks/:id/time/stop TimeTrackingController POST /api/tasks/:id/toggle-status TasksController POST /api/tasks/query TasksController GET /api/time/active TimeTrackingController GET /api/time/summary TimeTrackingController GET /api/webhooks WebhookController POST /api/webhooks WebhookController DELETE /api/webhooks/:id WebhookController GET /api/webhooks/deliveries WebhookController Generated from 40 implemented routes."},{"route":"/obsidian/reference/settings-source/","title":"Settings source reference","description":"The six TaskNotes settings tabs, their controls, and the complete default settings snapshot generated from source.","product":"obsidian","platforms":[],"version":"4.12.3","generated":true,"noIndex":false,"hideToc":false,"source":"tasknotes:docs-builder/src/generated-pages.js","namespace":"obsidian","relativePath":"reference/settings-source.md","raw":"---\ntitle: \"Settings source reference\"\ndescription: \"The six TaskNotes settings tabs, their controls, and the complete default settings snapshot generated from source.\"\ngenerated: true\nsource: [\"src/settings/TaskNotesSettingTab.ts\",\"src/settings/tabs/*.ts\",\"src/settings/defaults.ts\",\"src/i18n/resources/en.ts\"]\n---\n# Settings source reference\n\nTaskNotes currently exposes 6 settings tabs. This inventory is generated from the tab renderer and English translation source so additions cannot silently disappear from the documentation.\n\n## General\n\nSource: `src/settings/tabs/generalTab.ts`\n\n| Setting | Purpose |\n| --- | --- |\n| Default tasks folder | Default location for new tasks. Supports folder template variables like {{currentNotePath}}, {{currentNoteTitle}}, and {{projectFilePath}}, plus Daily Notes-style date tokens like YYYY/MM/DD. |\n| Folder for inline-created tasks | Folder where tasks created from inline commands or checkbox conversion will be created. Leave empty to use the default tasks folder. Use {{currentNotePath}} for the current note's folder, or {{currentNoteTitle}} for a subfolder named after the current note. |\n| Move archived tasks to folder | Automatically move archived tasks to an archive folder |\n| Archive folder | Folder to move tasks to when archived. Supports template variables like {{year}}, {{month}}, {{priority}}, etc. |\n| Identify tasks by | Choose whether to identify tasks by tag or by a frontmatter property |\n| Task tag | Tag that identifies notes as tasks (without #). Existing .base view filters keep their old tag when this changes; update default Base files or edit those filters. |\n| Hide identification tags in task cards | When enabled, tags matching the task identification tag (including hierarchical matches like 'task/project') will be hidden from task card displays |\n| Hidden tag scope | Choose whether hiding identification tags also hides nested tags. |\n| Task property name | The frontmatter property name (e.g., \"category\") |\n| Task property value | The value that identifies a note as a task (e.g., \"task\") |\n| Auto-create default files | Automatically create missing default base view files on startup. Disable to prevent deleted sample files from being recreated. |\n| Create default files | Create the default .base files in TaskNotes/Views/ directory. Existing files will not be overwritten. |\n| Update default files | Overwrite the configured default .base files with templates generated from your current TaskNotes settings. |\n| Export v3 saved views to Bases | Convert all your saved views from TaskNotes v3 into a single .base file with multiple views. This helps migrate your v3 filter configurations to the new Bases system. |\n| Excluded folders | Comma-separated list of folders to exclude from task indexing and project suggestions |\n| UI language | Select the language used for TaskNotes interface text |\n| Use Markdown links in frontmatter | Generate markdown links (`[text](path)`) instead of wikilinks ([[link]]) in frontmatter properties. ⚠️ Requires the 'obsidian-frontmatter-markdown-links' plugin to work correctly. |\n| Show release notes after update | Automatically open release notes when TaskNotes is updated to a new version |\n| Check for new releases on startup | Check GitHub once when TaskNotes starts and show a notice when a newer compatible release is available |\n| View release notes | See what's new in the latest version of TaskNotes |\n\n## Task properties\n\nSource: `src/settings/tabs/taskPropertiesTab.ts`\n\n| Setting | Purpose |\n| --- | --- |\n| No static controls detected | This tab is assembled dynamically. |\n\n## Modal fields\n\nSource: `src/settings/tabs/modalFieldsTab.ts`\n\n| Setting | Purpose |\n| --- | --- |\n| No static controls detected | This tab is assembled dynamically. |\n\n## Appearance & UI\n\nSource: `src/settings/tabs/appearanceTab.ts`\n\n| Setting | Purpose |\n| --- | --- |\n| Default visible properties | Choose which properties appear on task cards by default. |\n| Time format | Display time in 12-hour or 24-hour format throughout the plugin |\n| Default view | The calendar view shown when opening the calendar tab |\n| Custom view day count | Number of days to show in custom multi-day view |\n| First day of week | Which day should be the first column in week views |\n| Show weekends | Display weekends in calendar views |\n| Show week numbers | Display week numbers in calendar views |\n| Show today highlight | Highlight the current day in calendar views |\n| Show current time indicator | Display a line showing the current time in timeline views |\n| Selection mirror | Show a visual preview while dragging to select time ranges |\n| Calendar locale | Calendar locale for date formatting and calendar system (e.g., \"en\", \"fa\" for Farsi/Persian, \"de\" for German). Leave empty to auto-detect from browser. |\n| Show scheduled tasks | Display tasks with scheduled dates by default |\n| Show due dates | Display task due dates by default |\n| Show due dates when scheduled | Display due dates even for tasks that already have scheduled dates |\n| Show time entries | Display completed time tracking entries by default |\n| Show recurring tasks | Display recurring task instances by default |\n| Show ICS events | Display events from ICS subscriptions by default |\n| Time slot duration | Duration of each time slot in timeline views |\n| Start time | Earliest time shown in timeline views (HH:MM format) |\n| End time | Latest time shown in timeline views (HH:MM format). Use values above 24:00 to show early next-day hours, such as 26:00 for 2 AM. |\n| Initial scroll time | Time to scroll to when opening timeline views (HH:MM format) |\n| Event minimum height | Minimum height for events in timeline views (pixels) |\n| Show tracked tasks in status bar | Display currently tracked tasks in Obsidian's status bar |\n| Show relationships widget | Display a widget showing all relationships for the current note (subtasks, projects, dependencies) |\n| Relationships position | Where to position the relationships widget |\n| Show task card in note | Display a task card widget at the top of task notes showing the task details and actions |\n| Strike through completed task titles | Draw a line through completed task card titles. Turn off to keep completed tasks easier to read |\n| Show expandable subtasks | Allow expanding/collapsing subtask sections in task cards |\n| Expand subtasks by default | Show project subtasks expanded when task cards are rendered |\n| Subtask chevron position | Position of expand/collapse chevrons in task cards |\n| Views button alignment | Alignment of the views/filters button in the task interface |\n| Single-click action | Action performed when single-clicking a task card |\n| Double-click action | Action performed when double-clicking a task card |\n\n## Features\n\nSource: `src/settings/tabs/featuresTab.ts`\n\n| Setting | Purpose |\n| --- | --- |\n| Task link overlay | Show interactive overlays when hovering over task links |\n| Disable overlay for aliased links | Do not show the task widget if the link contains an alias (e.g. [[Task\\|Alias]]). |\n| Show convert button next to checkboxes | Display an inline button next to Markdown checkboxes that converts them to TaskNotes |\n| Keep checkbox when converting | Leave the original Markdown checkbox marker in place when converting a checkbox to a TaskNote link |\n| Enable natural language task input | Parse due dates, priorities, and contexts from natural language when creating tasks |\n| Default to scheduled | When NLP detects a date without context, treat it as scheduled rather than due |\n| NLP language | Language for natural language processing patterns and date parsing |\n| Open task after creation | Choose whether the task creation modal opens the new task note after saving. |\n| Use body template | Use a template file for task body content |\n| Body template file | Path to template file for task body content. Supports template variables like {{title}}, {{date}}, {{time}}, {{priority}}, {{status}}, etc. |\n| Use occurrence note template | Use a separate fallback template for materialized occurrence notes when the recurring task has no occurrence_template |\n| Occurrence note template file | Path to template file for materialized occurrence notes. A recurring task's occurrence_template field takes priority over this fallback. |\n| Template variables: | See the setting in Obsidian for contextual details. |\n| Use task defaults on instant convert | Apply default task settings when converting text to tasks instantly |\n| Work duration | Duration of work intervals in minutes |\n| Short break duration | Duration of short breaks in minutes |\n| Long break duration | Duration of long breaks in minutes |\n| Long break interval | Number of work sessions before a long break |\n| Auto-start breaks | Automatically start break timers after work sessions |\n| Auto-start work | Automatically start work sessions after breaks |\n| Pomodoro notifications | Show notifications when Pomodoro sessions end |\n| Show Pomodoro in status bar | Display the active Pomodoro countdown in Obsidian's status bar |\n| Sound enabled | Play sound when Pomodoro sessions end |\n| Sound volume | Volume for Pomodoro sounds (0-100) |\n| Pomodoro data storage | Configure where Pomodoro session data is stored and how it's managed. |\n| Mobile sidebar | Where to open the Pomodoro timer on mobile devices |\n| Enable notifications | Enable task reminder notifications |\n| Notification type | Type of notifications to show |\n| Send test reminder | Send a test reminder using the current notification type and sound settings. |\n| Notification sound | Play a sound when task reminders trigger |\n| Sound volume | Volume for task reminder sounds (0-100) |\n| Preview notification sound | Play the configured task reminder sound |\n| Hide completed tasks from overdue | Exclude completed tasks from overdue task calculations |\n| Disable note indexing | Disable automatic indexing of note content for better performance |\n| Suggestion debounce | Delay in milliseconds before showing suggestions |\n| Auto-stop time tracking | Automatically stop time tracking when a task is marked complete |\n| Time tracking stop notification | Show notification when time tracking is automatically stopped |\n| Maintain due date offset in recurring tasks | Keep the offset between due date and scheduled date when recurring tasks are completed |\n| Reset checkboxes on recurrence | Reset all Markdown checkboxes in the task body when a recurring task is completed and rescheduled |\n| Enable timeblocking | Enable timeblocking feature for lightweight scheduling in daily notes. When enabled, 'Timeblock' option appears in the calendar drag context menu. |\n| Show timeblocks | Display timeblocks from daily notes by default |\n| Default timeblock color | The default color used when creating new timeblocks |\n| Enable debug logging | Log detailed drag-and-drop and view diagnostics to the developer console. Useful for troubleshooting. |\n\n## Integrations\n\nSource: `src/settings/tabs/integrationsTab.ts`\n\n| Setting | Purpose |\n| --- | --- |\n| Generate mdbase type definitions | See the setting in Obsidian for contextual details. |\n| Disable calendar integrations on mobile | Skip Google, Microsoft, and ICS calendar loading on Obsidian mobile. Desktop calendar integrations are unchanged. |\n| Calendar integrations are disabled on this mobile device | See the setting in Obsidian for contextual details. |\n| Enable task export | When enabled, tasks with dates will be automatically synced to Google Calendar as events. |\n| Target calendar | See the setting in Obsidian for contextual details. |\n| Sync trigger | Which task date should trigger calendar event creation. |\n| Create as all-day events | When enabled, tasks are created as all-day events. When disabled, uses time estimate for duration. |\n| Default event duration | Duration in minutes for timed events (used when task has no time estimate). |\n| Event title template | Template for event titles. Available variables: {{title}}, {{status}}, {{priority}} |\n| Include task details in description | Add task metadata (priority, status, tags, etc.) to the event description. |\n| Include Obsidian link | Add a link back to the task in Obsidian in the event description. |\n| Default reminder | Add popup reminders to timed Google Calendar events. Enter minutes before the event, separated by commas. Leave empty to use calendar defaults. Common values: 15, 30, 60, 1440. |\n| Automatic sync behavior | See the setting in Obsidian for contextual details. |\n| Sync on task create | Automatically create calendar event when a new task is created. |\n| Sync on task update | Automatically update calendar event when a task is modified. |\n| Sync on task complete | Update calendar event when a task is completed (adds checkmark to title). |\n| Delete event on task delete | Remove calendar event when the corresponding task is deleted. |\n| Manual sync actions | See the setting in Obsidian for contextual details. |\n| Sync all tasks | Sync all existing tasks to Google Calendar. This will create events for tasks that haven't been synced yet. |\n| Unlink all tasks | Remove all task-event links without deleting calendar events. |\n| Default note template | Path to template file for notes created from ICS events |\n| Default note folder | Folder for notes created from ICS events |\n| ICS note filename format | How filenames are generated for notes created from ICS events |\n| Custom ICS filename template | Template for custom ICS event filenames |\n| Use ICS event end time as task due date | When enabled, tasks created from calendar events will have their due date set to the event's end time. For all-day events, the due date will be set to the event date. For timed events, the due date will include the end time. |\n| Recurring event related notes | Choose whether notes linked to one recurrence of an external calendar event appear across the loaded series or only on the selected instance. |\n| Add calendar subscription | Add a new calendar subscription from ICS/iCal URL or local file |\n| New calendar | See the setting in Obsidian for contextual details. |\n| Refresh all subscriptions | Manually refresh all enabled calendar subscriptions |\n| Enable automatic export | Automatically keep an ICS file updated with all your tasks |\n| Export file path | Path where the ICS file will be saved (relative to vault root) |\n| Update interval (between 5 and 1440 minutes) | How often to update the export file |\n| Use task duration for event length | When enabled, uses the task's time estimate (duration) instead of due date for the calendar event end time. This is useful for GTD workflows where scheduled + duration represents work planning, while due date represents deadlines. |\n| Exclude completed tasks | When enabled, completed tasks are omitted from ICS exports. Completed statuses are taken from your task statuses settings. |\n| Exclude archived tasks | When enabled, archived tasks are omitted from ICS exports. |\n| Require due date | When enabled, only tasks with a due date are included in ICS exports. |\n| Require scheduled date | When enabled, only tasks with a scheduled date are included in ICS exports. |\n| Export now | Manually trigger an immediate export |\n| Export status: | See the setting in Obsidian for contextual details. |\n| Enable HTTP API | Start local HTTP server for API access |\n| API port | Port number for the HTTP API server |\n| API authentication token | Token required for API authentication (leave empty for no auth) |\n| Enable MCP server | Expose TaskNotes tools via Model Context Protocol at /mcp endpoint. Requires HTTP API to be enabled. |\n| Add webhook | Register a new webhook endpoint |\n\n## Complete default settings snapshot\n\nThe following JSON is generated from `DEFAULT_SETTINGS`. Empty strings and disabled flags are intentional defaults.\n\n```json\n{\n \"tasksFolder\": \"TaskNotes/Tasks\",\n \"moveArchivedTasks\": false,\n \"archiveFolder\": \"TaskNotes/Archive\",\n \"taskTag\": \"task\",\n \"taskIdentificationMethod\": \"tag\",\n \"hideIdentifyingTagsInCards\": false,\n \"hideIdentifyingTagsMode\": \"all\",\n \"taskPropertyName\": \"\",\n \"taskPropertyValue\": \"\",\n \"excludedFolders\": \"\",\n \"defaultTaskPriority\": \"normal\",\n \"defaultTaskStatus\": \"open\",\n \"taskOrgFiltersCollapsed\": false,\n \"taskFilenameFormat\": \"zettel\",\n \"storeTitleInFilename\": true,\n \"customFilenameTemplate\": \"{{title}}\",\n \"occurrenceFilenameTemplate\": \"\",\n \"occurrenceFilenameTemplateProperty\": \"occurrenceFilenameTemplate\",\n \"taskCreationDefaults\": {\n \"defaultContexts\": \"\",\n \"defaultTags\": \"\",\n \"defaultProjects\": \"\",\n \"useParentNoteForTaskCreation\": false,\n \"useParentNoteAsProject\": false,\n \"useParentHeaderAsProject\": false,\n \"inheritParentTaskProperties\": false,\n \"defaultTimeEstimate\": 0,\n \"defaultRecurrence\": \"none\",\n \"defaultDueDate\": \"none\",\n \"defaultDueTime\": \"none\",\n \"defaultScheduledDate\": \"today\",\n \"defaultScheduledTime\": \"none\",\n \"bodyTemplate\": \"\",\n \"useBodyTemplate\": false,\n \"occurrenceBodyTemplate\": \"\",\n \"useOccurrenceBodyTemplate\": false,\n \"defaultReminders\": []\n },\n \"openTaskAfterCreation\": \"none\",\n \"calendarViewSettings\": {\n \"defaultView\": \"dayGridMonth\",\n \"customDayCount\": 3,\n \"slotDuration\": \"00:30:00\",\n \"slotMinTime\": \"00:00:00\",\n \"slotMaxTime\": \"24:00:00\",\n \"scrollTime\": \"08:00:00\",\n \"firstDay\": 1,\n \"timeFormat\": \"24\",\n \"showWeekends\": true,\n \"locale\": \"\",\n \"defaultShowScheduled\": true,\n \"defaultShowDue\": true,\n \"defaultShowDueWhenScheduled\": true,\n \"defaultShowScheduledToDueSpan\": false,\n \"defaultShowTimeEntries\": false,\n \"defaultShowRecurring\": true,\n \"defaultShowICSEvents\": true,\n \"enableTimeblocking\": false,\n \"defaultShowTimeblocks\": true,\n \"defaultTimeblockColor\": \"#6366f1\",\n \"timeblockAttachmentSearchOrder\": \"name-asc\",\n \"nowIndicator\": true,\n \"selectMirror\": true,\n \"weekNumbers\": false,\n \"showTodayHighlight\": true,\n \"eventMinHeight\": 15,\n \"slotEventOverlap\": true,\n \"eventMaxStack\": null,\n \"dayMaxEvents\": true,\n \"dayMaxEventRows\": false\n },\n \"pomodoroWorkDuration\": 25,\n \"pomodoroShortBreakDuration\": 5,\n \"pomodoroLongBreakDuration\": 15,\n \"pomodoroLongBreakInterval\": 4,\n \"pomodoroAutoStartBreaks\": true,\n \"pomodoroAutoStartWork\": false,\n \"pomodoroNotifications\": true,\n \"pomodoroSoundEnabled\": true,\n \"pomodoroSoundVolume\": 50,\n \"pomodoroStorageLocation\": \"plugin\",\n \"pomodoroMobileSidebar\": \"tab\",\n \"showPomodoroInStatusBar\": true,\n \"enableTaskLinkOverlay\": true,\n \"disableOverlayOnAlias\": false,\n \"enableInstantTaskConvert\": true,\n \"useDefaultsOnInstantConvert\": true,\n \"preserveCheckboxOnConvert\": false,\n \"taskModalTabMovesFocus\": true,\n \"enableNaturalLanguageInput\": true,\n \"nlpDefaultToScheduled\": true,\n \"nlpLanguage\": \"en\",\n \"uiLanguage\": \"system\",\n \"statusSuggestionTrigger\": \"*\",\n \"nlpTriggers\": {\n \"triggers\": [\n {\n \"propertyId\": \"tags\",\n \"trigger\": \"#\",\n \"enabled\": true\n },\n {\n \"propertyId\": \"contexts\",\n \"trigger\": \"@\",\n \"enabled\": true\n },\n {\n \"propertyId\": \"projects\",\n \"trigger\": \"+\",\n \"enabled\": true\n },\n {\n \"propertyId\": \"status\",\n \"trigger\": \"*\",\n \"enabled\": true\n },\n {\n \"propertyId\": \"priority\",\n \"trigger\": \"!\",\n \"enabled\": false\n }\n ]\n },\n \"singleClickAction\": \"edit\",\n \"doubleClickAction\": \"openNote\",\n \"projectAutosuggest\": {\n \"enableFuzzy\": false,\n \"rows\": [\n \"{title|n(Title)}\",\n \"{aliases|n(Aliases)}\",\n \"{file.path|n(Path)}\"\n ],\n \"showAdvanced\": false,\n \"requiredTags\": [],\n \"includeFolders\": [],\n \"propertyKey\": \"\",\n \"propertyValue\": \"\"\n },\n \"inlineTaskConvertFolder\": \"{{currentNotePath}}\",\n \"disableNoteIndexing\": false,\n \"suggestionDebounceMs\": 0,\n \"fieldMapping\": {\n \"title\": \"title\",\n \"status\": \"status\",\n \"priority\": \"priority\",\n \"due\": \"due\",\n \"scheduled\": \"scheduled\",\n \"contexts\": \"contexts\",\n \"projects\": \"projects\",\n \"attachments\": \"attachments\",\n \"timeEstimate\": \"timeEstimate\",\n \"completedDate\": \"completedDate\",\n \"dateCreated\": \"dateCreated\",\n \"dateModified\": \"dateModified\",\n \"recurrence\": \"recurrence\",\n \"recurrenceAnchor\": \"recurrence_anchor\",\n \"recurrenceParent\": \"recurrence_parent\",\n \"occurrenceDate\": \"occurrence_date\",\n \"occurrenceMaterialization\": \"occurrence_materialization\",\n \"occurrenceNextTrigger\": \"occurrence_next_trigger\",\n \"occurrenceTemplate\": \"occurrence_template\",\n \"occurrencePastHorizon\": \"occurrence_past_horizon\",\n \"occurrenceFutureHorizon\": \"occurrence_future_horizon\",\n \"archiveTag\": \"archived\",\n \"timeEntries\": \"timeEntries\",\n \"completeInstances\": \"complete_instances\",\n \"skippedInstances\": \"skipped_instances\",\n \"blockedBy\": \"blockedBy\",\n \"pomodoros\": \"pomodoros\",\n \"icsEventId\": \"icsEventId\",\n \"icsEventTag\": \"ics_event\",\n \"googleCalendarEventId\": \"googleCalendarEventId\",\n \"googleCalendarExceptionEventId\": \"googleCalendarExceptionEventId\",\n \"googleCalendarExceptionOriginalScheduled\": \"googleCalendarExceptionOriginalScheduled\",\n \"googleCalendarMovedOriginalDates\": \"googleCalendarMovedOriginalDates\",\n \"reminders\": \"reminders\",\n \"sortOrder\": \"tasknotes_manual_order\"\n },\n \"customStatuses\": [\n {\n \"id\": \"none\",\n \"value\": \"none\",\n \"label\": \"None\",\n \"color\": \"#cccccc\",\n \"isCompleted\": false,\n \"excludeFromCycle\": false,\n \"order\": 0,\n \"autoArchive\": false,\n \"autoArchiveDelay\": 5\n },\n {\n \"id\": \"open\",\n \"value\": \"open\",\n \"label\": \"Open\",\n \"color\": \"#808080\",\n \"isCompleted\": false,\n \"excludeFromCycle\": false,\n \"order\": 1,\n \"autoArchive\": false,\n \"autoArchiveDelay\": 5\n },\n {\n \"id\": \"in-progress\",\n \"value\": \"in-progress\",\n \"label\": \"In progress\",\n \"color\": \"#0066cc\",\n \"isCompleted\": false,\n \"excludeFromCycle\": false,\n \"order\": 2,\n \"autoArchive\": false,\n \"autoArchiveDelay\": 5\n },\n {\n \"id\": \"done\",\n \"value\": \"done\",\n \"label\": \"Done\",\n \"color\": \"#00aa00\",\n \"isCompleted\": true,\n \"excludeFromCycle\": false,\n \"order\": 3,\n \"autoArchive\": false,\n \"autoArchiveDelay\": 5\n }\n ],\n \"customPriorities\": [\n {\n \"id\": \"none\",\n \"value\": \"none\",\n \"label\": \"None\",\n \"color\": \"#cccccc\",\n \"weight\": 0\n },\n {\n \"id\": \"low\",\n \"value\": \"low\",\n \"label\": \"Low\",\n \"color\": \"#00aa00\",\n \"weight\": 1\n },\n {\n \"id\": \"normal\",\n \"value\": \"normal\",\n \"label\": \"Normal\",\n \"color\": \"#ffaa00\",\n \"weight\": 2\n },\n {\n \"id\": \"high\",\n \"value\": \"high\",\n \"label\": \"High\",\n \"color\": \"#ff0000\",\n \"weight\": 3\n }\n ],\n \"recurrenceMigrated\": false,\n \"showReleaseNotesOnUpdate\": true,\n \"checkForUpdatesOnStartup\": true,\n \"starterNoteCreated\": false,\n \"showTrackedTasksInStatusBar\": false,\n \"autoStopTimeTrackingOnComplete\": true,\n \"autoStopTimeTrackingNotification\": false,\n \"showRelationships\": true,\n \"relationshipsPosition\": \"bottom\",\n \"showTaskCardInNote\": true,\n \"showCompletedTaskStrikethrough\": true,\n \"showExpandableSubtasks\": true,\n \"expandSubtasksByDefault\": false,\n \"subtaskChevronPosition\": \"right\",\n \"viewsButtonAlignment\": \"right\",\n \"hideCompletedFromOverdue\": true,\n \"icsIntegration\": {\n \"defaultNoteTemplate\": \"\",\n \"defaultNoteFolder\": \"\",\n \"icsNoteFilenameFormat\": \"title\",\n \"customICSNoteFilenameTemplate\": \"{title}\",\n \"enableAutoExport\": false,\n \"autoExportPath\": \"tasknotes-calendar.ics\",\n \"autoExportInterval\": 60,\n \"useDurationForExport\": false,\n \"excludeArchivedFromExport\": false,\n \"excludeCompletedFromExport\": false,\n \"requireDueDateForExport\": false,\n \"requireScheduledDateForExport\": false,\n \"useICSEndAsDue\": false,\n \"recurringEventRelatedNotesMode\": \"series\"\n },\n \"savedViews\": [],\n \"enableNotifications\": true,\n \"notificationType\": \"system\",\n \"notificationSoundEnabled\": false,\n \"notificationSoundVolume\": 50,\n \"enableAPI\": false,\n \"apiPort\": 8080,\n \"apiAuthToken\": \"\",\n \"enableMCP\": false,\n \"webhooks\": [],\n \"userFields\": [],\n \"enableModalSplitLayout\": true,\n \"defaultVisibleProperties\": [\n \"status\",\n \"priority\",\n \"due\",\n \"scheduled\",\n \"projects\",\n \"contexts\",\n \"tags\",\n \"blocked\",\n \"blocking\"\n ],\n \"inlineVisibleProperties\": [\n \"status\",\n \"priority\",\n \"due\",\n \"scheduled\",\n \"recurrence\"\n ],\n \"enableBases\": true,\n \"enableMdbaseSpec\": false,\n \"autoCreateDefaultBasesFiles\": true,\n \"commandFileMapping\": {\n \"open-calendar-view\": \"TaskNotes/Views/mini-calendar-default.base\",\n \"open-kanban-view\": \"TaskNotes/Views/kanban-default.base\",\n \"open-tasks-view\": \"TaskNotes/Views/tasks-default.base\",\n \"open-advanced-calendar-view\": \"TaskNotes/Views/calendar-default.base\",\n \"open-agenda-view\": \"TaskNotes/Views/agenda-default.base\",\n \"pomodoro-stats-base\": \"TaskNotes/Views/pomodoro-stats.base\",\n \"relationships\": \"TaskNotes/Views/relationships.base\"\n },\n \"maintainDueDateOffsetInRecurring\": false,\n \"resetCheckboxesOnRecurrence\": false,\n \"useFrontmatterMarkdownLinks\": false,\n \"enableGoogleCalendar\": false,\n \"enableMicrosoftCalendar\": false,\n \"disableCalendarOnMobile\": false,\n \"enabledGoogleCalendars\": [],\n \"googleCalendarSyncTokens\": {},\n \"enabledMicrosoftCalendars\": [],\n \"microsoftCalendarSyncTokens\": {},\n \"googleCalendarExport\": {\n \"enabled\": false,\n \"targetCalendarId\": \"\",\n \"syncOnTaskCreate\": true,\n \"syncOnTaskUpdate\": true,\n \"syncOnTaskComplete\": true,\n \"syncOnTaskDelete\": true,\n \"eventTitleTemplate\": \"{{title}}\",\n \"includeDescription\": true,\n \"eventColorId\": null,\n \"syncTrigger\": \"scheduled\",\n \"createAsAllDay\": true,\n \"defaultEventDuration\": 60,\n \"includeObsidianLink\": true,\n \"defaultReminderMinutes\": null\n },\n \"enableDebugLogging\": false\n}\n```\n","aliases":["/reference/settings-source/","/reference/settings-source/"],"toc":[{"level":2,"id":"general","text":"General"},{"level":2,"id":"task-properties","text":"Task properties"},{"level":2,"id":"modal-fields","text":"Modal fields"},{"level":2,"id":"appearance-ui","text":"Appearance & UI"},{"level":2,"id":"features","text":"Features"},{"level":2,"id":"integrations","text":"Integrations"},{"level":2,"id":"complete-default-settings-snapshot","text":"Complete default settings snapshot"}],"html":"

TaskNotes currently exposes 6 settings tabs. This inventory is generated from the tab renderer and English translation source so additions cannot silently disappear from the documentation.

\n

General#

\n

Source: src/settings/tabs/generalTab.ts

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
SettingPurpose
Default tasks folderDefault location for new tasks. Supports folder template variables like {{currentNotePath}}, {{currentNoteTitle}}, and {{projectFilePath}}, plus Daily Notes-style date tokens like YYYY/MM/DD.
Folder for inline-created tasksFolder where tasks created from inline commands or checkbox conversion will be created. Leave empty to use the default tasks folder. Use {{currentNotePath}} for the current note's folder, or {{currentNoteTitle}} for a subfolder named after the current note.
Move archived tasks to folderAutomatically move archived tasks to an archive folder
Archive folderFolder to move tasks to when archived. Supports template variables like {{year}}, {{month}}, {{priority}}, etc.
Identify tasks byChoose whether to identify tasks by tag or by a frontmatter property
Task tagTag that identifies notes as tasks (without #). Existing .base view filters keep their old tag when this changes; update default Base files or edit those filters.
Hide identification tags in task cardsWhen enabled, tags matching the task identification tag (including hierarchical matches like 'task/project') will be hidden from task card displays
Hidden tag scopeChoose whether hiding identification tags also hides nested tags.
Task property nameThe frontmatter property name (e.g., "category")
Task property valueThe value that identifies a note as a task (e.g., "task")
Auto-create default filesAutomatically create missing default base view files on startup. Disable to prevent deleted sample files from being recreated.
Create default filesCreate the default .base files in TaskNotes/Views/ directory. Existing files will not be overwritten.
Update default filesOverwrite the configured default .base files with templates generated from your current TaskNotes settings.
Export v3 saved views to BasesConvert all your saved views from TaskNotes v3 into a single .base file with multiple views. This helps migrate your v3 filter configurations to the new Bases system.
Excluded foldersComma-separated list of folders to exclude from task indexing and project suggestions
UI languageSelect the language used for TaskNotes interface text
Use Markdown links in frontmatterGenerate markdown links ([text](path)) instead of wikilinks ([[link]]) in frontmatter properties. ⚠️ Requires the 'obsidian-frontmatter-markdown-links' plugin to work correctly.
Show release notes after updateAutomatically open release notes when TaskNotes is updated to a new version
Check for new releases on startupCheck GitHub once when TaskNotes starts and show a notice when a newer compatible release is available
View release notesSee what's new in the latest version of TaskNotes
\n

Task properties#

\n

Source: src/settings/tabs/taskPropertiesTab.ts

\n
\n\n\n\n\n\n\n\n\n\n\n
SettingPurpose
No static controls detectedThis tab is assembled dynamically.
\n

Modal fields#

\n

Source: src/settings/tabs/modalFieldsTab.ts

\n
\n\n\n\n\n\n\n\n\n\n\n
SettingPurpose
No static controls detectedThis tab is assembled dynamically.
\n

Appearance & UI#

\n

Source: src/settings/tabs/appearanceTab.ts

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
SettingPurpose
Default visible propertiesChoose which properties appear on task cards by default.
Time formatDisplay time in 12-hour or 24-hour format throughout the plugin
Default viewThe calendar view shown when opening the calendar tab
Custom view day countNumber of days to show in custom multi-day view
First day of weekWhich day should be the first column in week views
Show weekendsDisplay weekends in calendar views
Show week numbersDisplay week numbers in calendar views
Show today highlightHighlight the current day in calendar views
Show current time indicatorDisplay a line showing the current time in timeline views
Selection mirrorShow a visual preview while dragging to select time ranges
Calendar localeCalendar locale for date formatting and calendar system (e.g., "en", "fa" for Farsi/Persian, "de" for German). Leave empty to auto-detect from browser.
Show scheduled tasksDisplay tasks with scheduled dates by default
Show due datesDisplay task due dates by default
Show due dates when scheduledDisplay due dates even for tasks that already have scheduled dates
Show time entriesDisplay completed time tracking entries by default
Show recurring tasksDisplay recurring task instances by default
Show ICS eventsDisplay events from ICS subscriptions by default
Time slot durationDuration of each time slot in timeline views
Start timeEarliest time shown in timeline views (HH:MM format)
End timeLatest time shown in timeline views (HH:MM format). Use values above 24:00 to show early next-day hours, such as 26:00 for 2 AM.
Initial scroll timeTime to scroll to when opening timeline views (HH:MM format)
Event minimum heightMinimum height for events in timeline views (pixels)
Show tracked tasks in status barDisplay currently tracked tasks in Obsidian's status bar
Show relationships widgetDisplay a widget showing all relationships for the current note (subtasks, projects, dependencies)
Relationships positionWhere to position the relationships widget
Show task card in noteDisplay a task card widget at the top of task notes showing the task details and actions
Strike through completed task titlesDraw a line through completed task card titles. Turn off to keep completed tasks easier to read
Show expandable subtasksAllow expanding/collapsing subtask sections in task cards
Expand subtasks by defaultShow project subtasks expanded when task cards are rendered
Subtask chevron positionPosition of expand/collapse chevrons in task cards
Views button alignmentAlignment of the views/filters button in the task interface
Single-click actionAction performed when single-clicking a task card
Double-click actionAction performed when double-clicking a task card
\n

Features#

\n

Source: src/settings/tabs/featuresTab.ts

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
SettingPurpose
Task link overlayShow interactive overlays when hovering over task links
Disable overlay for aliased linksDo not show the task widget if the link contains an alias (e.g. [[Task|Alias]]).
Show convert button next to checkboxesDisplay an inline button next to Markdown checkboxes that converts them to TaskNotes
Keep checkbox when convertingLeave the original Markdown checkbox marker in place when converting a checkbox to a TaskNote link
Enable natural language task inputParse due dates, priorities, and contexts from natural language when creating tasks
Default to scheduledWhen NLP detects a date without context, treat it as scheduled rather than due
NLP languageLanguage for natural language processing patterns and date parsing
Open task after creationChoose whether the task creation modal opens the new task note after saving.
Use body templateUse a template file for task body content
Body template filePath to template file for task body content. Supports template variables like {{title}}, {{date}}, {{time}}, {{priority}}, {{status}}, etc.
Use occurrence note templateUse a separate fallback template for materialized occurrence notes when the recurring task has no occurrence_template
Occurrence note template filePath to template file for materialized occurrence notes. A recurring task's occurrence_template field takes priority over this fallback.
Template variables:See the setting in Obsidian for contextual details.
Use task defaults on instant convertApply default task settings when converting text to tasks instantly
Work durationDuration of work intervals in minutes
Short break durationDuration of short breaks in minutes
Long break durationDuration of long breaks in minutes
Long break intervalNumber of work sessions before a long break
Auto-start breaksAutomatically start break timers after work sessions
Auto-start workAutomatically start work sessions after breaks
Pomodoro notificationsShow notifications when Pomodoro sessions end
Show Pomodoro in status barDisplay the active Pomodoro countdown in Obsidian's status bar
Sound enabledPlay sound when Pomodoro sessions end
Sound volumeVolume for Pomodoro sounds (0-100)
Pomodoro data storageConfigure where Pomodoro session data is stored and how it's managed.
Mobile sidebarWhere to open the Pomodoro timer on mobile devices
Enable notificationsEnable task reminder notifications
Notification typeType of notifications to show
Send test reminderSend a test reminder using the current notification type and sound settings.
Notification soundPlay a sound when task reminders trigger
Sound volumeVolume for task reminder sounds (0-100)
Preview notification soundPlay the configured task reminder sound
Hide completed tasks from overdueExclude completed tasks from overdue task calculations
Disable note indexingDisable automatic indexing of note content for better performance
Suggestion debounceDelay in milliseconds before showing suggestions
Auto-stop time trackingAutomatically stop time tracking when a task is marked complete
Time tracking stop notificationShow notification when time tracking is automatically stopped
Maintain due date offset in recurring tasksKeep the offset between due date and scheduled date when recurring tasks are completed
Reset checkboxes on recurrenceReset all Markdown checkboxes in the task body when a recurring task is completed and rescheduled
Enable timeblockingEnable timeblocking feature for lightweight scheduling in daily notes. When enabled, 'Timeblock' option appears in the calendar drag context menu.
Show timeblocksDisplay timeblocks from daily notes by default
Default timeblock colorThe default color used when creating new timeblocks
Enable debug loggingLog detailed drag-and-drop and view diagnostics to the developer console. Useful for troubleshooting.
\n

Integrations#

\n

Source: src/settings/tabs/integrationsTab.ts

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
SettingPurpose
Generate mdbase type definitionsSee the setting in Obsidian for contextual details.
Disable calendar integrations on mobileSkip Google, Microsoft, and ICS calendar loading on Obsidian mobile. Desktop calendar integrations are unchanged.
Calendar integrations are disabled on this mobile deviceSee the setting in Obsidian for contextual details.
Enable task exportWhen enabled, tasks with dates will be automatically synced to Google Calendar as events.
Target calendarSee the setting in Obsidian for contextual details.
Sync triggerWhich task date should trigger calendar event creation.
Create as all-day eventsWhen enabled, tasks are created as all-day events. When disabled, uses time estimate for duration.
Default event durationDuration in minutes for timed events (used when task has no time estimate).
Event title templateTemplate for event titles. Available variables: {{title}}, {{status}}, {{priority}}
Include task details in descriptionAdd task metadata (priority, status, tags, etc.) to the event description.
Include Obsidian linkAdd a link back to the task in Obsidian in the event description.
Default reminderAdd popup reminders to timed Google Calendar events. Enter minutes before the event, separated by commas. Leave empty to use calendar defaults. Common values: 15, 30, 60, 1440.
Automatic sync behaviorSee the setting in Obsidian for contextual details.
Sync on task createAutomatically create calendar event when a new task is created.
Sync on task updateAutomatically update calendar event when a task is modified.
Sync on task completeUpdate calendar event when a task is completed (adds checkmark to title).
Delete event on task deleteRemove calendar event when the corresponding task is deleted.
Manual sync actionsSee the setting in Obsidian for contextual details.
Sync all tasksSync all existing tasks to Google Calendar. This will create events for tasks that haven't been synced yet.
Unlink all tasksRemove all task-event links without deleting calendar events.
Default note templatePath to template file for notes created from ICS events
Default note folderFolder for notes created from ICS events
ICS note filename formatHow filenames are generated for notes created from ICS events
Custom ICS filename templateTemplate for custom ICS event filenames
Use ICS event end time as task due dateWhen enabled, tasks created from calendar events will have their due date set to the event's end time. For all-day events, the due date will be set to the event date. For timed events, the due date will include the end time.
Recurring event related notesChoose whether notes linked to one recurrence of an external calendar event appear across the loaded series or only on the selected instance.
Add calendar subscriptionAdd a new calendar subscription from ICS/iCal URL or local file
New calendarSee the setting in Obsidian for contextual details.
Refresh all subscriptionsManually refresh all enabled calendar subscriptions
Enable automatic exportAutomatically keep an ICS file updated with all your tasks
Export file pathPath where the ICS file will be saved (relative to vault root)
Update interval (between 5 and 1440 minutes)How often to update the export file
Use task duration for event lengthWhen enabled, uses the task's time estimate (duration) instead of due date for the calendar event end time. This is useful for GTD workflows where scheduled + duration represents work planning, while due date represents deadlines.
Exclude completed tasksWhen enabled, completed tasks are omitted from ICS exports. Completed statuses are taken from your task statuses settings.
Exclude archived tasksWhen enabled, archived tasks are omitted from ICS exports.
Require due dateWhen enabled, only tasks with a due date are included in ICS exports.
Require scheduled dateWhen enabled, only tasks with a scheduled date are included in ICS exports.
Export nowManually trigger an immediate export
Export status:See the setting in Obsidian for contextual details.
Enable HTTP APIStart local HTTP server for API access
API portPort number for the HTTP API server
API authentication tokenToken required for API authentication (leave empty for no auth)
Enable MCP serverExpose TaskNotes tools via Model Context Protocol at /mcp endpoint. Requires HTTP API to be enabled.
Add webhookRegister a new webhook endpoint
\n

Complete default settings snapshot#

\n

The following JSON is generated from DEFAULT_SETTINGS. Empty strings and disabled flags are intentional defaults.

\n
{\n  "tasksFolder": "TaskNotes/Tasks",\n  "moveArchivedTasks": false,\n  "archiveFolder": "TaskNotes/Archive",\n  "taskTag": "task",\n  "taskIdentificationMethod": "tag",\n  "hideIdentifyingTagsInCards": false,\n  "hideIdentifyingTagsMode": "all",\n  "taskPropertyName": "",\n  "taskPropertyValue": "",\n  "excludedFolders": "",\n  "defaultTaskPriority": "normal",\n  "defaultTaskStatus": "open",\n  "taskOrgFiltersCollapsed": false,\n  "taskFilenameFormat": "zettel",\n  "storeTitleInFilename": true,\n  "customFilenameTemplate": "{{title}}",\n  "occurrenceFilenameTemplate": "",\n  "occurrenceFilenameTemplateProperty": "occurrenceFilenameTemplate",\n  "taskCreationDefaults": {\n    "defaultContexts": "",\n    "defaultTags": "",\n    "defaultProjects": "",\n    "useParentNoteForTaskCreation": false,\n    "useParentNoteAsProject": false,\n    "useParentHeaderAsProject": false,\n    "inheritParentTaskProperties": false,\n    "defaultTimeEstimate": 0,\n    "defaultRecurrence": "none",\n    "defaultDueDate": "none",\n    "defaultDueTime": "none",\n    "defaultScheduledDate": "today",\n    "defaultScheduledTime": "none",\n    "bodyTemplate": "",\n    "useBodyTemplate": false,\n    "occurrenceBodyTemplate": "",\n    "useOccurrenceBodyTemplate": false,\n    "defaultReminders": []\n  },\n  "openTaskAfterCreation": "none",\n  "calendarViewSettings": {\n    "defaultView": "dayGridMonth",\n    "customDayCount": 3,\n    "slotDuration": "00:30:00",\n    "slotMinTime": "00:00:00",\n    "slotMaxTime": "24:00:00",\n    "scrollTime": "08:00:00",\n    "firstDay": 1,\n    "timeFormat": "24",\n    "showWeekends": true,\n    "locale": "",\n    "defaultShowScheduled": true,\n    "defaultShowDue": true,\n    "defaultShowDueWhenScheduled": true,\n    "defaultShowScheduledToDueSpan": false,\n    "defaultShowTimeEntries": false,\n    "defaultShowRecurring": true,\n    "defaultShowICSEvents": true,\n    "enableTimeblocking": false,\n    "defaultShowTimeblocks": true,\n    "defaultTimeblockColor": "#6366f1",\n    "timeblockAttachmentSearchOrder": "name-asc",\n    "nowIndicator": true,\n    "selectMirror": true,\n    "weekNumbers": false,\n    "showTodayHighlight": true,\n    "eventMinHeight": 15,\n    "slotEventOverlap": true,\n    "eventMaxStack": null,\n    "dayMaxEvents": true,\n    "dayMaxEventRows": false\n  },\n  "pomodoroWorkDuration": 25,\n  "pomodoroShortBreakDuration": 5,\n  "pomodoroLongBreakDuration": 15,\n  "pomodoroLongBreakInterval": 4,\n  "pomodoroAutoStartBreaks": true,\n  "pomodoroAutoStartWork": false,\n  "pomodoroNotifications": true,\n  "pomodoroSoundEnabled": true,\n  "pomodoroSoundVolume": 50,\n  "pomodoroStorageLocation": "plugin",\n  "pomodoroMobileSidebar": "tab",\n  "showPomodoroInStatusBar": true,\n  "enableTaskLinkOverlay": true,\n  "disableOverlayOnAlias": false,\n  "enableInstantTaskConvert": true,\n  "useDefaultsOnInstantConvert": true,\n  "preserveCheckboxOnConvert": false,\n  "taskModalTabMovesFocus": true,\n  "enableNaturalLanguageInput": true,\n  "nlpDefaultToScheduled": true,\n  "nlpLanguage": "en",\n  "uiLanguage": "system",\n  "statusSuggestionTrigger": "*",\n  "nlpTriggers": {\n    "triggers": [\n      {\n        "propertyId": "tags",\n        "trigger": "#",\n        "enabled": true\n      },\n      {\n        "propertyId": "contexts",\n        "trigger": "@",\n        "enabled": true\n      },\n      {\n        "propertyId": "projects",\n        "trigger": "+",\n        "enabled": true\n      },\n      {\n        "propertyId": "status",\n        "trigger": "*",\n        "enabled": true\n      },\n      {\n        "propertyId": "priority",\n        "trigger": "!",\n        "enabled": false\n      }\n    ]\n  },\n  "singleClickAction": "edit",\n  "doubleClickAction": "openNote",\n  "projectAutosuggest": {\n    "enableFuzzy": false,\n    "rows": [\n      "{title|n(Title)}",\n      "{aliases|n(Aliases)}",\n      "{file.path|n(Path)}"\n    ],\n    "showAdvanced": false,\n    "requiredTags": [],\n    "includeFolders": [],\n    "propertyKey": "",\n    "propertyValue": ""\n  },\n  "inlineTaskConvertFolder": "{{currentNotePath}}",\n  "disableNoteIndexing": false,\n  "suggestionDebounceMs": 0,\n  "fieldMapping": {\n    "title": "title",\n    "status": "status",\n    "priority": "priority",\n    "due": "due",\n    "scheduled": "scheduled",\n    "contexts": "contexts",\n    "projects": "projects",\n    "attachments": "attachments",\n    "timeEstimate": "timeEstimate",\n    "completedDate": "completedDate",\n    "dateCreated": "dateCreated",\n    "dateModified": "dateModified",\n    "recurrence": "recurrence",\n    "recurrenceAnchor": "recurrence_anchor",\n    "recurrenceParent": "recurrence_parent",\n    "occurrenceDate": "occurrence_date",\n    "occurrenceMaterialization": "occurrence_materialization",\n    "occurrenceNextTrigger": "occurrence_next_trigger",\n    "occurrenceTemplate": "occurrence_template",\n    "occurrencePastHorizon": "occurrence_past_horizon",\n    "occurrenceFutureHorizon": "occurrence_future_horizon",\n    "archiveTag": "archived",\n    "timeEntries": "timeEntries",\n    "completeInstances": "complete_instances",\n    "skippedInstances": "skipped_instances",\n    "blockedBy": "blockedBy",\n    "pomodoros": "pomodoros",\n    "icsEventId": "icsEventId",\n    "icsEventTag": "ics_event",\n    "googleCalendarEventId": "googleCalendarEventId",\n    "googleCalendarExceptionEventId": "googleCalendarExceptionEventId",\n    "googleCalendarExceptionOriginalScheduled": "googleCalendarExceptionOriginalScheduled",\n    "googleCalendarMovedOriginalDates": "googleCalendarMovedOriginalDates",\n    "reminders": "reminders",\n    "sortOrder": "tasknotes_manual_order"\n  },\n  "customStatuses": [\n    {\n      "id": "none",\n      "value": "none",\n      "label": "None",\n      "color": "#cccccc",\n      "isCompleted": false,\n      "excludeFromCycle": false,\n      "order": 0,\n      "autoArchive": false,\n      "autoArchiveDelay": 5\n    },\n    {\n      "id": "open",\n      "value": "open",\n      "label": "Open",\n      "color": "#808080",\n      "isCompleted": false,\n      "excludeFromCycle": false,\n      "order": 1,\n      "autoArchive": false,\n      "autoArchiveDelay": 5\n    },\n    {\n      "id": "in-progress",\n      "value": "in-progress",\n      "label": "In progress",\n      "color": "#0066cc",\n      "isCompleted": false,\n      "excludeFromCycle": false,\n      "order": 2,\n      "autoArchive": false,\n      "autoArchiveDelay": 5\n    },\n    {\n      "id": "done",\n      "value": "done",\n      "label": "Done",\n      "color": "#00aa00",\n      "isCompleted": true,\n      "excludeFromCycle": false,\n      "order": 3,\n      "autoArchive": false,\n      "autoArchiveDelay": 5\n    }\n  ],\n  "customPriorities": [\n    {\n      "id": "none",\n      "value": "none",\n      "label": "None",\n      "color": "#cccccc",\n      "weight": 0\n    },\n    {\n      "id": "low",\n      "value": "low",\n      "label": "Low",\n      "color": "#00aa00",\n      "weight": 1\n    },\n    {\n      "id": "normal",\n      "value": "normal",\n      "label": "Normal",\n      "color": "#ffaa00",\n      "weight": 2\n    },\n    {\n      "id": "high",\n      "value": "high",\n      "label": "High",\n      "color": "#ff0000",\n      "weight": 3\n    }\n  ],\n  "recurrenceMigrated": false,\n  "showReleaseNotesOnUpdate": true,\n  "checkForUpdatesOnStartup": true,\n  "starterNoteCreated": false,\n  "showTrackedTasksInStatusBar": false,\n  "autoStopTimeTrackingOnComplete": true,\n  "autoStopTimeTrackingNotification": false,\n  "showRelationships": true,\n  "relationshipsPosition": "bottom",\n  "showTaskCardInNote": true,\n  "showCompletedTaskStrikethrough": true,\n  "showExpandableSubtasks": true,\n  "expandSubtasksByDefault": false,\n  "subtaskChevronPosition": "right",\n  "viewsButtonAlignment": "right",\n  "hideCompletedFromOverdue": true,\n  "icsIntegration": {\n    "defaultNoteTemplate": "",\n    "defaultNoteFolder": "",\n    "icsNoteFilenameFormat": "title",\n    "customICSNoteFilenameTemplate": "{title}",\n    "enableAutoExport": false,\n    "autoExportPath": "tasknotes-calendar.ics",\n    "autoExportInterval": 60,\n    "useDurationForExport": false,\n    "excludeArchivedFromExport": false,\n    "excludeCompletedFromExport": false,\n    "requireDueDateForExport": false,\n    "requireScheduledDateForExport": false,\n    "useICSEndAsDue": false,\n    "recurringEventRelatedNotesMode": "series"\n  },\n  "savedViews": [],\n  "enableNotifications": true,\n  "notificationType": "system",\n  "notificationSoundEnabled": false,\n  "notificationSoundVolume": 50,\n  "enableAPI": false,\n  "apiPort": 8080,\n  "apiAuthToken": "",\n  "enableMCP": false,\n  "webhooks": [],\n  "userFields": [],\n  "enableModalSplitLayout": true,\n  "defaultVisibleProperties": [\n    "status",\n    "priority",\n    "due",\n    "scheduled",\n    "projects",\n    "contexts",\n    "tags",\n    "blocked",\n    "blocking"\n  ],\n  "inlineVisibleProperties": [\n    "status",\n    "priority",\n    "due",\n    "scheduled",\n    "recurrence"\n  ],\n  "enableBases": true,\n  "enableMdbaseSpec": false,\n  "autoCreateDefaultBasesFiles": true,\n  "commandFileMapping": {\n    "open-calendar-view": "TaskNotes/Views/mini-calendar-default.base",\n    "open-kanban-view": "TaskNotes/Views/kanban-default.base",\n    "open-tasks-view": "TaskNotes/Views/tasks-default.base",\n    "open-advanced-calendar-view": "TaskNotes/Views/calendar-default.base",\n    "open-agenda-view": "TaskNotes/Views/agenda-default.base",\n    "pomodoro-stats-base": "TaskNotes/Views/pomodoro-stats.base",\n    "relationships": "TaskNotes/Views/relationships.base"\n  },\n  "maintainDueDateOffsetInRecurring": false,\n  "resetCheckboxesOnRecurrence": false,\n  "useFrontmatterMarkdownLinks": false,\n  "enableGoogleCalendar": false,\n  "enableMicrosoftCalendar": false,\n  "disableCalendarOnMobile": false,\n  "enabledGoogleCalendars": [],\n  "googleCalendarSyncTokens": {},\n  "enabledMicrosoftCalendars": [],\n  "microsoftCalendarSyncTokens": {},\n  "googleCalendarExport": {\n    "enabled": false,\n    "targetCalendarId": "",\n    "syncOnTaskCreate": true,\n    "syncOnTaskUpdate": true,\n    "syncOnTaskComplete": true,\n    "syncOnTaskDelete": true,\n    "eventTitleTemplate": "{{title}}",\n    "includeDescription": true,\n    "eventColorId": null,\n    "syncTrigger": "scheduled",\n    "createAsAllDay": true,\n    "defaultEventDuration": 60,\n    "includeObsidianLink": true,\n    "defaultReminderMinutes": null\n  },\n  "enableDebugLogging": false\n}\n
","text":"TaskNotes currently exposes 6 settings tabs. This inventory is generated from the tab renderer and English translation source so additions cannot silently disappear from the documentation. General# Source: src/settings/tabs/generalTab.ts Setting Purpose Default tasks folder Default location for new tasks. Supports folder template variables like {{currentNotePath}}, {{currentNoteTitle}}, and {{projectFilePath}}, plus Daily Notes-style date tokens like YYYY/MM/DD. Folder for inline-created tasks Folder where tasks created from inline commands or checkbox conversion will be created. Leave empty to use the default tasks folder. Use {{currentNotePath}} for the current note's folder, or {{currentNoteTitle}} for a subfolder named after the current note. Move archived tasks to folder Automatically move archived tasks to an archive folder Archive folder Folder to move tasks to when archived. Supports template variables like {{year}}, {{month}}, {{priority}}, etc. Identify tasks by Choose whether to identify tasks by tag or by a frontmatter property Task tag Tag that identifies notes as tasks (without #). Existing .base view filters keep their old tag when this changes; update default Base files or edit those filters. Hide identification tags in task cards When enabled, tags matching the task identification tag (including hierarchical matches like 'task/project') will be hidden from task card displays Hidden tag scope Choose whether hiding identification tags also hides nested tags. Task property name The frontmatter property name (e.g., \"category\") Task property value The value that identifies a note as a task (e.g., \"task\") Auto-create default files Automatically create missing default base view files on startup. Disable to prevent deleted sample files from being recreated. Create default files Create the default .base files in TaskNotes/Views/ directory. Existing files will not be overwritten. Update default files Overwrite the configured default .base files with templates generated from your current TaskNotes settings. Export v3 saved views to Bases Convert all your saved views from TaskNotes v3 into a single .base file with multiple views. This helps migrate your v3 filter configurations to the new Bases system. Excluded folders Comma-separated list of folders to exclude from task indexing and project suggestions UI language Select the language used for TaskNotes interface text Use Markdown links in frontmatter Generate markdown links ([text](path)) instead of wikilinks ([[link]]) in frontmatter properties. ⚠️ Requires the 'obsidian-frontmatter-markdown-links' plugin to work correctly. Show release notes after update Automatically open release notes when TaskNotes is updated to a new version Check for new releases on startup Check GitHub once when TaskNotes starts and show a notice when a newer compatible release is available View release notes See what's new in the latest version of TaskNotes Task properties# Source: src/settings/tabs/taskPropertiesTab.ts Setting Purpose No static controls detected This tab is assembled dynamically. Modal fields# Source: src/settings/tabs/modalFieldsTab.ts Setting Purpose No static controls detected This tab is assembled dynamically. Appearance & UI# Source: src/settings/tabs/appearanceTab.ts Setting Purpose Default visible properties Choose which properties appear on task cards by default. Time format Display time in 12-hour or 24-hour format throughout the plugin Default view The calendar view shown when opening the calendar tab Custom view day count Number of days to show in custom multi-day view First day of week Which day should be the first column in week views Show weekends Display weekends in calendar views Show week numbers Display week numbers in calendar views Show today highlight Highlight the current day in calendar views Show current time indicator Display a line showing the current time in timeline views Selection mirror Show a visual preview while dragging to select time ranges Calendar locale Calendar locale for date formatting and calendar system (e.g., \"en\", \"fa\" for Farsi/Persian, \"de\" for German). Leave empty to auto-detect from browser. Show scheduled tasks Display tasks with scheduled dates by default Show due dates Display task due dates by default Show due dates when scheduled Display due dates even for tasks that already have scheduled dates Show time entries Display completed time tracking entries by default Show recurring tasks Display recurring task instances by default Show ICS events Display events from ICS subscriptions by default Time slot duration Duration of each time slot in timeline views Start time Earliest time shown in timeline views (HH:MM format) End time Latest time shown in timeline views (HH:MM format). Use values above 24:00 to show early next-day hours, such as 26:00 for 2 AM. Initial scroll time Time to scroll to when opening timeline views (HH:MM format) Event minimum height Minimum height for events in timeline views (pixels) Show tracked tasks in status bar Display currently tracked tasks in Obsidian's status bar Show relationships widget Display a widget showing all relationships for the current note (subtasks, projects, dependencies) Relationships position Where to position the relationships widget Show task card in note Display a task card widget at the top of task notes showing the task details and actions Strike through completed task titles Draw a line through completed task card titles. Turn off to keep completed tasks easier to read Show expandable subtasks Allow expanding/collapsing subtask sections in task cards Expand subtasks by default Show project subtasks expanded when task cards are rendered Subtask chevron position Position of expand/collapse chevrons in task cards Views button alignment Alignment of the views/filters button in the task interface Single-click action Action performed when single-clicking a task card Double-click action Action performed when double-clicking a task card Features# Source: src/settings/tabs/featuresTab.ts Setting Purpose Task link overlay Show interactive overlays when hovering over task links Disable overlay for aliased links Do not show the task widget if the link contains an alias (e.g. [[Task|Alias]]). Show convert button next to checkboxes Display an inline button next to Markdown checkboxes that converts them to TaskNotes Keep checkbox when converting Leave the original Markdown checkbox marker in place when converting a checkbox to a TaskNote link Enable natural language task input Parse due dates, priorities, and contexts from natural language when creating tasks Default to scheduled When NLP detects a date without context, treat it as scheduled rather than due NLP language Language for natural language processing patterns and date parsing Open task after creation Choose whether the task creation modal opens the new task note after saving. Use body template Use a template file for task body content Body template file Path to template file for task body content. Supports template variables like {{title}}, {{date}}, {{time}}, {{priority}}, {{status}}, etc. Use occurrence note template Use a separate fallback template for materialized occurrence notes when the recurring task has no occurrence_template Occurrence note template file Path to template file for materialized occurrence notes. A recurring task's occurrence_template field takes priority over this fallback. Template variables: See the setting in Obsidian for contextual details. Use task defaults on instant convert Apply default task settings when converting text to tasks instantly Work duration Duration of work intervals in minutes Short break duration Duration of short breaks in minutes Long break duration Duration of long breaks in minutes Long break interval Number of work sessions before a long break Auto-start breaks Automatically start break timers after work sessions Auto-start work Automatically start work sessions after breaks Pomodoro notifications Show notifications when Pomodoro sessions end Show Pomodoro in status bar Display the active Pomodoro countdown in Obsidian's status bar Sound enabled Play sound when Pomodoro sessions end Sound volume Volume for Pomodoro sounds (0-100) Pomodoro data storage Configure where Pomodoro session data is stored and how it's managed. Mobile sidebar Where to open the Pomodoro timer on mobile devices Enable notifications Enable task reminder notifications Notification type Type of notifications to show Send test reminder Send a test reminder using the current notification type and sound settings. Notification sound Play a sound when task reminders trigger Sound volume Volume for task reminder sounds (0-100) Preview notification sound Play the configured task reminder sound Hide completed tasks from overdue Exclude completed tasks from overdue task calculations Disable note indexing Disable automatic indexing of note content for better performance Suggestion debounce Delay in milliseconds before showing suggestions Auto-stop time tracking Automatically stop time tracking when a task is marked complete Time tracking stop notification Show notification when time tracking is automatically stopped Maintain due date offset in recurring tasks Keep the offset between due date and scheduled date when recurring tasks are completed Reset checkboxes on recurrence Reset all Markdown checkboxes in the task body when a recurring task is completed and rescheduled Enable timeblocking Enable timeblocking feature for lightweight scheduling in daily notes. When enabled, 'Timeblock' option appears in the calendar drag context menu. Show timeblocks Display timeblocks from daily notes by default Default timeblock color The default color used when creating new timeblocks Enable debug logging Log detailed drag-and-drop and view diagnostics to the developer console. Useful for troubleshooting. Integrations# Source: src/settings/tabs/integrationsTab.ts Setting Purpose Generate mdbase type definitions See the setting in Obsidian for contextual details. Disable calendar integrations on mobile Skip Google, Microsoft, and ICS calendar loading on Obsidian mobile. Desktop calendar integrations are unchanged. Calendar integrations are disabled on this mobile device See the setting in Obsidian for contextual details. Enable task export When enabled, tasks with dates will be automatically synced to Google Calendar as events. Target calendar See the setting in Obsidian for contextual details. Sync trigger Which task date should trigger calendar event creation. Create as all-day events When enabled, tasks are created as all-day events. When disabled, uses time estimate for duration. Default event duration Duration in minutes for timed events (used when task has no time estimate). Event title template Template for event titles. Available variables: {{title}}, {{status}}, {{priority}} Include task details in description Add task metadata (priority, status, tags, etc.) to the event description. Include Obsidian link Add a link back to the task in Obsidian in the event description. Default reminder Add popup reminders to timed Google Calendar events. Enter minutes before the event, separated by commas. Leave empty to use calendar defaults. Common values: 15, 30, 60, 1440. Automatic sync behavior See the setting in Obsidian for contextual details. Sync on task create Automatically create calendar event when a new task is created. Sync on task update Automatically update calendar event when a task is modified. Sync on task complete Update calendar event when a task is completed (adds checkmark to title). Delete event on task delete Remove calendar event when the corresponding task is deleted. Manual sync actions See the setting in Obsidian for contextual details. Sync all tasks Sync all existing tasks to Google Calendar. This will create events for tasks that haven't been synced yet. Unlink all tasks Remove all task-event links without deleting calendar events. Default note template Path to template file for notes created from ICS events Default note folder Folder for notes created from ICS events ICS note filename format How filenames are generated for notes created from ICS events Custom ICS filename template Template for custom ICS event filenames Use ICS event end time as task due date When enabled, tasks created from calendar events will have their due date set to the event's end time. For all-day events, the due date will be set to the event date. For timed events, the due date will include the end time. Recurring event related notes Choose whether notes linked to one recurrence of an external calendar event appear across the loaded series or only on the selected instance. Add calendar subscription Add a new calendar subscription from ICS/iCal URL or local file New calendar See the setting in Obsidian for contextual details. Refresh all subscriptions Manually refresh all enabled calendar subscriptions Enable automatic export Automatically keep an ICS file updated with all your tasks Export file path Path where the ICS file will be saved (relative to vault root) Update interval (between 5 and 1440 minutes) How often to update the export file Use task duration for event length When enabled, uses the task's time estimate (duration) instead of due date for the calendar event end time. This is useful for GTD workflows where scheduled + duration represents work planning, while due date represents deadlines. Exclude completed tasks When enabled, completed tasks are omitted from ICS exports. Completed statuses are taken from your task statuses settings. Exclude archived tasks When enabled, archived tasks are omitted from ICS exports. Require due date When enabled, only tasks with a due date are included in ICS exports. Require scheduled date When enabled, only tasks with a scheduled date are included in ICS exports. Export now Manually trigger an immediate export Export status: See the setting in Obsidian for contextual details. Enable HTTP API Start local HTTP server for API access API port Port number for the HTTP API server API authentication token Token required for API authentication (leave empty for no auth) Enable MCP server Expose TaskNotes tools via Model Context Protocol at /mcp endpoint. Requires HTTP API to be enabled. Add webhook Register a new webhook endpoint Complete default settings snapshot# The following JSON is generated from DEFAULT_SETTINGS. Empty strings and disabled flags are intentional defaults. { \"tasksFolder\": \"TaskNotes/Tasks\", \"moveArchivedTasks\": false, \"archiveFolder\": \"TaskNotes/Archive\", \"taskTag\": \"task\", \"taskIdentificationMethod\": \"tag\", \"hideIdentifyingTagsInCards\": false, \"hideIdentifyingTagsMode\": \"all\", \"taskPropertyName\": \"\", \"taskPropertyValue\": \"\", \"excludedFolders\": \"\", \"defaultTaskPriority\": \"normal\", \"defaultTaskStatus\": \"open\", \"taskOrgFiltersCollapsed\": false, \"taskFilenameFormat\": \"zettel\", \"storeTitleInFilename\": true, \"customFilenameTemplate\": \"{{title}}\", \"occurrenceFilenameTemplate\": \"\", \"occurrenceFilenameTemplateProperty\": \"occurrenceFilenameTemplate\", \"taskCreationDefaults\": { \"defaultContexts\": \"\", \"defaultTags\": \"\", \"defaultProjects\": \"\", \"useParentNoteForTaskCreation\": false, \"useParentNoteAsProject\": false, \"useParentHeaderAsProject\": false, \"inheritParentTaskProperties\": false, \"defaultTimeEstimate\": 0, \"defaultRecurrence\": \"none\", \"defaultDueDate\": \"none\", \"defaultDueTime\": \"none\", \"defaultScheduledDate\": \"today\", \"defaultScheduledTime\": \"none\", \"bodyTemplate\": \"\", \"useBodyTemplate\": false, \"occurrenceBodyTemplate\": \"\", \"useOccurrenceBodyTemplate\": false, \"defaultReminders\": [] }, \"openTaskAfterCreation\": \"none\", \"calendarViewSettings\": { \"defaultView\": \"dayGridMonth\", \"customDayCount\": 3, \"slotDuration\": \"00:30:00\", \"slotMinTime\": \"00:00:00\", \"slotMaxTime\": \"24:00:00\", \"scrollTime\": \"08:00:00\", \"firstDay\": 1, \"timeFormat\": \"24\", \"showWeekends\": true, \"locale\": \"\", \"defaultShowSchedu"},{"route":"/obsidian/releases/","title":"Release Notes","description":"Welcome to the TaskNotes release notes. Here you can find detailed information about each version, including new features, bug fixes, and improvements.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases.md","namespace":"obsidian","relativePath":"releases.md","raw":"# Release Notes\n\nWelcome to the TaskNotes release notes. Here you can find detailed information about each version, including new features, bug fixes, and improvements.\n\n## Latest Releases\n\n### Version 4.x (Current)\n\n- [4.12.3](releases/4.12.3.md)\n- [4.12.2](releases/4.12.2.md)\n- [4.12.1](releases/4.12.1.md)\n- [4.12.0](releases/4.12.0.md)\n- [4.11.1](releases/4.11.1.md)\n- [4.11.0](releases/4.11.0.md)\n- [4.10.2](releases/4.10.2.md)\n- [4.10.1](releases/4.10.1.md)\n- [4.10.0](releases/4.10.0.md)\n- [4.9.2](releases/4.9.2.md)\n- [4.9.1](releases/4.9.1.md)\n- [4.9.0](releases/4.9.0.md)\n- [4.8.1](releases/4.8.1.md)\n- [4.8.0](releases/4.8.0.md)\n- [4.7.2](releases/4.7.2.md)\n- [4.7.1](releases/4.7.1.md)\n- [4.7.0](releases/4.7.0.md)\n- [4.6.0](releases/4.6.0.md)\n- [4.5.3](releases/4.5.3.md)\n- [4.5.2](releases/4.5.2.md)\n- [4.5.1](releases/4.5.1.md)\n- [4.5.0](releases/4.5.0.md)\n- [4.4.0](releases/4.4.0.md)\n- [4.3.3](releases/4.3.3.md)\n- [4.3.2](releases/4.3.2.md)\n- [4.3.1](releases/4.3.1.md)\n- [4.3.0](releases/4.3.0.md)\n- [4.2.1](releases/4.2.1.md)\n- [4.2.0](releases/4.2.0.md)\n- [4.1.3](releases/4.1.3.md)\n- [4.1.2](releases/4.1.2.md)\n- [4.1.1](releases/4.1.1.md)\n- [4.1.0](releases/4.1.0.md)\n- [4.0.5](releases/4.0.5.md)\n- [4.0.4](releases/4.0.4.md)\n- [4.0.3](releases/4.0.3.md)\n- [4.0.2](releases/4.0.2.md)\n- [4.0.1](releases/4.0.1.md)\n- [4.0.0-beta.3](releases/4.0.0-beta.3.md)\n- [4.0.0-beta.2](releases/4.0.0-beta.2.md)\n- [4.0.0-beta.1](releases/4.0.0-beta.1.md)\n- [4.0.0-beta.0](releases/4.0.0-beta.0.md)\n\n### Version 3.x\n\n- [3.25.6](releases/3.25.6.md)\n- [3.25.4](releases/3.25.4.md)\n- [3.25.3](releases/3.25.3.md)\n- [3.25.2](releases/3.25.2.md)\n- [3.25.1](releases/3.25.1.md)\n- [3.25.0](releases/3.25.0.md)\n- [3.24.6](releases/3.24.6.md)\n- [3.24.5](releases/3.24.5.md)\n- [3.24.4](releases/3.24.4.md)\n- [3.24.3](releases/3.24.3.md)\n- [3.24.2](releases/3.24.2.md)\n- [3.24.1](releases/3.24.1.md)\n- [3.24.0](releases/3.24.0.md)\n- [3.23.4](releases/3.23.4.md)\n- [3.23.3](releases/3.23.3.md)\n- [3.23.2](releases/3.23.2.md)\n- [3.23.1](releases/3.23.1.md)\n- [3.23.0](releases/3.23.0.md)\n- [3.22.1](releases/3.22.1.md)\n- [3.22.0](releases/3.22.0.md)\n- [3.21.0](releases/3.21.0.md)\n- [3.20.1](releases/3.20.1.md)\n- [3.20.0](releases/3.20.0.md)\n- [3.19.1](releases/3.19.1.md)\n- [3.19.0](releases/3.19.0.md)\n- [3.18.2](releases/3.18.2.md)\n- [3.18.1](releases/3.18.1.md)\n- [3.18.0](releases/3.18.0.md)\n- [3.17.1](releases/3.17.1.md)\n- [3.17.0](releases/3.17.0.md)\n- [3.16.4](releases/3.16.4.md)\n- [3.16.3](releases/3.16.3.md)\n- [3.16.2](releases/3.16.2.md)\n- [3.16.1](releases/3.16.1.md)\n- [3.16.0](releases/3.16.0.md)\n- [3.15.1](releases/3.15.1.md)\n- [3.15.0](releases/3.15.0.md)\n- [3.14.0](releases/3.14.0.md)\n- [3.13.4](releases/3.13.4.md)\n- [3.13.3](releases/3.13.3.md)\n- [3.13.2](releases/3.13.2.md)\n- [3.13.1](releases/3.13.1.md)\n- [3.13.0](releases/3.13.0.md)\n- [3.12.2](releases/3.12.2.md)\n- [3.12.1](releases/3.12.1.md)\n- [3.12.0](releases/3.12.0.md)\n- [3.11.2](releases/3.11.2.md)\n- [3.11.1](releases/3.11.1.md)\n- [3.11.0](releases/3.11.0.md)\n- [3.10.0](releases/3.10.0.md)\n- [3.9.1](releases/3.9.1.md)\n- [3.9.0](releases/3.9.0.md)\n- [3.8.7](releases/3.8.7.md)\n- [3.8.6](releases/3.8.6.md)\n- [3.8.5](releases/3.8.5.md)\n- [3.8.1](releases/3.8.1.md)\n- [3.7.1](releases/3.7.1.md)\n- [3.7.0](releases/3.7.0.md)\n- [3.6.0](releases/3.6.0.md)\n- [3.5.1](releases/3.5.1.md)\n- [3.4.2](releases/3.4.2.md)\n- [3.4.1](releases/3.4.1.md)\n- [3.4.0](releases/3.4.0.md)\n- [3.3.0](releases/3.3.0.md)\n- [3.1.1](releases/3.1.1.md)\n- [3.1.0](releases/3.1.0.md)\n- [3.0.1](releases/3.0.1.md)\n- [3.0.0](releases/3.0.0.md)\n\n### Version 2.x\n\n- [2.2.3](releases/2.2.3.md)\n- [2.2.2](releases/2.2.2.md)\n- [2.2.1](releases/2.2.1.md)\n- [2.2.0](releases/2.2.0.md)\n- [2.1.0](releases/2.1.0.md)\n- [2.0.4](releases/2.0.4.md)\n- [2.0.3](releases/2.0.3.md)\n- [2.0.2](releases/2.0.2.md)\n- [2.0.1](releases/2.0.1.md)\n- [2.0.0](releases/2.0.0.md)\n\n### Version 1.x\n\n- [1.2.0](releases/1.2.0.md)\n- [1.1.0](releases/1.1.0.md)\n- [1.0.0](releases/1.0.0.md)\n\n### Early Versions (0.x)\n\n- [0.8.0](releases/0.8.0.md)\n- [0.7.0](releases/0.7.0.md)\n- [0.6.3](releases/0.6.3.md)\n- [0.6.2](releases/0.6.2.md)\n- [0.6.1](releases/0.6.1.md)\n- [0.6.0](releases/0.6.0.md)\n- [0.4.2](releases/0.4.2.md)\n- [0.4.1](releases/0.4.1.md)\n- [0.4.0](releases/0.4.0.md)\n- [0.3.0](releases/0.3.0.md)\n- [0.2.4](releases/0.2.4.md)\n- [0.2.3](releases/0.2.3.md)\n- [0.2.2](releases/0.2.2.md)\n\n## Getting Updates\n\nTo update TaskNotes:\n1. Open Obsidian\n2. Go to Settings → Community Plugins\n3. Find TaskNotes and click \"Update\"\n4. Restart Obsidian if prompted\n\n## Feedback\n\nFound a bug or have a feature request? Please:\n\n- Check existing [GitHub Issues](https://github.com/callumalpass/tasknotes/issues)\n- Create a new issue with details\n","aliases":["/releases/","/releases/"],"toc":[{"level":2,"id":"latest-releases","text":"Latest Releases"},{"level":3,"id":"version-4x-current","text":"Version 4.x (Current)"},{"level":3,"id":"version-3x","text":"Version 3.x"},{"level":3,"id":"version-2x","text":"Version 2.x"},{"level":3,"id":"version-1x","text":"Version 1.x"},{"level":3,"id":"early-versions-0x","text":"Early Versions (0.x)"},{"level":2,"id":"getting-updates","text":"Getting Updates"},{"level":2,"id":"feedback","text":"Feedback"}],"html":"

Welcome to the TaskNotes release notes. Here you can find detailed information about each version, including new features, bug fixes, and improvements.

\n

Latest Releases#

\n

Version 4.x (Current)#

\n\n

Version 3.x#

\n\n

Version 2.x#

\n\n

Version 1.x#

\n\n

Early Versions (0.x)#

\n\n

Getting Updates#

\n

To update TaskNotes:

\n
    \n
  1. Open Obsidian
  2. \n
  3. Go to Settings → Community Plugins
  4. \n
  5. Find TaskNotes and click "Update"
  6. \n
  7. Restart Obsidian if prompted
  8. \n
\n

Feedback#

\n

Found a bug or have a feature request? Please:

\n
    \n
  • Check existing GitHub Issues
  • \n
  • Create a new issue with details
  • \n
\n","text":"Welcome to the TaskNotes release notes. Here you can find detailed information about each version, including new features, bug fixes, and improvements. Latest Releases# Version 4.x (Current)# 4.12.3 4.12.2 4.12.1 4.12.0 4.11.1 4.11.0 4.10.2 4.10.1 4.10.0 4.9.2 4.9.1 4.9.0 4.8.1 4.8.0 4.7.2 4.7.1 4.7.0 4.6.0 4.5.3 4.5.2 4.5.1 4.5.0 4.4.0 4.3.3 4.3.2 4.3.1 4.3.0 4.2.1 4.2.0 4.1.3 4.1.2 4.1.1 4.1.0 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 4.0.0-beta.3 4.0.0-beta.2 4.0.0-beta.1 4.0.0-beta.0 Version 3.x# 3.25.6 3.25.4 3.25.3 3.25.2 3.25.1 3.25.0 3.24.6 3.24.5 3.24.4 3.24.3 3.24.2 3.24.1 3.24.0 3.23.4 3.23.3 3.23.2 3.23.1 3.23.0 3.22.1 3.22.0 3.21.0 3.20.1 3.20.0 3.19.1 3.19.0 3.18.2 3.18.1 3.18.0 3.17.1 3.17.0 3.16.4 3.16.3 3.16.2 3.16.1 3.16.0 3.15.1 3.15.0 3.14.0 3.13.4 3.13.3 3.13.2 3.13.1 3.13.0 3.12.2 3.12.1 3.12.0 3.11.2 3.11.1 3.11.0 3.10.0 3.9.1 3.9.0 3.8.7 3.8.6 3.8.5 3.8.1 3.7.1 3.7.0 3.6.0 3.5.1 3.4.2 3.4.1 3.4.0 3.3.0 3.1.1 3.1.0 3.0.1 3.0.0 Version 2.x# 2.2.3 2.2.2 2.2.1 2.2.0 2.1.0 2.0.4 2.0.3 2.0.2 2.0.1 2.0.0 Version 1.x# 1.2.0 1.1.0 1.0.0 Early Versions (0.x)# 0.8.0 0.7.0 0.6.3 0.6.2 0.6.1 0.6.0 0.4.2 0.4.1 0.4.0 0.3.0 0.2.4 0.2.3 0.2.2 Getting Updates# To update TaskNotes: Open Obsidian Go to Settings → Community Plugins Find TaskNotes and click \"Update\" Restart Obsidian if prompted Feedback# Found a bug or have a feature request? Please: Check existing GitHub Issues Create a new issue with details"},{"route":"/obsidian/releases/0.2.2/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.1...0.2.2","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.2.2.md","namespace":"obsidian","relativePath":"releases/0.2.2.md","raw":"**Full Changelog**: https://github.com/callumalpass/chronosync/compare/0.2.1...0.2.2\n","aliases":["/releases/0.2.2/","/releases/0.2.2/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.1...0.2.2

\n","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.1...0.2.2"},{"route":"/obsidian/releases/0.2.3/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.2...0.2.3","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.2.3.md","namespace":"obsidian","relativePath":"releases/0.2.3.md","raw":"**Full Changelog**: https://github.com/callumalpass/chronosync/compare/0.2.2...0.2.3\n","aliases":["/releases/0.2.3/","/releases/0.2.3/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.2...0.2.3

\n","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.2...0.2.3"},{"route":"/obsidian/releases/0.2.4/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.3...0.2.4","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.2.4.md","namespace":"obsidian","relativePath":"releases/0.2.4.md","raw":"**Full Changelog**: https://github.com/callumalpass/chronosync/compare/0.2.3...0.2.4\n","aliases":["/releases/0.2.4/","/releases/0.2.4/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.3...0.2.4

\n","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.3...0.2.4"},{"route":"/obsidian/releases/0.3.0/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.4...0.3.0","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.3.0.md","namespace":"obsidian","relativePath":"releases/0.3.0.md","raw":"**Full Changelog**: https://github.com/callumalpass/chronosync/compare/0.2.4...0.3.0\n","aliases":["/releases/0.3.0/","/releases/0.3.0/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.4...0.3.0

\n","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.4...0.3.0"},{"route":"/obsidian/releases/0.4.0/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.3.0...0.4.0","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.4.0.md","namespace":"obsidian","relativePath":"releases/0.4.0.md","raw":"**Full Changelog**: https://github.com/callumalpass/chronosync/compare/0.3.0...0.4.0\n","aliases":["/releases/0.4.0/","/releases/0.4.0/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/chronosync/compare/0.3.0...0.4.0

\n","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.3.0...0.4.0"},{"route":"/obsidian/releases/0.4.1/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.1","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.4.1.md","namespace":"obsidian","relativePath":"releases/0.4.1.md","raw":"**Full Changelog**: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.1\n","aliases":["/releases/0.4.1/","/releases/0.4.1/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.1

\n","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.1"},{"route":"/obsidian/releases/0.4.2/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.2","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.4.2.md","namespace":"obsidian","relativePath":"releases/0.4.2.md","raw":"**Full Changelog**: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.2\n","aliases":["/releases/0.4.2/","/releases/0.4.2/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.2

\n","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.2"},{"route":"/obsidian/releases/0.6.0/","title":"Untitled","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.6.0.md","namespace":"obsidian","relativePath":"releases/0.6.0.md","raw":"\n","aliases":["/releases/0.6.0/","/releases/0.6.0/"],"toc":[],"html":"","text":""},{"route":"/obsidian/releases/0.6.1/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.0...0.6.1","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.6.1.md","namespace":"obsidian","relativePath":"releases/0.6.1.md","raw":"**Full Changelog**: https://github.com/callumalpass/chronosync/compare/0.6.0...0.6.1\n","aliases":["/releases/0.6.1/","/releases/0.6.1/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.0...0.6.1

\n","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.0...0.6.1"},{"route":"/obsidian/releases/0.6.2/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.1...0.6.2","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.6.2.md","namespace":"obsidian","relativePath":"releases/0.6.2.md","raw":"**Full Changelog**: https://github.com/callumalpass/chronosync/compare/0.6.1...0.6.2\n","aliases":["/releases/0.6.2/","/releases/0.6.2/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.1...0.6.2

\n","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.1...0.6.2"},{"route":"/obsidian/releases/0.6.3/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.2...0.6.3","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.6.3.md","namespace":"obsidian","relativePath":"releases/0.6.3.md","raw":"**Full Changelog**: https://github.com/callumalpass/chronosync/compare/0.6.2...0.6.3\n","aliases":["/releases/0.6.3/","/releases/0.6.3/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.2...0.6.3

\n","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.2...0.6.3"},{"route":"/obsidian/releases/0.7.0/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.7.0","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.7.0.md","namespace":"obsidian","relativePath":"releases/0.7.0.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.7.0\n","aliases":["/releases/0.7.0/","/releases/0.7.0/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.7.0

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.7.0"},{"route":"/obsidian/releases/0.8.0/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.8.0","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.8.0.md","namespace":"obsidian","relativePath":"releases/0.8.0.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.8.0\n","aliases":["/releases/0.8.0/","/releases/0.8.0/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.8.0

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.8.0"},{"route":"/obsidian/releases/1.0.0/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.8.0...1.0.0","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/1.0.0.md","namespace":"obsidian","relativePath":"releases/1.0.0.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/0.8.0...1.0.0\n","aliases":["/releases/1.0.0/","/releases/1.0.0/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.8.0...1.0.0

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.8.0...1.0.0"},{"route":"/obsidian/releases/1.1.0/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/1.0.0...1.1.0","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/1.1.0.md","namespace":"obsidian","relativePath":"releases/1.1.0.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/1.0.0...1.1.0\n","aliases":["/releases/1.1.0/","/releases/1.1.0/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/1.0.0...1.1.0

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/1.0.0...1.1.0"},{"route":"/obsidian/releases/1.2.0/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/1.1.0...1.2.0","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/1.2.0.md","namespace":"obsidian","relativePath":"releases/1.2.0.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/1.1.0...1.2.0\n","aliases":["/releases/1.2.0/","/releases/1.2.0/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/1.1.0...1.2.0

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/1.1.0...1.2.0"},{"route":"/obsidian/releases/2.0.0/","title":"Untitled","description":"TaskNotes 2.0.0 - Major Feature Release","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/2.0.0.md","namespace":"obsidian","relativePath":"releases/2.0.0.md","raw":"TaskNotes 2.0.0 - Major Feature Release\n\nMajor New Features:\n\n**Kanban Board View**\n\n- Visual task management with drag-and-drop functionality\n- Dynamic grouping by status, priority, or context\n- Search filtering across all columns\n- Real-time updates and collapsible columns\n\n**Enhanced Pomodoro System**\n\n- SVG progress circle with refined visual timer\n- Persistent session history and statistics tracking\n- Dedicated Pomodoro Statistics view with completion metrics\n- Enhanced UI with improved controls and display\n\n**Advanced Task Filtering & Grouping**\n\n- Unified filtering system with search, status, context, priority filters\n- Date range filtering with overdue task support\n- Flexible grouping options (status, priority, context, due date)\n- Performance-optimized filtering using cache indexes\n\n**Enhanced Recurring Tasks**\n\n- Visual distinction with special styling and indicators\n- Per-date completion tracking with smart UI controls\n- Context menus filtered to prevent status conflicts\n- Clear completion status display for selected dates\n\nUI/UX Improvements:\n\n**Task Management**\n\n- Enhanced task edit modal with improved form layout\n- Context menu (right-click) for quick property changes\n- Autocomplete for contexts and tags in task forms\n- Optimistic UI updates for better responsiveness\n\n**View Enhancements**\n\n- Agenda view with improved layout and timeline organization\n- Enhanced note cards with consistent styling across views\n- Improved calendar integration with better visual indicators\n- Unified card styling system across all views\n\n**Performance & Reliability**\n\n- Migrated to unified CacheManager from legacy FileIndexer\n- DOM reconciliation system for efficient UI updates\n- Enhanced async handling and error management\n- Improved cache update handling and race condition prevention\n\nAdditional Improvements:\n\n- Enhanced due date modal with better styling\n- Improved time tracking UX with visual feedback\n- Better task archival feedback and UI consistency\n- Refined keyboard navigation and accessibility\n- Updated README with comprehensive feature documentation\n\nBug Fixes:\n\n- Fixed 'No due date' group positioning in task list\n- Resolved various UI spacing and alignment issues\n- Improved handling of edge cases in recurring task logic\n- Enhanced stability of cache operations and file handling\n\nThis major release significantly expands TaskNotes capabilities with new views, enhanced filtering, and improved user experience while maintaining data compatibility with previous versions.\n","aliases":["/releases/2.0.0/","/releases/2.0.0/"],"toc":[],"html":"

TaskNotes 2.0.0 - Major Feature Release

\n

Major New Features:

\n

Kanban Board View

\n
    \n
  • Visual task management with drag-and-drop functionality
  • \n
  • Dynamic grouping by status, priority, or context
  • \n
  • Search filtering across all columns
  • \n
  • Real-time updates and collapsible columns
  • \n
\n

Enhanced Pomodoro System

\n
    \n
  • SVG progress circle with refined visual timer
  • \n
  • Persistent session history and statistics tracking
  • \n
  • Dedicated Pomodoro Statistics view with completion metrics
  • \n
  • Enhanced UI with improved controls and display
  • \n
\n

Advanced Task Filtering & Grouping

\n
    \n
  • Unified filtering system with search, status, context, priority filters
  • \n
  • Date range filtering with overdue task support
  • \n
  • Flexible grouping options (status, priority, context, due date)
  • \n
  • Performance-optimized filtering using cache indexes
  • \n
\n

Enhanced Recurring Tasks

\n
    \n
  • Visual distinction with special styling and indicators
  • \n
  • Per-date completion tracking with smart UI controls
  • \n
  • Context menus filtered to prevent status conflicts
  • \n
  • Clear completion status display for selected dates
  • \n
\n

UI/UX Improvements:

\n

Task Management

\n
    \n
  • Enhanced task edit modal with improved form layout
  • \n
  • Context menu (right-click) for quick property changes
  • \n
  • Autocomplete for contexts and tags in task forms
  • \n
  • Optimistic UI updates for better responsiveness
  • \n
\n

View Enhancements

\n
    \n
  • Agenda view with improved layout and timeline organization
  • \n
  • Enhanced note cards with consistent styling across views
  • \n
  • Improved calendar integration with better visual indicators
  • \n
  • Unified card styling system across all views
  • \n
\n

Performance & Reliability

\n
    \n
  • Migrated to unified CacheManager from legacy FileIndexer
  • \n
  • DOM reconciliation system for efficient UI updates
  • \n
  • Enhanced async handling and error management
  • \n
  • Improved cache update handling and race condition prevention
  • \n
\n

Additional Improvements:

\n
    \n
  • Enhanced due date modal with better styling
  • \n
  • Improved time tracking UX with visual feedback
  • \n
  • Better task archival feedback and UI consistency
  • \n
  • Refined keyboard navigation and accessibility
  • \n
  • Updated README with comprehensive feature documentation
  • \n
\n

Bug Fixes:

\n
    \n
  • Fixed 'No due date' group positioning in task list
  • \n
  • Resolved various UI spacing and alignment issues
  • \n
  • Improved handling of edge cases in recurring task logic
  • \n
  • Enhanced stability of cache operations and file handling
  • \n
\n

This major release significantly expands TaskNotes capabilities with new views, enhanced filtering, and improved user experience while maintaining data compatibility with previous versions.

\n","text":"TaskNotes 2.0.0 - Major Feature Release Major New Features: Kanban Board View Visual task management with drag-and-drop functionality Dynamic grouping by status, priority, or context Search filtering across all columns Real-time updates and collapsible columns Enhanced Pomodoro System SVG progress circle with refined visual timer Persistent session history and statistics tracking Dedicated Pomodoro Statistics view with completion metrics Enhanced UI with improved controls and display Advanced Task Filtering & Grouping Unified filtering system with search, status, context, priority filters Date range filtering with overdue task support Flexible grouping options (status, priority, context, due date) Performance-optimized filtering using cache indexes Enhanced Recurring Tasks Visual distinction with special styling and indicators Per-date completion tracking with smart UI controls Context menus filtered to prevent status conflicts Clear completion status display for selected dates UI/UX Improvements: Task Management Enhanced task edit modal with improved form layout Context menu (right-click) for quick property changes Autocomplete for contexts and tags in task forms Optimistic UI updates for better responsiveness View Enhancements Agenda view with improved layout and timeline organization Enhanced note cards with consistent styling across views Improved calendar integration with better visual indicators Unified card styling system across all views Performance & Reliability Migrated to unified CacheManager from legacy FileIndexer DOM reconciliation system for efficient UI updates Enhanced async handling and error management Improved cache update handling and race condition prevention Additional Improvements: Enhanced due date modal with better styling Improved time tracking UX with visual feedback Better task archival feedback and UI consistency Refined keyboard navigation and accessibility Updated README with comprehensive feature documentation Bug Fixes: Fixed 'No due date' group positioning in task list Resolved various UI spacing and alignment issues Improved handling of edge cases in recurring task logic Enhanced stability of cache operations and file handling This major release significantly expands TaskNotes capabilities with new views, enhanced filtering, and improved user experience while maintaining data compatibility with previous versions."},{"route":"/obsidian/releases/2.0.1/","title":"Untitled","description":"Bug Fixes and Enhancements:","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/2.0.1.md","namespace":"obsidian","relativePath":"releases/2.0.1.md","raw":" ## TaskNotes 2.0.1 - Recurring Tasks and Filtering Improvements\r\n\r\n Bug Fixes and Enhancements:\r\n\r\n Recurring Task Improvements:\r\n - Fixed recurring tasks not appearing in correct due date groups (Today, Tomorrow, etc.)\r\n - Recurring tasks now properly appear in 'Today' group when selected date matches recurrence pattern\r\n - Enhanced recurring task visual styling with distinctive indicators and backgrounds\r\n - Smart context menus for recurring tasks that prevent conflicting status changes\r\n - Fixed recurrence values not loading properly in task edit modal\r\n\r\n Task Filtering and Grouping:\r\n - Improved 'No due date' group positioning to appear at bottom of task list\r\n - Enhanced FilterService with target date awareness for intelligent recurring task grouping\r\n - Fixed cache integration issues where recurrence changes didn't trigger proper view updates\r\n - All views now properly refresh and regroup tasks when recurrence properties change\r\n\r\n UI and Data Consistency:\r\n - Fixed data format mismatch between stored abbreviations and UI display for day names\r\n - Improved task edit modal to properly convert between storage format and UI format\r\n - Enhanced cache workflow integration for seamless task property updates\r\n - Better synchronization between task edits and view refreshes\r\n\r\n Technical Improvements:\r\n - Added conversion helper methods for consistent day name handling\r\n - Enhanced cache manager with proper recurring task support\r\n - Improved event emission and handling for task updates\r\n - Better error handling and data validation in task modals\r\n\r\n This release focuses on making recurring tasks work seamlessly with the filtering and grouping system while maintaining data consistency and improving\r\n the overall user experience.\r\n\r\n","aliases":["/releases/2.0.1/","/releases/2.0.1/"],"toc":[{"level":2,"id":"tasknotes-201-recurring-tasks-and-filtering-improvements","text":"TaskNotes 2.0.1 - Recurring Tasks and Filtering Improvements"}],"html":"

TaskNotes 2.0.1 - Recurring Tasks and Filtering Improvements#

\n

Bug Fixes and Enhancements:

\n

Recurring Task Improvements:

\n
    \n
  • Fixed recurring tasks not appearing in correct due date groups (Today, Tomorrow, etc.)
  • \n
  • Recurring tasks now properly appear in 'Today' group when selected date matches recurrence pattern
  • \n
  • Enhanced recurring task visual styling with distinctive indicators and backgrounds
  • \n
  • Smart context menus for recurring tasks that prevent conflicting status changes
  • \n
  • Fixed recurrence values not loading properly in task edit modal
  • \n
\n

Task Filtering and Grouping:

\n
    \n
  • Improved 'No due date' group positioning to appear at bottom of task list
  • \n
  • Enhanced FilterService with target date awareness for intelligent recurring task grouping
  • \n
  • Fixed cache integration issues where recurrence changes didn't trigger proper view updates
  • \n
  • All views now properly refresh and regroup tasks when recurrence properties change
  • \n
\n

UI and Data Consistency:

\n
    \n
  • Fixed data format mismatch between stored abbreviations and UI display for day names
  • \n
  • Improved task edit modal to properly convert between storage format and UI format
  • \n
  • Enhanced cache workflow integration for seamless task property updates
  • \n
  • Better synchronization between task edits and view refreshes
  • \n
\n

Technical Improvements:

\n
    \n
  • Added conversion helper methods for consistent day name handling
  • \n
  • Enhanced cache manager with proper recurring task support
  • \n
  • Improved event emission and handling for task updates
  • \n
  • Better error handling and data validation in task modals
  • \n
\n

This release focuses on making recurring tasks work seamlessly with the filtering and grouping system while maintaining data consistency and improving\n the overall user experience.

\n","text":"TaskNotes 2.0.1 - Recurring Tasks and Filtering Improvements# Bug Fixes and Enhancements: Recurring Task Improvements: Fixed recurring tasks not appearing in correct due date groups (Today, Tomorrow, etc.) Recurring tasks now properly appear in 'Today' group when selected date matches recurrence pattern Enhanced recurring task visual styling with distinctive indicators and backgrounds Smart context menus for recurring tasks that prevent conflicting status changes Fixed recurrence values not loading properly in task edit modal Task Filtering and Grouping: Improved 'No due date' group positioning to appear at bottom of task list Enhanced FilterService with target date awareness for intelligent recurring task grouping Fixed cache integration issues where recurrence changes didn't trigger proper view updates All views now properly refresh and regroup tasks when recurrence properties change UI and Data Consistency: Fixed data format mismatch between stored abbreviations and UI display for day names Improved task edit modal to properly convert between storage format and UI format Enhanced cache workflow integration for seamless task property updates Better synchronization between task edits and view refreshes Technical Improvements: Added conversion helper methods for consistent day name handling Enhanced cache manager with proper recurring task support Improved event emission and handling for task updates Better error handling and data validation in task modals This release focuses on making recurring tasks work seamlessly with the filtering and grouping system while maintaining data consistency and improving the overall user experience."},{"route":"/obsidian/releases/2.0.2/","title":"Untitled","description":"Bug Fixes:","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/2.0.2.md","namespace":"obsidian","relativePath":"releases/2.0.2.md","raw":"## TaskNotes v2.0.2\r\n\r\nBug Fixes:\r\n- Fixed recurring tasks without due dates not appearing in agenda view\r\n- Recurring tasks now properly show on their scheduled days in agenda view\r\n\r\nSettings Improvements:\r\n- Enhanced Priorities settings tab with comprehensive usability improvements\r\n- Added detailed descriptions, help sections, and column headers\r\n- Added input validation and better visual organization\r\n- Matches the improved usability of the Statuses settings tab\r\n\r\nTechnical Details:\r\n- Modified FilterService date range filtering to properly handle recurring tasks without due dates\r\n- Added logic to check if recurring tasks should appear on any date within the specified range\r\n- Uses existing isRecurringTaskDueOn helper for accurate recurrence calculations\r\n- Maintains full backward compatibility for all existing functionality\n","aliases":["/releases/2.0.2/","/releases/2.0.2/"],"toc":[{"level":2,"id":"tasknotes-v202","text":"TaskNotes v2.0.2"}],"html":"

TaskNotes v2.0.2#

\n

Bug Fixes:

\n
    \n
  • Fixed recurring tasks without due dates not appearing in agenda view
  • \n
  • Recurring tasks now properly show on their scheduled days in agenda view
  • \n
\n

Settings Improvements:

\n
    \n
  • Enhanced Priorities settings tab with comprehensive usability improvements
  • \n
  • Added detailed descriptions, help sections, and column headers
  • \n
  • Added input validation and better visual organization
  • \n
  • Matches the improved usability of the Statuses settings tab
  • \n
\n

Technical Details:

\n
    \n
  • Modified FilterService date range filtering to properly handle recurring tasks without due dates
  • \n
  • Added logic to check if recurring tasks should appear on any date within the specified range
  • \n
  • Uses existing isRecurringTaskDueOn helper for accurate recurrence calculations
  • \n
  • Maintains full backward compatibility for all existing functionality
  • \n
\n","text":"TaskNotes v2.0.2# Bug Fixes: Fixed recurring tasks without due dates not appearing in agenda view Recurring tasks now properly show on their scheduled days in agenda view Settings Improvements: Enhanced Priorities settings tab with comprehensive usability improvements Added detailed descriptions, help sections, and column headers Added input validation and better visual organization Matches the improved usability of the Statuses settings tab Technical Details: Modified FilterService date range filtering to properly handle recurring tasks without due dates Added logic to check if recurring tasks should appear on any date within the specified range Uses existing isRecurringTaskDueOn helper for accurate recurrence calculations Maintains full backward compatibility for all existing functionality"},{"route":"/obsidian/releases/2.0.3/","title":"Untitled","description":"Bug Fixes:","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/2.0.3.md","namespace":"obsidian","relativePath":"releases/2.0.3.md","raw":"\r\nBug Fixes:\r\n- Fixed recurring tasks without due dates not appearing in agenda view\r\n- Recurring tasks now properly show on their scheduled days in agenda view\r\n\r\nCommand Improvements:\r\n- Removed layout-specific commands (open-linked-views, open-grid-layout, open-tabs-layout)\r\n- Removed popout window commands for cleaner command palette\r\n- Added 'Refresh TaskNotes cache' command for troubleshooting\r\n- Simplified ribbon icons to focus on core functionality\r\n\r\nTechnical Details:\r\n- Enhanced FilterService initial task set logic to include recurring tasks without due dates\r\n- Modified getTaskPathsInDateRange() to check all recurring tasks for date range inclusion\r\n- Added async processing with batched performance optimizations\r\n- Maintained backward compatibility and existing performance characteristics\r\n- Root cause: CacheManager only indexed tasks by actual due dates, excluding recurring tasks without due dates from date-based queries\r\n\r\nThe agenda view now correctly displays recurring tasks without due dates on their appropriate scheduled days.\n","aliases":["/releases/2.0.3/","/releases/2.0.3/"],"toc":[],"html":"

Bug Fixes:

\n
    \n
  • Fixed recurring tasks without due dates not appearing in agenda view
  • \n
  • Recurring tasks now properly show on their scheduled days in agenda view
  • \n
\n

Command Improvements:

\n
    \n
  • Removed layout-specific commands (open-linked-views, open-grid-layout, open-tabs-layout)
  • \n
  • Removed popout window commands for cleaner command palette
  • \n
  • Added 'Refresh TaskNotes cache' command for troubleshooting
  • \n
  • Simplified ribbon icons to focus on core functionality
  • \n
\n

Technical Details:

\n
    \n
  • Enhanced FilterService initial task set logic to include recurring tasks without due dates
  • \n
  • Modified getTaskPathsInDateRange() to check all recurring tasks for date range inclusion
  • \n
  • Added async processing with batched performance optimizations
  • \n
  • Maintained backward compatibility and existing performance characteristics
  • \n
  • Root cause: CacheManager only indexed tasks by actual due dates, excluding recurring tasks without due dates from date-based queries
  • \n
\n

The agenda view now correctly displays recurring tasks without due dates on their appropriate scheduled days.

\n","text":"Bug Fixes: Fixed recurring tasks without due dates not appearing in agenda view Recurring tasks now properly show on their scheduled days in agenda view Command Improvements: Removed layout-specific commands (open-linked-views, open-grid-layout, open-tabs-layout) Removed popout window commands for cleaner command palette Added 'Refresh TaskNotes cache' command for troubleshooting Simplified ribbon icons to focus on core functionality Technical Details: Enhanced FilterService initial task set logic to include recurring tasks without due dates Modified getTaskPathsInDateRange() to check all recurring tasks for date range inclusion Added async processing with batched performance optimizations Maintained backward compatibility and existing performance characteristics Root cause: CacheManager only indexed tasks by actual due dates, excluding recurring tasks without due dates from date-based queries The agenda view now correctly displays recurring tasks without due dates on their appropriate scheduled days."},{"route":"/obsidian/releases/2.0.4/","title":"TaskNotes v2.0.4","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.0.3...2.0.4","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/2.0.4.md","namespace":"obsidian","relativePath":"releases/2.0.4.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/2.0.3...2.0.4\r\n\r\n# TaskNotes v2.0.4\r\n\r\n- Allow multiple statuses to be filtered for at the same time, bringing\r\nstatus filtering in line with context and priority filtering\r\n- Fix flickering during kanban drag and drop\n","aliases":["/releases/2.0.4/","/releases/2.0.4/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.0.3...2.0.4

\n
    \n
  • Allow multiple statuses to be filtered for at the same time, bringing\nstatus filtering in line with context and priority filtering
  • \n
  • Fix flickering during kanban drag and drop
  • \n
\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.0.3...2.0.4 Allow multiple statuses to be filtered for at the same time, bringing status filtering in line with context and priority filtering Fix flickering during kanban drag and drop"},{"route":"/obsidian/releases/2.1.0/","title":"TaskNotes v2.1.0 - Major Feature Release","description":"This release introduces significant workflow enhancements and editor integration features that streamline task management directly within the Obsidian editing experience.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/2.1.0.md","namespace":"obsidian","relativePath":"releases/2.1.0.md","raw":"# TaskNotes v2.1.0 - Major Feature Release\r\n\r\nThis release introduces significant workflow enhancements and editor integration features that streamline task management directly within the Obsidian editing experience.\r\n\r\n## NEW FEATURES:\r\n\r\n**Instant Task Conversion**\r\n- One-click conversion of checkbox tasks to dedicated TaskNotes with inline convert buttons\r\n- Streamlined workflow for transforming simple tasks into structured task files\r\n- Configurable via settings to enable/disable the feature\r\n\r\n**Interactive Task Link Overlays**\r\n- Live task previews displayed on wikilinks in live preview mode\r\n- Hover and click interactions for editing tasks without leaving the current note\r\n- Context menus and inline task information display\r\n- Smart detection of task-related wikilinks with automatic enhancement\r\n\r\n**Enhanced Date Handling**\r\n- Improved overdue task detection that considers both due and scheduled dates\r\n- Better date consistency across all views and components\r\n- Expanded field mapping support for time tracking and completion data\r\n\r\n## IMPROVEMENTS:\r\n\r\n**Performance & Reliability**\r\n- Comprehensive resource cleanup to prevent memory leaks\r\n- Enhanced error handling with better user feedback\r\n- Performance optimizations in calendar view and task rendering\r\n- Improved DOM reconciliation and widget management\r\n\r\n**Accessibility & UX**\r\n- Enhanced accessibility with ARIA attributes and keyboard navigation\r\n- Consistent BEM CSS naming across all components\r\n- Better input validation and security measures\r\n- Improved visual consistency throughout the interface\r\n\r\n**Technical Enhancements**\r\n- Fixed deprecated Obsidian API usage for better compatibility\r\n- Standardized date handling using date-fns library\r\n- Configurable pomodoro field mapping\r\n- Better separation of concerns in component architecture\r\n\r\nThis release maintains full backward compatibility while adding new features that enhance the daily task management workflow.\n","aliases":["/releases/2.1.0/","/releases/2.1.0/"],"toc":[{"level":2,"id":"new-features","text":"NEW FEATURES:"},{"level":2,"id":"improvements","text":"IMPROVEMENTS:"}],"html":"

This release introduces significant workflow enhancements and editor integration features that streamline task management directly within the Obsidian editing experience.

\n

NEW FEATURES:#

\n

Instant Task Conversion

\n
    \n
  • One-click conversion of checkbox tasks to dedicated TaskNotes with inline convert buttons
  • \n
  • Streamlined workflow for transforming simple tasks into structured task files
  • \n
  • Configurable via settings to enable/disable the feature
  • \n
\n

Interactive Task Link Overlays

\n
    \n
  • Live task previews displayed on wikilinks in live preview mode
  • \n
  • Hover and click interactions for editing tasks without leaving the current note
  • \n
  • Context menus and inline task information display
  • \n
  • Smart detection of task-related wikilinks with automatic enhancement
  • \n
\n

Enhanced Date Handling

\n
    \n
  • Improved overdue task detection that considers both due and scheduled dates
  • \n
  • Better date consistency across all views and components
  • \n
  • Expanded field mapping support for time tracking and completion data
  • \n
\n

IMPROVEMENTS:#

\n

Performance & Reliability

\n
    \n
  • Comprehensive resource cleanup to prevent memory leaks
  • \n
  • Enhanced error handling with better user feedback
  • \n
  • Performance optimizations in calendar view and task rendering
  • \n
  • Improved DOM reconciliation and widget management
  • \n
\n

Accessibility & UX

\n
    \n
  • Enhanced accessibility with ARIA attributes and keyboard navigation
  • \n
  • Consistent BEM CSS naming across all components
  • \n
  • Better input validation and security measures
  • \n
  • Improved visual consistency throughout the interface
  • \n
\n

Technical Enhancements

\n
    \n
  • Fixed deprecated Obsidian API usage for better compatibility
  • \n
  • Standardized date handling using date-fns library
  • \n
  • Configurable pomodoro field mapping
  • \n
  • Better separation of concerns in component architecture
  • \n
\n

This release maintains full backward compatibility while adding new features that enhance the daily task management workflow.

\n","text":"This release introduces significant workflow enhancements and editor integration features that streamline task management directly within the Obsidian editing experience. NEW FEATURES:# Instant Task Conversion One-click conversion of checkbox tasks to dedicated TaskNotes with inline convert buttons Streamlined workflow for transforming simple tasks into structured task files Configurable via settings to enable/disable the feature Interactive Task Link Overlays Live task previews displayed on wikilinks in live preview mode Hover and click interactions for editing tasks without leaving the current note Context menus and inline task information display Smart detection of task-related wikilinks with automatic enhancement Enhanced Date Handling Improved overdue task detection that considers both due and scheduled dates Better date consistency across all views and components Expanded field mapping support for time tracking and completion data IMPROVEMENTS:# Performance & Reliability Comprehensive resource cleanup to prevent memory leaks Enhanced error handling with better user feedback Performance optimizations in calendar view and task rendering Improved DOM reconciliation and widget management Accessibility & UX Enhanced accessibility with ARIA attributes and keyboard navigation Consistent BEM CSS naming across all components Better input validation and security measures Improved visual consistency throughout the interface Technical Enhancements Fixed deprecated Obsidian API usage for better compatibility Standardized date handling using date-fns library Configurable pomodoro field mapping Better separation of concerns in component architecture This release maintains full backward compatibility while adding new features that enhance the daily task management workflow."},{"route":"/obsidian/releases/2.2.0/","title":"TaskNotes v2.2.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/2.2.0.md","namespace":"obsidian","relativePath":"releases/2.2.0.md","raw":"# TaskNotes v2.2.0\r\n\r\n## Major Features\r\n\r\n- Task Deletion: Added task deletion functionality with confirmation modal and proper event handling\r\n- Pomodoro Data Migration: Implemented migration utility for backward compatibility with existing Pomodoro session data\r\n- Enhanced Calendar Navigation: Improved CalendarView date navigation and refresh logic\r\n\r\n## Core Improvements\r\n\r\n- Timezone-Safe Date Handling: Complete overhaul of date utilities to ensure consistent timezone handling across the codebase\r\n- Centralized Task Management: Refactored task creation and editing to use centralized TaskService architecture\r\n- Improved Date Filtering: Enhanced FilterService with better date comparison logic for due and scheduled tasks\r\n- Pomodoro Session Tracking: Refactored session tracking and duration calculations for better accuracy\r\n\r\n## UI/UX Enhancements\r\n\r\n- Visual Consistency: Updated font sizes and UI element widths for better readability\r\n- Pomodoro Button Styling: Enhanced button styles with consistent visual feedback\r\n- Inline Widget Cleanup: Improved task update handling and cleaned up inline widget styles\r\n\r\n## Technical Improvements\r\n\r\n- Safer Date Parsing: Replaced parseISO with parseDate utilities for more robust date handling\r\n- ISO Timestamp Support: Updated timestamp generation to return ISO format with local timezone offset\r\n- Performance Optimizations: Various refactoring improvements for better code maintainability and performance\r\n\r\n","aliases":["/releases/2.2.0/","/releases/2.2.0/"],"toc":[{"level":2,"id":"major-features","text":"Major Features"},{"level":2,"id":"core-improvements","text":"Core Improvements"},{"level":2,"id":"uiux-enhancements","text":"UI/UX Enhancements"},{"level":2,"id":"technical-improvements","text":"Technical Improvements"}],"html":"

Major Features#

\n
    \n
  • Task Deletion: Added task deletion functionality with confirmation modal and proper event handling
  • \n
  • Pomodoro Data Migration: Implemented migration utility for backward compatibility with existing Pomodoro session data
  • \n
  • Enhanced Calendar Navigation: Improved CalendarView date navigation and refresh logic
  • \n
\n

Core Improvements#

\n
    \n
  • Timezone-Safe Date Handling: Complete overhaul of date utilities to ensure consistent timezone handling across the codebase
  • \n
  • Centralized Task Management: Refactored task creation and editing to use centralized TaskService architecture
  • \n
  • Improved Date Filtering: Enhanced FilterService with better date comparison logic for due and scheduled tasks
  • \n
  • Pomodoro Session Tracking: Refactored session tracking and duration calculations for better accuracy
  • \n
\n

UI/UX Enhancements#

\n
    \n
  • Visual Consistency: Updated font sizes and UI element widths for better readability
  • \n
  • Pomodoro Button Styling: Enhanced button styles with consistent visual feedback
  • \n
  • Inline Widget Cleanup: Improved task update handling and cleaned up inline widget styles
  • \n
\n

Technical Improvements#

\n
    \n
  • Safer Date Parsing: Replaced parseISO with parseDate utilities for more robust date handling
  • \n
  • ISO Timestamp Support: Updated timestamp generation to return ISO format with local timezone offset
  • \n
  • Performance Optimizations: Various refactoring improvements for better code maintainability and performance
  • \n
\n","text":"Major Features# Task Deletion: Added task deletion functionality with confirmation modal and proper event handling Pomodoro Data Migration: Implemented migration utility for backward compatibility with existing Pomodoro session data Enhanced Calendar Navigation: Improved CalendarView date navigation and refresh logic Core Improvements# Timezone-Safe Date Handling: Complete overhaul of date utilities to ensure consistent timezone handling across the codebase Centralized Task Management: Refactored task creation and editing to use centralized TaskService architecture Improved Date Filtering: Enhanced FilterService with better date comparison logic for due and scheduled tasks Pomodoro Session Tracking: Refactored session tracking and duration calculations for better accuracy UI/UX Enhancements# Visual Consistency: Updated font sizes and UI element widths for better readability Pomodoro Button Styling: Enhanced button styles with consistent visual feedback Inline Widget Cleanup: Improved task update handling and cleaned up inline widget styles Technical Improvements# Safer Date Parsing: Replaced parseISO with parseDate utilities for more robust date handling ISO Timestamp Support: Updated timestamp generation to return ISO format with local timezone offset Performance Optimizations: Various refactoring improvements for better code maintainability and performance"},{"route":"/obsidian/releases/2.2.1/","title":"Untitled","description":"Fix #22 and #24","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/2.2.1.md","namespace":"obsidian","relativePath":"releases/2.2.1.md","raw":"Fix #22 and #24 \n","aliases":["/releases/2.2.1/","/releases/2.2.1/"],"toc":[],"html":"

Fix #22 and #24

\n","text":"Fix #22 and #24"},{"route":"/obsidian/releases/2.2.2/","title":"Untitled","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/2.2.2.md","namespace":"obsidian","relativePath":"releases/2.2.2.md","raw":"\n","aliases":["/releases/2.2.2/","/releases/2.2.2/"],"toc":[],"html":"","text":""},{"route":"/obsidian/releases/2.2.3/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.2.2...2.2.3","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/2.2.3.md","namespace":"obsidian","relativePath":"releases/2.2.3.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/2.2.2...2.2.3\n","aliases":["/releases/2.2.3/","/releases/2.2.3/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.2.2...2.2.3

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.2.2...2.2.3"},{"route":"/obsidian/releases/3.0.0/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.3.0...3.0.0","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.0.0.md","namespace":"obsidian","relativePath":"releases/3.0.0.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/2.3.0...3.0.0\n","aliases":["/releases/3.0.0/","/releases/3.0.0/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.3.0...3.0.0

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.3.0...3.0.0"},{"route":"/obsidian/releases/3.0.1/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.0.0...3.0.1","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.0.1.md","namespace":"obsidian","relativePath":"releases/3.0.1.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.0.0...3.0.1\n","aliases":["/releases/3.0.1/","/releases/3.0.1/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.0.0...3.0.1

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.0.0...3.0.1"},{"route":"/obsidian/releases/3.1.0/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.0.1...3.1.0","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.1.0.md","namespace":"obsidian","relativePath":"releases/3.1.0.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.0.1...3.1.0\n","aliases":["/releases/3.1.0/","/releases/3.1.0/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.0.1...3.1.0

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.0.1...3.1.0"},{"route":"/obsidian/releases/3.1.1/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.1.0...3.1.1","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.1.1.md","namespace":"obsidian","relativePath":"releases/3.1.1.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.1.0...3.1.1\n","aliases":["/releases/3.1.1/","/releases/3.1.1/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.1.0...3.1.1

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.1.0...3.1.1"},{"route":"/obsidian/releases/3.10.0/","title":"Release Notes: 3.10.0","description":"This version introduces a new data storage option for tasks, adds a status bar component for time tracking, and includes several bug fixes and internal improvements.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.10.0.md","namespace":"obsidian","relativePath":"releases/3.10.0.md","raw":"# Release Notes: 3.10.0\r\n\r\n This version introduces a new data storage option for tasks, adds a status bar component for time tracking, and includes several bug fixes and internal improvements.\r\n\r\n## New Features\r\n\r\n### Option to Store Task Title in Filename\r\n\r\nA new setting, storeTitleInFilename, is available under \"Task Filenames\" in the settings tab. This feature changes how task titles are stored.\r\n\r\n**Implementation Details:**\r\n\r\n- When this setting is enabled, creating a new task will use its title to generate the filename (e.g., My New Task.md). The title field will be omitted from the task's frontmatter.\r\n- For reading tasks, the application will first look for a title field in the frontmatter. If it is not found, the system will use the filename as the task's title. This ensures backward compatibility with existing tasks.\r\n- When a task's title is updated, and this setting is active, the file itself is automatically renamed to match the new title. The file's frontmatter is updated before the rename operation occurs to ensure data integrity.\r\n- Enabling this setting disables and hides the other filename format options (Zettelkasten, timestamp, custom).\r\n- This setting is disabled by default.\r\n\r\n### Status Bar Component for Tracked Tasks\r\n\r\nA new UI component has been added to the app's status bar to display tasks with active time-tracking sessions.\r\n\r\n**Functionality:**\r\n\r\n- When a single task is being tracked, its title (truncated if necessary) is displayed in the status bar. The full title is visible in a tooltip.\r\n- When multiple tasks are being tracked, a count of these tasks is displayed. The tooltip lists the titles of the tracked tasks.\r\n- The status bar item is hidden when no tasks are being tracked.\r\n- This feature is controlled by the \"Show tracked tasks in status bar\" setting and is disabled by default.\r\n\r\n### Customizable First Day of Week for Mini Calendar\r\n\r\nThe mini calendar view now respects the \"First day of the week\" setting in Obsidian's general settings. The calendar grid will adjust to start the week on the day you have configured (e.g., Sunday or Monday).\r\n\r\n## Bug Fixes\r\n\r\n- Search Functionality: Resolved a type error in the search filter that occurred when a task's title or context field was null. The code now handles null values gracefully during search operations.\r\n- File Renaming: Corrected the order of operations when storeTitleInFilename is enabled. The previous implementation could rename the file before its frontmatter was updated, which has now been fixed.\r\n\r\n## Internal Improvements & Documentation\r\n\r\n- Service Refactoring: The TaskService, FieldMapper, and MinimalNativeCache have been updated to handle the new logic for storing and retrieving task titles from filenames.\r\n- `StatusBarService`: A new StatusBarService was implemented to encapsulate the logic for the new status bar component, including its creation, updates, and event handling.\r\n- Issue Templates: The GitHub issue templates for bug reports and questions have been updated to be more structured and improve the quality of submitted reports.\r\n- Documentation: Added a new section to the documentation explaining the storeTitleInFilename feature in detail.\r\n","aliases":["/releases/3.10.0/","/releases/3.10.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"option-to-store-task-title-in-filename","text":"Option to Store Task Title in Filename"},{"level":3,"id":"status-bar-component-for-tracked-tasks","text":"Status Bar Component for Tracked Tasks"},{"level":3,"id":"customizable-first-day-of-week-for-mini-calendar","text":"Customizable First Day of Week for Mini Calendar"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":2,"id":"internal-improvements-documentation","text":"Internal Improvements & Documentation"}],"html":"

This version introduces a new data storage option for tasks, adds a status bar component for time tracking, and includes several bug fixes and internal improvements.

\n

New Features#

\n

Option to Store Task Title in Filename#

\n

A new setting, storeTitleInFilename, is available under "Task Filenames" in the settings tab. This feature changes how task titles are stored.

\n

Implementation Details:

\n
    \n
  • When this setting is enabled, creating a new task will use its title to generate the filename (e.g., My New Task.md). The title field will be omitted from the task's frontmatter.
  • \n
  • For reading tasks, the application will first look for a title field in the frontmatter. If it is not found, the system will use the filename as the task's title. This ensures backward compatibility with existing tasks.
  • \n
  • When a task's title is updated, and this setting is active, the file itself is automatically renamed to match the new title. The file's frontmatter is updated before the rename operation occurs to ensure data integrity.
  • \n
  • Enabling this setting disables and hides the other filename format options (Zettelkasten, timestamp, custom).
  • \n
  • This setting is disabled by default.
  • \n
\n

Status Bar Component for Tracked Tasks#

\n

A new UI component has been added to the app's status bar to display tasks with active time-tracking sessions.

\n

Functionality:

\n
    \n
  • When a single task is being tracked, its title (truncated if necessary) is displayed in the status bar. The full title is visible in a tooltip.
  • \n
  • When multiple tasks are being tracked, a count of these tasks is displayed. The tooltip lists the titles of the tracked tasks.
  • \n
  • The status bar item is hidden when no tasks are being tracked.
  • \n
  • This feature is controlled by the "Show tracked tasks in status bar" setting and is disabled by default.
  • \n
\n

Customizable First Day of Week for Mini Calendar#

\n

The mini calendar view now respects the "First day of the week" setting in Obsidian's general settings. The calendar grid will adjust to start the week on the day you have configured (e.g., Sunday or Monday).

\n

Bug Fixes#

\n
    \n
  • Search Functionality: Resolved a type error in the search filter that occurred when a task's title or context field was null. The code now handles null values gracefully during search operations.
  • \n
  • File Renaming: Corrected the order of operations when storeTitleInFilename is enabled. The previous implementation could rename the file before its frontmatter was updated, which has now been fixed.
  • \n
\n

Internal Improvements & Documentation#

\n
    \n
  • Service Refactoring: The TaskService, FieldMapper, and MinimalNativeCache have been updated to handle the new logic for storing and retrieving task titles from filenames.
  • \n
  • StatusBarService: A new StatusBarService was implemented to encapsulate the logic for the new status bar component, including its creation, updates, and event handling.
  • \n
  • Issue Templates: The GitHub issue templates for bug reports and questions have been updated to be more structured and improve the quality of submitted reports.
  • \n
  • Documentation: Added a new section to the documentation explaining the storeTitleInFilename feature in detail.
  • \n
\n","text":"This version introduces a new data storage option for tasks, adds a status bar component for time tracking, and includes several bug fixes and internal improvements. New Features# Option to Store Task Title in Filename# A new setting, storeTitleInFilename, is available under \"Task Filenames\" in the settings tab. This feature changes how task titles are stored. Implementation Details: When this setting is enabled, creating a new task will use its title to generate the filename (e.g., My New Task.md). The title field will be omitted from the task's frontmatter. For reading tasks, the application will first look for a title field in the frontmatter. If it is not found, the system will use the filename as the task's title. This ensures backward compatibility with existing tasks. When a task's title is updated, and this setting is active, the file itself is automatically renamed to match the new title. The file's frontmatter is updated before the rename operation occurs to ensure data integrity. Enabling this setting disables and hides the other filename format options (Zettelkasten, timestamp, custom). This setting is disabled by default. Status Bar Component for Tracked Tasks# A new UI component has been added to the app's status bar to display tasks with active time-tracking sessions. Functionality: When a single task is being tracked, its title (truncated if necessary) is displayed in the status bar. The full title is visible in a tooltip. When multiple tasks are being tracked, a count of these tasks is displayed. The tooltip lists the titles of the tracked tasks. The status bar item is hidden when no tasks are being tracked. This feature is controlled by the \"Show tracked tasks in status bar\" setting and is disabled by default. Customizable First Day of Week for Mini Calendar# The mini calendar view now respects the \"First day of the week\" setting in Obsidian's general settings. The calendar grid will adjust to start the week on the day you have configured (e.g., Sunday or Monday). Bug Fixes# Search Functionality: Resolved a type error in the search filter that occurred when a task's title or context field was null. The code now handles null values gracefully during search operations. File Renaming: Corrected the order of operations when storeTitleInFilename is enabled. The previous implementation could rename the file before its frontmatter was updated, which has now been fixed. Internal Improvements & Documentation# Service Refactoring: The TaskService, FieldMapper, and MinimalNativeCache have been updated to handle the new logic for storing and retrieving task titles from filenames. StatusBarService: A new StatusBarService was implemented to encapsulate the logic for the new status bar component, including its creation, updates, and event handling. Issue Templates: The GitHub issue templates for bug reports and questions have been updated to be more structured and improve the quality of submitted reports. Documentation: Added a new section to the documentation explaining the storeTitleInFilename feature in detail."},{"route":"/obsidian/releases/3.11.0/","title":"Release Notes: 3.11.0","description":"This release introduces a new project management system, significant enhancements to the Pomodoro timer and workflows, and a number of quality-of-life improvements and bug fixes.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.11.0.md","namespace":"obsidian","relativePath":"releases/3.11.0.md","raw":"# Release Notes: 3.11.0\r\n\r\nThis release introduces a new project management system, significant enhancements to the Pomodoro timer and workflows, and a number of quality-of-life improvements and bug fixes.\r\n\r\n## New Features\r\n\r\n### Project Management\r\n\r\nA new project management system has been integrated, allowing for better organization and tracking of tasks within projects.\r\n\r\n- **Note-Based Projects**: Projects are now properly integrated into TaskNotes. You can link tasks to any note in your vault, effectively turning that note into a project. This leverages Obsidian's core linking capabilities, allowing you to see all tasks related to a project in the backlinks of the project note.\r\n- **Project Selection UI**: A new project selection modal has been added to the task creation and editing modals. It features fuzzy search to quickly find and assign tasks to project notes.\r\n- **Filtering and Grouping by Project**:\r\n - The Filter Bar in all views now includes a \"Project\" filter, allowing you to see tasks for one or more specific projects.\r\n - The \"Group By\" option now includes \"Project\", which organizes the Task List and Kanban views by project.\r\n- **Clickable Project Links**: In task cards and other views, project names are now clickable links that take you directly to the project note.\r\n\r\n### Workflow and UI Enhancements\r\n\r\n- **Redesigned Pomodoro Timer**: The Pomodoro timer has been completely redesigned for a more modern and user-friendly experience.\r\n - **New Interface**: A more compact and visually appealing interface.\r\n - **Time Adjustment**: You can now add or subtract time from the current session or the prepared timer.\r\n - **Skip Break**: A \"Skip break\" button is now available after a work session.\r\n- **Enhanced Pomodoro Stats**: The Pomodoro statistics view has been improved to provide more insights.\r\n - **Overview Section**: A new overview section shows today's completed Pomodoros, total focus time, and a comparison with yesterday's performance.\r\n- **Instant Task Conversion**: The \"Convert task to TaskNote\" command has been streamlined. It now instantly converts a checkbox task into a TaskNote without opening the creation modal, reducing friction.\r\n- **Quick Actions for Current Task**: A new command, \"Quick actions for current task,\" allows you to open the action palette for the currently active TaskNote, providing quick access to common operations.\r\n- **Improved Sorting Logic**: The task sorting algorithm has been enhanced. When the primary sorting criterion (e.g., due date) is the same for multiple tasks, a fallback sorting order is applied: `scheduled date` -> `due date` -> `priority` -> `title`. This ensures a more predictable and logical ordering of tasks.\r\n- **Archive Button in Edit Modal**: An \"Archive\" button has been added to the task edit modal, allowing for quick archiving and unarchiving of tasks.\r\n- **Week Start Day Setting**: All calendar views now respect the \"Start week on\" setting from Obsidian's calendar preferences.\r\n\r\n## Bug Fixes and Minor Improvements\r\n\r\n- **Recurring Task Date Consistency**: A critical bug has been fixed where recurring task dates could appear on the wrong day in different timezones (especially CST). The handling of dates and timezones for recurring tasks is now more robust, ensuring consistency across all views.\r\n- **Pomodoro Daily Note Integration**: The Pomodoro service now correctly handles adding session history to daily notes, preventing the creation of duplicate entries.\r\n- **Template Processing**:\r\n - The `{{parentNote}}` template variable now correctly resolves to a properly formatted markdown link.\r\n - YAML frontmatter in templates is now processed more safely to avoid parsing errors.\r\n- **Date Validation**: The `complete_instances` field for recurring tasks now has stricter validation to filter out invalid entries, improving data integrity.\r\n- **Natural Language Processing**: The natural language parser now correctly applies scheduled times (e.g., \"do something at 5pm\") to created tasks.\r\n- **Agenda View Quick Select**: A bug that prevented the date quick-select menus in the Agenda View from working after the first use has been fixed.\r\n- **Styling and CSS**: Numerous styling improvements have been made across the plugin for a more polished and consistent look and feel, including to the Pomodoro views, task cards, and modals.\r\n- **Documentation**:\r\n - The documentation has been updated to reflect the new project management features.\r\n - New workflow guides for \"Habit Tracking\" and \"Project Management\" have been added.\r\n\r\n","aliases":["/releases/3.11.0/","/releases/3.11.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"project-management","text":"Project Management"},{"level":3,"id":"workflow-and-ui-enhancements","text":"Workflow and UI Enhancements"},{"level":2,"id":"bug-fixes-and-minor-improvements","text":"Bug Fixes and Minor Improvements"}],"html":"

This release introduces a new project management system, significant enhancements to the Pomodoro timer and workflows, and a number of quality-of-life improvements and bug fixes.

\n

New Features#

\n

Project Management#

\n

A new project management system has been integrated, allowing for better organization and tracking of tasks within projects.

\n
    \n
  • Note-Based Projects: Projects are now properly integrated into TaskNotes. You can link tasks to any note in your vault, effectively turning that note into a project. This leverages Obsidian's core linking capabilities, allowing you to see all tasks related to a project in the backlinks of the project note.
  • \n
  • Project Selection UI: A new project selection modal has been added to the task creation and editing modals. It features fuzzy search to quickly find and assign tasks to project notes.
  • \n
  • Filtering and Grouping by Project:
      \n
    • The Filter Bar in all views now includes a "Project" filter, allowing you to see tasks for one or more specific projects.
    • \n
    • The "Group By" option now includes "Project", which organizes the Task List and Kanban views by project.
    • \n
    \n
  • \n
  • Clickable Project Links: In task cards and other views, project names are now clickable links that take you directly to the project note.
  • \n
\n

Workflow and UI Enhancements#

\n
    \n
  • Redesigned Pomodoro Timer: The Pomodoro timer has been completely redesigned for a more modern and user-friendly experience.
      \n
    • New Interface: A more compact and visually appealing interface.
    • \n
    • Time Adjustment: You can now add or subtract time from the current session or the prepared timer.
    • \n
    • Skip Break: A "Skip break" button is now available after a work session.
    • \n
    \n
  • \n
  • Enhanced Pomodoro Stats: The Pomodoro statistics view has been improved to provide more insights.
      \n
    • Overview Section: A new overview section shows today's completed Pomodoros, total focus time, and a comparison with yesterday's performance.
    • \n
    \n
  • \n
  • Instant Task Conversion: The "Convert task to TaskNote" command has been streamlined. It now instantly converts a checkbox task into a TaskNote without opening the creation modal, reducing friction.
  • \n
  • Quick Actions for Current Task: A new command, "Quick actions for current task," allows you to open the action palette for the currently active TaskNote, providing quick access to common operations.
  • \n
  • Improved Sorting Logic: The task sorting algorithm has been enhanced. When the primary sorting criterion (e.g., due date) is the same for multiple tasks, a fallback sorting order is applied: scheduled date -> due date -> priority -> title. This ensures a more predictable and logical ordering of tasks.
  • \n
  • Archive Button in Edit Modal: An "Archive" button has been added to the task edit modal, allowing for quick archiving and unarchiving of tasks.
  • \n
  • Week Start Day Setting: All calendar views now respect the "Start week on" setting from Obsidian's calendar preferences.
  • \n
\n

Bug Fixes and Minor Improvements#

\n
    \n
  • Recurring Task Date Consistency: A critical bug has been fixed where recurring task dates could appear on the wrong day in different timezones (especially CST). The handling of dates and timezones for recurring tasks is now more robust, ensuring consistency across all views.
  • \n
  • Pomodoro Daily Note Integration: The Pomodoro service now correctly handles adding session history to daily notes, preventing the creation of duplicate entries.
  • \n
  • Template Processing:
      \n
    • The {{parentNote}} template variable now correctly resolves to a properly formatted markdown link.
    • \n
    • YAML frontmatter in templates is now processed more safely to avoid parsing errors.
    • \n
    \n
  • \n
  • Date Validation: The complete_instances field for recurring tasks now has stricter validation to filter out invalid entries, improving data integrity.
  • \n
  • Natural Language Processing: The natural language parser now correctly applies scheduled times (e.g., "do something at 5pm") to created tasks.
  • \n
  • Agenda View Quick Select: A bug that prevented the date quick-select menus in the Agenda View from working after the first use has been fixed.
  • \n
  • Styling and CSS: Numerous styling improvements have been made across the plugin for a more polished and consistent look and feel, including to the Pomodoro views, task cards, and modals.
  • \n
  • Documentation:
      \n
    • The documentation has been updated to reflect the new project management features.
    • \n
    • New workflow guides for "Habit Tracking" and "Project Management" have been added.
    • \n
    \n
  • \n
\n","text":"This release introduces a new project management system, significant enhancements to the Pomodoro timer and workflows, and a number of quality-of-life improvements and bug fixes. New Features# Project Management# A new project management system has been integrated, allowing for better organization and tracking of tasks within projects. Note-Based Projects: Projects are now properly integrated into TaskNotes. You can link tasks to any note in your vault, effectively turning that note into a project. This leverages Obsidian's core linking capabilities, allowing you to see all tasks related to a project in the backlinks of the project note. Project Selection UI: A new project selection modal has been added to the task creation and editing modals. It features fuzzy search to quickly find and assign tasks to project notes. Filtering and Grouping by Project: The Filter Bar in all views now includes a \"Project\" filter, allowing you to see tasks for one or more specific projects. The \"Group By\" option now includes \"Project\", which organizes the Task List and Kanban views by project. Clickable Project Links: In task cards and other views, project names are now clickable links that take you directly to the project note. Workflow and UI Enhancements# Redesigned Pomodoro Timer: The Pomodoro timer has been completely redesigned for a more modern and user-friendly experience. New Interface: A more compact and visually appealing interface. Time Adjustment: You can now add or subtract time from the current session or the prepared timer. Skip Break: A \"Skip break\" button is now available after a work session. Enhanced Pomodoro Stats: The Pomodoro statistics view has been improved to provide more insights. Overview Section: A new overview section shows today's completed Pomodoros, total focus time, and a comparison with yesterday's performance. Instant Task Conversion: The \"Convert task to TaskNote\" command has been streamlined. It now instantly converts a checkbox task into a TaskNote without opening the creation modal, reducing friction. Quick Actions for Current Task: A new command, \"Quick actions for current task,\" allows you to open the action palette for the currently active TaskNote, providing quick access to common operations. Improved Sorting Logic: The task sorting algorithm has been enhanced. When the primary sorting criterion (e.g., due date) is the same for multiple tasks, a fallback sorting order is applied: scheduled date -> due date -> priority -> title. This ensures a more predictable and logical ordering of tasks. Archive Button in Edit Modal: An \"Archive\" button has been added to the task edit modal, allowing for quick archiving and unarchiving of tasks. Week Start Day Setting: All calendar views now respect the \"Start week on\" setting from Obsidian's calendar preferences. Bug Fixes and Minor Improvements# Recurring Task Date Consistency: A critical bug has been fixed where recurring task dates could appear on the wrong day in different timezones (especially CST). The handling of dates and timezones for recurring tasks is now more robust, ensuring consistency across all views. Pomodoro Daily Note Integration: The Pomodoro service now correctly handles adding session history to daily notes, preventing the creation of duplicate entries. Template Processing: The {{parentNote}} template variable now correctly resolves to a properly formatted markdown link. YAML frontmatter in templates is now processed more safely to avoid parsing errors. Date Validation: The complete_instances field for recurring tasks now has stricter validation to filter out invalid entries, improving data integrity. Natural Language Processing: The natural language parser now correctly applies scheduled times (e.g., \"do something at 5pm\") to created tasks. Agenda View Quick Select: A bug that prevented the date quick-select menus in the Agenda View from working after the first use has been fixed. Styling and CSS: Numerous styling improvements have been made across the plugin for a more polished and consistent look and feel, including to the Pomodoro views, task cards, and modals. Documentation: The documentation has been updated to reflect the new project management features. New workflow guides for \"Habit Tracking\" and \"Project Management\" have been added."},{"route":"/obsidian/releases/3.11.1/","title":"Release Notes 3.11.1","description":"This release focuses on adopting Obsidian's official APIs and improving plugin stability through better resource management.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.11.1.md","namespace":"obsidian","relativePath":"releases/3.11.1.md","raw":"# Release Notes 3.11.1\r\n\r\n## API Modernization & Performance Improvements\r\n\r\nThis release focuses on adopting Obsidian's official APIs and improving plugin stability through better resource management.\r\n\r\n### Improved autocomplete\r\n\r\n- Replaced custom autocomplete implementation with Obsidian's native AbstractInputSuggest API\r\n - Better keyboard navigation and visual consistency\r\n - More responsive type-ahead support for contexts and tags in task modals\r\n\r\n### API modernization\r\n\r\n- Atomic Frontmatter Updates: Now uses FileManager.processFrontMatter for safer file modifications\r\n - Eliminates risk of data corruption during migration processes\r\n - More reliable handling of YAML frontmatter updates\r\n- Native Link Parsing: Switched to Obsidian's built-in parseLinktext API\r\n - More robust wikilink parsing with better edge case handling\r\n - Improved consistency with Obsidian's internal link processing\r\n- Vault-Specific Storage: View preferences now use App.loadLocalStorage/saveLocalStorage\r\n - Fixes issue where settings were shared across different vaults\r\n - Each vault now maintains its own view state and preferences\r\n\r\n## Bug fixes & stability\r\n\r\n- Memory Leak Prevention: Properly register and cleanup event listeners\r\n - Event listeners are now tracked with EventRef objects for proper cleanup\r\n - Prevents memory leaks when plugin is disabled or reloaded\r\n- Debounce Optimization: Uses Obsidian's built-in debounce function\r\n - More efficient calendar refresh operations\r\n - Better performance consistency\r\n- UI Polish: Fixed sentence case issues throughout the interface\r\n\r\n## Security & reliability\r\n\r\n- Resource Cleanup: Enhanced plugin lifecycle management\r\n - Better cleanup of event listeners and cached data\r\n - Improved plugin disable/enable reliability\r\n\r\n","aliases":["/releases/3.11.1/","/releases/3.11.1/"],"toc":[{"level":2,"id":"api-modernization-performance-improvements","text":"API Modernization & Performance Improvements"},{"level":3,"id":"improved-autocomplete","text":"Improved autocomplete"},{"level":3,"id":"api-modernization","text":"API modernization"},{"level":2,"id":"bug-fixes-stability","text":"Bug fixes & stability"},{"level":2,"id":"security-reliability","text":"Security & reliability"}],"html":"

API Modernization & Performance Improvements#

\n

This release focuses on adopting Obsidian's official APIs and improving plugin stability through better resource management.

\n

Improved autocomplete#

\n
    \n
  • Replaced custom autocomplete implementation with Obsidian's native AbstractInputSuggest API
      \n
    • Better keyboard navigation and visual consistency
    • \n
    • More responsive type-ahead support for contexts and tags in task modals
    • \n
    \n
  • \n
\n

API modernization#

\n
    \n
  • Atomic Frontmatter Updates: Now uses FileManager.processFrontMatter for safer file modifications
      \n
    • Eliminates risk of data corruption during migration processes
    • \n
    • More reliable handling of YAML frontmatter updates
    • \n
    \n
  • \n
  • Native Link Parsing: Switched to Obsidian's built-in parseLinktext API
      \n
    • More robust wikilink parsing with better edge case handling
    • \n
    • Improved consistency with Obsidian's internal link processing
    • \n
    \n
  • \n
  • Vault-Specific Storage: View preferences now use App.loadLocalStorage/saveLocalStorage
      \n
    • Fixes issue where settings were shared across different vaults
    • \n
    • Each vault now maintains its own view state and preferences
    • \n
    \n
  • \n
\n

Bug fixes & stability#

\n
    \n
  • Memory Leak Prevention: Properly register and cleanup event listeners
      \n
    • Event listeners are now tracked with EventRef objects for proper cleanup
    • \n
    • Prevents memory leaks when plugin is disabled or reloaded
    • \n
    \n
  • \n
  • Debounce Optimization: Uses Obsidian's built-in debounce function
      \n
    • More efficient calendar refresh operations
    • \n
    • Better performance consistency
    • \n
    \n
  • \n
  • UI Polish: Fixed sentence case issues throughout the interface
  • \n
\n

Security & reliability#

\n
    \n
  • Resource Cleanup: Enhanced plugin lifecycle management
      \n
    • Better cleanup of event listeners and cached data
    • \n
    • Improved plugin disable/enable reliability
    • \n
    \n
  • \n
\n","text":"API Modernization & Performance Improvements# This release focuses on adopting Obsidian's official APIs and improving plugin stability through better resource management. Improved autocomplete# Replaced custom autocomplete implementation with Obsidian's native AbstractInputSuggest API Better keyboard navigation and visual consistency More responsive type-ahead support for contexts and tags in task modals API modernization# Atomic Frontmatter Updates: Now uses FileManager.processFrontMatter for safer file modifications Eliminates risk of data corruption during migration processes More reliable handling of YAML frontmatter updates Native Link Parsing: Switched to Obsidian's built-in parseLinktext API More robust wikilink parsing with better edge case handling Improved consistency with Obsidian's internal link processing Vault-Specific Storage: View preferences now use App.loadLocalStorage/saveLocalStorage Fixes issue where settings were shared across different vaults Each vault now maintains its own view state and preferences Bug fixes & stability# Memory Leak Prevention: Properly register and cleanup event listeners Event listeners are now tracked with EventRef objects for proper cleanup Prevents memory leaks when plugin is disabled or reloaded Debounce Optimization: Uses Obsidian's built-in debounce function More efficient calendar refresh operations Better performance consistency UI Polish: Fixed sentence case issues throughout the interface Security & reliability# Resource Cleanup: Enhanced plugin lifecycle management Better cleanup of event listeners and cached data Improved plugin disable/enable reliability"},{"route":"/obsidian/releases/3.11.2/","title":"Release Notes - 3.11.2","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.11.2.md","namespace":"obsidian","relativePath":"releases/3.11.2.md","raw":"# Release Notes - 3.11.2\r\n\r\n## Internal Improvements\r\n\r\n### API Standardization\r\n\r\n- Replaced custom wikilink parsing with Obsidian's native `parseLinktext` API\r\n- Migrated from custom debounce function to Obsidian's built-in debounce utility\r\n\r\n### Files Updated\r\n\r\n- TaskLinkOverlay.ts: Updated wikilink parsing\r\n- FilterService.ts: Improved project link resolution\r\n- TaskLinkDetectionService.ts: Simplified link detection\r\n- MinimalNativeCache.ts: Standardized project link handling\r\n- KanbanView.ts: Replaced custom debounce implementation\r\n- Test files: Updated mocks accordingly\r\n","aliases":["/releases/3.11.2/","/releases/3.11.2/"],"toc":[{"level":2,"id":"internal-improvements","text":"Internal Improvements"},{"level":3,"id":"api-standardization","text":"API Standardization"},{"level":3,"id":"files-updated","text":"Files Updated"}],"html":"

Internal Improvements#

\n

API Standardization#

\n
    \n
  • Replaced custom wikilink parsing with Obsidian's native parseLinktext API
  • \n
  • Migrated from custom debounce function to Obsidian's built-in debounce utility
  • \n
\n

Files Updated#

\n
    \n
  • TaskLinkOverlay.ts: Updated wikilink parsing
  • \n
  • FilterService.ts: Improved project link resolution
  • \n
  • TaskLinkDetectionService.ts: Simplified link detection
  • \n
  • MinimalNativeCache.ts: Standardized project link handling
  • \n
  • KanbanView.ts: Replaced custom debounce implementation
  • \n
  • Test files: Updated mocks accordingly
  • \n
\n","text":"Internal Improvements# API Standardization# Replaced custom wikilink parsing with Obsidian's native parseLinktext API Migrated from custom debounce function to Obsidian's built-in debounce utility Files Updated# TaskLinkOverlay.ts: Updated wikilink parsing FilterService.ts: Improved project link resolution TaskLinkDetectionService.ts: Simplified link detection MinimalNativeCache.ts: Standardized project link handling KanbanView.ts: Replaced custom debounce implementation Test files: Updated mocks accordingly"},{"route":"/obsidian/releases/3.12.0/","title":"Release Notes - 3.12.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.12.0.md","namespace":"obsidian","relativePath":"releases/3.12.0.md","raw":"# Release Notes - 3.12.0\r\n\r\n## New Features\r\n\r\n### Project Subtasks Widget\r\n\r\n- Add a collapsible widget that displays tasks linked to the current project note\r\n- Widget appears automatically in project notes and shows all tasks that reference the rpoject\r\n- Includes collapsible interface with persistent state across sessions\r\n- Updates automatically when tasks are modified or deleted\r\n- Can be enabled or disabled in plugin settings under \"Show project subtasks widget\"\r\n\r\n## Bug Fixes\r\n\r\n### FilterBar Improvements\r\n\r\n- Fixed FilterBar not updating dynamically when tasks get new contexts or projects (#138)\r\n- Fixed archived tasks' contexts and projects still appearing in filter bar (#139)\r\n- Resolved FilterBar showing projects with [[]] brackets\r\n- Fixed empty status list display on initial load\r\n- Improved initialization reliability with better event handling\r\n\r\n### Task Display\r\n\r\n- Fixed wikilink alias handling in TaskCard and inline displays (#145, #147)\r\n- Fixed projects not loading correctly in task edit modal (#141)\r\n- Improved cursor positioning in live preview mode\r\n\r\n## Documentation\r\n\r\n- Added documentation for project subtasks widget feature\r\n- Updated inline task integration documentation\r\n- Added configuration settings documentation\r\n","aliases":["/releases/3.12.0/","/releases/3.12.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"project-subtasks-widget","text":"Project Subtasks Widget"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"filterbar-improvements","text":"FilterBar Improvements"},{"level":3,"id":"task-display","text":"Task Display"},{"level":2,"id":"documentation","text":"Documentation"}],"html":"

New Features#

\n

Project Subtasks Widget#

\n
    \n
  • Add a collapsible widget that displays tasks linked to the current project note
  • \n
  • Widget appears automatically in project notes and shows all tasks that reference the rpoject
  • \n
  • Includes collapsible interface with persistent state across sessions
  • \n
  • Updates automatically when tasks are modified or deleted
  • \n
  • Can be enabled or disabled in plugin settings under "Show project subtasks widget"
  • \n
\n

Bug Fixes#

\n

FilterBar Improvements#

\n
    \n
  • Fixed FilterBar not updating dynamically when tasks get new contexts or projects (#138)
  • \n
  • Fixed archived tasks' contexts and projects still appearing in filter bar (#139)
  • \n
  • Resolved FilterBar showing projects with [[]] brackets
  • \n
  • Fixed empty status list display on initial load
  • \n
  • Improved initialization reliability with better event handling
  • \n
\n

Task Display#

\n
    \n
  • Fixed wikilink alias handling in TaskCard and inline displays (#145, #147)
  • \n
  • Fixed projects not loading correctly in task edit modal (#141)
  • \n
  • Improved cursor positioning in live preview mode
  • \n
\n

Documentation#

\n
    \n
  • Added documentation for project subtasks widget feature
  • \n
  • Updated inline task integration documentation
  • \n
  • Added configuration settings documentation
  • \n
\n","text":"New Features# Project Subtasks Widget# Add a collapsible widget that displays tasks linked to the current project note Widget appears automatically in project notes and shows all tasks that reference the rpoject Includes collapsible interface with persistent state across sessions Updates automatically when tasks are modified or deleted Can be enabled or disabled in plugin settings under \"Show project subtasks widget\" Bug Fixes# FilterBar Improvements# Fixed FilterBar not updating dynamically when tasks get new contexts or projects (#138) Fixed archived tasks' contexts and projects still appearing in filter bar (#139) Resolved FilterBar showing projects with [[]] brackets Fixed empty status list display on initial load Improved initialization reliability with better event handling Task Display# Fixed wikilink alias handling in TaskCard and inline displays (#145, #147) Fixed projects not loading correctly in task edit modal (#141) Improved cursor positioning in live preview mode Documentation# Added documentation for project subtasks widget feature Updated inline task integration documentation Added configuration settings documentation"},{"route":"/obsidian/releases/3.12.1/","title":"Release Notes - 3.12.1","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.12.1.md","namespace":"obsidian","relativePath":"releases/3.12.1.md","raw":"# Release Notes - 3.12.1\r\n\r\n## New Features\r\n\r\n### Project Subtasks Widget Enhancements\r\n\r\n- New button for task creation - Added \"New\" button to widget header for quick task creation\r\n- Auto-populated project field - New tasks automatically reference the current note as their project\r\n- Improved positioning - Widget now appears at the end of documents for better user experience\r\n- Improve visual design - Added dashed border to indicate virtual/generated content and improved styling\r\n\r\n## Bug Fixes\r\n\r\n### Timezone and Date Handling\r\n\r\n- Fixed timezone boundary issues in Agenda view date filtering (#153)\r\n- Resolved missing tasks that were scheduled 7 days ago or yesterday due to timezone drift\r\n- Enhanced date normalization in AgendaView for consistent behavior across timezones\r\n- Improved task filtering with better date handling in getTasksForDate()\r\n\r\n## UI and Display Improvements\r\n\r\n- Fixed cursor positioning to prevent cursor appearing after project subtasks widget\r\n- Resolved pre-populated projects not displaying correctly in task creation modal\r\n- Improved widget rendering with CSS-only styling approach for better performance\r\n\r\n## Settings Reorganization\r\n\r\n### New Misc Tab\r\n\r\n- Renamed \"Performance\" tab to \"Misc\" and moved to end of settings tab list\r\n- Consolidated miscellaneous features into a single organized location\r\n- Improved settings navigation by grouping related toggles together\r\n\r\n### Settings Moved to Misc Tab\r\n\r\n- Status bar toggle - Show tracked tasks in status bar\r\n- Project subtasks widget toggle - Show project subtasks widget in notes\r\n- Notes indexing toggle - Disable note indexing for performance optimization\r\n\r\n## Documentation Updates\r\n\r\n### Settings Documentation\r\n\r\n- Updated all documentation to reflect new settings organization\r\n- Created comprehensive Misc Settings documentation with detailed explanations\r\n- Removed outdated references from Advanced Settings documentation\r\n- Updated troubleshooting guides with correct setting locations\r\n\r\n## Reference Updates\r\n\r\n- Updated inline task feature documentation to reference new Misc tab location\r\n- Fixed all setting location references throughout documentation\r\n- Maintained backward compatibility information for users upgrading\r\n\r\n","aliases":["/releases/3.12.1/","/releases/3.12.1/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"project-subtasks-widget-enhancements","text":"Project Subtasks Widget Enhancements"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"timezone-and-date-handling","text":"Timezone and Date Handling"},{"level":2,"id":"ui-and-display-improvements","text":"UI and Display Improvements"},{"level":2,"id":"settings-reorganization","text":"Settings Reorganization"},{"level":3,"id":"new-misc-tab","text":"New Misc Tab"},{"level":3,"id":"settings-moved-to-misc-tab","text":"Settings Moved to Misc Tab"},{"level":2,"id":"documentation-updates","text":"Documentation Updates"},{"level":3,"id":"settings-documentation","text":"Settings Documentation"},{"level":2,"id":"reference-updates","text":"Reference Updates"}],"html":"

New Features#

\n

Project Subtasks Widget Enhancements#

\n
    \n
  • New button for task creation - Added "New" button to widget header for quick task creation
  • \n
  • Auto-populated project field - New tasks automatically reference the current note as their project
  • \n
  • Improved positioning - Widget now appears at the end of documents for better user experience
  • \n
  • Improve visual design - Added dashed border to indicate virtual/generated content and improved styling
  • \n
\n

Bug Fixes#

\n

Timezone and Date Handling#

\n
    \n
  • Fixed timezone boundary issues in Agenda view date filtering (#153)
  • \n
  • Resolved missing tasks that were scheduled 7 days ago or yesterday due to timezone drift
  • \n
  • Enhanced date normalization in AgendaView for consistent behavior across timezones
  • \n
  • Improved task filtering with better date handling in getTasksForDate()
  • \n
\n

UI and Display Improvements#

\n
    \n
  • Fixed cursor positioning to prevent cursor appearing after project subtasks widget
  • \n
  • Resolved pre-populated projects not displaying correctly in task creation modal
  • \n
  • Improved widget rendering with CSS-only styling approach for better performance
  • \n
\n

Settings Reorganization#

\n

New Misc Tab#

\n
    \n
  • Renamed "Performance" tab to "Misc" and moved to end of settings tab list
  • \n
  • Consolidated miscellaneous features into a single organized location
  • \n
  • Improved settings navigation by grouping related toggles together
  • \n
\n

Settings Moved to Misc Tab#

\n
    \n
  • Status bar toggle - Show tracked tasks in status bar
  • \n
  • Project subtasks widget toggle - Show project subtasks widget in notes
  • \n
  • Notes indexing toggle - Disable note indexing for performance optimization
  • \n
\n

Documentation Updates#

\n

Settings Documentation#

\n
    \n
  • Updated all documentation to reflect new settings organization
  • \n
  • Created comprehensive Misc Settings documentation with detailed explanations
  • \n
  • Removed outdated references from Advanced Settings documentation
  • \n
  • Updated troubleshooting guides with correct setting locations
  • \n
\n

Reference Updates#

\n
    \n
  • Updated inline task feature documentation to reference new Misc tab location
  • \n
  • Fixed all setting location references throughout documentation
  • \n
  • Maintained backward compatibility information for users upgrading
  • \n
\n","text":"New Features# Project Subtasks Widget Enhancements# New button for task creation - Added \"New\" button to widget header for quick task creation Auto-populated project field - New tasks automatically reference the current note as their project Improved positioning - Widget now appears at the end of documents for better user experience Improve visual design - Added dashed border to indicate virtual/generated content and improved styling Bug Fixes# Timezone and Date Handling# Fixed timezone boundary issues in Agenda view date filtering (#153) Resolved missing tasks that were scheduled 7 days ago or yesterday due to timezone drift Enhanced date normalization in AgendaView for consistent behavior across timezones Improved task filtering with better date handling in getTasksForDate() UI and Display Improvements# Fixed cursor positioning to prevent cursor appearing after project subtasks widget Resolved pre-populated projects not displaying correctly in task creation modal Improved widget rendering with CSS-only styling approach for better performance Settings Reorganization# New Misc Tab# Renamed \"Performance\" tab to \"Misc\" and moved to end of settings tab list Consolidated miscellaneous features into a single organized location Improved settings navigation by grouping related toggles together Settings Moved to Misc Tab# Status bar toggle - Show tracked tasks in status bar Project subtasks widget toggle - Show project subtasks widget in notes Notes indexing toggle - Disable note indexing for performance optimization Documentation Updates# Settings Documentation# Updated all documentation to reflect new settings organization Created comprehensive Misc Settings documentation with detailed explanations Removed outdated references from Advanced Settings documentation Updated troubleshooting guides with correct setting locations Reference Updates# Updated inline task feature documentation to reference new Misc tab location Fixed all setting location references throughout documentation Maintained backward compatibility information for users upgrading"},{"route":"/obsidian/releases/3.12.2/","title":"Release Notes - 3.12.2","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.12.2.md","namespace":"obsidian","relativePath":"releases/3.12.2.md","raw":"# Release Notes - 3.12.2\r\n\r\n## Bug Fixes\r\n\r\n### Calendar & Date Handling\r\n- Fixed off-by-one date bugs in completion calendar (#160)\r\n - Resolved timezone inconsistency where calendar showed one date but completion was recorded for another\r\n - Calendar rendering now uses UTC dates consistently across all components\r\n - Fixed \"Friday tasks appearing on Saturday\" issue in completion tracking\r\n\r\n### Task Management\r\n- Fixed project filters not working in agenda view (#161)\r\n - Project filtering now works consistently across all views\r\n- Fixed edit modal crash when tasks have empty project properties\r\n - Added null checks to prevent \"Cannot read properties of null\" errors\r\n - Handles null, undefined, and empty string project values gracefully\r\n- Fixed autofill suggestions not updating internal state (#159)\r\n - Context and tag suggestions now properly sync with modal internal state\r\n - Clicking suggestions now correctly updates the task data\r\n\r\n## UI & Styling\r\n- Fixed consistent styling for priorities and statuses settings tabs (#130)\r\n - Added missing BEM classes for proper grid alignment\r\n - Priority inputs now use same styling as status inputs\r\n - Fixed table column misalignment issues\r\n\r\n## Documentation\r\n\r\n- Improved README and documentation\r\n - Enhanced overview section with better flow and natural language\r\n - Added time-tracking and pomodoro feature descriptions\r\n - Fixed broken documentation links\r\n - Updated Core Features section with more accurate descriptions\r\n\r\n ## Testing\r\n\r\n- Added comprehensive tests for date handling issues\r\n - Increased test coverage for calendar and completion functionality\r\n - Added tests reproducing and verifying fixes for off-by-one date bugs\r\n","aliases":["/releases/3.12.2/","/releases/3.12.2/"],"toc":[{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"calendar-date-handling","text":"Calendar & Date Handling"},{"level":3,"id":"task-management","text":"Task Management"},{"level":2,"id":"ui-styling","text":"UI & Styling"},{"level":2,"id":"documentation","text":"Documentation"},{"level":2,"id":"testing","text":"Testing"}],"html":"

Bug Fixes#

\n

Calendar & Date Handling#

\n
    \n
  • Fixed off-by-one date bugs in completion calendar (#160)
      \n
    • Resolved timezone inconsistency where calendar showed one date but completion was recorded for another
    • \n
    • Calendar rendering now uses UTC dates consistently across all components
    • \n
    • Fixed "Friday tasks appearing on Saturday" issue in completion tracking
    • \n
    \n
  • \n
\n

Task Management#

\n
    \n
  • Fixed project filters not working in agenda view (#161)
      \n
    • Project filtering now works consistently across all views
    • \n
    \n
  • \n
  • Fixed edit modal crash when tasks have empty project properties
      \n
    • Added null checks to prevent "Cannot read properties of null" errors
    • \n
    • Handles null, undefined, and empty string project values gracefully
    • \n
    \n
  • \n
  • Fixed autofill suggestions not updating internal state (#159)
      \n
    • Context and tag suggestions now properly sync with modal internal state
    • \n
    • Clicking suggestions now correctly updates the task data
    • \n
    \n
  • \n
\n

UI & Styling#

\n
    \n
  • Fixed consistent styling for priorities and statuses settings tabs (#130)
      \n
    • Added missing BEM classes for proper grid alignment
    • \n
    • Priority inputs now use same styling as status inputs
    • \n
    • Fixed table column misalignment issues
    • \n
    \n
  • \n
\n

Documentation#

\n
    \n
  • Improved README and documentation
      \n
    • Enhanced overview section with better flow and natural language
    • \n
    • Added time-tracking and pomodoro feature descriptions
    • \n
    • Fixed broken documentation links
    • \n
    • Updated Core Features section with more accurate descriptions
    • \n
    \n
  • \n
\n

Testing#

\n
    \n
  • Added comprehensive tests for date handling issues
      \n
    • Increased test coverage for calendar and completion functionality
    • \n
    • Added tests reproducing and verifying fixes for off-by-one date bugs
    • \n
    \n
  • \n
\n","text":"Bug Fixes# Calendar & Date Handling# Fixed off-by-one date bugs in completion calendar (#160) Resolved timezone inconsistency where calendar showed one date but completion was recorded for another Calendar rendering now uses UTC dates consistently across all components Fixed \"Friday tasks appearing on Saturday\" issue in completion tracking Task Management# Fixed project filters not working in agenda view (#161) Project filtering now works consistently across all views Fixed edit modal crash when tasks have empty project properties Added null checks to prevent \"Cannot read properties of null\" errors Handles null, undefined, and empty string project values gracefully Fixed autofill suggestions not updating internal state (#159) Context and tag suggestions now properly sync with modal internal state Clicking suggestions now correctly updates the task data UI & Styling# Fixed consistent styling for priorities and statuses settings tabs (#130) Added missing BEM classes for proper grid alignment Priority inputs now use same styling as status inputs Fixed table column misalignment issues Documentation# Improved README and documentation Enhanced overview section with better flow and natural language Added time-tracking and pomodoro feature descriptions Fixed broken documentation links Updated Core Features section with more accurate descriptions Testing# Added comprehensive tests for date handling issues Increased test coverage for calendar and completion functionality Added tests reproducing and verifying fixes for off-by-one date bugs"},{"route":"/obsidian/releases/3.13.0/","title":"Release Notes - 3.13.0","description":"##Technical Changes","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.13.0.md","namespace":"obsidian","relativePath":"releases/3.13.0.md","raw":"# Release Notes - 3.13.0 \r\n\r\n## Major Changes\r\n\r\n### Filtering System Overhaul\r\n\r\n- Hierarchical Query Builder: Complete redesign of the filtering system with a query builder interface\r\n- Saved Views: Users can save, manage, and switch between custom filter configurations\r\n- FilterBar Redesign: Updated to use Obsidian components with improved styling\r\n\r\n### UI Updates\r\n\r\n- FilterBar Integration: Added to all task views (Kanban, List, Calendar, Agenda) with state management\r\n- Dropdown Improvements: Status and priority filters now use display labels\r\n- Dropdown Positioning: Fixed positioning and CSS styling issues\r\n\r\n## New Features\r\n\r\n### Natural Language Processing\r\n\r\n- Nested Tag Support: Tags with forward slashes are now supported (e.g., project/subtask)\r\n\r\n### Interface\r\n\r\n- Project Note Decorations: Updated styling and visual elements\r\n- Task Modal Styling: Refined task creation and editing interfaces\r\n\r\n## Bug Fixes\r\n\r\n### Filter System\r\n\r\n- Fixed handling of empty arrays in \"Projects is not empty\" conditions\r\n- Fixed incomplete filter conditions handling\r\n- Fixed saved views dropdown persistence when filters change\r\n- Fixed view options disappearing on refresh\r\n- Fixed view selector dropdown behavior\r\n\r\n### Testing\r\n\r\n- Fixed multiple unit and integration test failures\r\n- Fixed migration workflow test for YAML parsing errors\r\n- Expanded test coverage for task service completion\r\n\r\n### Code Quality\r\n\r\n- Removed debug console.log statements\r\n- Improved async handling and import organization\r\n- Better search functionality implementation\r\n\r\n##Technical Changes\r\n\r\n### Refactoring\r\n\r\n- Refactored FilterBar with Obsidian components\r\n- Updated filter rule definitions and UI components\r\n- Improved state management across views\r\n- Updated ViewStateManager\r\n\r\n## Development\r\n\r\n- Updated Typescript configuration\r\n- Added new Filter Utils.ts utility module\r\n- Improved code organization\r\n\r\n","aliases":["/releases/3.13.0/","/releases/3.13.0/"],"toc":[{"level":2,"id":"major-changes","text":"Major Changes"},{"level":3,"id":"filtering-system-overhaul","text":"Filtering System Overhaul"},{"level":3,"id":"ui-updates","text":"UI Updates"},{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"natural-language-processing","text":"Natural Language Processing"},{"level":3,"id":"interface","text":"Interface"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"filter-system","text":"Filter System"},{"level":3,"id":"testing","text":"Testing"},{"level":3,"id":"code-quality","text":"Code Quality"},{"level":3,"id":"refactoring","text":"Refactoring"},{"level":2,"id":"development","text":"Development"}],"html":"

Major Changes#

\n

Filtering System Overhaul#

\n
    \n
  • Hierarchical Query Builder: Complete redesign of the filtering system with a query builder interface
  • \n
  • Saved Views: Users can save, manage, and switch between custom filter configurations
  • \n
  • FilterBar Redesign: Updated to use Obsidian components with improved styling
  • \n
\n

UI Updates#

\n
    \n
  • FilterBar Integration: Added to all task views (Kanban, List, Calendar, Agenda) with state management
  • \n
  • Dropdown Improvements: Status and priority filters now use display labels
  • \n
  • Dropdown Positioning: Fixed positioning and CSS styling issues
  • \n
\n

New Features#

\n

Natural Language Processing#

\n
    \n
  • Nested Tag Support: Tags with forward slashes are now supported (e.g., project/subtask)
  • \n
\n

Interface#

\n
    \n
  • Project Note Decorations: Updated styling and visual elements
  • \n
  • Task Modal Styling: Refined task creation and editing interfaces
  • \n
\n

Bug Fixes#

\n

Filter System#

\n
    \n
  • Fixed handling of empty arrays in "Projects is not empty" conditions
  • \n
  • Fixed incomplete filter conditions handling
  • \n
  • Fixed saved views dropdown persistence when filters change
  • \n
  • Fixed view options disappearing on refresh
  • \n
  • Fixed view selector dropdown behavior
  • \n
\n

Testing#

\n
    \n
  • Fixed multiple unit and integration test failures
  • \n
  • Fixed migration workflow test for YAML parsing errors
  • \n
  • Expanded test coverage for task service completion
  • \n
\n

Code Quality#

\n
    \n
  • Removed debug console.log statements
  • \n
  • Improved async handling and import organization
  • \n
  • Better search functionality implementation
  • \n
\n

##Technical Changes

\n

Refactoring#

\n
    \n
  • Refactored FilterBar with Obsidian components
  • \n
  • Updated filter rule definitions and UI components
  • \n
  • Improved state management across views
  • \n
  • Updated ViewStateManager
  • \n
\n

Development#

\n
    \n
  • Updated Typescript configuration
  • \n
  • Added new Filter Utils.ts utility module
  • \n
  • Improved code organization
  • \n
\n","text":"Major Changes# Filtering System Overhaul# Hierarchical Query Builder: Complete redesign of the filtering system with a query builder interface Saved Views: Users can save, manage, and switch between custom filter configurations FilterBar Redesign: Updated to use Obsidian components with improved styling UI Updates# FilterBar Integration: Added to all task views (Kanban, List, Calendar, Agenda) with state management Dropdown Improvements: Status and priority filters now use display labels Dropdown Positioning: Fixed positioning and CSS styling issues New Features# Natural Language Processing# Nested Tag Support: Tags with forward slashes are now supported (e.g., project/subtask) Interface# Project Note Decorations: Updated styling and visual elements Task Modal Styling: Refined task creation and editing interfaces Bug Fixes# Filter System# Fixed handling of empty arrays in \"Projects is not empty\" conditions Fixed incomplete filter conditions handling Fixed saved views dropdown persistence when filters change Fixed view options disappearing on refresh Fixed view selector dropdown behavior Testing# Fixed multiple unit and integration test failures Fixed migration workflow test for YAML parsing errors Expanded test coverage for task service completion Code Quality# Removed debug console.log statements Improved async handling and import organization Better search functionality implementation ##Technical Changes Refactoring# Refactored FilterBar with Obsidian components Updated filter rule definitions and UI components Improved state management across views Updated ViewStateManager Development# Updated Typescript configuration Added new Filter Utils.ts utility module Improved code organization"},{"route":"/obsidian/releases/3.13.1/","title":"Release Notes - 3.13.1","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.13.1.md","namespace":"obsidian","relativePath":"releases/3.13.1.md","raw":"# Release Notes - 3.13.1 \r\n\r\n## New Features\r\n\r\n### Saved Filter Views Storage\r\n\r\n- Saved filter views now sync across devices with your vault\r\n- Views are stored in plugin data instead of browser localStorage\r\n- Automatic migration from previous storage system on first load\r\n\r\n### FilterBar Behavior\r\n\r\n- Filter panel now stays open when clicking elsewhere in the interface\r\n- Panel only closes when the filter button is clicked again\r\n- Eliminates accidental filter panel closures during normal use\r\n\r\n## Performance Improvements\r\n\r\n### Filter Operations\r\n\r\n- Adding and removing filters is now significantly faster\r\n- Reduced lag when building complex filter queries\r\n- Search input state preserved during filter modifications\r\n\r\n### Migration System\r\n\r\n- Early migration detection prevents DOM errors on first use\r\n- Better error handling during plugin initialization\r\n- Cleaner migration process for new users\r\n\r\n## Bug Fixes\r\n\r\n### First-Time User Experience\r\n\r\n- Fixed \"removeChild\" DOM errors when using filters for the first time\r\n- Resolved race conditions between migration and UI initialization\r\n- Added fallback UI states for improved reliability\r\n\r\n### FilterBar Stability\r\n\r\n- Added DOM connection checks before manipulation\r\n- Improved error boundaries in filter rendering\r\n- Better cleanup of event listeners on component destruction\r\n\r\n## Technical Changes\r\n\r\n### View State Management\r\n\r\n- Saved views migrate from localStorage to plugin data system\r\n- ViewStateManager now uses plugin settings for persistence\r\n- Enhanced migration detection and completion tracking\r\n\r\n### Error Handling\r\n\r\n- Added safety checks for DOM element manipulation\r\n- Graceful degradation when filter operations fail\r\n- Improved logging for troubleshooting migration issues\r\n\r\n","aliases":["/releases/3.13.1/","/releases/3.13.1/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"saved-filter-views-storage","text":"Saved Filter Views Storage"},{"level":3,"id":"filterbar-behavior","text":"FilterBar Behavior"},{"level":2,"id":"performance-improvements","text":"Performance Improvements"},{"level":3,"id":"filter-operations","text":"Filter Operations"},{"level":3,"id":"migration-system","text":"Migration System"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"first-time-user-experience","text":"First-Time User Experience"},{"level":3,"id":"filterbar-stability","text":"FilterBar Stability"},{"level":2,"id":"technical-changes","text":"Technical Changes"},{"level":3,"id":"view-state-management","text":"View State Management"},{"level":3,"id":"error-handling","text":"Error Handling"}],"html":"

New Features#

\n

Saved Filter Views Storage#

\n
    \n
  • Saved filter views now sync across devices with your vault
  • \n
  • Views are stored in plugin data instead of browser localStorage
  • \n
  • Automatic migration from previous storage system on first load
  • \n
\n

FilterBar Behavior#

\n
    \n
  • Filter panel now stays open when clicking elsewhere in the interface
  • \n
  • Panel only closes when the filter button is clicked again
  • \n
  • Eliminates accidental filter panel closures during normal use
  • \n
\n

Performance Improvements#

\n

Filter Operations#

\n
    \n
  • Adding and removing filters is now significantly faster
  • \n
  • Reduced lag when building complex filter queries
  • \n
  • Search input state preserved during filter modifications
  • \n
\n

Migration System#

\n
    \n
  • Early migration detection prevents DOM errors on first use
  • \n
  • Better error handling during plugin initialization
  • \n
  • Cleaner migration process for new users
  • \n
\n

Bug Fixes#

\n

First-Time User Experience#

\n
    \n
  • Fixed "removeChild" DOM errors when using filters for the first time
  • \n
  • Resolved race conditions between migration and UI initialization
  • \n
  • Added fallback UI states for improved reliability
  • \n
\n

FilterBar Stability#

\n
    \n
  • Added DOM connection checks before manipulation
  • \n
  • Improved error boundaries in filter rendering
  • \n
  • Better cleanup of event listeners on component destruction
  • \n
\n

Technical Changes#

\n

View State Management#

\n
    \n
  • Saved views migrate from localStorage to plugin data system
  • \n
  • ViewStateManager now uses plugin settings for persistence
  • \n
  • Enhanced migration detection and completion tracking
  • \n
\n

Error Handling#

\n
    \n
  • Added safety checks for DOM element manipulation
  • \n
  • Graceful degradation when filter operations fail
  • \n
  • Improved logging for troubleshooting migration issues
  • \n
\n","text":"New Features# Saved Filter Views Storage# Saved filter views now sync across devices with your vault Views are stored in plugin data instead of browser localStorage Automatic migration from previous storage system on first load FilterBar Behavior# Filter panel now stays open when clicking elsewhere in the interface Panel only closes when the filter button is clicked again Eliminates accidental filter panel closures during normal use Performance Improvements# Filter Operations# Adding and removing filters is now significantly faster Reduced lag when building complex filter queries Search input state preserved during filter modifications Migration System# Early migration detection prevents DOM errors on first use Better error handling during plugin initialization Cleaner migration process for new users Bug Fixes# First-Time User Experience# Fixed \"removeChild\" DOM errors when using filters for the first time Resolved race conditions between migration and UI initialization Added fallback UI states for improved reliability FilterBar Stability# Added DOM connection checks before manipulation Improved error boundaries in filter rendering Better cleanup of event listeners on component destruction Technical Changes# View State Management# Saved views migrate from localStorage to plugin data system ViewStateManager now uses plugin settings for persistence Enhanced migration detection and completion tracking Error Handling# Added safety checks for DOM element manipulation Graceful degradation when filter operations fail Improved logging for troubleshooting migration issues"},{"route":"/obsidian/releases/3.13.2/","title":"Release Notes - 3.13.2","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.13.2.md","namespace":"obsidian","relativePath":"releases/3.13.2.md","raw":"# Release Notes - 3.13.2\r\n\r\n## Performance Improvements\r\n\r\n### FilterBar and Saved Views\r\n- Fixed performance issue where adding new filter conditions would unnecessarily re-evaluate all existing filters\r\n- Added \"Select...\" placeholder option for new filter conditions to prevent premature filtering\r\n- Eliminated unnecessary cache re-indexing when saving or deleting saved views\r\n- Made settings system smarter to only trigger cache updates when indexing-related settings actually change\r\n\r\n### Filter Processing\r\n- Implemented index-backed filtering that processes significantly fewer tasks for filtered views\r\n- Added intelligent query result caching with automatic expiration to eliminate redundant operations\r\n- Improved candidate selection using existing status, date, and overdue task indexes\r\n- Enhanced set intersection logic for multiple AND conditions to further reduce processing\r\n\r\n## Bug Fixes\r\n\r\n### Filter Logic\r\n- Fixed critical bug where index optimization incorrectly excluded valid results for OR queries containing indexed conditions\r\n- Added detection logic to prevent unsafe optimizations when indexed conditions are part of OR groups\r\n- Improved query structure analysis to ensure filter correctness\r\n\r\n### Saved Views\r\n- Fixed issue where modifying one saved view could affect others due to shared object references\r\n- Added proper deep cloning of FilterQuery objects throughout the ViewStateManager\r\n- Ensured saved views remain independent when modified\r\n\r\n## Technical Details\r\n\r\n### Index Optimization Safety\r\n- Index optimizations now only apply when provably safe (AND relationships between indexed conditions)\r\n- Added recursive query analysis to detect OR groups containing indexed conditions\r\n- Maintains filter correctness while providing performance benefits where safe\r\n\r\n### Cache Management\r\n- Cache-related settings tracking: taskTag, excludedFolders, disableNoteIndexing, storeTitleInFilename, fieldMapping\r\n- Query result caching with 30-second auto-expiration and immediate invalidation on data changes\r\n- Debug logging available for performance monitoring\r\n\r\n## Performance Impact\r\n\r\n- Filter building is now responsive with no lag when adding conditions\r\n- Saved view operations are instant with no unnecessary re-indexing\r\n- Repeated filter operations are nearly instant due to intelligent caching\r\n- Significant memory usage reduction for large vaults\r\n\r\n","aliases":["/releases/3.13.2/","/releases/3.13.2/"],"toc":[{"level":2,"id":"performance-improvements","text":"Performance Improvements"},{"level":3,"id":"filterbar-and-saved-views","text":"FilterBar and Saved Views"},{"level":3,"id":"filter-processing","text":"Filter Processing"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"filter-logic","text":"Filter Logic"},{"level":3,"id":"saved-views","text":"Saved Views"},{"level":2,"id":"technical-details","text":"Technical Details"},{"level":3,"id":"index-optimization-safety","text":"Index Optimization Safety"},{"level":3,"id":"cache-management","text":"Cache Management"},{"level":2,"id":"performance-impact","text":"Performance Impact"}],"html":"

Performance Improvements#

\n

FilterBar and Saved Views#

\n
    \n
  • Fixed performance issue where adding new filter conditions would unnecessarily re-evaluate all existing filters
  • \n
  • Added "Select..." placeholder option for new filter conditions to prevent premature filtering
  • \n
  • Eliminated unnecessary cache re-indexing when saving or deleting saved views
  • \n
  • Made settings system smarter to only trigger cache updates when indexing-related settings actually change
  • \n
\n

Filter Processing#

\n
    \n
  • Implemented index-backed filtering that processes significantly fewer tasks for filtered views
  • \n
  • Added intelligent query result caching with automatic expiration to eliminate redundant operations
  • \n
  • Improved candidate selection using existing status, date, and overdue task indexes
  • \n
  • Enhanced set intersection logic for multiple AND conditions to further reduce processing
  • \n
\n

Bug Fixes#

\n

Filter Logic#

\n
    \n
  • Fixed critical bug where index optimization incorrectly excluded valid results for OR queries containing indexed conditions
  • \n
  • Added detection logic to prevent unsafe optimizations when indexed conditions are part of OR groups
  • \n
  • Improved query structure analysis to ensure filter correctness
  • \n
\n

Saved Views#

\n
    \n
  • Fixed issue where modifying one saved view could affect others due to shared object references
  • \n
  • Added proper deep cloning of FilterQuery objects throughout the ViewStateManager
  • \n
  • Ensured saved views remain independent when modified
  • \n
\n

Technical Details#

\n

Index Optimization Safety#

\n
    \n
  • Index optimizations now only apply when provably safe (AND relationships between indexed conditions)
  • \n
  • Added recursive query analysis to detect OR groups containing indexed conditions
  • \n
  • Maintains filter correctness while providing performance benefits where safe
  • \n
\n

Cache Management#

\n
    \n
  • Cache-related settings tracking: taskTag, excludedFolders, disableNoteIndexing, storeTitleInFilename, fieldMapping
  • \n
  • Query result caching with 30-second auto-expiration and immediate invalidation on data changes
  • \n
  • Debug logging available for performance monitoring
  • \n
\n

Performance Impact#

\n
    \n
  • Filter building is now responsive with no lag when adding conditions
  • \n
  • Saved view operations are instant with no unnecessary re-indexing
  • \n
  • Repeated filter operations are nearly instant due to intelligent caching
  • \n
  • Significant memory usage reduction for large vaults
  • \n
\n","text":"Performance Improvements# FilterBar and Saved Views# Fixed performance issue where adding new filter conditions would unnecessarily re-evaluate all existing filters Added \"Select...\" placeholder option for new filter conditions to prevent premature filtering Eliminated unnecessary cache re-indexing when saving or deleting saved views Made settings system smarter to only trigger cache updates when indexing-related settings actually change Filter Processing# Implemented index-backed filtering that processes significantly fewer tasks for filtered views Added intelligent query result caching with automatic expiration to eliminate redundant operations Improved candidate selection using existing status, date, and overdue task indexes Enhanced set intersection logic for multiple AND conditions to further reduce processing Bug Fixes# Filter Logic# Fixed critical bug where index optimization incorrectly excluded valid results for OR queries containing indexed conditions Added detection logic to prevent unsafe optimizations when indexed conditions are part of OR groups Improved query structure analysis to ensure filter correctness Saved Views# Fixed issue where modifying one saved view could affect others due to shared object references Added proper deep cloning of FilterQuery objects throughout the ViewStateManager Ensured saved views remain independent when modified Technical Details# Index Optimization Safety# Index optimizations now only apply when provably safe (AND relationships between indexed conditions) Added recursive query analysis to detect OR groups containing indexed conditions Maintains filter correctness while providing performance benefits where safe Cache Management# Cache-related settings tracking: taskTag, excludedFolders, disableNoteIndexing, storeTitleInFilename, fieldMapping Query result caching with 30-second auto-expiration and immediate invalidation on data changes Debug logging available for performance monitoring Performance Impact# Filter building is now responsive with no lag when adding conditions Saved view operations are instant with no unnecessary re-indexing Repeated filter operations are nearly instant due to intelligent caching Significant memory usage reduction for large vaults"},{"route":"/obsidian/releases/3.13.3/","title":"Release Notes - 3.13.3","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.13.3.md","namespace":"obsidian","relativePath":"releases/3.13.3.md","raw":"# Release Notes - 3.13.3\r\n\r\n## Bug Fixes\r\n\r\n### Fixed recurring task completion date recording\r\n- Resolved issue where \"mark completed for this date\" context menu option recorded completion for the wrong date\r\n- Fixed timezone inconsistency between completion date storage and checking logic\r\n- Recurring tasks now properly track completion status per calendar date\r\n\r\n### Improved recurring task filtering\r\n- Fixed \"Is completed\" filter condition to respect per-date completion status for recurring tasks\r\n- Filter results now accurately reflect whether recurring tasks are completed for specific dates\r\n\r\n## Enhancements\r\n\r\n### AgendaView improvements\r\n- Restored Today button with improved header layout\r\n- Reorganized header into three sections: navigation controls, period title, and actions\r\n- Fixed recurring task display to show tasks on their actual recurrence dates rather than just scheduled dates\r\n- Removed keyboard navigation shortcuts (left/right arrows)\r\n\r\n### Interface updates\r\n- Enhanced AgendaView header styling with better spacing and visual hierarchy\r\n- Added responsive design for mobile layouts\r\n- Improved button styling with proper hover and focus states\r\n\r\n## Technical Changes\r\n\r\n- Updated TaskService to use consistent local timezone formatting for completion dates\r\n- Enhanced FilterService to properly evaluate recurring task completion status\r\n- Improved AgendaView task fetching to use FilterService.getTasksForDate() for better recurrence handling\r\n\r\n## Testing\r\n\r\n- Added comprehensive test coverage for timezone handling and date formatting consistency\r\n- Added tests to verify recurring task completion behavior across different scenarios\r\n\r\n\r\n","aliases":["/releases/3.13.3/","/releases/3.13.3/"],"toc":[{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"fixed-recurring-task-completion-date-recording","text":"Fixed recurring task completion date recording"},{"level":3,"id":"improved-recurring-task-filtering","text":"Improved recurring task filtering"},{"level":2,"id":"enhancements","text":"Enhancements"},{"level":3,"id":"agendaview-improvements","text":"AgendaView improvements"},{"level":3,"id":"interface-updates","text":"Interface updates"},{"level":2,"id":"technical-changes","text":"Technical Changes"},{"level":2,"id":"testing","text":"Testing"}],"html":"

Bug Fixes#

\n

Fixed recurring task completion date recording#

\n
    \n
  • Resolved issue where "mark completed for this date" context menu option recorded completion for the wrong date
  • \n
  • Fixed timezone inconsistency between completion date storage and checking logic
  • \n
  • Recurring tasks now properly track completion status per calendar date
  • \n
\n

Improved recurring task filtering#

\n
    \n
  • Fixed "Is completed" filter condition to respect per-date completion status for recurring tasks
  • \n
  • Filter results now accurately reflect whether recurring tasks are completed for specific dates
  • \n
\n

Enhancements#

\n

AgendaView improvements#

\n
    \n
  • Restored Today button with improved header layout
  • \n
  • Reorganized header into three sections: navigation controls, period title, and actions
  • \n
  • Fixed recurring task display to show tasks on their actual recurrence dates rather than just scheduled dates
  • \n
  • Removed keyboard navigation shortcuts (left/right arrows)
  • \n
\n

Interface updates#

\n
    \n
  • Enhanced AgendaView header styling with better spacing and visual hierarchy
  • \n
  • Added responsive design for mobile layouts
  • \n
  • Improved button styling with proper hover and focus states
  • \n
\n

Technical Changes#

\n
    \n
  • Updated TaskService to use consistent local timezone formatting for completion dates
  • \n
  • Enhanced FilterService to properly evaluate recurring task completion status
  • \n
  • Improved AgendaView task fetching to use FilterService.getTasksForDate() for better recurrence handling
  • \n
\n

Testing#

\n
    \n
  • Added comprehensive test coverage for timezone handling and date formatting consistency
  • \n
  • Added tests to verify recurring task completion behavior across different scenarios
  • \n
\n","text":"Bug Fixes# Fixed recurring task completion date recording# Resolved issue where \"mark completed for this date\" context menu option recorded completion for the wrong date Fixed timezone inconsistency between completion date storage and checking logic Recurring tasks now properly track completion status per calendar date Improved recurring task filtering# Fixed \"Is completed\" filter condition to respect per-date completion status for recurring tasks Filter results now accurately reflect whether recurring tasks are completed for specific dates Enhancements# AgendaView improvements# Restored Today button with improved header layout Reorganized header into three sections: navigation controls, period title, and actions Fixed recurring task display to show tasks on their actual recurrence dates rather than just scheduled dates Removed keyboard navigation shortcuts (left/right arrows) Interface updates# Enhanced AgendaView header styling with better spacing and visual hierarchy Added responsive design for mobile layouts Improved button styling with proper hover and focus states Technical Changes# Updated TaskService to use consistent local timezone formatting for completion dates Enhanced FilterService to properly evaluate recurring task completion status Improved AgendaView task fetching to use FilterService.getTasksForDate() for better recurrence handling Testing# Added comprehensive test coverage for timezone handling and date formatting consistency Added tests to verify recurring task completion behavior across different scenarios"},{"route":"/obsidian/releases/3.13.4/","title":"Release Notes - 3.13.4","description":"Thanks to @cathywu, @Crunchnuggetz, @Poly-0000, @jpmoo and finally @bcohen44 for reporting the FilterBar crashes that led to identifying these migration issues.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.13.4.md","namespace":"obsidian","relativePath":"releases/3.13.4.md","raw":"# Release Notes - 3.13.4\r\n\r\n## Bug Fixes\r\n\r\n### FilterBar Migration Issues\r\n- Fixed critical TypeError crashes when upgrading from versions prior to 3.13.0\r\n- Resolved `Cannot read properties of undefined (reading 'forEach')` and `Cannot read properties of undefined (reading 'find')` errors in FilterBar rendering\r\n- Added detection for old FilterQuery format and automatic replacement with fresh defaults\r\n- Users upgrading from older versions now get clean filter states instead of broken data structures\r\n- Preserved valid sort and grouping settings when replacing incompatible filter data\r\n- Added error boundaries with console warnings for better debugging\r\n\r\n*Thanks to @cathywu, @Crunchnuggetz, @Poly-0000, @jpmoo and finally [@bcohen44](https://github.com/callumalpass/tasknotes/issues/170#issuecomment-3066981483) for reporting the FilterBar crashes that led to identifying these migration issues.*\r\n\r\n## Features\r\n\r\n### Calendar View Improvements\r\n- Added ICS refresh button directly in the Advanced Calendar view toolbar\r\n- ICS calendar subscriptions can now be refreshed without opening settings\r\n- Button integrates with existing ICS subscription service and triggers immediate calendar re-render\r\n- Improved ICS settings layout with horizontal button arrangement\r\n- Enhanced calendar styling with proper hover states and removed unnecessary CSS overrides\r\n- Extended today highlight disable to timegrid columns for visual consistency\r\n\r\n## Notes\r\n\r\nThis release focuses on stability improvements for users upgrading from older versions. The FilterBar migration fixes ensure that users moving from pre-3.13.0 versions will have a smooth experience with the new filtering system introduced in 3.13.0.\r\n\r\nThe ICS refresh button provides better user experience by allowing calendar data to be updated directly from the calendar view without navigating to settings.\r\n","aliases":["/releases/3.13.4/","/releases/3.13.4/"],"toc":[{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"filterbar-migration-issues","text":"FilterBar Migration Issues"},{"level":2,"id":"features","text":"Features"},{"level":3,"id":"calendar-view-improvements","text":"Calendar View Improvements"},{"level":2,"id":"notes","text":"Notes"}],"html":"

Bug Fixes#

\n

FilterBar Migration Issues#

\n
    \n
  • Fixed critical TypeError crashes when upgrading from versions prior to 3.13.0
  • \n
  • Resolved Cannot read properties of undefined (reading 'forEach') and Cannot read properties of undefined (reading 'find') errors in FilterBar rendering
  • \n
  • Added detection for old FilterQuery format and automatic replacement with fresh defaults
  • \n
  • Users upgrading from older versions now get clean filter states instead of broken data structures
  • \n
  • Preserved valid sort and grouping settings when replacing incompatible filter data
  • \n
  • Added error boundaries with console warnings for better debugging
  • \n
\n

Thanks to @cathywu, @Crunchnuggetz, @Poly-0000, @jpmoo and finally @bcohen44 for reporting the FilterBar crashes that led to identifying these migration issues.

\n

Features#

\n

Calendar View Improvements#

\n
    \n
  • Added ICS refresh button directly in the Advanced Calendar view toolbar
  • \n
  • ICS calendar subscriptions can now be refreshed without opening settings
  • \n
  • Button integrates with existing ICS subscription service and triggers immediate calendar re-render
  • \n
  • Improved ICS settings layout with horizontal button arrangement
  • \n
  • Enhanced calendar styling with proper hover states and removed unnecessary CSS overrides
  • \n
  • Extended today highlight disable to timegrid columns for visual consistency
  • \n
\n

Notes#

\n

This release focuses on stability improvements for users upgrading from older versions. The FilterBar migration fixes ensure that users moving from pre-3.13.0 versions will have a smooth experience with the new filtering system introduced in 3.13.0.

\n

The ICS refresh button provides better user experience by allowing calendar data to be updated directly from the calendar view without navigating to settings.

\n","text":"Bug Fixes# FilterBar Migration Issues# Fixed critical TypeError crashes when upgrading from versions prior to 3.13.0 Resolved Cannot read properties of undefined (reading 'forEach') and Cannot read properties of undefined (reading 'find') errors in FilterBar rendering Added detection for old FilterQuery format and automatic replacement with fresh defaults Users upgrading from older versions now get clean filter states instead of broken data structures Preserved valid sort and grouping settings when replacing incompatible filter data Added error boundaries with console warnings for better debugging Thanks to @cathywu, @Crunchnuggetz, @Poly-0000, @jpmoo and finally @bcohen44 for reporting the FilterBar crashes that led to identifying these migration issues. Features# Calendar View Improvements# Added ICS refresh button directly in the Advanced Calendar view toolbar ICS calendar subscriptions can now be refreshed without opening settings Button integrates with existing ICS subscription service and triggers immediate calendar re-render Improved ICS settings layout with horizontal button arrangement Enhanced calendar styling with proper hover states and removed unnecessary CSS overrides Extended today highlight disable to timegrid columns for visual consistency Notes# This release focuses on stability improvements for users upgrading from older versions. The FilterBar migration fixes ensure that users moving from pre-3.13.0 versions will have a smooth experience with the new filtering system introduced in 3.13.0. The ICS refresh button provides better user experience by allowing calendar data to be updated directly from the calendar view without navigating to settings."},{"route":"/obsidian/releases/3.14.0/","title":"Release 3.14.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.14.0.md","namespace":"obsidian","relativePath":"releases/3.14.0.md","raw":"# Release 3.14.0\r\n\r\n## New Features\r\n\r\n### Project Management Enhancements\r\n\r\n- Project Indicator Icons: TaskCard now displays visual indicators when tasks are used as projects [#191] - Thanks to @Poly-0000 for the suggestion\r\n- Project Filtering: Added comprehensive project filtering functionality to the main plugin [#191]\r\n- Create Subtask Option: Added \"Create subtask\" option to task card context menu for improved project workflow [#192] - Thanks to @Poly-0000 for the feature request\r\n- Project Detection: Enhanced ProjectSubtasksService with isTaskUsedAsProject method for better project identification [#191]\r\n\r\n### User Interface Improvements\r\n\r\n- Drag-and-Drop Saved Views: Implemented drag-and-drop reordering for saved views to improve workflow customization [#203] - Thanks to @jpmoo for the suggestion\r\n- Project Styling: Added CSS styling for project indicator icons to improve visual hierarchy [#191]\r\n- Created Date Sorting: Added 'Created Date' as a sort key option for better task organization [#188] - Thanks to @bl4z3ng41n for the PR\r\n\r\n## Bug Fixes\r\n\r\n### Calendar and Recurring Tasks\r\n\r\n- Calendar Resize Support: Fixed duration updates for recurring tasks via calendar resize operations\r\n- All-Day Handling: Improved recurring task all-day handling in calendar view [#201] - Thanks to @anomatomato and @bespokecomp for reporting\r\n\r\n### Settings and State Management\r\n\r\n- Pomodoro Session Persistence: Fixed issue where pomodoro sessions were being cleared when changing settings [#196] - Thanks to @anomatomato for the bug report\r\n\r\n### Technical Changes\r\n\r\n### Performance and Stability\r\n\r\n- Enhanced cache management and event handling for project-related functionality\r\n- Improved error handling in project subtask operations\r\n- Optimized project detection algorithms for better performance\r\n\r\n### Code Organization\r\n\r\n- Refactored project-related services for better modularity\r\n- Enhanced TypeScript type definitions for project functionality\r\n- Improved service initialization and cleanup processes\r\n\r\n## Documentation\r\n\r\n- Updated README with new project assets and feature documentation\r\n","aliases":["/releases/3.14.0/","/releases/3.14.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"project-management-enhancements","text":"Project Management Enhancements"},{"level":3,"id":"user-interface-improvements","text":"User Interface Improvements"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"calendar-and-recurring-tasks","text":"Calendar and Recurring Tasks"},{"level":3,"id":"settings-and-state-management","text":"Settings and State Management"},{"level":3,"id":"technical-changes","text":"Technical Changes"},{"level":3,"id":"performance-and-stability","text":"Performance and Stability"},{"level":3,"id":"code-organization","text":"Code Organization"},{"level":2,"id":"documentation","text":"Documentation"}],"html":"

New Features#

\n

Project Management Enhancements#

\n
    \n
  • Project Indicator Icons: TaskCard now displays visual indicators when tasks are used as projects [#191] - Thanks to @Poly-0000 for the suggestion
  • \n
  • Project Filtering: Added comprehensive project filtering functionality to the main plugin [#191]
  • \n
  • Create Subtask Option: Added "Create subtask" option to task card context menu for improved project workflow [#192] - Thanks to @Poly-0000 for the feature request
  • \n
  • Project Detection: Enhanced ProjectSubtasksService with isTaskUsedAsProject method for better project identification [#191]
  • \n
\n

User Interface Improvements#

\n
    \n
  • Drag-and-Drop Saved Views: Implemented drag-and-drop reordering for saved views to improve workflow customization [#203] - Thanks to @jpmoo for the suggestion
  • \n
  • Project Styling: Added CSS styling for project indicator icons to improve visual hierarchy [#191]
  • \n
  • Created Date Sorting: Added 'Created Date' as a sort key option for better task organization [#188] - Thanks to @bl4z3ng41n for the PR
  • \n
\n

Bug Fixes#

\n

Calendar and Recurring Tasks#

\n
    \n
  • Calendar Resize Support: Fixed duration updates for recurring tasks via calendar resize operations
  • \n
  • All-Day Handling: Improved recurring task all-day handling in calendar view [#201] - Thanks to @anomatomato and @bespokecomp for reporting
  • \n
\n

Settings and State Management#

\n
    \n
  • Pomodoro Session Persistence: Fixed issue where pomodoro sessions were being cleared when changing settings [#196] - Thanks to @anomatomato for the bug report
  • \n
\n

Technical Changes#

\n

Performance and Stability#

\n
    \n
  • Enhanced cache management and event handling for project-related functionality
  • \n
  • Improved error handling in project subtask operations
  • \n
  • Optimized project detection algorithms for better performance
  • \n
\n

Code Organization#

\n
    \n
  • Refactored project-related services for better modularity
  • \n
  • Enhanced TypeScript type definitions for project functionality
  • \n
  • Improved service initialization and cleanup processes
  • \n
\n

Documentation#

\n
    \n
  • Updated README with new project assets and feature documentation
  • \n
\n","text":"New Features# Project Management Enhancements# Project Indicator Icons: TaskCard now displays visual indicators when tasks are used as projects [#191] - Thanks to @Poly-0000 for the suggestion Project Filtering: Added comprehensive project filtering functionality to the main plugin [#191] Create Subtask Option: Added \"Create subtask\" option to task card context menu for improved project workflow [#192] - Thanks to @Poly-0000 for the feature request Project Detection: Enhanced ProjectSubtasksService with isTaskUsedAsProject method for better project identification [#191] User Interface Improvements# Drag-and-Drop Saved Views: Implemented drag-and-drop reordering for saved views to improve workflow customization [#203] - Thanks to @jpmoo for the suggestion Project Styling: Added CSS styling for project indicator icons to improve visual hierarchy [#191] Created Date Sorting: Added 'Created Date' as a sort key option for better task organization [#188] - Thanks to @bl4z3ng41n for the PR Bug Fixes# Calendar and Recurring Tasks# Calendar Resize Support: Fixed duration updates for recurring tasks via calendar resize operations All-Day Handling: Improved recurring task all-day handling in calendar view [#201] - Thanks to @anomatomato and @bespokecomp for reporting Settings and State Management# Pomodoro Session Persistence: Fixed issue where pomodoro sessions were being cleared when changing settings [#196] - Thanks to @anomatomato for the bug report Technical Changes# Performance and Stability# Enhanced cache management and event handling for project-related functionality Improved error handling in project subtask operations Optimized project detection algorithms for better performance Code Organization# Refactored project-related services for better modularity Enhanced TypeScript type definitions for project functionality Improved service initialization and cleanup processes Documentation# Updated README with new project assets and feature documentation"},{"route":"/obsidian/releases/3.15.0/","title":"Release 3.15.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.15.0.md","namespace":"obsidian","relativePath":"releases/3.15.0.md","raw":"# Release 3.15.0\n\n## New Features\n\n### NLP Input Enhancements\n\n- Auto-suggestions: Added autocomplete functionality for tags and contexts in NLP input [#131] - Thanks to @Poly-0000 for the suggestion\n- Project Auto-suggestions: Enhanced project auto-suggestions with rich display and field mapper integration\n- Context and Tag Suggestions: Implemented auto-suggestion system to prevent typos and improve consistency [#131]\n\n### Calendar Integration\n\n- ICS Event Integration: Added comprehensive ICS calendar event support with content creation capabilities [#122, #220] - Thanks to @donjjones and @Crunchnuggetz for the feature requests\n- ICS Event Creation: Integrated ICS events into field mapping and type system for note creation [#122, #220]\n- ICS Settings: Added ICS integration settings to calendar tab\n- Calendar Hover Previews: Implemented hover preview functionality for advanced calendar - Thanks @nightroman for noticing this\n- Time Entry Interaction: Added time entry interaction functionality to advanced calendar\n\n### Time Management\n\n- Auto-stop Tracking: Added automatic time tracking termination when tasks are completed - Thanks to @cathywu for the suggestion [#184]\n- Total Tracked Time: Enhanced edit modal to display total tracked time information [#181] - Thanks to @bcohen44 for the feature request\n- Pomodoro View: Added task card display and improved controls to pomodoro view [#184]\n- Timeblock Management: Enhanced TimeblockInfoModal with editing and deletion capabilities [#74] - Thanks to @bepolymathe for the suggestion\n\n### User Interface Improvements\n\n- Fuzzy Note Pickers: Enhanced note pickers with title and alias support [#192] - Thanks to @Poly-0000 for the feedback\n- Persistent Column Ordering: Added persistent column ordering to kanban board [#61] - Thanks to @slepsl for the suggestion\n- Click-outside Support: Added click-outside and keyboard support to filter bar [#227] - Thanks to @cstelmach for the UX improvement request\n- UI Polish: Removed unnecessary borders, shadows and transitions from various UI elements\n\n## Bug Fixes\n\n### Task Management\n\n- Nested Tags: Fixed support for nested tags in FilterBar\n- TypeError Resolution: Resolved TypeError when calling includes on non-array values\n\n### Calendar Integration\n\n- Default Time Estimate: Fixed calendar click-to-add operations to respect default time estimate setting [#233] - Thanks to @nightroman for the bug report\n- Time Slot Duration: Improved click detection in calendar to use time slot duration setting [#233]\n\n## Documentation\n\n- Auto-suggestion Documentation: Added comprehensive documentation for auto-suggestion functionality\n- ICS Integration Guide: Created detailed ICS calendar integration documentation\n- Release Notes: Added comprehensive release notes documentation with links to all versions\n- Inline Task Widget: Added screenshots and documentation for inline task widgets\n\n## Technical Changes\n\n### Code Organization\n\n- Enhanced service architecture for ICS integration\n- Improved field mapping system for calendar events\n- Optimized auto-suggestion algorithms\n- Enhanced type definitions for new functionality\n\n### Performance\n\n- Improved rendering performance for pomodoro view\n- Optimized calendar event handling\n- Enhanced note picker search capabilities\n","aliases":["/releases/3.15.0/","/releases/3.15.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"nlp-input-enhancements","text":"NLP Input Enhancements"},{"level":3,"id":"calendar-integration","text":"Calendar Integration"},{"level":3,"id":"time-management","text":"Time Management"},{"level":3,"id":"user-interface-improvements","text":"User Interface Improvements"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"task-management","text":"Task Management"},{"level":3,"id":"calendar-integration-2","text":"Calendar Integration"},{"level":2,"id":"documentation","text":"Documentation"},{"level":2,"id":"technical-changes","text":"Technical Changes"},{"level":3,"id":"code-organization","text":"Code Organization"},{"level":3,"id":"performance","text":"Performance"}],"html":"

New Features#

\n

NLP Input Enhancements#

\n
    \n
  • Auto-suggestions: Added autocomplete functionality for tags and contexts in NLP input [#131] - Thanks to @Poly-0000 for the suggestion
  • \n
  • Project Auto-suggestions: Enhanced project auto-suggestions with rich display and field mapper integration
  • \n
  • Context and Tag Suggestions: Implemented auto-suggestion system to prevent typos and improve consistency [#131]
  • \n
\n

Calendar Integration#

\n
    \n
  • ICS Event Integration: Added comprehensive ICS calendar event support with content creation capabilities [#122, #220] - Thanks to @donjjones and @Crunchnuggetz for the feature requests
  • \n
  • ICS Event Creation: Integrated ICS events into field mapping and type system for note creation [#122, #220]
  • \n
  • ICS Settings: Added ICS integration settings to calendar tab
  • \n
  • Calendar Hover Previews: Implemented hover preview functionality for advanced calendar - Thanks @nightroman for noticing this
  • \n
  • Time Entry Interaction: Added time entry interaction functionality to advanced calendar
  • \n
\n

Time Management#

\n
    \n
  • Auto-stop Tracking: Added automatic time tracking termination when tasks are completed - Thanks to @cathywu for the suggestion [#184]
  • \n
  • Total Tracked Time: Enhanced edit modal to display total tracked time information [#181] - Thanks to @bcohen44 for the feature request
  • \n
  • Pomodoro View: Added task card display and improved controls to pomodoro view [#184]
  • \n
  • Timeblock Management: Enhanced TimeblockInfoModal with editing and deletion capabilities [#74] - Thanks to @bepolymathe for the suggestion
  • \n
\n

User Interface Improvements#

\n
    \n
  • Fuzzy Note Pickers: Enhanced note pickers with title and alias support [#192] - Thanks to @Poly-0000 for the feedback
  • \n
  • Persistent Column Ordering: Added persistent column ordering to kanban board [#61] - Thanks to @slepsl for the suggestion
  • \n
  • Click-outside Support: Added click-outside and keyboard support to filter bar [#227] - Thanks to @cstelmach for the UX improvement request
  • \n
  • UI Polish: Removed unnecessary borders, shadows and transitions from various UI elements
  • \n
\n

Bug Fixes#

\n

Task Management#

\n
    \n
  • Nested Tags: Fixed support for nested tags in FilterBar
  • \n
  • TypeError Resolution: Resolved TypeError when calling includes on non-array values
  • \n
\n

Calendar Integration#

\n
    \n
  • Default Time Estimate: Fixed calendar click-to-add operations to respect default time estimate setting [#233] - Thanks to @nightroman for the bug report
  • \n
  • Time Slot Duration: Improved click detection in calendar to use time slot duration setting [#233]
  • \n
\n

Documentation#

\n
    \n
  • Auto-suggestion Documentation: Added comprehensive documentation for auto-suggestion functionality
  • \n
  • ICS Integration Guide: Created detailed ICS calendar integration documentation
  • \n
  • Release Notes: Added comprehensive release notes documentation with links to all versions
  • \n
  • Inline Task Widget: Added screenshots and documentation for inline task widgets
  • \n
\n

Technical Changes#

\n

Code Organization#

\n
    \n
  • Enhanced service architecture for ICS integration
  • \n
  • Improved field mapping system for calendar events
  • \n
  • Optimized auto-suggestion algorithms
  • \n
  • Enhanced type definitions for new functionality
  • \n
\n

Performance#

\n
    \n
  • Improved rendering performance for pomodoro view
  • \n
  • Optimized calendar event handling
  • \n
  • Enhanced note picker search capabilities
  • \n
\n","text":"New Features# NLP Input Enhancements# Auto-suggestions: Added autocomplete functionality for tags and contexts in NLP input [#131] - Thanks to @Poly-0000 for the suggestion Project Auto-suggestions: Enhanced project auto-suggestions with rich display and field mapper integration Context and Tag Suggestions: Implemented auto-suggestion system to prevent typos and improve consistency [#131] Calendar Integration# ICS Event Integration: Added comprehensive ICS calendar event support with content creation capabilities [#122, #220] - Thanks to @donjjones and @Crunchnuggetz for the feature requests ICS Event Creation: Integrated ICS events into field mapping and type system for note creation [#122, #220] ICS Settings: Added ICS integration settings to calendar tab Calendar Hover Previews: Implemented hover preview functionality for advanced calendar - Thanks @nightroman for noticing this Time Entry Interaction: Added time entry interaction functionality to advanced calendar Time Management# Auto-stop Tracking: Added automatic time tracking termination when tasks are completed - Thanks to @cathywu for the suggestion [#184] Total Tracked Time: Enhanced edit modal to display total tracked time information [#181] - Thanks to @bcohen44 for the feature request Pomodoro View: Added task card display and improved controls to pomodoro view [#184] Timeblock Management: Enhanced TimeblockInfoModal with editing and deletion capabilities [#74] - Thanks to @bepolymathe for the suggestion User Interface Improvements# Fuzzy Note Pickers: Enhanced note pickers with title and alias support [#192] - Thanks to @Poly-0000 for the feedback Persistent Column Ordering: Added persistent column ordering to kanban board [#61] - Thanks to @slepsl for the suggestion Click-outside Support: Added click-outside and keyboard support to filter bar [#227] - Thanks to @cstelmach for the UX improvement request UI Polish: Removed unnecessary borders, shadows and transitions from various UI elements Bug Fixes# Task Management# Nested Tags: Fixed support for nested tags in FilterBar TypeError Resolution: Resolved TypeError when calling includes on non-array values Calendar Integration# Default Time Estimate: Fixed calendar click-to-add operations to respect default time estimate setting [#233] - Thanks to @nightroman for the bug report Time Slot Duration: Improved click detection in calendar to use time slot duration setting [#233] Documentation# Auto-suggestion Documentation: Added comprehensive documentation for auto-suggestion functionality ICS Integration Guide: Created detailed ICS calendar integration documentation Release Notes: Added comprehensive release notes documentation with links to all versions Inline Task Widget: Added screenshots and documentation for inline task widgets Technical Changes# Code Organization# Enhanced service architecture for ICS integration Improved field mapping system for calendar events Optimized auto-suggestion algorithms Enhanced type definitions for new functionality Performance# Improved rendering performance for pomodoro view Optimized calendar event handling Enhanced note picker search capabilities"},{"route":"/obsidian/releases/3.15.1/","title":"Release 3.15.1","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.15.1.md","namespace":"obsidian","relativePath":"releases/3.15.1.md","raw":"# Release 3.15.1\n\n## New Features\n\n### Kanban Board Enhancements\n\n- Show Empty Status Columns: Kanban board now displays empty columns for all configured statuses, providing better visual structure and workflow clarity\n- Enhanced Task Grouping: Introduced GetGroupedTasksOptions interface for improved task grouping functionality with target date support and group pre-population [#236] - Thanks to @srcnDev for the implementation\n\n### Calendar Improvements\n\n- All-Day Event Styling: Added line-through styling for completed all-day events in the Advanced Calendar view [#252, #254] - Thanks to @anomatomato for reporting the issue and submitting the PR\n- Task Event Customization: Task events in the Advanced Calendar now include CSS classes based on their tags (e.g., `fc-tag-meeting`, `fc-tag-work`), enabling custom styling per tag [#243, #244] - Thanks to @jradam for the feature request and implementation\n\n## Bug Fixes\n\n### Kanban Board\n\n- Duplicate Column Prevention: Fixed issue where renaming existing statuses in Kanban configuration could result in duplicate columns appearing in the board [#258] - Thanks to @mat2022a for the bug report\n\n### Subtask Widget Issues\n\n- Split Pane Display: Resolved issue where subtask widgets would inappropriately appear on notes in split panes when focusing on different notes [#234]\n- Table Cell Interference: Fixed subtask widgets appearing inside table cells when editing tables in project notes [#207]\n\n## Technical Changes\n\n### Documentation\n\n- Fixed line break formatting issues in documentation files\n\n### Code Organization\n\n- Improved task grouping architecture with new options interface\n- Enhanced calendar event rendering system for better tag-based customization\n- Refined subtask widget positioning logic for better editor integration\n","aliases":["/releases/3.15.1/","/releases/3.15.1/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"kanban-board-enhancements","text":"Kanban Board Enhancements"},{"level":3,"id":"calendar-improvements","text":"Calendar Improvements"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"kanban-board","text":"Kanban Board"},{"level":3,"id":"subtask-widget-issues","text":"Subtask Widget Issues"},{"level":2,"id":"technical-changes","text":"Technical Changes"},{"level":3,"id":"documentation","text":"Documentation"},{"level":3,"id":"code-organization","text":"Code Organization"}],"html":"

New Features#

\n

Kanban Board Enhancements#

\n
    \n
  • Show Empty Status Columns: Kanban board now displays empty columns for all configured statuses, providing better visual structure and workflow clarity
  • \n
  • Enhanced Task Grouping: Introduced GetGroupedTasksOptions interface for improved task grouping functionality with target date support and group pre-population [#236] - Thanks to @srcnDev for the implementation
  • \n
\n

Calendar Improvements#

\n
    \n
  • All-Day Event Styling: Added line-through styling for completed all-day events in the Advanced Calendar view [#252, #254] - Thanks to @anomatomato for reporting the issue and submitting the PR
  • \n
  • Task Event Customization: Task events in the Advanced Calendar now include CSS classes based on their tags (e.g., fc-tag-meeting, fc-tag-work), enabling custom styling per tag [#243, #244] - Thanks to @jradam for the feature request and implementation
  • \n
\n

Bug Fixes#

\n

Kanban Board#

\n
    \n
  • Duplicate Column Prevention: Fixed issue where renaming existing statuses in Kanban configuration could result in duplicate columns appearing in the board [#258] - Thanks to @mat2022a for the bug report
  • \n
\n

Subtask Widget Issues#

\n
    \n
  • Split Pane Display: Resolved issue where subtask widgets would inappropriately appear on notes in split panes when focusing on different notes [#234]
  • \n
  • Table Cell Interference: Fixed subtask widgets appearing inside table cells when editing tables in project notes [#207]
  • \n
\n

Technical Changes#

\n

Documentation#

\n
    \n
  • Fixed line break formatting issues in documentation files
  • \n
\n

Code Organization#

\n
    \n
  • Improved task grouping architecture with new options interface
  • \n
  • Enhanced calendar event rendering system for better tag-based customization
  • \n
  • Refined subtask widget positioning logic for better editor integration
  • \n
\n","text":"New Features# Kanban Board Enhancements# Show Empty Status Columns: Kanban board now displays empty columns for all configured statuses, providing better visual structure and workflow clarity Enhanced Task Grouping: Introduced GetGroupedTasksOptions interface for improved task grouping functionality with target date support and group pre-population [#236] - Thanks to @srcnDev for the implementation Calendar Improvements# All-Day Event Styling: Added line-through styling for completed all-day events in the Advanced Calendar view [#252, #254] - Thanks to @anomatomato for reporting the issue and submitting the PR Task Event Customization: Task events in the Advanced Calendar now include CSS classes based on their tags (e.g., fc-tag-meeting, fc-tag-work), enabling custom styling per tag [#243, #244] - Thanks to @jradam for the feature request and implementation Bug Fixes# Kanban Board# Duplicate Column Prevention: Fixed issue where renaming existing statuses in Kanban configuration could result in duplicate columns appearing in the board [#258] - Thanks to @mat2022a for the bug report Subtask Widget Issues# Split Pane Display: Resolved issue where subtask widgets would inappropriately appear on notes in split panes when focusing on different notes [#234] Table Cell Interference: Fixed subtask widgets appearing inside table cells when editing tables in project notes [#207] Technical Changes# Documentation# Fixed line break formatting issues in documentation files Code Organization# Improved task grouping architecture with new options interface Enhanced calendar event rendering system for better tag-based customization Refined subtask widget positioning logic for better editor integration"},{"route":"/obsidian/releases/3.16.0/","title":"TaskNotes 3.16.0","description":"Extra thanks to @Totobal5 for multiple code contributions including (tricky!) Pomodoro timer fixes and advanced calendar resizing fixes","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.16.0.md","namespace":"obsidian","relativePath":"releases/3.16.0.md","raw":"# TaskNotes 3.16.0\n\n## New Features\n\n### Task Management\n\n- **Bulk Task Conversion**: Added command to convert all checkbox tasks in a note to TaskNotes at once (#28) - Thanks to @TheSnakePolyglot for the feature request\n- **Instant Task Conversion Enhancement**: Enable instant task conversion for any line type, not just existing tasks (#259, #262) - Thanks to @ghelton and @cathywu for the suggestions\n- **Default Project Setting**: Added option to set a default project for new tasks in task creation settings (#250) - Thanks to @davidszerman for the request\n- **Advanced Tag and Project Parsing**: Implement intelligent parsing of tags and projects during instant task conversion (#260) - Thanks to @mdbraber for reporting this bug\n- **Enhanced Filter Bar Integration**: Added FilterBar integration to subtask widget for better task organization (#267) - Thanks to @mdbraber for the suggestion\n\n### Calendar and Views\n\n- **Custom Multi-Day Calendar View**: Added configurable custom multi-day calendar view with support for 3-day, work week, and full week layouts (#282) - Thanks to @girisumit for the feature request\n- **Responsive Calendar UI**: Hide calendar title in narrow containers for better responsive design (#285) - Thanks to @girisumit for the improvement suggestion\n- **Locale-Aware Date Formatting**: Added locale-aware date formatting to advanced calendar view (#210) - Thanks to @emes81 for highlighting this usability issue\n- **Saved Views Enhancement**: Added view options support to saved views with active view name display in filter condition builder (#245) - Thanks to @kmaustral and @digitaldoctors for the feedback\n\n### Task Organization\n\n- **Drag and Drop Status Reordering**: Added drag and drop reordering for status configurations with hamburger menu icon (#291) - Thanks to @23426356587 for the suggestion\n- **Overdue Tasks Filter**: Added setting to hide completed tasks from overdue status display (#300) - Thanks to @Lankly and @violetbp for reporting the issue\n- **Project Group Enhancements**: Made project group labels clickable in Task List View with ctrl+hover preview support (#198) - Thanks to @jpmoo for the suggestion\n\n### Pomodoro Timer\n\n- **Background Timer Continuity**: Pomodoro timer now continues running when app is minimized or loses focus (#136) - Thanks to @Poly_0000 for reporting and @Totobal5 for the fix\n- **System Notifications**: Convert Pomodoro notices to system notifications for better visibility (#136)\n- **Manual Duration Adjustment**: Fixed manually adjusted Pomodoro duration being ignored on start (#293) - Thanks to @Totobal5 for identifying and fixing\n- **Task Completion Sorting**: Sort completed tasks to end of Pomodoro task selector for better organization\n\n## Bug Fixes\n\n### UI and Interaction\n\n- **Tooltip Standardization**: Standardized tooltips to use Obsidian's native setTooltip function to eliminate duplicate tooltips (#257) - Thanks to @digitaldoctors for the bug report\n- **Open Note Button Stability**: Stabilized Open note button hover behavior and made font size consistent with other modal buttons\n- **Date Context Menu Clarity**: Added titles to date context menus for better user clarity (#253) - Thanks to @digitaldoctors for the suggestion\n- **Project Removal**: Fixed project removal in edit modal not saving changes properly (#213)\n- **Advanced Calendar Resizing**: Fixed Advanced Calendar view not resizing correctly in detached windows (#137) - Thanks to @macbikegeek for reporting and very much to @Totobal5 for the fix\n\n### Calendar and Recurring Tasks\n\n- **Timezone Bug Fixes**: Resolved multiple timezone-related off-by-one bugs in recurring task completion and agenda view display - A big thanks to @jpmoo and @kmaustral for reporting and describing in detail this bug\n- **Custom Calendar Display**: Fixed undefined days display in custom calendar view\n- **Calendar Recurrence**: Resolved timezone-based off-by-one bugs in calendar recurrence calculations - Thanks to @jpmoo and @kmaustral for reporting this bug\n\n### Task Management\n\n- **Pomodoro Task Tracking**: Handle task filename changes in pomodoro view to prevent tracking issues (#289) - Thanks to @cathywu for the report\n- **Plugin Conflict Protection**: Made suggestion objects defensive against potential plugin conflicts (#304) - Thanks to @zeltak for reporting the plugin conflict\n- **Instant Conversion Improvements**: Use cleaned title for NLP parsing in instant task conversion with fallback to default tasks folder (#128) - Thanks to @bepolymathe for reporting the folder issues\n\n## Improvements\n\n### User Interface\n\n- **Minimalist Design System**: Implemented consistent borderless button design system across all components\n- **UI Polish**: Applied minimalist styling with cleaned up borders and shadows throughout the interface\n- **Settings Enhancement**: Enhanced settings explanatory sections with improved minimalist styling\n- **Advanced Calendar Title**: Made advanced calendar title smaller for better proportions\n\n### Search and Filtering\n\n- **Enhanced Search**: Improved search functionality to preserve existing filters when performing new searches\n- **Filter Preservation**: Better handling of filter states across different search operations\n\n### Development and Code Quality\n\n- **Code Documentation**: Improved code comments and documentation throughout the codebase\n- **Linting Cleanup**: Resolved various linting errors and improved code consistency\n- **Test Infrastructure**: Updated timezone-related tests to work reliably in CI environment\n- **GitHub Actions**: Added timeouts and offline preferences to improve CI reliability\n\n## Technical Improvements\n\n- Reduced excessive console logging from filter components\n- Updated Jest coverage thresholds to realistic levels\n- Improved error handling in various components\n- Improved defensive programming practices throughout the codebase\n\n## Contributors\n\nExtra thanks to **@Totobal5** for multiple code contributions including (tricky!) Pomodoro timer fixes and advanced calendar resizing fixes\n\n","aliases":["/releases/3.16.0/","/releases/3.16.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"task-management","text":"Task Management"},{"level":3,"id":"calendar-and-views","text":"Calendar and Views"},{"level":3,"id":"task-organization","text":"Task Organization"},{"level":3,"id":"pomodoro-timer","text":"Pomodoro Timer"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"ui-and-interaction","text":"UI and Interaction"},{"level":3,"id":"calendar-and-recurring-tasks","text":"Calendar and Recurring Tasks"},{"level":3,"id":"task-management-2","text":"Task Management"},{"level":2,"id":"improvements","text":"Improvements"},{"level":3,"id":"user-interface","text":"User Interface"},{"level":3,"id":"search-and-filtering","text":"Search and Filtering"},{"level":3,"id":"development-and-code-quality","text":"Development and Code Quality"},{"level":2,"id":"technical-improvements","text":"Technical Improvements"},{"level":2,"id":"contributors","text":"Contributors"}],"html":"

New Features#

\n

Task Management#

\n
    \n
  • Bulk Task Conversion: Added command to convert all checkbox tasks in a note to TaskNotes at once (#28) - Thanks to @TheSnakePolyglot for the feature request
  • \n
  • Instant Task Conversion Enhancement: Enable instant task conversion for any line type, not just existing tasks (#259, #262) - Thanks to @ghelton and @cathywu for the suggestions
  • \n
  • Default Project Setting: Added option to set a default project for new tasks in task creation settings (#250) - Thanks to @davidszerman for the request
  • \n
  • Advanced Tag and Project Parsing: Implement intelligent parsing of tags and projects during instant task conversion (#260) - Thanks to @mdbraber for reporting this bug
  • \n
  • Enhanced Filter Bar Integration: Added FilterBar integration to subtask widget for better task organization (#267) - Thanks to @mdbraber for the suggestion
  • \n
\n

Calendar and Views#

\n
    \n
  • Custom Multi-Day Calendar View: Added configurable custom multi-day calendar view with support for 3-day, work week, and full week layouts (#282) - Thanks to @girisumit for the feature request
  • \n
  • Responsive Calendar UI: Hide calendar title in narrow containers for better responsive design (#285) - Thanks to @girisumit for the improvement suggestion
  • \n
  • Locale-Aware Date Formatting: Added locale-aware date formatting to advanced calendar view (#210) - Thanks to @emes81 for highlighting this usability issue
  • \n
  • Saved Views Enhancement: Added view options support to saved views with active view name display in filter condition builder (#245) - Thanks to @kmaustral and @digitaldoctors for the feedback
  • \n
\n

Task Organization#

\n
    \n
  • Drag and Drop Status Reordering: Added drag and drop reordering for status configurations with hamburger menu icon (#291) - Thanks to @23426356587 for the suggestion
  • \n
  • Overdue Tasks Filter: Added setting to hide completed tasks from overdue status display (#300) - Thanks to @Lankly and @violetbp for reporting the issue
  • \n
  • Project Group Enhancements: Made project group labels clickable in Task List View with ctrl+hover preview support (#198) - Thanks to @jpmoo for the suggestion
  • \n
\n

Pomodoro Timer#

\n
    \n
  • Background Timer Continuity: Pomodoro timer now continues running when app is minimized or loses focus (#136) - Thanks to @Poly_0000 for reporting and @Totobal5 for the fix
  • \n
  • System Notifications: Convert Pomodoro notices to system notifications for better visibility (#136)
  • \n
  • Manual Duration Adjustment: Fixed manually adjusted Pomodoro duration being ignored on start (#293) - Thanks to @Totobal5 for identifying and fixing
  • \n
  • Task Completion Sorting: Sort completed tasks to end of Pomodoro task selector for better organization
  • \n
\n

Bug Fixes#

\n

UI and Interaction#

\n
    \n
  • Tooltip Standardization: Standardized tooltips to use Obsidian's native setTooltip function to eliminate duplicate tooltips (#257) - Thanks to @digitaldoctors for the bug report
  • \n
  • Open Note Button Stability: Stabilized Open note button hover behavior and made font size consistent with other modal buttons
  • \n
  • Date Context Menu Clarity: Added titles to date context menus for better user clarity (#253) - Thanks to @digitaldoctors for the suggestion
  • \n
  • Project Removal: Fixed project removal in edit modal not saving changes properly (#213)
  • \n
  • Advanced Calendar Resizing: Fixed Advanced Calendar view not resizing correctly in detached windows (#137) - Thanks to @macbikegeek for reporting and very much to @Totobal5 for the fix
  • \n
\n

Calendar and Recurring Tasks#

\n
    \n
  • Timezone Bug Fixes: Resolved multiple timezone-related off-by-one bugs in recurring task completion and agenda view display - A big thanks to @jpmoo and @kmaustral for reporting and describing in detail this bug
  • \n
  • Custom Calendar Display: Fixed undefined days display in custom calendar view
  • \n
  • Calendar Recurrence: Resolved timezone-based off-by-one bugs in calendar recurrence calculations - Thanks to @jpmoo and @kmaustral for reporting this bug
  • \n
\n

Task Management#

\n
    \n
  • Pomodoro Task Tracking: Handle task filename changes in pomodoro view to prevent tracking issues (#289) - Thanks to @cathywu for the report
  • \n
  • Plugin Conflict Protection: Made suggestion objects defensive against potential plugin conflicts (#304) - Thanks to @zeltak for reporting the plugin conflict
  • \n
  • Instant Conversion Improvements: Use cleaned title for NLP parsing in instant task conversion with fallback to default tasks folder (#128) - Thanks to @bepolymathe for reporting the folder issues
  • \n
\n

Improvements#

\n

User Interface#

\n
    \n
  • Minimalist Design System: Implemented consistent borderless button design system across all components
  • \n
  • UI Polish: Applied minimalist styling with cleaned up borders and shadows throughout the interface
  • \n
  • Settings Enhancement: Enhanced settings explanatory sections with improved minimalist styling
  • \n
  • Advanced Calendar Title: Made advanced calendar title smaller for better proportions
  • \n
\n

Search and Filtering#

\n
    \n
  • Enhanced Search: Improved search functionality to preserve existing filters when performing new searches
  • \n
  • Filter Preservation: Better handling of filter states across different search operations
  • \n
\n

Development and Code Quality#

\n
    \n
  • Code Documentation: Improved code comments and documentation throughout the codebase
  • \n
  • Linting Cleanup: Resolved various linting errors and improved code consistency
  • \n
  • Test Infrastructure: Updated timezone-related tests to work reliably in CI environment
  • \n
  • GitHub Actions: Added timeouts and offline preferences to improve CI reliability
  • \n
\n

Technical Improvements#

\n
    \n
  • Reduced excessive console logging from filter components
  • \n
  • Updated Jest coverage thresholds to realistic levels
  • \n
  • Improved error handling in various components
  • \n
  • Improved defensive programming practices throughout the codebase
  • \n
\n

Contributors#

\n

Extra thanks to @Totobal5 for multiple code contributions including (tricky!) Pomodoro timer fixes and advanced calendar resizing fixes

\n","text":"New Features# Task Management# Bulk Task Conversion: Added command to convert all checkbox tasks in a note to TaskNotes at once (#28) - Thanks to @TheSnakePolyglot for the feature request Instant Task Conversion Enhancement: Enable instant task conversion for any line type, not just existing tasks (#259, #262) - Thanks to @ghelton and @cathywu for the suggestions Default Project Setting: Added option to set a default project for new tasks in task creation settings (#250) - Thanks to @davidszerman for the request Advanced Tag and Project Parsing: Implement intelligent parsing of tags and projects during instant task conversion (#260) - Thanks to @mdbraber for reporting this bug Enhanced Filter Bar Integration: Added FilterBar integration to subtask widget for better task organization (#267) - Thanks to @mdbraber for the suggestion Calendar and Views# Custom Multi-Day Calendar View: Added configurable custom multi-day calendar view with support for 3-day, work week, and full week layouts (#282) - Thanks to @girisumit for the feature request Responsive Calendar UI: Hide calendar title in narrow containers for better responsive design (#285) - Thanks to @girisumit for the improvement suggestion Locale-Aware Date Formatting: Added locale-aware date formatting to advanced calendar view (#210) - Thanks to @emes81 for highlighting this usability issue Saved Views Enhancement: Added view options support to saved views with active view name display in filter condition builder (#245) - Thanks to @kmaustral and @digitaldoctors for the feedback Task Organization# Drag and Drop Status Reordering: Added drag and drop reordering for status configurations with hamburger menu icon (#291) - Thanks to @23426356587 for the suggestion Overdue Tasks Filter: Added setting to hide completed tasks from overdue status display (#300) - Thanks to @Lankly and @violetbp for reporting the issue Project Group Enhancements: Made project group labels clickable in Task List View with ctrl+hover preview support (#198) - Thanks to @jpmoo for the suggestion Pomodoro Timer# Background Timer Continuity: Pomodoro timer now continues running when app is minimized or loses focus (#136) - Thanks to @Poly_0000 for reporting and @Totobal5 for the fix System Notifications: Convert Pomodoro notices to system notifications for better visibility (#136) Manual Duration Adjustment: Fixed manually adjusted Pomodoro duration being ignored on start (#293) - Thanks to @Totobal5 for identifying and fixing Task Completion Sorting: Sort completed tasks to end of Pomodoro task selector for better organization Bug Fixes# UI and Interaction# Tooltip Standardization: Standardized tooltips to use Obsidian's native setTooltip function to eliminate duplicate tooltips (#257) - Thanks to @digitaldoctors for the bug report Open Note Button Stability: Stabilized Open note button hover behavior and made font size consistent with other modal buttons Date Context Menu Clarity: Added titles to date context menus for better user clarity (#253) - Thanks to @digitaldoctors for the suggestion Project Removal: Fixed project removal in edit modal not saving changes properly (#213) Advanced Calendar Resizing: Fixed Advanced Calendar view not resizing correctly in detached windows (#137) - Thanks to @macbikegeek for reporting and very much to @Totobal5 for the fix Calendar and Recurring Tasks# Timezone Bug Fixes: Resolved multiple timezone-related off-by-one bugs in recurring task completion and agenda view display - A big thanks to @jpmoo and @kmaustral for reporting and describing in detail this bug Custom Calendar Display: Fixed undefined days display in custom calendar view Calendar Recurrence: Resolved timezone-based off-by-one bugs in calendar recurrence calculations - Thanks to @jpmoo and @kmaustral for reporting this bug Task Management# Pomodoro Task Tracking: Handle task filename changes in pomodoro view to prevent tracking issues (#289) - Thanks to @cathywu for the report Plugin Conflict Protection: Made suggestion objects defensive against potential plugin conflicts (#304) - Thanks to @zeltak for reporting the plugin conflict Instant Conversion Improvements: Use cleaned title for NLP parsing in instant task conversion with fallback to default tasks folder (#128) - Thanks to @bepolymathe for reporting the folder issues Improvements# User Interface# Minimalist Design System: Implemented consistent borderless button design system across all components UI Polish: Applied minimalist styling with cleaned up borders and shadows throughout the interface Settings Enhancement: Enhanced settings explanatory sections with improved minimalist styling Advanced Calendar Title: Made advanced calendar title smaller for better proportions Search and Filtering# Enhanced Search: Improved search functionality to preserve existing filters when performing new searches Filter Preservation: Better handling of filter states across different search operations Development and Code Quality# Code Documentation: Improved code comments and documentation throughout the codebase Linting Cleanup: Resolved various linting errors and improved code consistency Test Infrastructure: Updated timezone-related tests to work reliably in CI environment GitHub Actions: Added timeouts and offline preferences to improve CI reliability Technical Improvements# Reduced excessive console logging from filter components Updated Jest coverage thresholds to realistic levels Improved error handling in various components Improved defensive programming practices throughout the codebase Contributors# Extra thanks to @Totobal5 for multiple code contributions including (tricky!) Pomodoro timer fixes and advanced calendar resizing fixes"},{"route":"/obsidian/releases/3.16.1/","title":"TaskNotes 3.16.1","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.16.1.md","namespace":"obsidian","relativePath":"releases/3.16.1.md","raw":"# TaskNotes 3.16.1\n\n## New Features\n\n### Task Management\n\n- **Visual Filter State Indicators**: Added visual state indicators for active saved views in FilterBar to provide better feedback when a saved view is currently active\n\n## Bug Fixes\n\n### Link Generation and Consistency\n\n- **Obsidian Link Format Compliance**: Fixed \"Insert tasknote link\" and \"Convert task to TaskNote\" commands to use Obsidian's native generateMarkdownLink method, respecting user's link format preferences in Files & Links settings [#312] - Thanks to @nightroman for reporting the inconsistency and requesting proper format support\n- **Consistent Link Formatting**: Both commands now generate links in the same format and are compatible with external tools when markdown links are preferred\n\n### Timezone and Date Handling\n\n- **Recurring Task Completion Fix**: Resolved critical timezone bug where recurring task completion dates were stored incorrectly in non-UTC timezones [#314] - Thanks to @kmaustral for detailed reporting and testing across multiple views\n- **UTC Date Consistency**: Updated all date utilities to use UTC methods consistently across calendar components, fixing off-by-one date issues in task completion tracking\n- **Calendar Date Normalization**: Added createSafeUTCDate utility function and converted MiniCalendarView navigation to UTC methods for reliable date handling\n\n### User Interface\n\n- **Sort Arrow Visibility**: Enhanced sort direction arrow visibility and positioning in filter condition builder with increased font size, bold weight, and accent color [#307] - Thanks to @kmaustral for noting the arrow was difficult to see in dark mode\n- **Duplicate Tooltip Prevention**: Removed duplicate tooltips on recurring task indicators by using Obsidian's native setTooltip function instead of HTML title attributes\n- **Pointer Cursor Consistency**: Added pointer cursor styling to all buttons in Pomodoro view for better usability [#308] - Thanks to @anomatomato for the contribution\n\n### Error Handling and Stability\n\n- **Daily Note Creation Protection**: Added proper error handling for createDailyNote failures across TimeblockCreationModal, PomodoroService, and helper utilities, preventing \"Cannot read properties of undefined\" errors\n- **Security Compliance**: Replaced unsafe innerHTML assignment with textContent in drag handle creation to resolve ESLint security violations\n\n## Improvements\n\n### User Interface\n\n- **Calendar Styling Enhancements**: Improved advanced calendar view with better borders, header text readability, and removed custom scrollbar styling for system consistency\n- **Enhanced Visual Definition**: Added border and border radius to calendar container, plus consistent borders on column headers and toolbar for cleaner appearance\n\n### Development and Code Quality\n\n- **Test Infrastructure**: Added missing setTooltip mock to resolve 39 failing TaskCard tests\n- **Documentation Updates**: Improved documentation formatting and appearance\n\n## Technical Improvements\n\n- Enhanced date handling throughout the codebase with UTC method standardization\n- Improved defensive programming practices for timezone-sensitive operations\n- Better error messaging for daily note creation failures\n- Code security improvements with ESLint compliance\n\n","aliases":["/releases/3.16.1/","/releases/3.16.1/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"task-management","text":"Task Management"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"link-generation-and-consistency","text":"Link Generation and Consistency"},{"level":3,"id":"timezone-and-date-handling","text":"Timezone and Date Handling"},{"level":3,"id":"user-interface","text":"User Interface"},{"level":3,"id":"error-handling-and-stability","text":"Error Handling and Stability"},{"level":2,"id":"improvements","text":"Improvements"},{"level":3,"id":"user-interface-2","text":"User Interface"},{"level":3,"id":"development-and-code-quality","text":"Development and Code Quality"},{"level":2,"id":"technical-improvements","text":"Technical Improvements"}],"html":"

New Features#

\n

Task Management#

\n
    \n
  • Visual Filter State Indicators: Added visual state indicators for active saved views in FilterBar to provide better feedback when a saved view is currently active
  • \n
\n

Bug Fixes#

\n\n
    \n
  • Obsidian Link Format Compliance: Fixed "Insert tasknote link" and "Convert task to TaskNote" commands to use Obsidian's native generateMarkdownLink method, respecting user's link format preferences in Files & Links settings [#312] - Thanks to @nightroman for reporting the inconsistency and requesting proper format support
  • \n
  • Consistent Link Formatting: Both commands now generate links in the same format and are compatible with external tools when markdown links are preferred
  • \n
\n

Timezone and Date Handling#

\n
    \n
  • Recurring Task Completion Fix: Resolved critical timezone bug where recurring task completion dates were stored incorrectly in non-UTC timezones [#314] - Thanks to @kmaustral for detailed reporting and testing across multiple views
  • \n
  • UTC Date Consistency: Updated all date utilities to use UTC methods consistently across calendar components, fixing off-by-one date issues in task completion tracking
  • \n
  • Calendar Date Normalization: Added createSafeUTCDate utility function and converted MiniCalendarView navigation to UTC methods for reliable date handling
  • \n
\n

User Interface#

\n
    \n
  • Sort Arrow Visibility: Enhanced sort direction arrow visibility and positioning in filter condition builder with increased font size, bold weight, and accent color [#307] - Thanks to @kmaustral for noting the arrow was difficult to see in dark mode
  • \n
  • Duplicate Tooltip Prevention: Removed duplicate tooltips on recurring task indicators by using Obsidian's native setTooltip function instead of HTML title attributes
  • \n
  • Pointer Cursor Consistency: Added pointer cursor styling to all buttons in Pomodoro view for better usability [#308] - Thanks to @anomatomato for the contribution
  • \n
\n

Error Handling and Stability#

\n
    \n
  • Daily Note Creation Protection: Added proper error handling for createDailyNote failures across TimeblockCreationModal, PomodoroService, and helper utilities, preventing "Cannot read properties of undefined" errors
  • \n
  • Security Compliance: Replaced unsafe innerHTML assignment with textContent in drag handle creation to resolve ESLint security violations
  • \n
\n

Improvements#

\n

User Interface#

\n
    \n
  • Calendar Styling Enhancements: Improved advanced calendar view with better borders, header text readability, and removed custom scrollbar styling for system consistency
  • \n
  • Enhanced Visual Definition: Added border and border radius to calendar container, plus consistent borders on column headers and toolbar for cleaner appearance
  • \n
\n

Development and Code Quality#

\n
    \n
  • Test Infrastructure: Added missing setTooltip mock to resolve 39 failing TaskCard tests
  • \n
  • Documentation Updates: Improved documentation formatting and appearance
  • \n
\n

Technical Improvements#

\n
    \n
  • Enhanced date handling throughout the codebase with UTC method standardization
  • \n
  • Improved defensive programming practices for timezone-sensitive operations
  • \n
  • Better error messaging for daily note creation failures
  • \n
  • Code security improvements with ESLint compliance
  • \n
\n","text":"New Features# Task Management# Visual Filter State Indicators: Added visual state indicators for active saved views in FilterBar to provide better feedback when a saved view is currently active Bug Fixes# Link Generation and Consistency# Obsidian Link Format Compliance: Fixed \"Insert tasknote link\" and \"Convert task to TaskNote\" commands to use Obsidian's native generateMarkdownLink method, respecting user's link format preferences in Files & Links settings [#312] - Thanks to @nightroman for reporting the inconsistency and requesting proper format support Consistent Link Formatting: Both commands now generate links in the same format and are compatible with external tools when markdown links are preferred Timezone and Date Handling# Recurring Task Completion Fix: Resolved critical timezone bug where recurring task completion dates were stored incorrectly in non-UTC timezones [#314] - Thanks to @kmaustral for detailed reporting and testing across multiple views UTC Date Consistency: Updated all date utilities to use UTC methods consistently across calendar components, fixing off-by-one date issues in task completion tracking Calendar Date Normalization: Added createSafeUTCDate utility function and converted MiniCalendarView navigation to UTC methods for reliable date handling User Interface# Sort Arrow Visibility: Enhanced sort direction arrow visibility and positioning in filter condition builder with increased font size, bold weight, and accent color [#307] - Thanks to @kmaustral for noting the arrow was difficult to see in dark mode Duplicate Tooltip Prevention: Removed duplicate tooltips on recurring task indicators by using Obsidian's native setTooltip function instead of HTML title attributes Pointer Cursor Consistency: Added pointer cursor styling to all buttons in Pomodoro view for better usability [#308] - Thanks to @anomatomato for the contribution Error Handling and Stability# Daily Note Creation Protection: Added proper error handling for createDailyNote failures across TimeblockCreationModal, PomodoroService, and helper utilities, preventing \"Cannot read properties of undefined\" errors Security Compliance: Replaced unsafe innerHTML assignment with textContent in drag handle creation to resolve ESLint security violations Improvements# User Interface# Calendar Styling Enhancements: Improved advanced calendar view with better borders, header text readability, and removed custom scrollbar styling for system consistency Enhanced Visual Definition: Added border and border radius to calendar container, plus consistent borders on column headers and toolbar for cleaner appearance Development and Code Quality# Test Infrastructure: Added missing setTooltip mock to resolve 39 failing TaskCard tests Documentation Updates: Improved documentation formatting and appearance Technical Improvements# Enhanced date handling throughout the codebase with UTC method standardization Improved defensive programming practices for timezone-sensitive operations Better error messaging for daily note creation failures Code security improvements with ESLint compliance"},{"route":"/obsidian/releases/3.16.2/","title":"TaskNotes 3.16.2","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.16.2.md","namespace":"obsidian","relativePath":"releases/3.16.2.md","raw":"# TaskNotes 3.16.2\n\n## New Features\n\n### Task Link Integration\n\n- **Markdown Link Support for Inline Task Widgets**: Extended task link detection and rendering to support both wikilinks and markdown links. The plugin now properly renders `[text](path)` markdown links as interactive inline task widgets in both live preview and reading modes [#312] - Thanks to @nightroman for noting the missing link overlays on markdown links\n\n## Improvements\n\n### Link Processing\n\n- **Link Detection**: Improved TaskLinkDetectionService to detect both `[[wikilinks]]` and `[markdown](links)` with proper URL decoding for paths containing spaces\n- **Link Rendering**: Updated both TaskLinkOverlay (live preview) and ReadingModeTaskLinkProcessor (reading mode) to handle both link types consistently\n- **API Integration**: Uses proper Obsidian API functions (`parseLinktext()` and `getFirstLinkpathDest()`) for reliable link resolution\n","aliases":["/releases/3.16.2/","/releases/3.16.2/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"task-link-integration","text":"Task Link Integration"},{"level":2,"id":"improvements","text":"Improvements"},{"level":3,"id":"link-processing","text":"Link Processing"}],"html":"

New Features#

\n\n
    \n
  • Markdown Link Support for Inline Task Widgets: Extended task link detection and rendering to support both wikilinks and markdown links. The plugin now properly renders [text](path) markdown links as interactive inline task widgets in both live preview and reading modes [#312] - Thanks to @nightroman for noting the missing link overlays on markdown links
  • \n
\n

Improvements#

\n\n
    \n
  • Link Detection: Improved TaskLinkDetectionService to detect both [[wikilinks]] and [markdown](links) with proper URL decoding for paths containing spaces
  • \n
  • Link Rendering: Updated both TaskLinkOverlay (live preview) and ReadingModeTaskLinkProcessor (reading mode) to handle both link types consistently
  • \n
  • API Integration: Uses proper Obsidian API functions (parseLinktext() and getFirstLinkpathDest()) for reliable link resolution
  • \n
\n","text":"New Features# Task Link Integration# Markdown Link Support for Inline Task Widgets: Extended task link detection and rendering to support both wikilinks and markdown links. The plugin now properly renders [text](path) markdown links as interactive inline task widgets in both live preview and reading modes [#312] - Thanks to @nightroman for noting the missing link overlays on markdown links Improvements# Link Processing# Link Detection: Improved TaskLinkDetectionService to detect both [[wikilinks]] and [markdown](links) with proper URL decoding for paths containing spaces Link Rendering: Updated both TaskLinkOverlay (live preview) and ReadingModeTaskLinkProcessor (reading mode) to handle both link types consistently API Integration: Uses proper Obsidian API functions (parseLinktext() and getFirstLinkpathDest()) for reliable link resolution"},{"route":"/obsidian/releases/3.16.3/","title":"TaskNotes 3.16.3","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.16.3.md","namespace":"obsidian","relativePath":"releases/3.16.3.md","raw":"# TaskNotes 3.16.3\n\n## Bug Fixes\n\n### User Interface\n\n- **Create Task Modal Accessibility**: Fixed UI issues when creating tasks with natural language input disabled. The modal now opens in an expanded state with immediate access to all input fields, eliminating the need to click or tab before entering task details [#324] - Thanks to @nightroman for reporting this usability issue\n\n### Timezone Handling\n\n- **Recurring Task Calendar Display**: Fixed timezone-related display bug where recurring tasks appeared on the wrong day for users in negative UTC timezones. Tuesday tasks no longer incorrectly appear on Monday in the calendar view\n- **Task Completion Calendar**: Improved timezone consistency in the TaskEditModal completion calendar to ensure dates display correctly across all timezones\n\n### Task Conversion\n\n- **Context Detection in Instant Tasks**: Fixed instant task conversion to properly detect and preserve contexts specified with \"@context\" syntax when converting inline tasks to TaskNotes [#320] - Thanks to @nslee123 for reporting this issue\n- **Time Preservation**: Fixed instant task conversion to preserve time information when converting tasks with scheduled or due times. Time components are now correctly carried over during the conversion process\n\n## Improvements\n\n### Code Quality\n\n- **Test Coverage**: Added comprehensive unit tests for InstantTaskConvertService context detection to ensure reliable context parsing in future releases","aliases":["/releases/3.16.3/","/releases/3.16.3/"],"toc":[{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"user-interface","text":"User Interface"},{"level":3,"id":"timezone-handling","text":"Timezone Handling"},{"level":3,"id":"task-conversion","text":"Task Conversion"},{"level":2,"id":"improvements","text":"Improvements"},{"level":3,"id":"code-quality","text":"Code Quality"}],"html":"

Bug Fixes#

\n

User Interface#

\n
    \n
  • Create Task Modal Accessibility: Fixed UI issues when creating tasks with natural language input disabled. The modal now opens in an expanded state with immediate access to all input fields, eliminating the need to click or tab before entering task details [#324] - Thanks to @nightroman for reporting this usability issue
  • \n
\n

Timezone Handling#

\n
    \n
  • Recurring Task Calendar Display: Fixed timezone-related display bug where recurring tasks appeared on the wrong day for users in negative UTC timezones. Tuesday tasks no longer incorrectly appear on Monday in the calendar view
  • \n
  • Task Completion Calendar: Improved timezone consistency in the TaskEditModal completion calendar to ensure dates display correctly across all timezones
  • \n
\n

Task Conversion#

\n
    \n
  • Context Detection in Instant Tasks: Fixed instant task conversion to properly detect and preserve contexts specified with "@context" syntax when converting inline tasks to TaskNotes [#320] - Thanks to @nslee123 for reporting this issue
  • \n
  • Time Preservation: Fixed instant task conversion to preserve time information when converting tasks with scheduled or due times. Time components are now correctly carried over during the conversion process
  • \n
\n

Improvements#

\n

Code Quality#

\n
    \n
  • Test Coverage: Added comprehensive unit tests for InstantTaskConvertService context detection to ensure reliable context parsing in future releases
  • \n
\n","text":"Bug Fixes# User Interface# Create Task Modal Accessibility: Fixed UI issues when creating tasks with natural language input disabled. The modal now opens in an expanded state with immediate access to all input fields, eliminating the need to click or tab before entering task details [#324] - Thanks to @nightroman for reporting this usability issue Timezone Handling# Recurring Task Calendar Display: Fixed timezone-related display bug where recurring tasks appeared on the wrong day for users in negative UTC timezones. Tuesday tasks no longer incorrectly appear on Monday in the calendar view Task Completion Calendar: Improved timezone consistency in the TaskEditModal completion calendar to ensure dates display correctly across all timezones Task Conversion# Context Detection in Instant Tasks: Fixed instant task conversion to properly detect and preserve contexts specified with \"@context\" syntax when converting inline tasks to TaskNotes [#320] - Thanks to @nslee123 for reporting this issue Time Preservation: Fixed instant task conversion to preserve time information when converting tasks with scheduled or due times. Time components are now correctly carried over during the conversion process Improvements# Code Quality# Test Coverage: Added comprehensive unit tests for InstantTaskConvertService context detection to ensure reliable context parsing in future releases"},{"route":"/obsidian/releases/3.16.4/","title":"TaskNotes 3.16.4","description":"This ensures users can always edit task titles regardless of the modal type or natural language input settings.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.16.4.md","namespace":"obsidian","relativePath":"releases/3.16.4.md","raw":"# TaskNotes 3.16.4\n\n## Bug Fixes\n\n### User Interface\n\n- **Task Modal Title Field**: Fixed regression from version 3.16.3 where the title field was inadvertently removed from all task modals. The title field is now properly displayed with correct visibility logic:\n - Edit modals: Title field always visible in the details section\n - Create modals with natural language input enabled: Title field visible in details section (as the main input becomes the NLP textarea)\n - Create modals with natural language input disabled: Title field only appears at the top of the modal\n\nThis ensures users can always edit task titles regardless of the modal type or natural language input settings.","aliases":["/releases/3.16.4/","/releases/3.16.4/"],"toc":[{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"user-interface","text":"User Interface"}],"html":"

Bug Fixes#

\n

User Interface#

\n
    \n
  • Task Modal Title Field: Fixed regression from version 3.16.3 where the title field was inadvertently removed from all task modals. The title field is now properly displayed with correct visibility logic:
      \n
    • Edit modals: Title field always visible in the details section
    • \n
    • Create modals with natural language input enabled: Title field visible in details section (as the main input becomes the NLP textarea)
    • \n
    • Create modals with natural language input disabled: Title field only appears at the top of the modal
    • \n
    \n
  • \n
\n

This ensures users can always edit task titles regardless of the modal type or natural language input settings.

\n","text":"Bug Fixes# User Interface# Task Modal Title Field: Fixed regression from version 3.16.3 where the title field was inadvertently removed from all task modals. The title field is now properly displayed with correct visibility logic: Edit modals: Title field always visible in the details section Create modals with natural language input enabled: Title field visible in details section (as the main input becomes the NLP textarea) Create modals with natural language input disabled: Title field only appears at the top of the modal This ensures users can always edit task titles regardless of the modal type or natural language input settings."},{"route":"/obsidian/releases/3.17.0/","title":"TaskNotes 3.17.0","description":"This release introduces improvements to recurring task handling with full DTSTART (start date/time) integration, addressing long-standing challenges in recurring task management...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.17.0.md","namespace":"obsidian","relativePath":"releases/3.17.0.md","raw":"# TaskNotes 3.17.0\n\n## Major Features\n\n### Enhanced Recurring Tasks with DTSTART Support\n\nThis release introduces improvements to recurring task handling with full DTSTART (start date/time) integration, addressing long-standing challenges in recurring task management and filtering.\n\n**Background and Motivation:**\n\nThe previous recurring task system created difficulties for users in filtering and managing task schedules. Users experienced unintuitive behavior where recurring tasks couldn't be treated consistently with regular tasks, making it challenging to see when the next occurrence would appear or to dynamically update task schedules upon completion. This implementation follows RFC 5545 standards to provide a more robust foundation for recurring task behavior.\n\n**Key Improvements:**\n\n- **DTSTART Integration**: All recurring tasks now include proper start dates and times in their recurrence rules, ensuring consistent behavior across timezones and providing a clear anchor point for the recurring pattern\n- **Dynamic Date Updates**: The `task.scheduled` field now always shows the next uncompleted occurrence, automatically updating when tasks are completed rather than showing static pattern dates\n- **Flexible Next Occurrence Scheduling**: The next scheduled occurrence can now be placed anywhere - before the pattern start date, outside the recurring pattern, or at any custom time, giving users complete control over scheduling\n- **Visual Hierarchy**: Pattern instances display with dashed borders while the next scheduled occurrence shows with solid borders, providing clear visual distinction between the recurring pattern and the active next task\n- **Independent Time Control**: Pattern instances and next occurrences can have different times (e.g., daily pattern at 9 AM, next occurrence at 2:30 PM), allowing for exceptions without breaking the recurring pattern\n- **Dual Drag Behavior**: Dragging pattern instances updates the recurring pattern timing globally, while dragging the next occurrence reschedules only that specific instance\n- **Automatic DTSTART Addition**: The system automatically adds DTSTART when completing recurring tasks, editing recurrence rules, or converting tasks to recurring, ensuring backward compatibility while upgrading task definitions\n- **Manual Rescheduling Support**: Clear flags indicate when tasks have been manually rescheduled, maintaining transparency about schedule modifications\n\n### Expandable Project Subtasks\n\nA new feature allows users to expand project task cards to view subtasks inline with proper visual hierarchy.\n\n**Features:**\n\n- **Chevron Controls**: Click chevron icons on project task cards to expand/collapse subtask display\n- **Configurable**: New \"Show expandable subtasks\" setting allows users to enable/disable the feature\n\n### Responsive Pomodoro View\n\nThe Pomodoro view now adapts seamlessly to different container sizes with comprehensive responsive design.\n\nThanks to @oliverlalan for requesting this improvement (#339).\n\n### Enhanced Filename Templates\n\nSignificant expansion of available template variables for task creation, providing much greater flexibility in filename patterns.\n\n**New Template Variables:**\n\n- **Date/Time Variations**: shortDate, monthName, dayName, week, quarter, time12, time24\n- **Unix Timestamps**: unix (seconds), unixMs (milliseconds) \n- **Title Case Variations**: titleLower, titleUpper, titleSnake, titleKebab, titleCamel, titlePascal\n- **Short Forms**: priorityShort, statusShort for single-letter representations\n- **Unique Identifiers**: zettel (Zettelkasten ID), nano (high-precision unique ID)\n\nThe settings UI now documents all 40+ available template variables for easy reference.\n\nThanks to @fastrick for the original unix timestamp request.\n\n## Bug Fixes\n\n### Critical Timezone Handling Fixes\n\nThis release resolves multiple timezone-related bugs that affected users worldwide, particularly those in non-UTC timezones. These fixes implement the \"UTC Anchor\" principle for consistent date handling.\n\n**Major Timezone Bugs Fixed:**\n\n- **Recurring Task Completion**: Fixed critical issue where marking recurring tasks complete would affect the wrong day for users in certain timezones, addressing reports from multiple users including issues #327, #322, and #314\n- **Calendar Date Misalignment**: Resolved off-by-one day errors in calendar rendering and task indicators, addressing inconsistencies across different views (originally reported by @Crunchnuggetz in issue #129, with additional reports from @donjjones and @robmikulec)\n- **Weekly Task Display**: Fixed issue where weekly recurring tasks set for specific days (e.g., Tuesdays) were showing completion dates on the wrong day (Monday) - reported by @jpmoo in issue #322\n- **Task Completion Date Bug**: Resolved bug where `complete_instances` was being set to the previous day, causing tasks to remain visible in Agenda view until manually corrected - reported in issue #314\n- **Date Parsing Inconsistencies**: Eliminated mixing of UTC and local date parsing that caused timezone-dependent behavior across the application\n- **Filter Date Handling**: Fixed date filtering to work consistently across all timezones\n- **Agenda View \"Today\" Detection**: Corrected timezone-sensitive today detection that affected agenda headers\n- **ICS Import Timezone Issues**: Resolved timezone problems with both recurring and single events from ICS imports\n\n**Technical Implementation:**\n\n- Introduced `parseDateToUTC()` function for consistent UTC anchoring of date-only strings\n- Updated date comparison functions to use UTC anchors throughout\n- Replaced timezone-sensitive date operations with consistent UTC-based alternatives\n- Comprehensive audit and fix of all date handling patterns in the codebase\n\n### Project Filtering Improvements\n\nResolved critical bugs in project filtering that prevented proper task display and project selection.\n\n**Fixes:**\n- **Wikilink Resolution**: Fixed handling of relative vs absolute project wikilinks (e.g., `[[../Projects/My Project]]` vs `[[My Project]]`) - thanks to @xorander00 for the detailed bug report\n- **Filter Grouping Logic**: Corrected AND/OR grouping in project filters to prevent showing too many tasks\n- **Missing Projects**: Fixed issue where not all projects appeared in filter dropdown selection\n- **Cache Management**: Improved cache invalidation and project name extraction with better validation\n\n### Subtask Widget Improvements\n\nFixed several issues with the project subtasks widget affecting user experience and reliability.\n\n**Widget Fixes:**\n\n- **View State Persistence**: Fixed issue where subtask widget views would reset when switching between notes or modifying subtasks (reported by @Poly-0000 in issue #329)\n- **Filter State Isolation**: Prevented filter settings from bleeding between different notes' subtask widgets\n- **Configurable Positioning**: Added setting to control widget placement at top or bottom of notes (requested by @michelebugio in issue #164)\n- **Event Listener Management**: Improved cleanup to prevent memory leaks and event accumulation\n- **Event Bubbling**: Fixed issue where clicking subtasks would trigger both subtask and parent task modals\n- **Styling Isolation**: Prevented completion styles from affecting nested subtasks incorrectly\n\n### ICS Calendar Integration\n\n**Timezone Processing**: Fixed timezone handling bug in ICS calendar subscriptions where VTIMEZONE components weren't being registered before parsing events, causing incorrect display times for timezone-specific calendar events.\n\n### Performance and Reliability\n\n**Cache Optimization**: Restored FilterService cache TTL to 30 seconds after temporary reduction, balancing performance with data freshness.\n\n**Type Safety**: Added proper type assertions for ICAL.TimezoneService calls to resolve TypeScript compilation issues.\n\n**Error Handling**: Enhanced error handling and null safety checks throughout project filtering and service initialization.\n\n## Technical Improvements\n\n### UTC Anchor Implementation\n\nComprehensive implementation of the UTC Anchor principle for robust timezone handling:\n\n- All date-only strings now consistently parsed as UTC anchors\n- Date comparison operations standardized using UTC methods\n- Eliminated timezone-dependent date creation patterns\n- Added comprehensive timezone test coverage\n\n### Service Architecture\n\n**Expanded Projects Service**: Enhanced state management and tracking for expandable project subtasks with proper cleanup and memory management.\n\n**View State Manager**: Improved view state persistence across different contexts and note switches.\n\n### Documentation Updates\n\n- Updated recurring tasks documentation to reflect new behavior\n- Added timezone handling guides for developers\n- Enhanced calendar views documentation with drag behavior explanations\n- Comprehensive template variable documentation\n\n## Breaking Changes\n\n**Date Handling**: While maintaining backward compatibility for user data, the internal date handling now consistently uses the UTC Anchor principle.\n\n## Migration Notes\n\nExisting recurring tasks will continue to work without modification. The system automatically adds DTSTART components when users interact with recurring tasks (completing, editing, or rescheduling).\n\n","aliases":["/releases/3.17.0/","/releases/3.17.0/"],"toc":[{"level":2,"id":"major-features","text":"Major Features"},{"level":3,"id":"enhanced-recurring-tasks-with-dtstart-support","text":"Enhanced Recurring Tasks with DTSTART Support"},{"level":3,"id":"expandable-project-subtasks","text":"Expandable Project Subtasks"},{"level":3,"id":"responsive-pomodoro-view","text":"Responsive Pomodoro View"},{"level":3,"id":"enhanced-filename-templates","text":"Enhanced Filename Templates"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"critical-timezone-handling-fixes","text":"Critical Timezone Handling Fixes"},{"level":3,"id":"project-filtering-improvements","text":"Project Filtering Improvements"},{"level":3,"id":"subtask-widget-improvements","text":"Subtask Widget Improvements"},{"level":3,"id":"ics-calendar-integration","text":"ICS Calendar Integration"},{"level":3,"id":"performance-and-reliability","text":"Performance and Reliability"},{"level":2,"id":"technical-improvements","text":"Technical Improvements"},{"level":3,"id":"utc-anchor-implementation","text":"UTC Anchor Implementation"},{"level":3,"id":"service-architecture","text":"Service Architecture"},{"level":3,"id":"documentation-updates","text":"Documentation Updates"},{"level":2,"id":"breaking-changes","text":"Breaking Changes"},{"level":2,"id":"migration-notes","text":"Migration Notes"}],"html":"

Major Features#

\n

Enhanced Recurring Tasks with DTSTART Support#

\n

This release introduces improvements to recurring task handling with full DTSTART (start date/time) integration, addressing long-standing challenges in recurring task management and filtering.

\n

Background and Motivation:

\n

The previous recurring task system created difficulties for users in filtering and managing task schedules. Users experienced unintuitive behavior where recurring tasks couldn't be treated consistently with regular tasks, making it challenging to see when the next occurrence would appear or to dynamically update task schedules upon completion. This implementation follows RFC 5545 standards to provide a more robust foundation for recurring task behavior.

\n

Key Improvements:

\n
    \n
  • DTSTART Integration: All recurring tasks now include proper start dates and times in their recurrence rules, ensuring consistent behavior across timezones and providing a clear anchor point for the recurring pattern
  • \n
  • Dynamic Date Updates: The task.scheduled field now always shows the next uncompleted occurrence, automatically updating when tasks are completed rather than showing static pattern dates
  • \n
  • Flexible Next Occurrence Scheduling: The next scheduled occurrence can now be placed anywhere - before the pattern start date, outside the recurring pattern, or at any custom time, giving users complete control over scheduling
  • \n
  • Visual Hierarchy: Pattern instances display with dashed borders while the next scheduled occurrence shows with solid borders, providing clear visual distinction between the recurring pattern and the active next task
  • \n
  • Independent Time Control: Pattern instances and next occurrences can have different times (e.g., daily pattern at 9 AM, next occurrence at 2:30 PM), allowing for exceptions without breaking the recurring pattern
  • \n
  • Dual Drag Behavior: Dragging pattern instances updates the recurring pattern timing globally, while dragging the next occurrence reschedules only that specific instance
  • \n
  • Automatic DTSTART Addition: The system automatically adds DTSTART when completing recurring tasks, editing recurrence rules, or converting tasks to recurring, ensuring backward compatibility while upgrading task definitions
  • \n
  • Manual Rescheduling Support: Clear flags indicate when tasks have been manually rescheduled, maintaining transparency about schedule modifications
  • \n
\n

Expandable Project Subtasks#

\n

A new feature allows users to expand project task cards to view subtasks inline with proper visual hierarchy.

\n

Features:

\n
    \n
  • Chevron Controls: Click chevron icons on project task cards to expand/collapse subtask display
  • \n
  • Configurable: New "Show expandable subtasks" setting allows users to enable/disable the feature
  • \n
\n

Responsive Pomodoro View#

\n

The Pomodoro view now adapts seamlessly to different container sizes with comprehensive responsive design.

\n

Thanks to @oliverlalan for requesting this improvement (#339).

\n

Enhanced Filename Templates#

\n

Significant expansion of available template variables for task creation, providing much greater flexibility in filename patterns.

\n

New Template Variables:

\n
    \n
  • Date/Time Variations: shortDate, monthName, dayName, week, quarter, time12, time24
  • \n
  • Unix Timestamps: unix (seconds), unixMs (milliseconds)
  • \n
  • Title Case Variations: titleLower, titleUpper, titleSnake, titleKebab, titleCamel, titlePascal
  • \n
  • Short Forms: priorityShort, statusShort for single-letter representations
  • \n
  • Unique Identifiers: zettel (Zettelkasten ID), nano (high-precision unique ID)
  • \n
\n

The settings UI now documents all 40+ available template variables for easy reference.

\n

Thanks to @fastrick for the original unix timestamp request.

\n

Bug Fixes#

\n

Critical Timezone Handling Fixes#

\n

This release resolves multiple timezone-related bugs that affected users worldwide, particularly those in non-UTC timezones. These fixes implement the "UTC Anchor" principle for consistent date handling.

\n

Major Timezone Bugs Fixed:

\n
    \n
  • Recurring Task Completion: Fixed critical issue where marking recurring tasks complete would affect the wrong day for users in certain timezones, addressing reports from multiple users including issues #327, #322, and #314
  • \n
  • Calendar Date Misalignment: Resolved off-by-one day errors in calendar rendering and task indicators, addressing inconsistencies across different views (originally reported by @Crunchnuggetz in issue #129, with additional reports from @donjjones and @robmikulec)
  • \n
  • Weekly Task Display: Fixed issue where weekly recurring tasks set for specific days (e.g., Tuesdays) were showing completion dates on the wrong day (Monday) - reported by @jpmoo in issue #322
  • \n
  • Task Completion Date Bug: Resolved bug where complete_instances was being set to the previous day, causing tasks to remain visible in Agenda view until manually corrected - reported in issue #314
  • \n
  • Date Parsing Inconsistencies: Eliminated mixing of UTC and local date parsing that caused timezone-dependent behavior across the application
  • \n
  • Filter Date Handling: Fixed date filtering to work consistently across all timezones
  • \n
  • Agenda View "Today" Detection: Corrected timezone-sensitive today detection that affected agenda headers
  • \n
  • ICS Import Timezone Issues: Resolved timezone problems with both recurring and single events from ICS imports
  • \n
\n

Technical Implementation:

\n
    \n
  • Introduced parseDateToUTC() function for consistent UTC anchoring of date-only strings
  • \n
  • Updated date comparison functions to use UTC anchors throughout
  • \n
  • Replaced timezone-sensitive date operations with consistent UTC-based alternatives
  • \n
  • Comprehensive audit and fix of all date handling patterns in the codebase
  • \n
\n

Project Filtering Improvements#

\n

Resolved critical bugs in project filtering that prevented proper task display and project selection.

\n

Fixes:

\n
    \n
  • Wikilink Resolution: Fixed handling of relative vs absolute project wikilinks (e.g., [[../Projects/My Project]] vs [[My Project]]) - thanks to @xorander00 for the detailed bug report
  • \n
  • Filter Grouping Logic: Corrected AND/OR grouping in project filters to prevent showing too many tasks
  • \n
  • Missing Projects: Fixed issue where not all projects appeared in filter dropdown selection
  • \n
  • Cache Management: Improved cache invalidation and project name extraction with better validation
  • \n
\n

Subtask Widget Improvements#

\n

Fixed several issues with the project subtasks widget affecting user experience and reliability.

\n

Widget Fixes:

\n
    \n
  • View State Persistence: Fixed issue where subtask widget views would reset when switching between notes or modifying subtasks (reported by @Poly-0000 in issue #329)
  • \n
  • Filter State Isolation: Prevented filter settings from bleeding between different notes' subtask widgets
  • \n
  • Configurable Positioning: Added setting to control widget placement at top or bottom of notes (requested by @michelebugio in issue #164)
  • \n
  • Event Listener Management: Improved cleanup to prevent memory leaks and event accumulation
  • \n
  • Event Bubbling: Fixed issue where clicking subtasks would trigger both subtask and parent task modals
  • \n
  • Styling Isolation: Prevented completion styles from affecting nested subtasks incorrectly
  • \n
\n

ICS Calendar Integration#

\n

Timezone Processing: Fixed timezone handling bug in ICS calendar subscriptions where VTIMEZONE components weren't being registered before parsing events, causing incorrect display times for timezone-specific calendar events.

\n

Performance and Reliability#

\n

Cache Optimization: Restored FilterService cache TTL to 30 seconds after temporary reduction, balancing performance with data freshness.

\n

Type Safety: Added proper type assertions for ICAL.TimezoneService calls to resolve TypeScript compilation issues.

\n

Error Handling: Enhanced error handling and null safety checks throughout project filtering and service initialization.

\n

Technical Improvements#

\n

UTC Anchor Implementation#

\n

Comprehensive implementation of the UTC Anchor principle for robust timezone handling:

\n
    \n
  • All date-only strings now consistently parsed as UTC anchors
  • \n
  • Date comparison operations standardized using UTC methods
  • \n
  • Eliminated timezone-dependent date creation patterns
  • \n
  • Added comprehensive timezone test coverage
  • \n
\n

Service Architecture#

\n

Expanded Projects Service: Enhanced state management and tracking for expandable project subtasks with proper cleanup and memory management.

\n

View State Manager: Improved view state persistence across different contexts and note switches.

\n

Documentation Updates#

\n
    \n
  • Updated recurring tasks documentation to reflect new behavior
  • \n
  • Added timezone handling guides for developers
  • \n
  • Enhanced calendar views documentation with drag behavior explanations
  • \n
  • Comprehensive template variable documentation
  • \n
\n

Breaking Changes#

\n

Date Handling: While maintaining backward compatibility for user data, the internal date handling now consistently uses the UTC Anchor principle.

\n

Migration Notes#

\n

Existing recurring tasks will continue to work without modification. The system automatically adds DTSTART components when users interact with recurring tasks (completing, editing, or rescheduling).

\n","text":"Major Features# Enhanced Recurring Tasks with DTSTART Support# This release introduces improvements to recurring task handling with full DTSTART (start date/time) integration, addressing long-standing challenges in recurring task management and filtering. Background and Motivation: The previous recurring task system created difficulties for users in filtering and managing task schedules. Users experienced unintuitive behavior where recurring tasks couldn't be treated consistently with regular tasks, making it challenging to see when the next occurrence would appear or to dynamically update task schedules upon completion. This implementation follows RFC 5545 standards to provide a more robust foundation for recurring task behavior. Key Improvements: DTSTART Integration: All recurring tasks now include proper start dates and times in their recurrence rules, ensuring consistent behavior across timezones and providing a clear anchor point for the recurring pattern Dynamic Date Updates: The task.scheduled field now always shows the next uncompleted occurrence, automatically updating when tasks are completed rather than showing static pattern dates Flexible Next Occurrence Scheduling: The next scheduled occurrence can now be placed anywhere - before the pattern start date, outside the recurring pattern, or at any custom time, giving users complete control over scheduling Visual Hierarchy: Pattern instances display with dashed borders while the next scheduled occurrence shows with solid borders, providing clear visual distinction between the recurring pattern and the active next task Independent Time Control: Pattern instances and next occurrences can have different times (e.g., daily pattern at 9 AM, next occurrence at 2:30 PM), allowing for exceptions without breaking the recurring pattern Dual Drag Behavior: Dragging pattern instances updates the recurring pattern timing globally, while dragging the next occurrence reschedules only that specific instance Automatic DTSTART Addition: The system automatically adds DTSTART when completing recurring tasks, editing recurrence rules, or converting tasks to recurring, ensuring backward compatibility while upgrading task definitions Manual Rescheduling Support: Clear flags indicate when tasks have been manually rescheduled, maintaining transparency about schedule modifications Expandable Project Subtasks# A new feature allows users to expand project task cards to view subtasks inline with proper visual hierarchy. Features: Chevron Controls: Click chevron icons on project task cards to expand/collapse subtask display Configurable: New \"Show expandable subtasks\" setting allows users to enable/disable the feature Responsive Pomodoro View# The Pomodoro view now adapts seamlessly to different container sizes with comprehensive responsive design. Thanks to @oliverlalan for requesting this improvement (#339). Enhanced Filename Templates# Significant expansion of available template variables for task creation, providing much greater flexibility in filename patterns. New Template Variables: Date/Time Variations: shortDate, monthName, dayName, week, quarter, time12, time24 Unix Timestamps: unix (seconds), unixMs (milliseconds) Title Case Variations: titleLower, titleUpper, titleSnake, titleKebab, titleCamel, titlePascal Short Forms: priorityShort, statusShort for single-letter representations Unique Identifiers: zettel (Zettelkasten ID), nano (high-precision unique ID) The settings UI now documents all 40+ available template variables for easy reference. Thanks to @fastrick for the original unix timestamp request. Bug Fixes# Critical Timezone Handling Fixes# This release resolves multiple timezone-related bugs that affected users worldwide, particularly those in non-UTC timezones. These fixes implement the \"UTC Anchor\" principle for consistent date handling. Major Timezone Bugs Fixed: Recurring Task Completion: Fixed critical issue where marking recurring tasks complete would affect the wrong day for users in certain timezones, addressing reports from multiple users including issues #327, #322, and #314 Calendar Date Misalignment: Resolved off-by-one day errors in calendar rendering and task indicators, addressing inconsistencies across different views (originally reported by @Crunchnuggetz in issue #129, with additional reports from @donjjones and @robmikulec) Weekly Task Display: Fixed issue where weekly recurring tasks set for specific days (e.g., Tuesdays) were showing completion dates on the wrong day (Monday) - reported by @jpmoo in issue #322 Task Completion Date Bug: Resolved bug where complete_instances was being set to the previous day, causing tasks to remain visible in Agenda view until manually corrected - reported in issue #314 Date Parsing Inconsistencies: Eliminated mixing of UTC and local date parsing that caused timezone-dependent behavior across the application Filter Date Handling: Fixed date filtering to work consistently across all timezones Agenda View \"Today\" Detection: Corrected timezone-sensitive today detection that affected agenda headers ICS Import Timezone Issues: Resolved timezone problems with both recurring and single events from ICS imports Technical Implementation: Introduced parseDateToUTC() function for consistent UTC anchoring of date-only strings Updated date comparison functions to use UTC anchors throughout Replaced timezone-sensitive date operations with consistent UTC-based alternatives Comprehensive audit and fix of all date handling patterns in the codebase Project Filtering Improvements# Resolved critical bugs in project filtering that prevented proper task display and project selection. Fixes: Wikilink Resolution: Fixed handling of relative vs absolute project wikilinks (e.g., [[../Projects/My Project]] vs [[My Project]]) - thanks to @xorander00 for the detailed bug report Filter Grouping Logic: Corrected AND/OR grouping in project filters to prevent showing too many tasks Missing Projects: Fixed issue where not all projects appeared in filter dropdown selection Cache Management: Improved cache invalidation and project name extraction with better validation Subtask Widget Improvements# Fixed several issues with the project subtasks widget affecting user experience and reliability. Widget Fixes: View State Persistence: Fixed issue where subtask widget views would reset when switching between notes or modifying subtasks (reported by @Poly-0000 in issue #329) Filter State Isolation: Prevented filter settings from bleeding between different notes' subtask widgets Configurable Positioning: Added setting to control widget placement at top or bottom of notes (requested by @michelebugio in issue #164) Event Listener Management: Improved cleanup to prevent memory leaks and event accumulation Event Bubbling: Fixed issue where clicking subtasks would trigger both subtask and parent task modals Styling Isolation: Prevented completion styles from affecting nested subtasks incorrectly ICS Calendar Integration# Timezone Processing: Fixed timezone handling bug in ICS calendar subscriptions where VTIMEZONE components weren't being registered before parsing events, causing incorrect display times for timezone-specific calendar events. Performance and Reliability# Cache Optimization: Restored FilterService cache TTL to 30 seconds after temporary reduction, balancing performance with data freshness. Type Safety: Added proper type assertions for ICAL.TimezoneService calls to resolve TypeScript compilation issues. Error Handling: Enhanced error handling and null safety checks throughout project filtering and service initialization. Technical Improvements# UTC Anchor Implementation# Comprehensive implementation of the UTC Anchor principle for robust timezone handling: All date-only strings now consistently parsed as UTC anchors Date comparison operations standardized using UTC methods Eliminated timezone-dependent date creation patterns Added comprehensive timezone test coverage Service Architecture# Expanded Projects Service: Enhanced state management and tracking for expandable project subtasks with proper cleanup and memory management. View State Manager: Improved view state persistence across different contexts and note switches. Documentation Updates# Updated recurring tasks documentation to reflect new behavior Added timezone handling guides for developers Enhanced calendar views documentation with drag behavior explanations Comprehensive template variable documentation Breaking Changes# Date Handling: While maintaining backward compatibility for user data, the internal date handling now consistently uses the UTC Anchor principle. Migration Notes# Existing recurring tasks will continue to work without modification. The system automatically adds DTSTART components when users interact with recurring tasks (completing, editing, or rescheduling)."},{"route":"/obsidian/releases/3.17.1/","title":"TaskNotes 3.17.1","description":"This patch release resolves three critical timezone-related bugs that affected users in specific timezones, particularly those west of UTC (such as users in the Americas). These...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.17.1.md","namespace":"obsidian","relativePath":"releases/3.17.1.md","raw":"# TaskNotes 3.17.1\n\n## Bug Fixes\n\n### Critical Timezone Handling Fixes\n\nThis patch release resolves three critical timezone-related bugs that affected users in specific timezones, particularly those west of UTC (such as users in the Americas). These fixes ensure consistent calendar rendering and task interaction behavior across all timezones.\n\n#### Completions Calendar Rendering (#322)\n\nFixed three critical timezone bugs in the completions calendar that caused visual misalignment for users in timezones west of UTC:\n\n- **Day Number Display**: Corrected day numbers in the calendar grid to display accurately regardless of user timezone by replacing timezone-sensitive formatting with UTC-anchored date extraction\n- **Month Comparison Logic**: Fixed current month highlighting logic that was mixing local and UTC date values, causing incorrect month boundary detection\n- **Calendar Navigation**: Updated previous/next month navigation to use consistent UTC methods, preventing timezone drift when navigating between months\n\nThese fixes ensure the completions calendar visual representation aligns with the underlying UTC-anchored recurrence data for all users.\n\n#### Advanced Calendar Drag-and-Drop Operations (#344)\n\nResolved a critical bug where all-day tasks would shift back by one day after dragging and dropping them in the Advanced Calendar view. This issue particularly affected users in timezones ahead of UTC.\n\nThanks to @trang-ngn for reporting this issue with clear reproduction steps.\n\n**Root Cause**: The drag-and-drop system was using `formatDateForStorage()` which applies UTC methods to Date objects provided by FullCalendar. For users in positive UTC offset timezones, this would cause the stored date to be one day earlier than the date shown in the UI.\n\n**Fixed Operations**:\n\n- All-day and timed event drag-and-drop (`handleEventDrop`)\n- External task drag-and-drop from outside the calendar (`handleExternalDrop`)\n- Modal-based task scheduling (`scheduleTask`)\n- Date selection task creation (`handleDateSelect`)\n- Timeblock creation and event resizing operations\n- Event context menu date handling\n\nThe fix ensures that the date displayed in the calendar UI exactly matches the date that gets stored in the task data.\n\n#### Task Completion Status Checks (#322)\n\nFixed incorrect completion status checks in recurring tasks caused by timezone-sensitive date formatting in `getEffectiveTaskStatus()`. \n\n**Root Cause**: The function was using timezone-sensitive `date-fns format()` for completion date comparisons, causing completion status to be checked against the wrong date for users west of UTC (e.g., checking October 26 instead of October 27 for EDT users).\n\n**Solution**: Replaced timezone-sensitive formatting with `formatDateForStorage()` to ensure consistent UTC-anchored date strings that match the format used in `complete_instances`.\n\nThis fix ensures recurring task completions are correctly identified regardless of user timezone, preventing tasks from incorrectly appearing as incomplete.\n\n## Technical Implementation\n\nAll fixes implement the established \"UTC Anchor\" principle for consistent timezone handling:\n\n- Consistent use of UTC-anchored date operations for date-only comparisons\n- Replacement of timezone-sensitive date formatting with UTC-based alternatives \n- Proper separation of display dates (which can be timezone-sensitive) from storage dates (which must be timezone-neutral)\n\n","aliases":["/releases/3.17.1/","/releases/3.17.1/"],"toc":[{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"critical-timezone-handling-fixes","text":"Critical Timezone Handling Fixes"},{"level":2,"id":"technical-implementation","text":"Technical Implementation"}],"html":"

Bug Fixes#

\n

Critical Timezone Handling Fixes#

\n

This patch release resolves three critical timezone-related bugs that affected users in specific timezones, particularly those west of UTC (such as users in the Americas). These fixes ensure consistent calendar rendering and task interaction behavior across all timezones.

\n

Completions Calendar Rendering (#322)#

\n

Fixed three critical timezone bugs in the completions calendar that caused visual misalignment for users in timezones west of UTC:

\n
    \n
  • Day Number Display: Corrected day numbers in the calendar grid to display accurately regardless of user timezone by replacing timezone-sensitive formatting with UTC-anchored date extraction
  • \n
  • Month Comparison Logic: Fixed current month highlighting logic that was mixing local and UTC date values, causing incorrect month boundary detection
  • \n
  • Calendar Navigation: Updated previous/next month navigation to use consistent UTC methods, preventing timezone drift when navigating between months
  • \n
\n

These fixes ensure the completions calendar visual representation aligns with the underlying UTC-anchored recurrence data for all users.

\n

Advanced Calendar Drag-and-Drop Operations (#344)#

\n

Resolved a critical bug where all-day tasks would shift back by one day after dragging and dropping them in the Advanced Calendar view. This issue particularly affected users in timezones ahead of UTC.

\n

Thanks to @trang-ngn for reporting this issue with clear reproduction steps.

\n

Root Cause: The drag-and-drop system was using formatDateForStorage() which applies UTC methods to Date objects provided by FullCalendar. For users in positive UTC offset timezones, this would cause the stored date to be one day earlier than the date shown in the UI.

\n

Fixed Operations:

\n
    \n
  • All-day and timed event drag-and-drop (handleEventDrop)
  • \n
  • External task drag-and-drop from outside the calendar (handleExternalDrop)
  • \n
  • Modal-based task scheduling (scheduleTask)
  • \n
  • Date selection task creation (handleDateSelect)
  • \n
  • Timeblock creation and event resizing operations
  • \n
  • Event context menu date handling
  • \n
\n

The fix ensures that the date displayed in the calendar UI exactly matches the date that gets stored in the task data.

\n

Task Completion Status Checks (#322)#

\n

Fixed incorrect completion status checks in recurring tasks caused by timezone-sensitive date formatting in getEffectiveTaskStatus().

\n

Root Cause: The function was using timezone-sensitive date-fns format() for completion date comparisons, causing completion status to be checked against the wrong date for users west of UTC (e.g., checking October 26 instead of October 27 for EDT users).

\n

Solution: Replaced timezone-sensitive formatting with formatDateForStorage() to ensure consistent UTC-anchored date strings that match the format used in complete_instances.

\n

This fix ensures recurring task completions are correctly identified regardless of user timezone, preventing tasks from incorrectly appearing as incomplete.

\n

Technical Implementation#

\n

All fixes implement the established "UTC Anchor" principle for consistent timezone handling:

\n
    \n
  • Consistent use of UTC-anchored date operations for date-only comparisons
  • \n
  • Replacement of timezone-sensitive date formatting with UTC-based alternatives
  • \n
  • Proper separation of display dates (which can be timezone-sensitive) from storage dates (which must be timezone-neutral)
  • \n
\n","text":"Bug Fixes# Critical Timezone Handling Fixes# This patch release resolves three critical timezone-related bugs that affected users in specific timezones, particularly those west of UTC (such as users in the Americas). These fixes ensure consistent calendar rendering and task interaction behavior across all timezones. Completions Calendar Rendering (#322)# Fixed three critical timezone bugs in the completions calendar that caused visual misalignment for users in timezones west of UTC: Day Number Display: Corrected day numbers in the calendar grid to display accurately regardless of user timezone by replacing timezone-sensitive formatting with UTC-anchored date extraction Month Comparison Logic: Fixed current month highlighting logic that was mixing local and UTC date values, causing incorrect month boundary detection Calendar Navigation: Updated previous/next month navigation to use consistent UTC methods, preventing timezone drift when navigating between months These fixes ensure the completions calendar visual representation aligns with the underlying UTC-anchored recurrence data for all users. Advanced Calendar Drag-and-Drop Operations (#344)# Resolved a critical bug where all-day tasks would shift back by one day after dragging and dropping them in the Advanced Calendar view. This issue particularly affected users in timezones ahead of UTC. Thanks to @trang-ngn for reporting this issue with clear reproduction steps. Root Cause: The drag-and-drop system was using formatDateForStorage() which applies UTC methods to Date objects provided by FullCalendar. For users in positive UTC offset timezones, this would cause the stored date to be one day earlier than the date shown in the UI. Fixed Operations: All-day and timed event drag-and-drop (handleEventDrop) External task drag-and-drop from outside the calendar (handleExternalDrop) Modal-based task scheduling (scheduleTask) Date selection task creation (handleDateSelect) Timeblock creation and event resizing operations Event context menu date handling The fix ensures that the date displayed in the calendar UI exactly matches the date that gets stored in the task data. Task Completion Status Checks (#322)# Fixed incorrect completion status checks in recurring tasks caused by timezone-sensitive date formatting in getEffectiveTaskStatus(). Root Cause: The function was using timezone-sensitive date-fns format() for completion date comparisons, causing completion status to be checked against the wrong date for users west of UTC (e.g., checking October 26 instead of October 27 for EDT users). Solution: Replaced timezone-sensitive formatting with formatDateForStorage() to ensure consistent UTC-anchored date strings that match the format used in complete_instances. This fix ensures recurring task completions are correctly identified regardless of user timezone, preventing tasks from incorrectly appearing as incomplete. Technical Implementation# All fixes implement the established \"UTC Anchor\" principle for consistent timezone handling: Consistent use of UTC-anchored date operations for date-only comparisons Replacement of timezone-sensitive date formatting with UTC-based alternatives Proper separation of display dates (which can be timezone-sensitive) from storage dates (which must be timezone-neutral)"},{"route":"/obsidian/releases/3.18.0/","title":"TaskNotes 3.18.0","description":"A complete reminder system has been added to TaskNotes, providing iCalendar VALARM-compliant reminder functionality.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.18.0.md","namespace":"obsidian","relativePath":"releases/3.18.0.md","raw":"# TaskNotes 3.18.0\n\n## New Features\n\n### Task Reminders System\n\nA complete reminder system has been added to TaskNotes, providing iCalendar VALARM-compliant reminder functionality.\n\n**Core Features:**\n\n- Support for both relative reminders (e.g., \"15 minutes before due date\") and absolute reminders (specific date/time)\n- Visual reminder indicators on task cards with clickable bell icons\n- Integration with task creation and editing workflows\n\n**User Interface:**\n\n- **Reminder Modal**: Modal for managing task reminders with form validation and real-time preview\n- **Reminder Context Menu**: Quick access to common reminder options (5min, 15min, 1hr, 1day before due/scheduled dates)\n- Reminder management accessible from task creation modal, edit modal, and task cards\n\n**Default Reminders:**\n\n- Configure default reminders that automatically apply to new tasks\n- Support for multiple default reminders per task type\n- Applies to both manual task creation and instant conversion workflows\n\n### Property-Based Task Identification\n\nTasks can now be identified using frontmatter properties instead of requiring tags.\n\n- Configure property name and value for task identification (e.g., `categories: [[Tasks]]`)\n- Full backward compatibility with existing tag-based workflows\n- Addresses modern Obsidian property-based vault organization patterns\n\n*Thanks to @mdbraber for the feature request (#340)*\n\n### Enhanced Saved Views\n- Clicking an active saved view now clears all filters, providing quick access to unfiltered task list\n- Preserves sort and group settings while resetting filters\n\n*Thanks to @oldjove for the suggestion (#351)*\n\n### Parent Note as Project Option\n- New setting to automatically use parent note as project during instant task conversion\n- Useful for users who organize tasks within project-specific notes\n- Merges with existing default projects to avoid duplicates\n\n*Thanks to @FindingJohnny for the feature request (#348)*\n\n## Bug Fixes\n\n### ICS Calendar Integration\n\n- **Fixed recurring event exceptions**: Properly handle EXDATE properties and RECURRENCE-ID for modified instances\n- **Eliminated duplicate events**: Resolved issue where deleted or rescheduled recurring events from external calendars still appeared\n\n*Thanks to @robmikulec for reporting the recurring events issue (#342)*\n\n### Settings Persistence\n\n- **Fixed settings reset during updates**: Prevent user configuration loss when plugin updates introduce new default settings\n- Apply deep merge strategy to preserve customizations in nested configuration objects\n\n## Improvements\n\n### User Interface\n\n- Reminder modal uses consistent design patterns with task creation/edit modals\n- Fixed task card icon overlap issues with proper spacing for multiple indicators\n\n### Code Quality\n\n- Added unit test coverage for new reminder functionality\n- Improved type safety with proper TypeScript interfaces for reminder data structures\n- Improved error handling and user feedback across reminder operations\n\n## Technical Details\n\n### Data Model Changes\n\n- Added optional `reminders` array field to TaskInfo interface\n- Extended field mapping support for custom reminder property names\n- Enhanced cache system to include reminder data in task extraction\n\n","aliases":["/releases/3.18.0/","/releases/3.18.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"task-reminders-system","text":"Task Reminders System"},{"level":3,"id":"property-based-task-identification","text":"Property-Based Task Identification"},{"level":3,"id":"enhanced-saved-views","text":"Enhanced Saved Views"},{"level":3,"id":"parent-note-as-project-option","text":"Parent Note as Project Option"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"ics-calendar-integration","text":"ICS Calendar Integration"},{"level":3,"id":"settings-persistence","text":"Settings Persistence"},{"level":2,"id":"improvements","text":"Improvements"},{"level":3,"id":"user-interface","text":"User Interface"},{"level":3,"id":"code-quality","text":"Code Quality"},{"level":2,"id":"technical-details","text":"Technical Details"},{"level":3,"id":"data-model-changes","text":"Data Model Changes"}],"html":"

New Features#

\n

Task Reminders System#

\n

A complete reminder system has been added to TaskNotes, providing iCalendar VALARM-compliant reminder functionality.

\n

Core Features:

\n
    \n
  • Support for both relative reminders (e.g., "15 minutes before due date") and absolute reminders (specific date/time)
  • \n
  • Visual reminder indicators on task cards with clickable bell icons
  • \n
  • Integration with task creation and editing workflows
  • \n
\n

User Interface:

\n
    \n
  • Reminder Modal: Modal for managing task reminders with form validation and real-time preview
  • \n
  • Reminder Context Menu: Quick access to common reminder options (5min, 15min, 1hr, 1day before due/scheduled dates)
  • \n
  • Reminder management accessible from task creation modal, edit modal, and task cards
  • \n
\n

Default Reminders:

\n
    \n
  • Configure default reminders that automatically apply to new tasks
  • \n
  • Support for multiple default reminders per task type
  • \n
  • Applies to both manual task creation and instant conversion workflows
  • \n
\n

Property-Based Task Identification#

\n

Tasks can now be identified using frontmatter properties instead of requiring tags.

\n
    \n
  • Configure property name and value for task identification (e.g., categories: [[Tasks]])
  • \n
  • Full backward compatibility with existing tag-based workflows
  • \n
  • Addresses modern Obsidian property-based vault organization patterns
  • \n
\n

Thanks to @mdbraber for the feature request (#340)

\n

Enhanced Saved Views#

\n
    \n
  • Clicking an active saved view now clears all filters, providing quick access to unfiltered task list
  • \n
  • Preserves sort and group settings while resetting filters
  • \n
\n

Thanks to @oldjove for the suggestion (#351)

\n

Parent Note as Project Option#

\n
    \n
  • New setting to automatically use parent note as project during instant task conversion
  • \n
  • Useful for users who organize tasks within project-specific notes
  • \n
  • Merges with existing default projects to avoid duplicates
  • \n
\n

Thanks to @FindingJohnny for the feature request (#348)

\n

Bug Fixes#

\n

ICS Calendar Integration#

\n
    \n
  • Fixed recurring event exceptions: Properly handle EXDATE properties and RECURRENCE-ID for modified instances
  • \n
  • Eliminated duplicate events: Resolved issue where deleted or rescheduled recurring events from external calendars still appeared
  • \n
\n

Thanks to @robmikulec for reporting the recurring events issue (#342)

\n

Settings Persistence#

\n
    \n
  • Fixed settings reset during updates: Prevent user configuration loss when plugin updates introduce new default settings
  • \n
  • Apply deep merge strategy to preserve customizations in nested configuration objects
  • \n
\n

Improvements#

\n

User Interface#

\n
    \n
  • Reminder modal uses consistent design patterns with task creation/edit modals
  • \n
  • Fixed task card icon overlap issues with proper spacing for multiple indicators
  • \n
\n

Code Quality#

\n
    \n
  • Added unit test coverage for new reminder functionality
  • \n
  • Improved type safety with proper TypeScript interfaces for reminder data structures
  • \n
  • Improved error handling and user feedback across reminder operations
  • \n
\n

Technical Details#

\n

Data Model Changes#

\n
    \n
  • Added optional reminders array field to TaskInfo interface
  • \n
  • Extended field mapping support for custom reminder property names
  • \n
  • Enhanced cache system to include reminder data in task extraction
  • \n
\n","text":"New Features# Task Reminders System# A complete reminder system has been added to TaskNotes, providing iCalendar VALARM-compliant reminder functionality. Core Features: Support for both relative reminders (e.g., \"15 minutes before due date\") and absolute reminders (specific date/time) Visual reminder indicators on task cards with clickable bell icons Integration with task creation and editing workflows User Interface: Reminder Modal: Modal for managing task reminders with form validation and real-time preview Reminder Context Menu: Quick access to common reminder options (5min, 15min, 1hr, 1day before due/scheduled dates) Reminder management accessible from task creation modal, edit modal, and task cards Default Reminders: Configure default reminders that automatically apply to new tasks Support for multiple default reminders per task type Applies to both manual task creation and instant conversion workflows Property-Based Task Identification# Tasks can now be identified using frontmatter properties instead of requiring tags. Configure property name and value for task identification (e.g., categories: [[Tasks]]) Full backward compatibility with existing tag-based workflows Addresses modern Obsidian property-based vault organization patterns Thanks to @mdbraber for the feature request (#340) Enhanced Saved Views# Clicking an active saved view now clears all filters, providing quick access to unfiltered task list Preserves sort and group settings while resetting filters Thanks to @oldjove for the suggestion (#351) Parent Note as Project Option# New setting to automatically use parent note as project during instant task conversion Useful for users who organize tasks within project-specific notes Merges with existing default projects to avoid duplicates Thanks to @FindingJohnny for the feature request (#348) Bug Fixes# ICS Calendar Integration# Fixed recurring event exceptions: Properly handle EXDATE properties and RECURRENCE-ID for modified instances Eliminated duplicate events: Resolved issue where deleted or rescheduled recurring events from external calendars still appeared Thanks to @robmikulec for reporting the recurring events issue (#342) Settings Persistence# Fixed settings reset during updates: Prevent user configuration loss when plugin updates introduce new default settings Apply deep merge strategy to preserve customizations in nested configuration objects Improvements# User Interface# Reminder modal uses consistent design patterns with task creation/edit modals Fixed task card icon overlap issues with proper spacing for multiple indicators Code Quality# Added unit test coverage for new reminder functionality Improved type safety with proper TypeScript interfaces for reminder data structures Improved error handling and user feedback across reminder operations Technical Details# Data Model Changes# Added optional reminders array field to TaskInfo interface Extended field mapping support for custom reminder property names Enhanced cache system to include reminder data in task extraction"},{"route":"/obsidian/releases/3.18.1/","title":"TaskNotes 3.18.1","description":"Fixed critical race conditions in cache synchronization that occurred when task operations completed before Obsidian's metadata cache had fully processed file changes. This...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.18.1.md","namespace":"obsidian","relativePath":"releases/3.18.1.md","raw":"# TaskNotes 3.18.1\n\n## Bug Fixes\n\n### Cache Synchronization Race Conditions (#358)\n\nFixed critical race conditions in cache synchronization that occurred when task operations completed before Obsidian's metadata cache had fully processed file changes. This resulted in stale or missing task data across all calendar views and task operations.\n\n*Thanks to @willgraham345 for reporting the calendar auto-refresh issue*\n\n## Code Quality Improvements\n\n### Event Listener Management\n\nSimplified event listener cleanup in AdvancedCalendarView by removing manual listener tracking array.\n\n## Technical Details\n\n**Cache Synchronization Strategy**: The implementation follows a \"wait-then-update\" pattern where all cache modifications are preceded by verification that Obsidian's metadata cache contains the expected changes. This prevents race conditions while maintaining performance through minimal wait times.\n\n","aliases":["/releases/3.18.1/","/releases/3.18.1/"],"toc":[{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"cache-synchronization-race-conditions-358","text":"Cache Synchronization Race Conditions (#358)"},{"level":2,"id":"code-quality-improvements","text":"Code Quality Improvements"},{"level":3,"id":"event-listener-management","text":"Event Listener Management"},{"level":2,"id":"technical-details","text":"Technical Details"}],"html":"

Bug Fixes#

\n

Cache Synchronization Race Conditions (#358)#

\n

Fixed critical race conditions in cache synchronization that occurred when task operations completed before Obsidian's metadata cache had fully processed file changes. This resulted in stale or missing task data across all calendar views and task operations.

\n

Thanks to @willgraham345 for reporting the calendar auto-refresh issue

\n

Code Quality Improvements#

\n

Event Listener Management#

\n

Simplified event listener cleanup in AdvancedCalendarView by removing manual listener tracking array.

\n

Technical Details#

\n

Cache Synchronization Strategy: The implementation follows a "wait-then-update" pattern where all cache modifications are preceded by verification that Obsidian's metadata cache contains the expected changes. This prevents race conditions while maintaining performance through minimal wait times.

\n","text":"Bug Fixes# Cache Synchronization Race Conditions (#358)# Fixed critical race conditions in cache synchronization that occurred when task operations completed before Obsidian's metadata cache had fully processed file changes. This resulted in stale or missing task data across all calendar views and task operations. Thanks to @willgraham345 for reporting the calendar auto-refresh issue Code Quality Improvements# Event Listener Management# Simplified event listener cleanup in AdvancedCalendarView by removing manual listener tracking array. Technical Details# Cache Synchronization Strategy: The implementation follows a \"wait-then-update\" pattern where all cache modifications are preceded by verification that Obsidian's metadata cache contains the expected changes. This prevents race conditions while maintaining performance through minimal wait times."},{"route":"/obsidian/releases/3.18.2/","title":"TaskNotes 3.18.2","description":"Fixed timeblocks appearing one day earlier than expected by implementing the UTC Anchor pattern throughout the timeblocking feature. The previous implementation used problematic...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.18.2.md","namespace":"obsidian","relativePath":"releases/3.18.2.md","raw":"# TaskNotes 3.18.2\n\n## Bug Fixes\n\n### Timeblock Date Shift Issue (#368)\n\nFixed timeblocks appearing one day earlier than expected by implementing the UTC Anchor pattern throughout the timeblocking feature. The previous implementation used problematic millisecond-based date iteration that caused timezone-dependent date shift bugs.\n\nTimeblocks now appear on the correct calendar day regardless of user timezone or DST transitions.\n\n*Thanks to @zolotyh-dk for reporting this issue with detailed screenshots and system information.*\n\n### Performance Issues with Task Views\n\nEliminated typing lag that occurred when Task, Agenda, and Kanban views were open in large vaults. The plugin was triggering unnecessary view updates during text editing.\n\n## New Features\n\n### Enhanced Filename Template Variables (#370)\n\nAdded new timestamp variables for filename templates to support ISO 8601 formats and Google Keep compatibility:\n\n- `{milliseconds}`, `{ms}` - 3-digit milliseconds (000-999)\n- `{timezone}`, `{utcOffset}` - UTC offset in ±HH:MM format \n- `{timezoneShort}`, `{utcOffsetShort}` - UTC offset in ±HHMM format\n\n*Thanks to @mnipritom for requesting these variables*. \n\n### Boolean Property Identification\n\nEnhanced property-based task identification to handle boolean values correctly. Tasks can now be identified using boolean properties in frontmatter.\n\n*A big thanks to @renatomen for contributing the boolean property identification implementation, documentation, and test coverage*\n\n### Boolean Status Field Support (#108)\n\nAdded automatic boolean conversion for status values to support Obsidian's checkbox property format. The status field now handles boolean true/false values:\n\n- String \"true\" → boolean true (in frontmatter)\n- String \"false\" → boolean false (in frontmatter) \n- Boolean true → string \"true\" (when read back)\n- Boolean false → string \"false\" (when read back)\n- Other status values remain unchanged as strings\n\n*Thanks to @arminta7 for reporting the checkbox property compatibility issue and @imed-ghomari for contributing to the discussion on status field handling.*\n*And thanks again to @renatomen--the boolean property identification fix inspired this change!*","aliases":["/releases/3.18.2/","/releases/3.18.2/"],"toc":[{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"timeblock-date-shift-issue-368","text":"Timeblock Date Shift Issue (#368)"},{"level":3,"id":"performance-issues-with-task-views","text":"Performance Issues with Task Views"},{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"enhanced-filename-template-variables-370","text":"Enhanced Filename Template Variables (#370)"},{"level":3,"id":"boolean-property-identification","text":"Boolean Property Identification"},{"level":3,"id":"boolean-status-field-support-108","text":"Boolean Status Field Support (#108)"}],"html":"

Bug Fixes#

\n

Timeblock Date Shift Issue (#368)#

\n

Fixed timeblocks appearing one day earlier than expected by implementing the UTC Anchor pattern throughout the timeblocking feature. The previous implementation used problematic millisecond-based date iteration that caused timezone-dependent date shift bugs.

\n

Timeblocks now appear on the correct calendar day regardless of user timezone or DST transitions.

\n

Thanks to @zolotyh-dk for reporting this issue with detailed screenshots and system information.

\n

Performance Issues with Task Views#

\n

Eliminated typing lag that occurred when Task, Agenda, and Kanban views were open in large vaults. The plugin was triggering unnecessary view updates during text editing.

\n

New Features#

\n

Enhanced Filename Template Variables (#370)#

\n

Added new timestamp variables for filename templates to support ISO 8601 formats and Google Keep compatibility:

\n
    \n
  • {milliseconds}, {ms} - 3-digit milliseconds (000-999)
  • \n
  • {timezone}, {utcOffset} - UTC offset in ±HH:MM format
  • \n
  • {timezoneShort}, {utcOffsetShort} - UTC offset in ±HHMM format
  • \n
\n

Thanks to @mnipritom for requesting these variables.

\n

Boolean Property Identification#

\n

Enhanced property-based task identification to handle boolean values correctly. Tasks can now be identified using boolean properties in frontmatter.

\n

A big thanks to @renatomen for contributing the boolean property identification implementation, documentation, and test coverage

\n

Boolean Status Field Support (#108)#

\n

Added automatic boolean conversion for status values to support Obsidian's checkbox property format. The status field now handles boolean true/false values:

\n
    \n
  • String "true" → boolean true (in frontmatter)
  • \n
  • String "false" → boolean false (in frontmatter)
  • \n
  • Boolean true → string "true" (when read back)
  • \n
  • Boolean false → string "false" (when read back)
  • \n
  • Other status values remain unchanged as strings
  • \n
\n

Thanks to @arminta7 for reporting the checkbox property compatibility issue and @imed-ghomari for contributing to the discussion on status field handling.\nAnd thanks again to @renatomen--the boolean property identification fix inspired this change!

\n","text":"Bug Fixes# Timeblock Date Shift Issue (#368)# Fixed timeblocks appearing one day earlier than expected by implementing the UTC Anchor pattern throughout the timeblocking feature. The previous implementation used problematic millisecond-based date iteration that caused timezone-dependent date shift bugs. Timeblocks now appear on the correct calendar day regardless of user timezone or DST transitions. Thanks to @zolotyh-dk for reporting this issue with detailed screenshots and system information. Performance Issues with Task Views# Eliminated typing lag that occurred when Task, Agenda, and Kanban views were open in large vaults. The plugin was triggering unnecessary view updates during text editing. New Features# Enhanced Filename Template Variables (#370)# Added new timestamp variables for filename templates to support ISO 8601 formats and Google Keep compatibility: {milliseconds}, {ms} - 3-digit milliseconds (000-999) {timezone}, {utcOffset} - UTC offset in ±HH:MM format {timezoneShort}, {utcOffsetShort} - UTC offset in ±HHMM format Thanks to @mnipritom for requesting these variables. Boolean Property Identification# Enhanced property-based task identification to handle boolean values correctly. Tasks can now be identified using boolean properties in frontmatter. A big thanks to @renatomen for contributing the boolean property identification implementation, documentation, and test coverage Boolean Status Field Support (#108)# Added automatic boolean conversion for status values to support Obsidian's checkbox property format. The status field now handles boolean true/false values: String \"true\" → boolean true (in frontmatter) String \"false\" → boolean false (in frontmatter) Boolean true → string \"true\" (when read back) Boolean false → string \"false\" (when read back) Other status values remain unchanged as strings Thanks to @arminta7 for reporting the checkbox property compatibility issue and @imed-ghomari for contributing to the discussion on status field handling. And thanks again to @renatomen--the boolean property identification fix inspired this change!"},{"route":"/obsidian/releases/3.19.0/","title":"TaskNotes 3.19.0","description":"TaskNotes now includes a HTTP REST API that enables external integrations and powers companion projects. The API provides full task management capabilities with intelligent natu...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.19.0.md","namespace":"obsidian","relativePath":"releases/3.19.0.md","raw":"# TaskNotes 3.19.0\n\n## New Features\n\n### HTTP REST API with Natural Language Processing\n\nTaskNotes now includes a HTTP REST API that enables external integrations and powers companion projects. The API provides full task management capabilities with intelligent natural language processing.\n\n**Key API Features:**\n\n- Complete CRUD operations for tasks\n- Time tracking endpoints\n- Task statistics and filtering\n- Bearer token authentication\n- CORS support for browser extensions\n- Desktop-only implementation with mobile-safe architecture\n\n**Natural Language Processing Endpoints:**\n\n- `/api/nlp/parse` - Parse natural language into structured task data\n- `/api/nlp/create` - Create tasks directly from natural language input\n- Supports extraction of dates, times, priorities, tags, contexts, projects, and recurrence\n- Intelligent parsing of expressions like \"Review PR #123 tomorrow high priority @work\"\n\n**Companion Project Integration:**\n\nThe HTTP API enables two new companion projects:\n- [tasknotes-cli](https://github.com/callumalpass/tasknotes-cli) - Command-line interface for TaskNotes task management\n- [tasknotes-browser-extension](https://github.com/callumalpass/tasknotes-browser-extension) - Browser extension for quick task creation\n\n**Configuration:**\n\n- Enable via Settings → HTTP API tab (desktop only)\n- Configurable port (default 8080) and optional authentication token\n- Documentation at `/docs/HTTP_API.md` and `/docs/nlp-api.md`\n\n### Enhanced Calendar Integration\n\n#### Calendar Export and Context Menu System\n\n**Task Calendar Export:**\n\n- Add tasks to external calendars (Google, Outlook, Yahoo)\n- Download ICS files\n- Right-click context menu support for quick calendar actions\n\n#### Agenda View Calendar Improvements\n\n**ICS Integration in Agenda:**\n\n- Calendar event cards now display in Agenda view\n- Toggle calendar subscriptions visibility via FilterBar\n- Always-available \"Refresh calendars\" button\n- Normalized scheduled date handling for all-day and timed events\n\n*Thanks @scottaltham-payroc for the feature request!*\n\n## Bug Fixes\n\n### Task Styling Enhancement (#355)\n\nAdded CSS class `task-card--has-projects` to task cards that contain projects.\n\n*Thanks @mdbraber for the suggestion*\n\n### Calendar Event Scheduling\n\nFixed scheduled date normalization when creating tasks from ICS events:\n\n- All-day events: Use YYYY-MM-DD format\n- Timed events: Use YYYY-MM-DDTHH:mm format\n- Consistent behavior across all calendar interfaces\n\n### File Copy Script Improvements\n\nEnhanced copy-files script with better error handling:\n\n- Improved default path handling\n- Destination directory creation\n- Better ENOENT error handling\n\n## API Documentation\n\n### New Documentation Files\n\n- **HTTP_API.md** - Complete API reference with examples\n- **nlp-api.md** - Natural language processing capabilities and usage\n\n## Technical Enhancements\n\n### Core Infrastructure\n\n**API Service Architecture:**\n\n- Mobile-compatible implementation using Node.js http module\n- Platform detection prevents mobile loading\n- Express.js alternative for lightweight operation\n- Full error handling and validation\n\n**Calendar Service Integration:**\n- Extracted reusable CalendarExportService\n- Unified TaskContextMenu component\n- Enhanced event listener management\n\n### Development Improvements\n\n**Code Organization:**\n\n- Modular component extraction for better reusability\n- Consistent API response formats\n- Comprehensive test coverage for new features\n- TypeScript improvements for icon handling\n\n## Migration Notes\n\n### HTTP API Setup\n\nFor users wanting to enable the new HTTP API:\n\n1. Navigate to Settings → HTTP API tab (desktop only)\n2. Configure desired port (default 8080)\n3. Optionally set authentication token for security\n4. Restart Obsidian to start the API server\n5. Test with: `curl http://localhost:8080/api/health`\n\n","aliases":["/releases/3.19.0/","/releases/3.19.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"http-rest-api-with-natural-language-processing","text":"HTTP REST API with Natural Language Processing"},{"level":3,"id":"enhanced-calendar-integration","text":"Enhanced Calendar Integration"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"task-styling-enhancement-355","text":"Task Styling Enhancement (#355)"},{"level":3,"id":"calendar-event-scheduling","text":"Calendar Event Scheduling"},{"level":3,"id":"file-copy-script-improvements","text":"File Copy Script Improvements"},{"level":2,"id":"api-documentation","text":"API Documentation"},{"level":3,"id":"new-documentation-files","text":"New Documentation Files"},{"level":2,"id":"technical-enhancements","text":"Technical Enhancements"},{"level":3,"id":"core-infrastructure","text":"Core Infrastructure"},{"level":3,"id":"development-improvements","text":"Development Improvements"},{"level":2,"id":"migration-notes","text":"Migration Notes"},{"level":3,"id":"http-api-setup","text":"HTTP API Setup"}],"html":"

New Features#

\n

HTTP REST API with Natural Language Processing#

\n

TaskNotes now includes a HTTP REST API that enables external integrations and powers companion projects. The API provides full task management capabilities with intelligent natural language processing.

\n

Key API Features:

\n
    \n
  • Complete CRUD operations for tasks
  • \n
  • Time tracking endpoints
  • \n
  • Task statistics and filtering
  • \n
  • Bearer token authentication
  • \n
  • CORS support for browser extensions
  • \n
  • Desktop-only implementation with mobile-safe architecture
  • \n
\n

Natural Language Processing Endpoints:

\n
    \n
  • /api/nlp/parse - Parse natural language into structured task data
  • \n
  • /api/nlp/create - Create tasks directly from natural language input
  • \n
  • Supports extraction of dates, times, priorities, tags, contexts, projects, and recurrence
  • \n
  • Intelligent parsing of expressions like "Review PR #123 tomorrow high priority @work"
  • \n
\n

Companion Project Integration:

\n

The HTTP API enables two new companion projects:

\n\n

Configuration:

\n
    \n
  • Enable via Settings → HTTP API tab (desktop only)
  • \n
  • Configurable port (default 8080) and optional authentication token
  • \n
  • Documentation at /docs/HTTP_API.md and /docs/nlp-api.md
  • \n
\n

Enhanced Calendar Integration#

\n

Calendar Export and Context Menu System#

\n

Task Calendar Export:

\n
    \n
  • Add tasks to external calendars (Google, Outlook, Yahoo)
  • \n
  • Download ICS files
  • \n
  • Right-click context menu support for quick calendar actions
  • \n
\n

Agenda View Calendar Improvements#

\n

ICS Integration in Agenda:

\n
    \n
  • Calendar event cards now display in Agenda view
  • \n
  • Toggle calendar subscriptions visibility via FilterBar
  • \n
  • Always-available "Refresh calendars" button
  • \n
  • Normalized scheduled date handling for all-day and timed events
  • \n
\n

Thanks @scottaltham-payroc for the feature request!

\n

Bug Fixes#

\n

Task Styling Enhancement (#355)#

\n

Added CSS class task-card--has-projects to task cards that contain projects.

\n

Thanks @mdbraber for the suggestion

\n

Calendar Event Scheduling#

\n

Fixed scheduled date normalization when creating tasks from ICS events:

\n
    \n
  • All-day events: Use YYYY-MM-DD format
  • \n
  • Timed events: Use YYYY-MM-DDTHH:mm format
  • \n
  • Consistent behavior across all calendar interfaces
  • \n
\n

File Copy Script Improvements#

\n

Enhanced copy-files script with better error handling:

\n
    \n
  • Improved default path handling
  • \n
  • Destination directory creation
  • \n
  • Better ENOENT error handling
  • \n
\n

API Documentation#

\n

New Documentation Files#

\n
    \n
  • HTTP_API.md - Complete API reference with examples
  • \n
  • nlp-api.md - Natural language processing capabilities and usage
  • \n
\n

Technical Enhancements#

\n

Core Infrastructure#

\n

API Service Architecture:

\n
    \n
  • Mobile-compatible implementation using Node.js http module
  • \n
  • Platform detection prevents mobile loading
  • \n
  • Express.js alternative for lightweight operation
  • \n
  • Full error handling and validation
  • \n
\n

Calendar Service Integration:

\n
    \n
  • Extracted reusable CalendarExportService
  • \n
  • Unified TaskContextMenu component
  • \n
  • Enhanced event listener management
  • \n
\n

Development Improvements#

\n

Code Organization:

\n
    \n
  • Modular component extraction for better reusability
  • \n
  • Consistent API response formats
  • \n
  • Comprehensive test coverage for new features
  • \n
  • TypeScript improvements for icon handling
  • \n
\n

Migration Notes#

\n

HTTP API Setup#

\n

For users wanting to enable the new HTTP API:

\n
    \n
  1. Navigate to Settings → HTTP API tab (desktop only)
  2. \n
  3. Configure desired port (default 8080)
  4. \n
  5. Optionally set authentication token for security
  6. \n
  7. Restart Obsidian to start the API server
  8. \n
  9. Test with: curl http://localhost:8080/api/health
  10. \n
\n","text":"New Features# HTTP REST API with Natural Language Processing# TaskNotes now includes a HTTP REST API that enables external integrations and powers companion projects. The API provides full task management capabilities with intelligent natural language processing. Key API Features: Complete CRUD operations for tasks Time tracking endpoints Task statistics and filtering Bearer token authentication CORS support for browser extensions Desktop-only implementation with mobile-safe architecture Natural Language Processing Endpoints: /api/nlp/parse - Parse natural language into structured task data /api/nlp/create - Create tasks directly from natural language input Supports extraction of dates, times, priorities, tags, contexts, projects, and recurrence Intelligent parsing of expressions like \"Review PR #123 tomorrow high priority @work\" Companion Project Integration: The HTTP API enables two new companion projects: tasknotes-cli - Command-line interface for TaskNotes task management tasknotes-browser-extension - Browser extension for quick task creation Configuration: Enable via Settings → HTTP API tab (desktop only) Configurable port (default 8080) and optional authentication token Documentation at /docs/HTTP_API.md and /docs/nlp-api.md Enhanced Calendar Integration# Calendar Export and Context Menu System# Task Calendar Export: Add tasks to external calendars (Google, Outlook, Yahoo) Download ICS files Right-click context menu support for quick calendar actions Agenda View Calendar Improvements# ICS Integration in Agenda: Calendar event cards now display in Agenda view Toggle calendar subscriptions visibility via FilterBar Always-available \"Refresh calendars\" button Normalized scheduled date handling for all-day and timed events Thanks @scottaltham-payroc for the feature request! Bug Fixes# Task Styling Enhancement (#355)# Added CSS class task-card--has-projects to task cards that contain projects. Thanks @mdbraber for the suggestion Calendar Event Scheduling# Fixed scheduled date normalization when creating tasks from ICS events: All-day events: Use YYYY-MM-DD format Timed events: Use YYYY-MM-DDTHH:mm format Consistent behavior across all calendar interfaces File Copy Script Improvements# Enhanced copy-files script with better error handling: Improved default path handling Destination directory creation Better ENOENT error handling API Documentation# New Documentation Files# HTTP_API.md - Complete API reference with examples nlp-api.md - Natural language processing capabilities and usage Technical Enhancements# Core Infrastructure# API Service Architecture: Mobile-compatible implementation using Node.js http module Platform detection prevents mobile loading Express.js alternative for lightweight operation Full error handling and validation Calendar Service Integration: Extracted reusable CalendarExportService Unified TaskContextMenu component Enhanced event listener management Development Improvements# Code Organization: Modular component extraction for better reusability Consistent API response formats Comprehensive test coverage for new features TypeScript improvements for icon handling Migration Notes# HTTP API Setup# For users wanting to enable the new HTTP API: Navigate to Settings → HTTP API tab (desktop only) Configure desired port (default 8080) Optionally set authentication token for security Restart Obsidian to start the API server Test with: curl http://localhost:8080/api/health"},{"route":"/obsidian/releases/3.19.1/","title":"TaskNotes 3.19.1","description":"Added webhook system enabling integrations with external services and automation workflows.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.19.1.md","namespace":"obsidian","relativePath":"releases/3.19.1.md","raw":"# TaskNotes 3.19.1\n\n## New Features\n\n### Webhook Support\n\nAdded webhook system enabling integrations with external services and automation workflows.\n\n**Webhook Management:**\n\n- CRUD operations for webhook configuration\n- HTTP API endpoints for webhook management (`POST /api/webhooks`, `GET /api/webhooks`, `DELETE /api/webhooks/{id}`)\n- Delivery history tracking (`GET /api/webhooks/deliveries`)\n- Settings UI integration with event subscription controls\n\n**Event Types:**\n\n- **Task events:** created, updated, deleted, completed, archived, unarchived\n- **Time tracking:** started, stopped\n- **Pomodoro:** started, completed, interrupted \n- **Recurring tasks:** instance completed\n- **Reminders:** triggered\n\n**Security and Reliability:**\n\n- HMAC-SHA256 signature verification for payload authentication\n- Automatic retries with exponential backoff (3 attempts)\n- 10-second delivery timeout with failure monitoring\n- Auto-disable webhooks after repeated failures\n- Non-blocking async delivery maintains TaskNotes responsiveness\n\nDocumentation and testing utilities included in `docs/webhooks.md` and `test-webhook.js`.\n\n## Bug Fixes\n\n### Boolean Property Identification Regression (#367)\n\nFixed regression from version 3.18.2 where boolean checkbox properties stopped working for property-based task identification.\n\nDuring code refactoring, the `comparePropertyValues` function was accidentally removed, breaking boolean-to-string coercion needed for Obsidian checkbox properties. The fix restores this function with proper type-aware comparison logic, allowing boolean `true`/`false` frontmatter values to correctly match `\"true\"`/`\"false\"` setting values.\n\n*Thanks to @renatomen for reporting this regression*\n","aliases":["/releases/3.19.1/","/releases/3.19.1/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"webhook-support","text":"Webhook Support"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"boolean-property-identification-regression-367","text":"Boolean Property Identification Regression (#367)"}],"html":"

New Features#

\n

Webhook Support#

\n

Added webhook system enabling integrations with external services and automation workflows.

\n

Webhook Management:

\n
    \n
  • CRUD operations for webhook configuration
  • \n
  • HTTP API endpoints for webhook management (POST /api/webhooks, GET /api/webhooks, DELETE /api/webhooks/{id})
  • \n
  • Delivery history tracking (GET /api/webhooks/deliveries)
  • \n
  • Settings UI integration with event subscription controls
  • \n
\n

Event Types:

\n
    \n
  • Task events: created, updated, deleted, completed, archived, unarchived
  • \n
  • Time tracking: started, stopped
  • \n
  • Pomodoro: started, completed, interrupted
  • \n
  • Recurring tasks: instance completed
  • \n
  • Reminders: triggered
  • \n
\n

Security and Reliability:

\n
    \n
  • HMAC-SHA256 signature verification for payload authentication
  • \n
  • Automatic retries with exponential backoff (3 attempts)
  • \n
  • 10-second delivery timeout with failure monitoring
  • \n
  • Auto-disable webhooks after repeated failures
  • \n
  • Non-blocking async delivery maintains TaskNotes responsiveness
  • \n
\n

Documentation and testing utilities included in docs/webhooks.md and test-webhook.js.

\n

Bug Fixes#

\n

Boolean Property Identification Regression (#367)#

\n

Fixed regression from version 3.18.2 where boolean checkbox properties stopped working for property-based task identification.

\n

During code refactoring, the comparePropertyValues function was accidentally removed, breaking boolean-to-string coercion needed for Obsidian checkbox properties. The fix restores this function with proper type-aware comparison logic, allowing boolean true/false frontmatter values to correctly match "true"/"false" setting values.

\n

Thanks to @renatomen for reporting this regression

\n","text":"New Features# Webhook Support# Added webhook system enabling integrations with external services and automation workflows. Webhook Management: CRUD operations for webhook configuration HTTP API endpoints for webhook management (POST /api/webhooks, GET /api/webhooks, DELETE /api/webhooks/{id}) Delivery history tracking (GET /api/webhooks/deliveries) Settings UI integration with event subscription controls Event Types: Task events: created, updated, deleted, completed, archived, unarchived Time tracking: started, stopped Pomodoro: started, completed, interrupted Recurring tasks: instance completed Reminders: triggered Security and Reliability: HMAC-SHA256 signature verification for payload authentication Automatic retries with exponential backoff (3 attempts) 10-second delivery timeout with failure monitoring Auto-disable webhooks after repeated failures Non-blocking async delivery maintains TaskNotes responsiveness Documentation and testing utilities included in docs/webhooks.md and test-webhook.js. Bug Fixes# Boolean Property Identification Regression (#367)# Fixed regression from version 3.18.2 where boolean checkbox properties stopped working for property-based task identification. During code refactoring, the comparePropertyValues function was accidentally removed, breaking boolean-to-string coercion needed for Obsidian checkbox properties. The fix restores this function with proper type-aware comparison logic, allowing boolean true/false frontmatter values to correctly match \"true\"/\"false\" setting values. Thanks to @renatomen for reporting this regression"},{"route":"/obsidian/releases/3.20.0/","title":"TaskNotes 3.20.0","description":"Folder-Based Task Filtering - Added task filtering by folder location with dropdown selection of vault folder paths, special handling for root-level tasks, and support for conta...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.20.0.md","namespace":"obsidian","relativePath":"releases/3.20.0.md","raw":"# TaskNotes 3.20.0\n\n## New Features\n\n### Task Organization and Filtering\n\n**Folder-Based Task Filtering** - Added task filtering by folder location with dropdown selection of vault folder paths, special handling for root-level tasks, and support for contains/empty operators. *Addresses issue #369 reported by kmaustral*\n\n**Dynamic Task Folder Organization** - Added template variable support for default task folder setting with task variables (`{{context}}`, `{{project}}`, `{{priority}}`, `{{status}}`, `{{title}}`) and date variables (`{{year}}`, `{{month}}`, `{{day}}`, `{{date}}`). Supports automatic folder creation and title sanitization. *Addresses feature request #376 by Mara-Li*\n\n**Archive Task Organization** - Added optional bidirectional task movement between archive folder and default tasks folder. Disabled by default with settings in Task defaults → Task organization (`moveArchivedTasks`, `archiveFolder`). *Addresses feature request #402 by anareaty*\n\n### Enhanced UI and Controls\n\n**Enhanced Filter Bar** - Improved filter bar with instant badge updates, right-click clear functionality, \"Clear All Filters\" button, and better UI synchronization across main and subtask views. *Contributed by renatomen*\n\n**Collapsible Groups** - Added collapsible groups with persisted state, chevron indicators, and keyboard navigation. Works with all grouping options while preserving wikilink functionality. Extended to subtask widget with consistent behavior. *Contributed by renatomen*\n\n**Expand/Collapse All Controls** - Added \"Expand All\" and \"Collapse All\" buttons to task list toolbar that appear when grouping is active. *Contributed by renatomen*\n\n**Configurable UI Elements** - Added settings for subtask chevron position (right/left) and saved views button positioning in task view toolbar. *Contributed by renatomen*\n\n### Advanced API Architecture and Webhook System\n\nRefactored HTTP API from monolithic design to controller/service pattern, reducing HTTPAPIService from 1,061 to 231 lines (78% reduction). Added dedicated controllers for tasks, time tracking, Pomodoro, system, and webhooks with 100% backward compatibility.\n\n**Webhook System** - Added complete webhook infrastructure with signature verification, automatic retries with exponential backoff, 10-second delivery timeout, and auto-disable after repeated failures. Supports all task lifecycle events (created, updated, deleted, completed, archived, unarchived), time tracking events, Pomodoro sessions, recurring task instances, and reminders.\n\n**Webhook Testing and Development** - Included standalone webhook testing server (`test-webhook.js`) with real-time payload inspection, signature verification testing, and comprehensive event logging for development and debugging.\n\n## Improvements\n\n### UI and Visual Enhancements\n\n**TaskNotes Icons** - Added TaskNotes icons throughout interface and edit task modal headers with new SVG assets.\n\n**Task Card Polish** - Improved status and priority dot alignment and reordered context menu (\"Copy task title\" moved to top). *Addresses alignment issue #410 reported by kmaustral*\n\n**Button Styling** - Fixed agenda view and filter popup button backgrounds with improved styling consistency.\n\n### Technical Improvements\n\n**Settings Architecture** - Decomposed monolithic settings.ts into focused modules: defaults, settings management, type definitions, and utilities for better maintainability.\n\n**Documentation** - Added extensive webhook documentation in `docs/examples/webhook-transforms/` with ready-to-use transform examples for Discord (rich embeds with colors), Slack (compatible attachments), Microsoft Teams (MessageCard format), and generic JSON templates. Expanded API documentation with complete endpoint reference, examples, error handling, authentication, and OpenAPI specification.\n\n**Webhook Integration Services** - Enhanced core services (TaskService, PomodoroService) with webhook notifications integrated into task lifecycle events, ensuring all user actions trigger appropriate webhook deliveries for external automation and monitoring.\n\n## Bug Fixes\n\n**Mobile Modal Close Button** - Fixed close button (X) touch event handling in task edit modals on mobile devices, particularly Android. *Addresses issue #404 reported by anareaty*\n\n**Test Suite Stabilization** - Resolved test failures and linting errors\n\n**HTTP API Field Consistency** - Updated API examples to use correct 'details' field instead of deprecated 'notes' field. *Addresses issue #393 reported by @nightroman*\n\n**Missing Webhook Trigger** - Added webhook trigger for recurring task completion events.\n\n## Documentation Updates\n\n- Task defaults documentation with template variables\n- Miscellaneous settings documentation \n- Webhook transform documentation and examples\n- Demo GIFs for new features\n\nThanks @renatomen!\n\n## Contributors\n\nSpecial thanks to the following contributors:\n\n- **@Mara-Li** - Feature request for template variables in task folders\n- **@kmaustral** - Feature requests for folder filtering and UI alignment improvements\n- **@anareaty** - Bug report for mobile modal close button issue\n- **@nightroman** - Reported mislead API documentation\n\nA really big thanks to @renatomen whose very polished contributions form the bulk of this update!\n\n\n","aliases":["/releases/3.20.0/","/releases/3.20.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"task-organization-and-filtering","text":"Task Organization and Filtering"},{"level":3,"id":"enhanced-ui-and-controls","text":"Enhanced UI and Controls"},{"level":3,"id":"advanced-api-architecture-and-webhook-system","text":"Advanced API Architecture and Webhook System"},{"level":2,"id":"improvements","text":"Improvements"},{"level":3,"id":"ui-and-visual-enhancements","text":"UI and Visual Enhancements"},{"level":3,"id":"technical-improvements","text":"Technical Improvements"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":2,"id":"documentation-updates","text":"Documentation Updates"},{"level":2,"id":"contributors","text":"Contributors"}],"html":"

New Features#

\n

Task Organization and Filtering#

\n

Folder-Based Task Filtering - Added task filtering by folder location with dropdown selection of vault folder paths, special handling for root-level tasks, and support for contains/empty operators. Addresses issue #369 reported by kmaustral

\n

Dynamic Task Folder Organization - Added template variable support for default task folder setting with task variables ({{context}}, {{project}}, {{priority}}, {{status}}, {{title}}) and date variables ({{year}}, {{month}}, {{day}}, {{date}}). Supports automatic folder creation and title sanitization. Addresses feature request #376 by Mara-Li

\n

Archive Task Organization - Added optional bidirectional task movement between archive folder and default tasks folder. Disabled by default with settings in Task defaults → Task organization (moveArchivedTasks, archiveFolder). Addresses feature request #402 by anareaty

\n

Enhanced UI and Controls#

\n

Enhanced Filter Bar - Improved filter bar with instant badge updates, right-click clear functionality, "Clear All Filters" button, and better UI synchronization across main and subtask views. Contributed by renatomen

\n

Collapsible Groups - Added collapsible groups with persisted state, chevron indicators, and keyboard navigation. Works with all grouping options while preserving wikilink functionality. Extended to subtask widget with consistent behavior. Contributed by renatomen

\n

Expand/Collapse All Controls - Added "Expand All" and "Collapse All" buttons to task list toolbar that appear when grouping is active. Contributed by renatomen

\n

Configurable UI Elements - Added settings for subtask chevron position (right/left) and saved views button positioning in task view toolbar. Contributed by renatomen

\n

Advanced API Architecture and Webhook System#

\n

Refactored HTTP API from monolithic design to controller/service pattern, reducing HTTPAPIService from 1,061 to 231 lines (78% reduction). Added dedicated controllers for tasks, time tracking, Pomodoro, system, and webhooks with 100% backward compatibility.

\n

Webhook System - Added complete webhook infrastructure with signature verification, automatic retries with exponential backoff, 10-second delivery timeout, and auto-disable after repeated failures. Supports all task lifecycle events (created, updated, deleted, completed, archived, unarchived), time tracking events, Pomodoro sessions, recurring task instances, and reminders.

\n

Webhook Testing and Development - Included standalone webhook testing server (test-webhook.js) with real-time payload inspection, signature verification testing, and comprehensive event logging for development and debugging.

\n

Improvements#

\n

UI and Visual Enhancements#

\n

TaskNotes Icons - Added TaskNotes icons throughout interface and edit task modal headers with new SVG assets.

\n

Task Card Polish - Improved status and priority dot alignment and reordered context menu ("Copy task title" moved to top). Addresses alignment issue #410 reported by kmaustral

\n

Button Styling - Fixed agenda view and filter popup button backgrounds with improved styling consistency.

\n

Technical Improvements#

\n

Settings Architecture - Decomposed monolithic settings.ts into focused modules: defaults, settings management, type definitions, and utilities for better maintainability.

\n

Documentation - Added extensive webhook documentation in docs/examples/webhook-transforms/ with ready-to-use transform examples for Discord (rich embeds with colors), Slack (compatible attachments), Microsoft Teams (MessageCard format), and generic JSON templates. Expanded API documentation with complete endpoint reference, examples, error handling, authentication, and OpenAPI specification.

\n

Webhook Integration Services - Enhanced core services (TaskService, PomodoroService) with webhook notifications integrated into task lifecycle events, ensuring all user actions trigger appropriate webhook deliveries for external automation and monitoring.

\n

Bug Fixes#

\n

Mobile Modal Close Button - Fixed close button (X) touch event handling in task edit modals on mobile devices, particularly Android. Addresses issue #404 reported by anareaty

\n

Test Suite Stabilization - Resolved test failures and linting errors

\n

HTTP API Field Consistency - Updated API examples to use correct 'details' field instead of deprecated 'notes' field. Addresses issue #393 reported by @nightroman

\n

Missing Webhook Trigger - Added webhook trigger for recurring task completion events.

\n

Documentation Updates#

\n
    \n
  • Task defaults documentation with template variables
  • \n
  • Miscellaneous settings documentation
  • \n
  • Webhook transform documentation and examples
  • \n
  • Demo GIFs for new features
  • \n
\n

Thanks @renatomen!

\n

Contributors#

\n

Special thanks to the following contributors:

\n
    \n
  • @Mara-Li - Feature request for template variables in task folders
  • \n
  • @kmaustral - Feature requests for folder filtering and UI alignment improvements
  • \n
  • @anareaty - Bug report for mobile modal close button issue
  • \n
  • @nightroman - Reported mislead API documentation
  • \n
\n

A really big thanks to @renatomen whose very polished contributions form the bulk of this update!

\n","text":"New Features# Task Organization and Filtering# Folder-Based Task Filtering - Added task filtering by folder location with dropdown selection of vault folder paths, special handling for root-level tasks, and support for contains/empty operators. Addresses issue #369 reported by kmaustral Dynamic Task Folder Organization - Added template variable support for default task folder setting with task variables ({{context}}, {{project}}, {{priority}}, {{status}}, {{title}}) and date variables ({{year}}, {{month}}, {{day}}, {{date}}). Supports automatic folder creation and title sanitization. Addresses feature request #376 by Mara-Li Archive Task Organization - Added optional bidirectional task movement between archive folder and default tasks folder. Disabled by default with settings in Task defaults → Task organization (moveArchivedTasks, archiveFolder). Addresses feature request #402 by anareaty Enhanced UI and Controls# Enhanced Filter Bar - Improved filter bar with instant badge updates, right-click clear functionality, \"Clear All Filters\" button, and better UI synchronization across main and subtask views. Contributed by renatomen Collapsible Groups - Added collapsible groups with persisted state, chevron indicators, and keyboard navigation. Works with all grouping options while preserving wikilink functionality. Extended to subtask widget with consistent behavior. Contributed by renatomen Expand/Collapse All Controls - Added \"Expand All\" and \"Collapse All\" buttons to task list toolbar that appear when grouping is active. Contributed by renatomen Configurable UI Elements - Added settings for subtask chevron position (right/left) and saved views button positioning in task view toolbar. Contributed by renatomen Advanced API Architecture and Webhook System# Refactored HTTP API from monolithic design to controller/service pattern, reducing HTTPAPIService from 1,061 to 231 lines (78% reduction). Added dedicated controllers for tasks, time tracking, Pomodoro, system, and webhooks with 100% backward compatibility. Webhook System - Added complete webhook infrastructure with signature verification, automatic retries with exponential backoff, 10-second delivery timeout, and auto-disable after repeated failures. Supports all task lifecycle events (created, updated, deleted, completed, archived, unarchived), time tracking events, Pomodoro sessions, recurring task instances, and reminders. Webhook Testing and Development - Included standalone webhook testing server (test-webhook.js) with real-time payload inspection, signature verification testing, and comprehensive event logging for development and debugging. Improvements# UI and Visual Enhancements# TaskNotes Icons - Added TaskNotes icons throughout interface and edit task modal headers with new SVG assets. Task Card Polish - Improved status and priority dot alignment and reordered context menu (\"Copy task title\" moved to top). Addresses alignment issue #410 reported by kmaustral Button Styling - Fixed agenda view and filter popup button backgrounds with improved styling consistency. Technical Improvements# Settings Architecture - Decomposed monolithic settings.ts into focused modules: defaults, settings management, type definitions, and utilities for better maintainability. Documentation - Added extensive webhook documentation in docs/examples/webhook-transforms/ with ready-to-use transform examples for Discord (rich embeds with colors), Slack (compatible attachments), Microsoft Teams (MessageCard format), and generic JSON templates. Expanded API documentation with complete endpoint reference, examples, error handling, authentication, and OpenAPI specification. Webhook Integration Services - Enhanced core services (TaskService, PomodoroService) with webhook notifications integrated into task lifecycle events, ensuring all user actions trigger appropriate webhook deliveries for external automation and monitoring. Bug Fixes# Mobile Modal Close Button - Fixed close button (X) touch event handling in task edit modals on mobile devices, particularly Android. Addresses issue #404 reported by anareaty Test Suite Stabilization - Resolved test failures and linting errors HTTP API Field Consistency - Updated API examples to use correct 'details' field instead of deprecated 'notes' field. Addresses issue #393 reported by @nightroman Missing Webhook Trigger - Added webhook trigger for recurring task completion events. Documentation Updates# Task defaults documentation with template variables Miscellaneous settings documentation Webhook transform documentation and examples Demo GIFs for new features Thanks @renatomen! Contributors# Special thanks to the following contributors: @Mara-Li - Feature request for template variables in task folders @kmaustral - Feature requests for folder filtering and UI alignment improvements @anareaty - Bug report for mobile modal close button issue @nightroman - Reported mislead API documentation A really big thanks to @renatomen whose very polished contributions form the bulk of this update!"},{"route":"/obsidian/releases/3.20.1/","title":"TaskNotes 3.20.1","description":"Saved View Headings with Completion Counts - Added visible filter headings across all views (Task List, Subtask Widget, and Agenda) that display the current saved view name and...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.20.1.md","namespace":"obsidian","relativePath":"releases/3.20.1.md","raw":"# TaskNotes 3.20.1\n\n## New Features\n\n### Enhanced View Organization and Visual Feedback\n\n**Saved View Headings with Completion Counts** - Added visible filter headings across all views (Task List, Subtask Widget, and Agenda) that display the current saved view name and completion statistics in \"completed / total\" format. Shows \"All\" when no saved view is active. Headings update immediately on filter changes and persist correctly when switching tabs or reloading. *Contributed by @renatomen*\n\n**Consistent Group Count Badges** - Standardized completion count display across all group headers in Task List, Subtask Widget, and Agenda views using unified \"completed / total\" format. Removed redundant bracketed counts for cleaner presentation. *Contributed by @renatomen*\n\n**Collapsible Agenda Date Groups** - Added collapsible date headers to Agenda view with persistent state management. Date sections can be collapsed individually or controlled via \"Expand All\" / \"Collapse All\" buttons that are always visible in the FilterBar. Collapsed state is preserved between sessions using ViewStateManager. *Contributed by @renatomen*\n\n### Improved User Interface\n\n**Reorganized Task Context Menu** - Enhanced context menu organization by replacing individual buttons with logical submenus for status, priority, dates, recurrence, and reminders. Applied user-configured colors to main menu icons while maintaining all existing functionality. \n\n## Bug Fixes\n\n### Calendar Integration Fixes\n\n**Outlook Calendar 500 Errors** - Fixed Microsoft Outlook ICS endpoint failures by updating User-Agent header from 'TaskNotes-Plugin/1.0' to browser-compatible string and adding Accept-Language header. Improved error handling with specific guidance for Outlook 500 errors. *Fixes issue #458 reported by @girisumit and @heinzochsner*\n\n**Recurring Tasks Date Display** - Fixed timezone-dependent bug where recurring tasks appeared one day ahead or behind their actual due date in Agenda View. Replaced manual UTC date construction with parseDateToUTC() following UTC Anchor principle from development guidelines. Added regression test for consistent date handling. *Fixes issue #439 reported by @brianarn and @jpmoo*\n\n### Task Management Fixes \n\n**Project Suggestions Crash Prevention** - Fixed crash in Task Creation modal when typing \"+\" to add projects inline, caused by non-string title values in frontmatter. Added title normalization (arrays join with \", \", numbers/booleans stringify, objects become empty strings) and defensive guards in suggestion filtering. Particularly important for large vaults with heterogeneous frontmatter. *Contributed by @renatomen*\n\n## Documentation Updates\n\n- Added screenshots demonstrating saved view headings and completion counts for Task List and Subtask Widget\n- Created demo GIF showing Agenda view collapsible groups with Expand/Collapse All functionality \n- Updated view documentation with new visual features\n- Enhanced inline task documentation for Subtask Widget improvements\n\n*Contributed by @renatomen*\n\n## Contributors\n\nSpecial recognition goes to **@renatomen** for the substantial contributions that form the core of this release, including the saved view headings system, consistent count badges, and collapsible Agenda functionality.\n\nThanks to the following community members for their bug reports and feedback:\n\n- **@girisumit and @heinzochsner** - Reported Outlook calendar integration issues\n- **@brianarn and @jpmoo** - Identified recurring tasks date display bug with detailed reproduction steps\n","aliases":["/releases/3.20.1/","/releases/3.20.1/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"enhanced-view-organization-and-visual-feedback","text":"Enhanced View Organization and Visual Feedback"},{"level":3,"id":"improved-user-interface","text":"Improved User Interface"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"calendar-integration-fixes","text":"Calendar Integration Fixes"},{"level":3,"id":"task-management-fixes","text":"Task Management Fixes"},{"level":2,"id":"documentation-updates","text":"Documentation Updates"},{"level":2,"id":"contributors","text":"Contributors"}],"html":"

New Features#

\n

Enhanced View Organization and Visual Feedback#

\n

Saved View Headings with Completion Counts - Added visible filter headings across all views (Task List, Subtask Widget, and Agenda) that display the current saved view name and completion statistics in "completed / total" format. Shows "All" when no saved view is active. Headings update immediately on filter changes and persist correctly when switching tabs or reloading. Contributed by @renatomen

\n

Consistent Group Count Badges - Standardized completion count display across all group headers in Task List, Subtask Widget, and Agenda views using unified "completed / total" format. Removed redundant bracketed counts for cleaner presentation. Contributed by @renatomen

\n

Collapsible Agenda Date Groups - Added collapsible date headers to Agenda view with persistent state management. Date sections can be collapsed individually or controlled via "Expand All" / "Collapse All" buttons that are always visible in the FilterBar. Collapsed state is preserved between sessions using ViewStateManager. Contributed by @renatomen

\n

Improved User Interface#

\n

Reorganized Task Context Menu - Enhanced context menu organization by replacing individual buttons with logical submenus for status, priority, dates, recurrence, and reminders. Applied user-configured colors to main menu icons while maintaining all existing functionality.

\n

Bug Fixes#

\n

Calendar Integration Fixes#

\n

Outlook Calendar 500 Errors - Fixed Microsoft Outlook ICS endpoint failures by updating User-Agent header from 'TaskNotes-Plugin/1.0' to browser-compatible string and adding Accept-Language header. Improved error handling with specific guidance for Outlook 500 errors. Fixes issue #458 reported by @girisumit and @heinzochsner

\n

Recurring Tasks Date Display - Fixed timezone-dependent bug where recurring tasks appeared one day ahead or behind their actual due date in Agenda View. Replaced manual UTC date construction with parseDateToUTC() following UTC Anchor principle from development guidelines. Added regression test for consistent date handling. Fixes issue #439 reported by @brianarn and @jpmoo

\n

Task Management Fixes#

\n

Project Suggestions Crash Prevention - Fixed crash in Task Creation modal when typing "+" to add projects inline, caused by non-string title values in frontmatter. Added title normalization (arrays join with ", ", numbers/booleans stringify, objects become empty strings) and defensive guards in suggestion filtering. Particularly important for large vaults with heterogeneous frontmatter. Contributed by @renatomen

\n

Documentation Updates#

\n
    \n
  • Added screenshots demonstrating saved view headings and completion counts for Task List and Subtask Widget
  • \n
  • Created demo GIF showing Agenda view collapsible groups with Expand/Collapse All functionality
  • \n
  • Updated view documentation with new visual features
  • \n
  • Enhanced inline task documentation for Subtask Widget improvements
  • \n
\n

Contributed by @renatomen

\n

Contributors#

\n

Special recognition goes to @renatomen for the substantial contributions that form the core of this release, including the saved view headings system, consistent count badges, and collapsible Agenda functionality.

\n

Thanks to the following community members for their bug reports and feedback:

\n
    \n
  • @girisumit and @heinzochsner - Reported Outlook calendar integration issues
  • \n
  • @brianarn and @jpmoo - Identified recurring tasks date display bug with detailed reproduction steps
  • \n
\n","text":"New Features# Enhanced View Organization and Visual Feedback# Saved View Headings with Completion Counts - Added visible filter headings across all views (Task List, Subtask Widget, and Agenda) that display the current saved view name and completion statistics in \"completed / total\" format. Shows \"All\" when no saved view is active. Headings update immediately on filter changes and persist correctly when switching tabs or reloading. Contributed by @renatomen Consistent Group Count Badges - Standardized completion count display across all group headers in Task List, Subtask Widget, and Agenda views using unified \"completed / total\" format. Removed redundant bracketed counts for cleaner presentation. Contributed by @renatomen Collapsible Agenda Date Groups - Added collapsible date headers to Agenda view with persistent state management. Date sections can be collapsed individually or controlled via \"Expand All\" / \"Collapse All\" buttons that are always visible in the FilterBar. Collapsed state is preserved between sessions using ViewStateManager. Contributed by @renatomen Improved User Interface# Reorganized Task Context Menu - Enhanced context menu organization by replacing individual buttons with logical submenus for status, priority, dates, recurrence, and reminders. Applied user-configured colors to main menu icons while maintaining all existing functionality. Bug Fixes# Calendar Integration Fixes# Outlook Calendar 500 Errors - Fixed Microsoft Outlook ICS endpoint failures by updating User-Agent header from 'TaskNotes-Plugin/1.0' to browser-compatible string and adding Accept-Language header. Improved error handling with specific guidance for Outlook 500 errors. Fixes issue #458 reported by @girisumit and @heinzochsner Recurring Tasks Date Display - Fixed timezone-dependent bug where recurring tasks appeared one day ahead or behind their actual due date in Agenda View. Replaced manual UTC date construction with parseDateToUTC() following UTC Anchor principle from development guidelines. Added regression test for consistent date handling. Fixes issue #439 reported by @brianarn and @jpmoo Task Management Fixes# Project Suggestions Crash Prevention - Fixed crash in Task Creation modal when typing \"+\" to add projects inline, caused by non-string title values in frontmatter. Added title normalization (arrays join with \", \", numbers/booleans stringify, objects become empty strings) and defensive guards in suggestion filtering. Particularly important for large vaults with heterogeneous frontmatter. Contributed by @renatomen Documentation Updates# Added screenshots demonstrating saved view headings and completion counts for Task List and Subtask Widget Created demo GIF showing Agenda view collapsible groups with Expand/Collapse All functionality Updated view documentation with new visual features Enhanced inline task documentation for Subtask Widget improvements Contributed by @renatomen Contributors# Special recognition goes to @renatomen for the substantial contributions that form the core of this release, including the saved view headings system, consistent count badges, and collapsible Agenda functionality. Thanks to the following community members for their bug reports and feedback: @girisumit and @heinzochsner - Reported Outlook calendar integration issues @brianarn and @jpmoo - Identified recurring tasks date display bug with detailed reproduction steps"},{"route":"/obsidian/releases/3.21.0/","title":"TaskNotes 3.21.0","description":"Custom User Fields Mapping - Added ability to define custom frontmatter properties for task filtering, grouping, and sorting. Users can configure field mappings in Settings → Ad...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.21.0.md","namespace":"obsidian","relativePath":"releases/3.21.0.md","raw":"# TaskNotes 3.21.0\n\n## New Features\n\n### Custom User Fields System\n\n**Custom User Fields Mapping** - Added ability to define custom frontmatter properties for task filtering, grouping, and sorting. Users can configure field mappings in Settings → Advanced → User Fields with support for text, number, date, boolean, and list field types. List fields preserve wikilinks and quoted tokens, while numeric fields intelligently parse mixed text-number values like \"2-Medium\" as numeric 2. *Contributed by @renatomen*\n\n**Group and Sort by Custom User Fields** - Extended grouping and sorting functionality to work with user-defined custom fields. Includes type-aware comparators for each field type and proper group header ordering when grouping and sorting by the same field. *Contributed by @renatomen*\n\n**User Fields in Task Modals** - Added custom user field support to task creation and edit modals with autocomplete suggestions from existing field values. Fields are stored as frontmatter properties and include change detection for edit scenarios. *Contributed by @callumalpass*\n\n### Enhanced Task Interaction\n\n**Configurable Click Behavior** - Added option to configure single-click and double-click behavior for task cards and inline task widgets. Users can choose between opening the edit modal or the source note file for each click type. Includes shared click handler utility with 250ms detection delay. *Contributed by @fastrick*\n\n### Calendar Integration Enhancements\n\n**Calendar Event Filename Templates** - Added separate filename template configuration for notes created from calendar events. Supports ICS-specific template variables including `{icsEventTitle}`, `{icsEventLocation}`, `{icsEventDescription}`, and `{icsEventTitleWithDate}`. The `{title}` variable now uses clean event titles without date suffixes. *Fixes issue #362 reported by @bepolymathe*\n\n**Chronological ICS Event Sorting** - Fixed ICS calendar events to display in chronological order by start time within each day in the agenda view. Applied to both grouped and flat agenda view modes. *Fixes issue #472 reported by @Crunchnuggetz*\n\n## Bug Fixes\n\n### API Endpoint Improvements\n\n**Custom Status Configuration Support** - Fixed API endpoints (`/api/nlp/parse` and `/api/nlp/create`) not respecting custom status configurations. API now uses proper default status logic matching the UI instead of hardcoded 'todo' values, with proper handling of boolean status values. *Fixes issue #487 reported by @23maverick23*\n\n**Task Creation Defaults** - Fixed REST API endpoint (`POST /api/tasks`) missing default properties like scheduled dates, tags, and reminders. API-created tasks now receive the same defaults as UI-created tasks. *Fixes issue reported by @nightroman*\n\n### Project Management Fixes\n\n**Project Consolidation and Display** - Fixed project grouping to consolidate different formats pointing to the same file (e.g., `[[project]]` and `[[project|alias]]` now group together). Improved display formatting with clickable headers showing absolute paths without `.md` extensions and proper wikilink alias parsing. Task cards preserve original formats while grouping logic ignores display aliases. *Fixes issues #448 reported by @minchinweb and #469 reported by @anareaty*\n\n### User Experience Improvements\n\n**Tag Input Sanitization** - Added automatic sanitization to remove `#` prefixes from tag input, preventing duplicate tags like `#tag1` and `##tag1`. Applied to task creation, editing, and real-time input handling. *Fixes issue #331 reported by @AndreMonthy*\n\n## Contributors\n\nSpecial recognition goes to **@renatomen** for the extensive custom user fields system that forms the core of this release, including field mapping, filtering, grouping, and sorting capabilities.\n\nThanks to **@fastrick** for implementing the configurable click behavior feature.\n\nThanks to the following community members for their bug reports and feature requests:\n\n- **@23maverick23** - Reported API custom status configuration issues with detailed technical analysis\n- **@Crunchnuggetz** - Identified ICS calendar event sorting problem in agenda view\n- **@minchinweb** - Reported project consolidation issues with wikilink variations \n- **@anareaty** - Identified project display formatting problems in kanban view\n- **@bepolymathe** - Requested calendar event filename template functionality\n- **@AndreMonthy** - Reported tag input sanitization issues with clear examples\n- **@nightroman** - Reported API issues where defaults were not being applied","aliases":["/releases/3.21.0/","/releases/3.21.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"custom-user-fields-system","text":"Custom User Fields System"},{"level":3,"id":"enhanced-task-interaction","text":"Enhanced Task Interaction"},{"level":3,"id":"calendar-integration-enhancements","text":"Calendar Integration Enhancements"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"api-endpoint-improvements","text":"API Endpoint Improvements"},{"level":3,"id":"project-management-fixes","text":"Project Management Fixes"},{"level":3,"id":"user-experience-improvements","text":"User Experience Improvements"},{"level":2,"id":"contributors","text":"Contributors"}],"html":"

New Features#

\n

Custom User Fields System#

\n

Custom User Fields Mapping - Added ability to define custom frontmatter properties for task filtering, grouping, and sorting. Users can configure field mappings in Settings → Advanced → User Fields with support for text, number, date, boolean, and list field types. List fields preserve wikilinks and quoted tokens, while numeric fields intelligently parse mixed text-number values like "2-Medium" as numeric 2. Contributed by @renatomen

\n

Group and Sort by Custom User Fields - Extended grouping and sorting functionality to work with user-defined custom fields. Includes type-aware comparators for each field type and proper group header ordering when grouping and sorting by the same field. Contributed by @renatomen

\n

User Fields in Task Modals - Added custom user field support to task creation and edit modals with autocomplete suggestions from existing field values. Fields are stored as frontmatter properties and include change detection for edit scenarios. Contributed by @callumalpass

\n

Enhanced Task Interaction#

\n

Configurable Click Behavior - Added option to configure single-click and double-click behavior for task cards and inline task widgets. Users can choose between opening the edit modal or the source note file for each click type. Includes shared click handler utility with 250ms detection delay. Contributed by @fastrick

\n

Calendar Integration Enhancements#

\n

Calendar Event Filename Templates - Added separate filename template configuration for notes created from calendar events. Supports ICS-specific template variables including {icsEventTitle}, {icsEventLocation}, {icsEventDescription}, and {icsEventTitleWithDate}. The {title} variable now uses clean event titles without date suffixes. Fixes issue #362 reported by @bepolymathe

\n

Chronological ICS Event Sorting - Fixed ICS calendar events to display in chronological order by start time within each day in the agenda view. Applied to both grouped and flat agenda view modes. Fixes issue #472 reported by @Crunchnuggetz

\n

Bug Fixes#

\n

API Endpoint Improvements#

\n

Custom Status Configuration Support - Fixed API endpoints (/api/nlp/parse and /api/nlp/create) not respecting custom status configurations. API now uses proper default status logic matching the UI instead of hardcoded 'todo' values, with proper handling of boolean status values. Fixes issue #487 reported by @23maverick23

\n

Task Creation Defaults - Fixed REST API endpoint (POST /api/tasks) missing default properties like scheduled dates, tags, and reminders. API-created tasks now receive the same defaults as UI-created tasks. Fixes issue reported by @nightroman

\n

Project Management Fixes#

\n

Project Consolidation and Display - Fixed project grouping to consolidate different formats pointing to the same file (e.g., [[project]] and [[project|alias]] now group together). Improved display formatting with clickable headers showing absolute paths without .md extensions and proper wikilink alias parsing. Task cards preserve original formats while grouping logic ignores display aliases. Fixes issues #448 reported by @minchinweb and #469 reported by @anareaty

\n

User Experience Improvements#

\n

Tag Input Sanitization - Added automatic sanitization to remove # prefixes from tag input, preventing duplicate tags like #tag1 and ##tag1. Applied to task creation, editing, and real-time input handling. Fixes issue #331 reported by @AndreMonthy

\n

Contributors#

\n

Special recognition goes to @renatomen for the extensive custom user fields system that forms the core of this release, including field mapping, filtering, grouping, and sorting capabilities.

\n

Thanks to @fastrick for implementing the configurable click behavior feature.

\n

Thanks to the following community members for their bug reports and feature requests:

\n
    \n
  • @23maverick23 - Reported API custom status configuration issues with detailed technical analysis
  • \n
  • @Crunchnuggetz - Identified ICS calendar event sorting problem in agenda view
  • \n
  • @minchinweb - Reported project consolidation issues with wikilink variations
  • \n
  • @anareaty - Identified project display formatting problems in kanban view
  • \n
  • @bepolymathe - Requested calendar event filename template functionality
  • \n
  • @AndreMonthy - Reported tag input sanitization issues with clear examples
  • \n
  • @nightroman - Reported API issues where defaults were not being applied
  • \n
\n","text":"New Features# Custom User Fields System# Custom User Fields Mapping - Added ability to define custom frontmatter properties for task filtering, grouping, and sorting. Users can configure field mappings in Settings → Advanced → User Fields with support for text, number, date, boolean, and list field types. List fields preserve wikilinks and quoted tokens, while numeric fields intelligently parse mixed text-number values like \"2-Medium\" as numeric 2. Contributed by @renatomen Group and Sort by Custom User Fields - Extended grouping and sorting functionality to work with user-defined custom fields. Includes type-aware comparators for each field type and proper group header ordering when grouping and sorting by the same field. Contributed by @renatomen User Fields in Task Modals - Added custom user field support to task creation and edit modals with autocomplete suggestions from existing field values. Fields are stored as frontmatter properties and include change detection for edit scenarios. Contributed by @callumalpass Enhanced Task Interaction# Configurable Click Behavior - Added option to configure single-click and double-click behavior for task cards and inline task widgets. Users can choose between opening the edit modal or the source note file for each click type. Includes shared click handler utility with 250ms detection delay. Contributed by @fastrick Calendar Integration Enhancements# Calendar Event Filename Templates - Added separate filename template configuration for notes created from calendar events. Supports ICS-specific template variables including {icsEventTitle}, {icsEventLocation}, {icsEventDescription}, and {icsEventTitleWithDate}. The {title} variable now uses clean event titles without date suffixes. Fixes issue #362 reported by @bepolymathe Chronological ICS Event Sorting - Fixed ICS calendar events to display in chronological order by start time within each day in the agenda view. Applied to both grouped and flat agenda view modes. Fixes issue #472 reported by @Crunchnuggetz Bug Fixes# API Endpoint Improvements# Custom Status Configuration Support - Fixed API endpoints (/api/nlp/parse and /api/nlp/create) not respecting custom status configurations. API now uses proper default status logic matching the UI instead of hardcoded 'todo' values, with proper handling of boolean status values. Fixes issue #487 reported by @23maverick23 Task Creation Defaults - Fixed REST API endpoint (POST /api/tasks) missing default properties like scheduled dates, tags, and reminders. API-created tasks now receive the same defaults as UI-created tasks. Fixes issue reported by @nightroman Project Management Fixes# Project Consolidation and Display - Fixed project grouping to consolidate different formats pointing to the same file (e.g., [[project]] and [[project|alias]] now group together). Improved display formatting with clickable headers showing absolute paths without .md extensions and proper wikilink alias parsing. Task cards preserve original formats while grouping logic ignores display aliases. Fixes issues #448 reported by @minchinweb and #469 reported by @anareaty User Experience Improvements# Tag Input Sanitization - Added automatic sanitization to remove # prefixes from tag input, preventing duplicate tags like #tag1 and ##tag1. Applied to task creation, editing, and real-time input handling. Fixes issue #331 reported by @AndreMonthy Contributors# Special recognition goes to @renatomen for the extensive custom user fields system that forms the core of this release, including field mapping, filtering, grouping, and sorting capabilities. Thanks to @fastrick for implementing the configurable click behavior feature. Thanks to the following community members for their bug reports and feature requests: @23maverick23 - Reported API custom status configuration issues with detailed technical analysis @Crunchnuggetz - Identified ICS calendar event sorting problem in agenda view @minchinweb - Reported project consolidation issues with wikilink variations @anareaty - Identified project display formatting problems in kanban view @bepolymathe - Requested calendar event filename template functionality @AndreMonthy - Reported tag input sanitization issues with clear examples @nightroman - Reported API issues where defaults were not being applied"},{"route":"/obsidian/releases/3.22.0/","title":"TaskNotes 3.22.0","description":"Added modular properties system allowing users to control visibility of task properties (due date, scheduled date, priority, projects, contexts, tags, custom fields, and total t...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.22.0.md","namespace":"obsidian","relativePath":"releases/3.22.0.md","raw":"# TaskNotes 3.22.0\n\n## Major Features\n\n### Modular Properties System\n\n- Added modular properties system allowing users to control visibility of task properties (due date, scheduled date, priority, projects, contexts, tags, custom fields, and total tracked time) both globally and per saved view. Properties can be configured through a new Properties dropdown in the filter bar, with settings automatically saved per view. Includes performance optimizations to render properties only when visible. *Thanks to @renatomen for the initial implementation of this feature*\n\n- Task cards now dynamically render properties based on visibility settings with improved error handling and type safety. System supports both core properties and user-defined custom fields with proper fallback to default configurations for new users.\n\n- Added total tracked time as a configurable property in the modular system, calculated from time entries and displayed consistently across all views when enabled.\n\n### Bases-style Filter Bar Redesign\n\n- Complete filter bar redesign matching Obsidian's bases plugin styling with improved layout, spacing, and button appearance. Added text labels and chevron icons to all filter buttons (Sort, Filters, Properties, New) for better discoverability.\n- Replaced dropdown menus with native Obsidian context menus featuring section headers and improved reliability. Sort/Group functionality now uses unified context menu system with better organization.\n- Implemented intelligent filter popup positioning using boundary detection to prevent popups from hiding under adjacent panes. Increased default popup width from 300px to 500px for better usability.\n- Moved expand/collapse controls from separate containers directly into filter headings across all views (TaskListView, AgendaView, subtask widget) for cleaner interface and consistent user experience.\n- Added dedicated \"+ New\" task creation button to filter bar with neutral styling and proper view context awareness.\n\n### Statistics view\n\n- Implement a new view to track statistics about projects and time tracking. \n\n## UX\n\n### Task Interaction Improvements\n\n- Changed \"This Week\" grouping label to \"Next seven days\" for clearer, more specific language about the 7-day time period while maintaining identical underlying functionality. *Fixes issue #516 reported by @anareaty*\n\n### External Contributions\n\n- Type-aware input fields in task modals now provide appropriate UI components based on field type (text/list with autosuggest, date with picker icon, boolean with toggle). Project autosuggest during task creation now supports multi-word project names without interrupting suggestions on spaces. *Contributed by @renatomen*\n- Fixed subtask right-click context menus that were incorrectly showing parent task options instead of subtask-specific options. Enhanced inline task overlay cursor behavior with configurable timing settings (0-500ms) for predictable overlay hiding when cursor approaches link boundaries. *Contributed by @renatomen* \n- Fixed project names containing commas (e.g., `[[Money, Org & Adm]]`) being incorrectly split, breaking selection and display across task modals, settings, and instant conversion. Now uses proper wikilink parsing to preserve comma-containing project names as single entities. *Contributed by @renatomen*\n- Fixed date parsing errors caused by hardcoded field mapping not respecting user's custom field configurations. Plugin now properly uses field mapper for note date extraction with fallback to hardcoded fields for backward compatibility. *Contributed by @renatomen*\n- Fixed User Fields column order in settings to match Field mapping configuration for consistency. *Contributed by @renatomen*\n\n## Bug Fixes\n\n### Timezone and Date Handling\n\n- Fixed timezone-dependent \"Today\" identification issues across multiple views including MiniCalendarView tooltips, PomodoroService session categorization, PomodoroStatsView statistics, and StatsView date calculations. All date-sensitive components now use UTC-anchored dates for timezone-independent behavior. *Fixes issue #452 reported by @MinchinWeb*\n\n\n### User Interface Fixes\n\n- Redesigned group counters with clean appearance (removed background, border, padding), positioned to far right of headers using muted text color for subtle display while maintaining left-aligned headings.\n- Improved contrast for INTERRUPTED status badge in pomodoro statistics for better readability. *Fixes issue #529 reported by @motusira*\n- Removed title length limits that were causing text truncation, allowing full title display. *Fixes issue #378 reported by @nsstrickland*\n- Added all-day slot toggle to calendar view for better event organization. *Fixes issue #242 requested by @Crunchnuggetz*\n- Added calendar locale configuration for international calendar support with proper localization. *Contributed by @pixeler*\n- Fixed task states not refreshing when date changes at midnight, ensuring accurate daily task status updates. *Fixes issue #527 reported by @jordandrako*\n- Fixed inline task overlay title wrapping using `white-space: break-spaces` for proper text display. *Fixes issue #517 reported by @cathywu*\n\n### New Capabilities\n\n- Added weekday display and increment options to date picker with integration into task context menus for improved date selection experience. *Fixes issue #238 requested by @girisumit*\n- Added tags to available sorting and grouping options for more flexible task organization. *Fixes issue #169 requested by @bce283c*\n- Added create inline task command for quick task creation within notes with NLP project support for automatic project assignment based on context. *Fixes issue #299 requested by @0dfa1bc*\n- Added filename template variables to folder templates including support for additional customization options. *Fixes issue #473 requested by @oliverlalan*\n- Implemented status auto-suggestion with NLP integration for intelligent status recommendations during task creation and editing.\n\n## Infrastructure Improvements\n\n### Development and Testing\n\n- Updated multiple npm dependencies including ical.js (1.5.0 → 2.2.1) and Jest (29.7.0 → 30.1.1) with compatibility fixes. Resolved all npm security vulnerabilities and updated ICS subscription service for ical.js v2.x compatibility.\n- Fixed all test suite failures and infrastructure issues including Jest 30 compatibility, RRule mocking, TypeScript configuration, and CI environment setup. Removed coverage thresholds that were causing CI failures while maintaining test quality.\n- Improved code quality throughout modular properties system with proper TypeScript compliance, error handling, performance optimizations, and memory cleanup functions. Replaced 'any' types with proper type guards and added comprehensive interface definitions.\n\n## Contributors\n\nSpecial recognition goes to **@renatomen** for multiple substantial contributions including type-aware custom field inputs, enhanced task interaction fixes, project name handling improvements, date parsing fixes, and settings alignment.\n\nThanks to the following community members for their bug reports and feature requests:\n\n- **@anareaty** - Reported grouping label confusion with clear examples\n- **@MinchinWeb** - Identified timezone handling inconsistencies across multiple views\n- **@motusira** - Reported contrast issues with INTERRUPTED status badge\n- **@nsstrickland** - Identified title truncation problems\n- **@Crunchnuggetz** - Requested all-day slot toggle for calendar views\n- **@jordandrako** - Reported task state refresh issues at midnight\n- **@cathywu** - Identified text wrapping problems in overlays \n- **@girisumit** - Requested enhanced date picker functionality\n- **@oliverlalan** - Requested template variable enhancements","aliases":["/releases/3.22.0/","/releases/3.22.0/"],"toc":[{"level":2,"id":"major-features","text":"Major Features"},{"level":3,"id":"modular-properties-system","text":"Modular Properties System"},{"level":3,"id":"bases-style-filter-bar-redesign","text":"Bases-style Filter Bar Redesign"},{"level":3,"id":"statistics-view","text":"Statistics view"},{"level":2,"id":"ux","text":"UX"},{"level":3,"id":"task-interaction-improvements","text":"Task Interaction Improvements"},{"level":3,"id":"external-contributions","text":"External Contributions"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"timezone-and-date-handling","text":"Timezone and Date Handling"},{"level":3,"id":"user-interface-fixes","text":"User Interface Fixes"},{"level":3,"id":"new-capabilities","text":"New Capabilities"},{"level":2,"id":"infrastructure-improvements","text":"Infrastructure Improvements"},{"level":3,"id":"development-and-testing","text":"Development and Testing"},{"level":2,"id":"contributors","text":"Contributors"}],"html":"

Major Features#

\n

Modular Properties System#

\n
    \n
  • Added modular properties system allowing users to control visibility of task properties (due date, scheduled date, priority, projects, contexts, tags, custom fields, and total tracked time) both globally and per saved view. Properties can be configured through a new Properties dropdown in the filter bar, with settings automatically saved per view. Includes performance optimizations to render properties only when visible. Thanks to @renatomen for the initial implementation of this feature

    \n
  • \n
  • Task cards now dynamically render properties based on visibility settings with improved error handling and type safety. System supports both core properties and user-defined custom fields with proper fallback to default configurations for new users.

    \n
  • \n
  • Added total tracked time as a configurable property in the modular system, calculated from time entries and displayed consistently across all views when enabled.

    \n
  • \n
\n

Bases-style Filter Bar Redesign#

\n
    \n
  • Complete filter bar redesign matching Obsidian's bases plugin styling with improved layout, spacing, and button appearance. Added text labels and chevron icons to all filter buttons (Sort, Filters, Properties, New) for better discoverability.
  • \n
  • Replaced dropdown menus with native Obsidian context menus featuring section headers and improved reliability. Sort/Group functionality now uses unified context menu system with better organization.
  • \n
  • Implemented intelligent filter popup positioning using boundary detection to prevent popups from hiding under adjacent panes. Increased default popup width from 300px to 500px for better usability.
  • \n
  • Moved expand/collapse controls from separate containers directly into filter headings across all views (TaskListView, AgendaView, subtask widget) for cleaner interface and consistent user experience.
  • \n
  • Added dedicated "+ New" task creation button to filter bar with neutral styling and proper view context awareness.
  • \n
\n

Statistics view#

\n
    \n
  • Implement a new view to track statistics about projects and time tracking.
  • \n
\n

UX#

\n

Task Interaction Improvements#

\n
    \n
  • Changed "This Week" grouping label to "Next seven days" for clearer, more specific language about the 7-day time period while maintaining identical underlying functionality. Fixes issue #516 reported by @anareaty
  • \n
\n

External Contributions#

\n
    \n
  • Type-aware input fields in task modals now provide appropriate UI components based on field type (text/list with autosuggest, date with picker icon, boolean with toggle). Project autosuggest during task creation now supports multi-word project names without interrupting suggestions on spaces. Contributed by @renatomen
  • \n
  • Fixed subtask right-click context menus that were incorrectly showing parent task options instead of subtask-specific options. Enhanced inline task overlay cursor behavior with configurable timing settings (0-500ms) for predictable overlay hiding when cursor approaches link boundaries. Contributed by @renatomen
  • \n
  • Fixed project names containing commas (e.g., [[Money, Org & Adm]]) being incorrectly split, breaking selection and display across task modals, settings, and instant conversion. Now uses proper wikilink parsing to preserve comma-containing project names as single entities. Contributed by @renatomen
  • \n
  • Fixed date parsing errors caused by hardcoded field mapping not respecting user's custom field configurations. Plugin now properly uses field mapper for note date extraction with fallback to hardcoded fields for backward compatibility. Contributed by @renatomen
  • \n
  • Fixed User Fields column order in settings to match Field mapping configuration for consistency. Contributed by @renatomen
  • \n
\n

Bug Fixes#

\n

Timezone and Date Handling#

\n
    \n
  • Fixed timezone-dependent "Today" identification issues across multiple views including MiniCalendarView tooltips, PomodoroService session categorization, PomodoroStatsView statistics, and StatsView date calculations. All date-sensitive components now use UTC-anchored dates for timezone-independent behavior. Fixes issue #452 reported by @MinchinWeb
  • \n
\n

User Interface Fixes#

\n
    \n
  • Redesigned group counters with clean appearance (removed background, border, padding), positioned to far right of headers using muted text color for subtle display while maintaining left-aligned headings.
  • \n
  • Improved contrast for INTERRUPTED status badge in pomodoro statistics for better readability. Fixes issue #529 reported by @motusira
  • \n
  • Removed title length limits that were causing text truncation, allowing full title display. Fixes issue #378 reported by @nsstrickland
  • \n
  • Added all-day slot toggle to calendar view for better event organization. Fixes issue #242 requested by @Crunchnuggetz
  • \n
  • Added calendar locale configuration for international calendar support with proper localization. Contributed by @pixeler
  • \n
  • Fixed task states not refreshing when date changes at midnight, ensuring accurate daily task status updates. Fixes issue #527 reported by @jordandrako
  • \n
  • Fixed inline task overlay title wrapping using white-space: break-spaces for proper text display. Fixes issue #517 reported by @cathywu
  • \n
\n

New Capabilities#

\n
    \n
  • Added weekday display and increment options to date picker with integration into task context menus for improved date selection experience. Fixes issue #238 requested by @girisumit
  • \n
  • Added tags to available sorting and grouping options for more flexible task organization. Fixes issue #169 requested by @bce283c
  • \n
  • Added create inline task command for quick task creation within notes with NLP project support for automatic project assignment based on context. Fixes issue #299 requested by @0dfa1bc
  • \n
  • Added filename template variables to folder templates including support for additional customization options. Fixes issue #473 requested by @oliverlalan
  • \n
  • Implemented status auto-suggestion with NLP integration for intelligent status recommendations during task creation and editing.
  • \n
\n

Infrastructure Improvements#

\n

Development and Testing#

\n
    \n
  • Updated multiple npm dependencies including ical.js (1.5.0 → 2.2.1) and Jest (29.7.0 → 30.1.1) with compatibility fixes. Resolved all npm security vulnerabilities and updated ICS subscription service for ical.js v2.x compatibility.
  • \n
  • Fixed all test suite failures and infrastructure issues including Jest 30 compatibility, RRule mocking, TypeScript configuration, and CI environment setup. Removed coverage thresholds that were causing CI failures while maintaining test quality.
  • \n
  • Improved code quality throughout modular properties system with proper TypeScript compliance, error handling, performance optimizations, and memory cleanup functions. Replaced 'any' types with proper type guards and added comprehensive interface definitions.
  • \n
\n

Contributors#

\n

Special recognition goes to @renatomen for multiple substantial contributions including type-aware custom field inputs, enhanced task interaction fixes, project name handling improvements, date parsing fixes, and settings alignment.

\n

Thanks to the following community members for their bug reports and feature requests:

\n
    \n
  • @anareaty - Reported grouping label confusion with clear examples
  • \n
  • @MinchinWeb - Identified timezone handling inconsistencies across multiple views
  • \n
  • @motusira - Reported contrast issues with INTERRUPTED status badge
  • \n
  • @nsstrickland - Identified title truncation problems
  • \n
  • @Crunchnuggetz - Requested all-day slot toggle for calendar views
  • \n
  • @jordandrako - Reported task state refresh issues at midnight
  • \n
  • @cathywu - Identified text wrapping problems in overlays
  • \n
  • @girisumit - Requested enhanced date picker functionality
  • \n
  • @oliverlalan - Requested template variable enhancements
  • \n
\n","text":"Major Features# Modular Properties System# Added modular properties system allowing users to control visibility of task properties (due date, scheduled date, priority, projects, contexts, tags, custom fields, and total tracked time) both globally and per saved view. Properties can be configured through a new Properties dropdown in the filter bar, with settings automatically saved per view. Includes performance optimizations to render properties only when visible. Thanks to @renatomen for the initial implementation of this feature Task cards now dynamically render properties based on visibility settings with improved error handling and type safety. System supports both core properties and user-defined custom fields with proper fallback to default configurations for new users. Added total tracked time as a configurable property in the modular system, calculated from time entries and displayed consistently across all views when enabled. Bases-style Filter Bar Redesign# Complete filter bar redesign matching Obsidian's bases plugin styling with improved layout, spacing, and button appearance. Added text labels and chevron icons to all filter buttons (Sort, Filters, Properties, New) for better discoverability. Replaced dropdown menus with native Obsidian context menus featuring section headers and improved reliability. Sort/Group functionality now uses unified context menu system with better organization. Implemented intelligent filter popup positioning using boundary detection to prevent popups from hiding under adjacent panes. Increased default popup width from 300px to 500px for better usability. Moved expand/collapse controls from separate containers directly into filter headings across all views (TaskListView, AgendaView, subtask widget) for cleaner interface and consistent user experience. Added dedicated \"+ New\" task creation button to filter bar with neutral styling and proper view context awareness. Statistics view# Implement a new view to track statistics about projects and time tracking. UX# Task Interaction Improvements# Changed \"This Week\" grouping label to \"Next seven days\" for clearer, more specific language about the 7-day time period while maintaining identical underlying functionality. Fixes issue #516 reported by @anareaty External Contributions# Type-aware input fields in task modals now provide appropriate UI components based on field type (text/list with autosuggest, date with picker icon, boolean with toggle). Project autosuggest during task creation now supports multi-word project names without interrupting suggestions on spaces. Contributed by @renatomen Fixed subtask right-click context menus that were incorrectly showing parent task options instead of subtask-specific options. Enhanced inline task overlay cursor behavior with configurable timing settings (0-500ms) for predictable overlay hiding when cursor approaches link boundaries. Contributed by @renatomen Fixed project names containing commas (e.g., [[Money, Org & Adm]]) being incorrectly split, breaking selection and display across task modals, settings, and instant conversion. Now uses proper wikilink parsing to preserve comma-containing project names as single entities. Contributed by @renatomen Fixed date parsing errors caused by hardcoded field mapping not respecting user's custom field configurations. Plugin now properly uses field mapper for note date extraction with fallback to hardcoded fields for backward compatibility. Contributed by @renatomen Fixed User Fields column order in settings to match Field mapping configuration for consistency. Contributed by @renatomen Bug Fixes# Timezone and Date Handling# Fixed timezone-dependent \"Today\" identification issues across multiple views including MiniCalendarView tooltips, PomodoroService session categorization, PomodoroStatsView statistics, and StatsView date calculations. All date-sensitive components now use UTC-anchored dates for timezone-independent behavior. Fixes issue #452 reported by @MinchinWeb User Interface Fixes# Redesigned group counters with clean appearance (removed background, border, padding), positioned to far right of headers using muted text color for subtle display while maintaining left-aligned headings. Improved contrast for INTERRUPTED status badge in pomodoro statistics for better readability. Fixes issue #529 reported by @motusira Removed title length limits that were causing text truncation, allowing full title display. Fixes issue #378 reported by @nsstrickland Added all-day slot toggle to calendar view for better event organization. Fixes issue #242 requested by @Crunchnuggetz Added calendar locale configuration for international calendar support with proper localization. Contributed by @pixeler Fixed task states not refreshing when date changes at midnight, ensuring accurate daily task status updates. Fixes issue #527 reported by @jordandrako Fixed inline task overlay title wrapping using white-space: break-spaces for proper text display. Fixes issue #517 reported by @cathywu New Capabilities# Added weekday display and increment options to date picker with integration into task context menus for improved date selection experience. Fixes issue #238 requested by @girisumit Added tags to available sorting and grouping options for more flexible task organization. Fixes issue #169 requested by @bce283c Added create inline task command for quick task creation within notes with NLP project support for automatic project assignment based on context. Fixes issue #299 requested by @0dfa1bc Added filename template variables to folder templates including support for additional customization options. Fixes issue #473 requested by @oliverlalan Implemented status auto-suggestion with NLP integration for intelligent status recommendations during task creation and editing. Infrastructure Improvements# Development and Testing# Updated multiple npm dependencies including ical.js (1.5.0 → 2.2.1) and Jest (29.7.0 → 30.1.1) with compatibility fixes. Resolved all npm security vulnerabilities and updated ICS subscription service for ical.js v2.x compatibility. Fixed all test suite failures and infrastructure issues including Jest 30 compatibility, RRule mocking, TypeScript configuration, and CI environment setup. Removed coverage thresholds that were causing CI failures while maintaining test quality. Improved code quality throughout modular properties system with proper TypeScript compliance, error handling, performance optimizations, and memory cleanup functions. Replaced 'any' types with proper type guards and added comprehensive interface definitions. Contributors# Special recognition goes to @renatomen for multiple substantial contributions including type-aware custom field inputs, enhanced task interaction fixes, project name handling improvements, date parsing fixes, and settings alignment. Thanks to the following community members for their bug reports and feature requests: @anareaty - Reported grouping label confusion with clear examples @MinchinWeb - Identified timezone handling inconsistencies across multiple views @motusira - Reported contrast issues with INTERRUPTED status badge @nsstrickland - Identified title truncation problems @Crunchnuggetz - Requested all-day slot toggle for calendar views @jordandrako - Reported task state refresh issues at midnight @cathywu - Identified text wrapping problems in overlays @girisumit - Requested enhanced date picker functionality @oliverlalan - Requested template variable enhancements"},{"route":"/obsidian/releases/3.22.1/","title":"TaskNotes 3.22.1","description":"Thanks to @jhedlund for implementing the configurable recurring task due date feature.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.22.1.md","namespace":"obsidian","relativePath":"releases/3.22.1.md","raw":"# TaskNotes 3.22.1\n\n## New Features\n\n### Configurable Recurring Task Due Date Behavior\n\n- Added optional due date advancement for recurring tasks. When enabled, maintains the time separation between scheduled and due dates when tasks are completed. The new \"Maintain due date offset in recurring tasks\" setting in Misc preferences controls this behavior and defaults to disabled to preserve existing behavior. *Contributed by @jhedlund, fixes issue #470*\n\n## Bug Fixes\n\n### Calendar and Task Display\n\n- Fixed calendar view issues where tasks were not displaying correctly due to empty status values causing infinite loops and TypeErrors. Resolved `timeEntries.filter is not a function` errors when loading calendar events and prevented Obsidian freezing during task creation with empty status text. *Fixes issue #520 reported by @cathywu*\n\n### Saved Views and Property Management\n\n- Fixed property visibility settings not being preserved when saving filter views. View configurations now properly store and restore property display preferences. *Fixes issue #545 reported by @anareaty*\n- Fixed saved view selection to prefer newly created views over older matching views, ensuring the correct view is activated after saving.\n- Added proper null safety checks for FilterBar interactions to prevent errors during view save operations.\n\n### User Interface Improvements\n\n- Added responsive behavior to filter bar buttons that automatically hide button text when pane width falls below 500px to prevent overflow in narrow sidebars. Uses container queries with media query fallback for broader browser support. *Fixes issue #549 reported by @TonyAtlas*\n\n## Development Improvements\n\n- Reduced excessive console logging in TaskListView by removing 37+ debug statements while preserving essential error logging for troubleshooting.\n\n## Contributors\n\nThanks to **@jhedlund** for implementing the configurable recurring task due date feature.\n\nThanks to the following community members for their bug reports:\n\n- **@cathywu** - Reported calendar view task display issues with detailed technical information\n- **@anareaty** - Identified property visibility persistence problems in saved views \n- **@TonyAtlas** - Reported filter bar overflow issues in narrow sidebars with helpful screenshots","aliases":["/releases/3.22.1/","/releases/3.22.1/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"configurable-recurring-task-due-date-behavior","text":"Configurable Recurring Task Due Date Behavior"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"calendar-and-task-display","text":"Calendar and Task Display"},{"level":3,"id":"saved-views-and-property-management","text":"Saved Views and Property Management"},{"level":3,"id":"user-interface-improvements","text":"User Interface Improvements"},{"level":2,"id":"development-improvements","text":"Development Improvements"},{"level":2,"id":"contributors","text":"Contributors"}],"html":"

New Features#

\n

Configurable Recurring Task Due Date Behavior#

\n
    \n
  • Added optional due date advancement for recurring tasks. When enabled, maintains the time separation between scheduled and due dates when tasks are completed. The new "Maintain due date offset in recurring tasks" setting in Misc preferences controls this behavior and defaults to disabled to preserve existing behavior. Contributed by @jhedlund, fixes issue #470
  • \n
\n

Bug Fixes#

\n

Calendar and Task Display#

\n
    \n
  • Fixed calendar view issues where tasks were not displaying correctly due to empty status values causing infinite loops and TypeErrors. Resolved timeEntries.filter is not a function errors when loading calendar events and prevented Obsidian freezing during task creation with empty status text. Fixes issue #520 reported by @cathywu
  • \n
\n

Saved Views and Property Management#

\n
    \n
  • Fixed property visibility settings not being preserved when saving filter views. View configurations now properly store and restore property display preferences. Fixes issue #545 reported by @anareaty
  • \n
  • Fixed saved view selection to prefer newly created views over older matching views, ensuring the correct view is activated after saving.
  • \n
  • Added proper null safety checks for FilterBar interactions to prevent errors during view save operations.
  • \n
\n

User Interface Improvements#

\n
    \n
  • Added responsive behavior to filter bar buttons that automatically hide button text when pane width falls below 500px to prevent overflow in narrow sidebars. Uses container queries with media query fallback for broader browser support. Fixes issue #549 reported by @TonyAtlas
  • \n
\n

Development Improvements#

\n
    \n
  • Reduced excessive console logging in TaskListView by removing 37+ debug statements while preserving essential error logging for troubleshooting.
  • \n
\n

Contributors#

\n

Thanks to @jhedlund for implementing the configurable recurring task due date feature.

\n

Thanks to the following community members for their bug reports:

\n
    \n
  • @cathywu - Reported calendar view task display issues with detailed technical information
  • \n
  • @anareaty - Identified property visibility persistence problems in saved views
  • \n
  • @TonyAtlas - Reported filter bar overflow issues in narrow sidebars with helpful screenshots
  • \n
\n","text":"New Features# Configurable Recurring Task Due Date Behavior# Added optional due date advancement for recurring tasks. When enabled, maintains the time separation between scheduled and due dates when tasks are completed. The new \"Maintain due date offset in recurring tasks\" setting in Misc preferences controls this behavior and defaults to disabled to preserve existing behavior. Contributed by @jhedlund, fixes issue #470 Bug Fixes# Calendar and Task Display# Fixed calendar view issues where tasks were not displaying correctly due to empty status values causing infinite loops and TypeErrors. Resolved timeEntries.filter is not a function errors when loading calendar events and prevented Obsidian freezing during task creation with empty status text. Fixes issue #520 reported by @cathywu Saved Views and Property Management# Fixed property visibility settings not being preserved when saving filter views. View configurations now properly store and restore property display preferences. Fixes issue #545 reported by @anareaty Fixed saved view selection to prefer newly created views over older matching views, ensuring the correct view is activated after saving. Added proper null safety checks for FilterBar interactions to prevent errors during view save operations. User Interface Improvements# Added responsive behavior to filter bar buttons that automatically hide button text when pane width falls below 500px to prevent overflow in narrow sidebars. Uses container queries with media query fallback for broader browser support. Fixes issue #549 reported by @TonyAtlas Development Improvements# Reduced excessive console logging in TaskListView by removing 37+ debug statements while preserving essential error logging for troubleshooting. Contributors# Thanks to @jhedlund for implementing the configurable recurring task due date feature. Thanks to the following community members for their bug reports: @cathywu - Reported calendar view task display issues with detailed technical information @anareaty - Identified property visibility persistence problems in saved views @TonyAtlas - Reported filter bar overflow issues in narrow sidebars with helpful screenshots"},{"route":"/obsidian/releases/3.23.0/","title":"TaskNotes 3.23.0","description":"We extend special thanks to @renatomen for his exceptional contributions to this release:","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.23.0.md","namespace":"obsidian","relativePath":"releases/3.23.0.md","raw":"# TaskNotes 3.23.0\n\n## New Features\n\n### ICS Export and Calendar Integration\n\n- Added full ICS export functionality with proper RFC 5545 compliance for improved calendar application compatibility\n- Implemented automatic ICS export with configurable interval updates (5-1440 minutes) for calendar subscription workflows\n- Added manual \"Export all tasks as ICS file\" command for bulk export operations\n- *Thanks to @mdbraber for requesting this feature (#422)*\n\n### Status-Based Auto-Archive\n\n- Introduced configurable auto-archive system with per-status timeout settings (1-1440 minutes)\n- Added persistent queue that survives plugin restarts for reliable task archiving\n- Implemented settings UI for fine-grained control over auto-archive behavior\n- *Thanks to @TonyAtlas for requesting this feature (#547) and to @renatomen for design suggestions*\n\n### Multi-Language Natural Language Processing\n\n- Added NLP support for 12 languages: English, Spanish, French, German, Russian, Chinese, Japanese, Italian, Dutch, Portuguese, Swedish, Ukrainian\n- Implemented locale-specific date parsing using chrono-node language support\n- Enhanced pattern matching with proper handling for Latin, Cyrillic, Chinese, and Japanese scripts\n- *Thanks to @pschoenbach for requesting German language support (#563)*\n\n### Enhanced Project Autosuggest\n\n- Implemented configurable multi-row project cards with customizable display fields\n- Added selective search functionality across chosen fields with simple flag system\n- Introduced fuzzy search option for broader, multi-word matching capabilities\n- Enhanced project selection with clear metadata display (title, aliases, path)\n- *Thanks to @renatomen for implementing this feature (#555)*\n\n### Bases Plugin Integration\n\n- Added experimental integration with the Bases plugin for enhanced task management workflows\n- Implemented direct formula computation and custom property support\n- Added clickable tags and contexts with accessibility support\n- Created simplified kanban view integration with proper lifecycle management\n- *Thanks to @renatomen for his incredible work developing the proof-of-concept for this feature*\n\n### Settings UI Modernization\n\n- Complete redesign of settings interface with card-based design system\n- Added collapsible functionality and live API documentation\n- Enhanced calendar subscription interface with local file support\n\n## Bug Fixes\n\n### Task Creation and File Handling\n\n- Fixed startup crash when templates contain empty reminders property (*reported by @glpayson, #583*)\n- Implemented automatic sanitization of forbidden characters in task titles instead of blocking creation (*reported by @glpayson, #590*)\n- Added support for platform-specific filename characters (hash, square brackets)\n- Resolved inconsistent behavior between instant convert and manual task creation\n\n### Project and Link Functionality \n\n- Added clickable project links in task edit modal for better navigation (*requested by @anareaty, #432*)\n- Fixed completion date timezone handling to ensure consistent local time recording\n- Corrected frontmatter property naming in Bases kanban drag-and-drop operations\n\n### Property Display and Performance\n\n- Fixed custom property duplication when configured in both settings and filter bar\n- Resolved unwanted total tracked time display showing zero values\n- Standardized custom property identifiers with consistent prefix format\n\n### Plugin Integration and Stability\n\n- Resolved Bases plugin integration issues and view switching problems\n- Fixed kanban view loading with proper static imports and interface consistency\n- Improved error handling and cleanup patterns for better stability\n- Fixed API endpoints to respect custom status configurations (*reported by @23maverick23, #487*)\n\n## Acknowledgments\n\n### Special Recognition\n\nWe extend special thanks to **@renatomen** for his exceptional contributions to this release:\n\n- Created the enhanced project autosuggest system with configurable cards and selective search functionality (PR #555)\n- Developed a proof-of-concept integration with the Bases plugin that demonstrated full compatibility and provided the technical foundation for our experimental Bases integration\n- His innovative work on the Bases POC revealed that everything that I was hoping might be possible in a future integration with Bases was actually possible!\n\n### Community Contributors\n\nWe're grateful to the community members whose issues were resolved in this release:\n\n- **@glpayson** for providing detailed bug reports with reproduction steps that led to fixes for the startup crash with empty reminders (#583) and character handling improvements (#590)\n- **@mdbraber** for requesting ICS export functionality that became a major feature in this release (#422)\n- **@TonyAtlas** for the auto-archive feature request that resulted in the new status-based auto-archive system (#547)\n- **@anareaty** for requesting clickable project links (#432) and reporting the \"This Week\" grouping label issue (#516)\n- **@pschoenbach** for requesting multi-language NLP support, specifically German language support (#563)\n- **@23maverick23** for reporting API status configuration issues that improved custom status handling (#487)\n- **@Burrish** for the documentation correction (#597)\n\n---\n\n**Full Changelog**: [3.22.1...3.23.0](https://github.com/callumalpass/tasknotes/compare/3.22.1...3.23.0)\n\n","aliases":["/releases/3.23.0/","/releases/3.23.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"ics-export-and-calendar-integration","text":"ICS Export and Calendar Integration"},{"level":3,"id":"status-based-auto-archive","text":"Status-Based Auto-Archive"},{"level":3,"id":"multi-language-natural-language-processing","text":"Multi-Language Natural Language Processing"},{"level":3,"id":"enhanced-project-autosuggest","text":"Enhanced Project Autosuggest"},{"level":3,"id":"bases-plugin-integration","text":"Bases Plugin Integration"},{"level":3,"id":"settings-ui-modernization","text":"Settings UI Modernization"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"task-creation-and-file-handling","text":"Task Creation and File Handling"},{"level":3,"id":"project-and-link-functionality","text":"Project and Link Functionality"},{"level":3,"id":"property-display-and-performance","text":"Property Display and Performance"},{"level":3,"id":"plugin-integration-and-stability","text":"Plugin Integration and Stability"},{"level":2,"id":"acknowledgments","text":"Acknowledgments"},{"level":3,"id":"special-recognition","text":"Special Recognition"},{"level":3,"id":"community-contributors","text":"Community Contributors"}],"html":"

New Features#

\n

ICS Export and Calendar Integration#

\n
    \n
  • Added full ICS export functionality with proper RFC 5545 compliance for improved calendar application compatibility
  • \n
  • Implemented automatic ICS export with configurable interval updates (5-1440 minutes) for calendar subscription workflows
  • \n
  • Added manual "Export all tasks as ICS file" command for bulk export operations
  • \n
  • Thanks to @mdbraber for requesting this feature (#422)
  • \n
\n

Status-Based Auto-Archive#

\n
    \n
  • Introduced configurable auto-archive system with per-status timeout settings (1-1440 minutes)
  • \n
  • Added persistent queue that survives plugin restarts for reliable task archiving
  • \n
  • Implemented settings UI for fine-grained control over auto-archive behavior
  • \n
  • Thanks to @TonyAtlas for requesting this feature (#547) and to @renatomen for design suggestions
  • \n
\n

Multi-Language Natural Language Processing#

\n
    \n
  • Added NLP support for 12 languages: English, Spanish, French, German, Russian, Chinese, Japanese, Italian, Dutch, Portuguese, Swedish, Ukrainian
  • \n
  • Implemented locale-specific date parsing using chrono-node language support
  • \n
  • Enhanced pattern matching with proper handling for Latin, Cyrillic, Chinese, and Japanese scripts
  • \n
  • Thanks to @pschoenbach for requesting German language support (#563)
  • \n
\n

Enhanced Project Autosuggest#

\n
    \n
  • Implemented configurable multi-row project cards with customizable display fields
  • \n
  • Added selective search functionality across chosen fields with simple flag system
  • \n
  • Introduced fuzzy search option for broader, multi-word matching capabilities
  • \n
  • Enhanced project selection with clear metadata display (title, aliases, path)
  • \n
  • Thanks to @renatomen for implementing this feature (#555)
  • \n
\n

Bases Plugin Integration#

\n
    \n
  • Added experimental integration with the Bases plugin for enhanced task management workflows
  • \n
  • Implemented direct formula computation and custom property support
  • \n
  • Added clickable tags and contexts with accessibility support
  • \n
  • Created simplified kanban view integration with proper lifecycle management
  • \n
  • Thanks to @renatomen for his incredible work developing the proof-of-concept for this feature
  • \n
\n

Settings UI Modernization#

\n
    \n
  • Complete redesign of settings interface with card-based design system
  • \n
  • Added collapsible functionality and live API documentation
  • \n
  • Enhanced calendar subscription interface with local file support
  • \n
\n

Bug Fixes#

\n

Task Creation and File Handling#

\n
    \n
  • Fixed startup crash when templates contain empty reminders property (reported by @glpayson, #583)
  • \n
  • Implemented automatic sanitization of forbidden characters in task titles instead of blocking creation (reported by @glpayson, #590)
  • \n
  • Added support for platform-specific filename characters (hash, square brackets)
  • \n
  • Resolved inconsistent behavior between instant convert and manual task creation
  • \n
\n\n
    \n
  • Added clickable project links in task edit modal for better navigation (requested by @anareaty, #432)
  • \n
  • Fixed completion date timezone handling to ensure consistent local time recording
  • \n
  • Corrected frontmatter property naming in Bases kanban drag-and-drop operations
  • \n
\n

Property Display and Performance#

\n
    \n
  • Fixed custom property duplication when configured in both settings and filter bar
  • \n
  • Resolved unwanted total tracked time display showing zero values
  • \n
  • Standardized custom property identifiers with consistent prefix format
  • \n
\n

Plugin Integration and Stability#

\n
    \n
  • Resolved Bases plugin integration issues and view switching problems
  • \n
  • Fixed kanban view loading with proper static imports and interface consistency
  • \n
  • Improved error handling and cleanup patterns for better stability
  • \n
  • Fixed API endpoints to respect custom status configurations (reported by @23maverick23, #487)
  • \n
\n

Acknowledgments#

\n

Special Recognition#

\n

We extend special thanks to @renatomen for his exceptional contributions to this release:

\n
    \n
  • Created the enhanced project autosuggest system with configurable cards and selective search functionality (PR #555)
  • \n
  • Developed a proof-of-concept integration with the Bases plugin that demonstrated full compatibility and provided the technical foundation for our experimental Bases integration
  • \n
  • His innovative work on the Bases POC revealed that everything that I was hoping might be possible in a future integration with Bases was actually possible!
  • \n
\n

Community Contributors#

\n

We're grateful to the community members whose issues were resolved in this release:

\n
    \n
  • @glpayson for providing detailed bug reports with reproduction steps that led to fixes for the startup crash with empty reminders (#583) and character handling improvements (#590)
  • \n
  • @mdbraber for requesting ICS export functionality that became a major feature in this release (#422)
  • \n
  • @TonyAtlas for the auto-archive feature request that resulted in the new status-based auto-archive system (#547)
  • \n
  • @anareaty for requesting clickable project links (#432) and reporting the "This Week" grouping label issue (#516)
  • \n
  • @pschoenbach for requesting multi-language NLP support, specifically German language support (#563)
  • \n
  • @23maverick23 for reporting API status configuration issues that improved custom status handling (#487)
  • \n
  • @Burrish for the documentation correction (#597)
  • \n
\n
\n

Full Changelog: 3.22.1...3.23.0

\n","text":"New Features# ICS Export and Calendar Integration# Added full ICS export functionality with proper RFC 5545 compliance for improved calendar application compatibility Implemented automatic ICS export with configurable interval updates (5-1440 minutes) for calendar subscription workflows Added manual \"Export all tasks as ICS file\" command for bulk export operations Thanks to @mdbraber for requesting this feature (#422) Status-Based Auto-Archive# Introduced configurable auto-archive system with per-status timeout settings (1-1440 minutes) Added persistent queue that survives plugin restarts for reliable task archiving Implemented settings UI for fine-grained control over auto-archive behavior Thanks to @TonyAtlas for requesting this feature (#547) and to @renatomen for design suggestions Multi-Language Natural Language Processing# Added NLP support for 12 languages: English, Spanish, French, German, Russian, Chinese, Japanese, Italian, Dutch, Portuguese, Swedish, Ukrainian Implemented locale-specific date parsing using chrono-node language support Enhanced pattern matching with proper handling for Latin, Cyrillic, Chinese, and Japanese scripts Thanks to @pschoenbach for requesting German language support (#563) Enhanced Project Autosuggest# Implemented configurable multi-row project cards with customizable display fields Added selective search functionality across chosen fields with simple flag system Introduced fuzzy search option for broader, multi-word matching capabilities Enhanced project selection with clear metadata display (title, aliases, path) Thanks to @renatomen for implementing this feature (#555) Bases Plugin Integration# Added experimental integration with the Bases plugin for enhanced task management workflows Implemented direct formula computation and custom property support Added clickable tags and contexts with accessibility support Created simplified kanban view integration with proper lifecycle management Thanks to @renatomen for his incredible work developing the proof-of-concept for this feature Settings UI Modernization# Complete redesign of settings interface with card-based design system Added collapsible functionality and live API documentation Enhanced calendar subscription interface with local file support Bug Fixes# Task Creation and File Handling# Fixed startup crash when templates contain empty reminders property (reported by @glpayson, #583) Implemented automatic sanitization of forbidden characters in task titles instead of blocking creation (reported by @glpayson, #590) Added support for platform-specific filename characters (hash, square brackets) Resolved inconsistent behavior between instant convert and manual task creation Project and Link Functionality# Added clickable project links in task edit modal for better navigation (requested by @anareaty, #432) Fixed completion date timezone handling to ensure consistent local time recording Corrected frontmatter property naming in Bases kanban drag-and-drop operations Property Display and Performance# Fixed custom property duplication when configured in both settings and filter bar Resolved unwanted total tracked time display showing zero values Standardized custom property identifiers with consistent prefix format Plugin Integration and Stability# Resolved Bases plugin integration issues and view switching problems Fixed kanban view loading with proper static imports and interface consistency Improved error handling and cleanup patterns for better stability Fixed API endpoints to respect custom status configurations (reported by @23maverick23, #487) Acknowledgments# Special Recognition# We extend special thanks to @renatomen for his exceptional contributions to this release: Created the enhanced project autosuggest system with configurable cards and selective search functionality (PR #555) Developed a proof-of-concept integration with the Bases plugin that demonstrated full compatibility and provided the technical foundation for our experimental Bases integration His innovative work on the Bases POC revealed that everything that I was hoping might be possible in a future integration with Bases was actually possible! Community Contributors# We're grateful to the community members whose issues were resolved in this release: @glpayson for providing detailed bug reports with reproduction steps that led to fixes for the startup crash with empty reminders (#583) and character handling improvements (#590) @mdbraber for requesting ICS export functionality that became a major feature in this release (#422) @TonyAtlas for the auto-archive feature request that resulted in the new status-based auto-archive system (#547) @anareaty for requesting clickable project links (#432) and reporting the \"This Week\" grouping label issue (#516) @pschoenbach for requesting multi-language NLP support, specifically German language support (#563) @23maverick23 for reporting API status configuration issues that improved custom status handling (#487) @Burrish for the documentation correction (#597) Full Changelog: 3.22.1...3.23.0"},{"route":"/obsidian/releases/3.23.1/","title":"TaskNotes 3.23.1","description":"Full Changelog: 3.23.0...3.23.1","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.23.1.md","namespace":"obsidian","relativePath":"releases/3.23.1.md","raw":"# TaskNotes 3.23.1\n\n## Bug Fixes\n\n### Bases Plugin Integration\n\n- Fixed Bases views not recognizing custom field mappings when using non-default property names. Status dots, priority colors, and dates now display correctly in Bases views when using custom field names, including Cyrillic and other localized property names. *Thanks to @anareaty for reporting this issue (#607)*\n\n---\n\n**Full Changelog**: [3.23.0...3.23.1](https://github.com/callumalpass/tasknotes/compare/3.23.0...3.23.1)","aliases":["/releases/3.23.1/","/releases/3.23.1/"],"toc":[{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"bases-plugin-integration","text":"Bases Plugin Integration"}],"html":"

Bug Fixes#

\n

Bases Plugin Integration#

\n
    \n
  • Fixed Bases views not recognizing custom field mappings when using non-default property names. Status dots, priority colors, and dates now display correctly in Bases views when using custom field names, including Cyrillic and other localized property names. Thanks to @anareaty for reporting this issue (#607)
  • \n
\n
\n

Full Changelog: 3.23.0...3.23.1

\n","text":"Bug Fixes# Bases Plugin Integration# Fixed Bases views not recognizing custom field mappings when using non-default property names. Status dots, priority colors, and dates now display correctly in Bases views when using custom field names, including Cyrillic and other localized property names. Thanks to @anareaty for reporting this issue (#607) Full Changelog: 3.23.0...3.23.1"},{"route":"/obsidian/releases/3.23.2/","title":"TaskNotes v3.23.2 Release Notes","description":"This release focusses on performance improvements. These improvements should be especially noticeable in vaults with a large number of tasks.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.23.2.md","namespace":"obsidian","relativePath":"releases/3.23.2.md","raw":"# TaskNotes v3.23.2 Release Notes\n\nThis release focusses on performance improvements. These improvements should be especially noticeable in vaults with a large number of tasks. \n\n## New Features\n\n- Added agenda/list view to Advanced Calendar \n- New `{{contexts}}` template variable for joining multiple context values\n- New `{{projects}}` template variable for joining multiple project values *Thanks to @Mara-Li for these additions*\n\n### Time Format Consistency\n\n- Plugin-wide 12hr/24hr time format preference support\n- Consistent time display across all calendar views and components\n- *Thanks to @anareaty and @Astrusia for this suggestion #431*\n\n### Performance Architecture\n\n- Centralized ViewPerformanceService for all TaskNotes views\n- Global task version cache with change detection\n- Debounced updates with configurable batching\n- View-specific update handlers with selective refresh logic\n- Memory management and automatic cache cleanup\n\n## Bug Fixes\n\n- Fixed cursor positioning issues when creating subtask widgets *Thanks to @jhedlund for this fix!*\n\n## Contributors\n\nSpecial thanks to contributors:\n- @jhedlund for fixing cursor positioning with subtasks\n- @Mara-Li for implementing context/project template variables and bracket fixes\n- @anareaty for reporting time format inconsistencies\n","aliases":["/releases/3.23.2/","/releases/3.23.2/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"time-format-consistency","text":"Time Format Consistency"},{"level":3,"id":"performance-architecture","text":"Performance Architecture"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":2,"id":"contributors","text":"Contributors"}],"html":"

This release focusses on performance improvements. These improvements should be especially noticeable in vaults with a large number of tasks.

\n

New Features#

\n
    \n
  • Added agenda/list view to Advanced Calendar
  • \n
  • New {{contexts}} template variable for joining multiple context values
  • \n
  • New {{projects}} template variable for joining multiple project values Thanks to @Mara-Li for these additions
  • \n
\n

Time Format Consistency#

\n
    \n
  • Plugin-wide 12hr/24hr time format preference support
  • \n
  • Consistent time display across all calendar views and components
  • \n
  • Thanks to @anareaty and @Astrusia for this suggestion #431
  • \n
\n

Performance Architecture#

\n
    \n
  • Centralized ViewPerformanceService for all TaskNotes views
  • \n
  • Global task version cache with change detection
  • \n
  • Debounced updates with configurable batching
  • \n
  • View-specific update handlers with selective refresh logic
  • \n
  • Memory management and automatic cache cleanup
  • \n
\n

Bug Fixes#

\n
    \n
  • Fixed cursor positioning issues when creating subtask widgets Thanks to @jhedlund for this fix!
  • \n
\n

Contributors#

\n

Special thanks to contributors:

\n
    \n
  • @jhedlund for fixing cursor positioning with subtasks
  • \n
  • @Mara-Li for implementing context/project template variables and bracket fixes
  • \n
  • @anareaty for reporting time format inconsistencies
  • \n
\n","text":"This release focusses on performance improvements. These improvements should be especially noticeable in vaults with a large number of tasks. New Features# Added agenda/list view to Advanced Calendar New {{contexts}} template variable for joining multiple context values New {{projects}} template variable for joining multiple project values Thanks to @Mara-Li for these additions Time Format Consistency# Plugin-wide 12hr/24hr time format preference support Consistent time display across all calendar views and components Thanks to @anareaty and @Astrusia for this suggestion #431 Performance Architecture# Centralized ViewPerformanceService for all TaskNotes views Global task version cache with change detection Debounced updates with configurable batching View-specific update handlers with selective refresh logic Memory management and automatic cache cleanup Bug Fixes# Fixed cursor positioning issues when creating subtask widgets Thanks to @jhedlund for this fix! Contributors# Special thanks to contributors: @jhedlund for fixing cursor positioning with subtasks @Mara-Li for implementing context/project template variables and bracket fixes @anareaty for reporting time format inconsistencies"},{"route":"/obsidian/releases/3.23.3/","title":"TaskNotes v3.23.3 Release Notes","description":"This release addresses critical bugs with project and subtask functionality, ensuring proper field mapping support and expanding project filtering capabilities.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.23.3.md","namespace":"obsidian","relativePath":"releases/3.23.3.md","raw":"# TaskNotes v3.23.3 Release Notes\n\nThis release addresses critical bugs with project and subtask functionality, ensuring proper field mapping support and expanding project filtering capabilities.\n\n## New Features\n\n### Project Property Filter Support\n\n- Added property-based filtering for project picker dropdown\n- Configure projects to appear in picker based on frontmatter properties (e.g., `type: project`)\n- Complements existing folder and tag filtering options\n- *Thanks to @aubreyz for requesting this feature enhancement (#660)*\n\n## Bug Fixes\n\n### Project/Subtask Field Mapping\n\n- Fixed project and subtask functionality not working when users customize project field names\n- ProjectSubtasksService and MinimalNativeCache now properly respect user field mapping configuration\n- Resolves issue where hardcoded 'projects' field lookup ignored custom field mappings\n- *Thanks to @JD2026 (#674), @anareaty, (#674) and @Volker-brdb (#672) and for reporting these subtask display issues*\n\n### Test Infrastructure\n\n- Added missing test mocks for `isTaskUsedAsProjectSync` and `formatDateForStorage` functions\n- Ensures test suite stability for project-related functionality\n","aliases":["/releases/3.23.3/","/releases/3.23.3/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"project-property-filter-support","text":"Project Property Filter Support"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"projectsubtask-field-mapping","text":"Project/Subtask Field Mapping"},{"level":3,"id":"test-infrastructure","text":"Test Infrastructure"}],"html":"

This release addresses critical bugs with project and subtask functionality, ensuring proper field mapping support and expanding project filtering capabilities.

\n

New Features#

\n

Project Property Filter Support#

\n
    \n
  • Added property-based filtering for project picker dropdown
  • \n
  • Configure projects to appear in picker based on frontmatter properties (e.g., type: project)
  • \n
  • Complements existing folder and tag filtering options
  • \n
  • Thanks to @aubreyz for requesting this feature enhancement (#660)
  • \n
\n

Bug Fixes#

\n

Project/Subtask Field Mapping#

\n
    \n
  • Fixed project and subtask functionality not working when users customize project field names
  • \n
  • ProjectSubtasksService and MinimalNativeCache now properly respect user field mapping configuration
  • \n
  • Resolves issue where hardcoded 'projects' field lookup ignored custom field mappings
  • \n
  • Thanks to @JD2026 (#674), @anareaty, (#674) and @Volker-brdb (#672) and for reporting these subtask display issues
  • \n
\n

Test Infrastructure#

\n
    \n
  • Added missing test mocks for isTaskUsedAsProjectSync and formatDateForStorage functions
  • \n
  • Ensures test suite stability for project-related functionality
  • \n
\n","text":"This release addresses critical bugs with project and subtask functionality, ensuring proper field mapping support and expanding project filtering capabilities. New Features# Project Property Filter Support# Added property-based filtering for project picker dropdown Configure projects to appear in picker based on frontmatter properties (e.g., type: project) Complements existing folder and tag filtering options Thanks to @aubreyz for requesting this feature enhancement (#660) Bug Fixes# Project/Subtask Field Mapping# Fixed project and subtask functionality not working when users customize project field names ProjectSubtasksService and MinimalNativeCache now properly respect user field mapping configuration Resolves issue where hardcoded 'projects' field lookup ignored custom field mappings Thanks to @JD2026 (#674), @anareaty, (#674) and @Volker-brdb (#672) and for reporting these subtask display issues Test Infrastructure# Added missing test mocks for isTaskUsedAsProjectSync and formatDateForStorage functions Ensures test suite stability for project-related functionality"},{"route":"/obsidian/releases/3.23.4/","title":"TaskNotes 3.23.4","description":"Special thanks to contributors:","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.23.4.md","namespace":"obsidian","relativePath":"releases/3.23.4.md","raw":"# TaskNotes 3.23.4\n\n## Bug Fixes\n\n### Task Scheduling & Natural Language Processing\n\n- Fixed Russian weekday scheduling conflict where single weekdays (e.g., \"воскресенье\") were incorrectly interpreted as recurring tasks instead of single-day scheduling ([#665](https://github.com/callumalpass/tasknotes/issues/665), thanks to @anareaty for the report)\n- Fixed issue where natural language processing failed to save parsed time estimates in task creation modal ([#682](https://github.com/callumalpass/tasknotes/issues/682), thanks to @RumiaKitinari for the detailed report)\n- Fixed scheduled task grouping UTC anchor regression that caused today's tasks to appear under \"Past Scheduled\" instead of \"Today\" ([#384](https://github.com/callumalpass/tasknotes/issues/384), thanks to @jcromwell for the report)\n\n### Settings & Configuration\n\n- Fixed plugin failure when excluded folders setting contains trailing commas - the parsing logic now properly filters empty strings ([#664](https://github.com/callumalpass/tasknotes/issues/664), thanks to @Yoav6 for identifying this issue)\n\n### Calendar & Time Management\n\n- Fixed calendar not refreshing when task duration or time tracking changes ([#382](https://github.com/callumalpass/tasknotes/issues/382), thanks to @mdbraber)\n- Fixed calendar not refreshing after task archive or move operations\n- Fixed timeblock editing using stored date instead of current date for past day modifications ([#647](https://github.com/callumalpass/tasknotes/issues/647), thanks to @RumiaKitinari)\n- Fixed Pomodoro timer not preserving task context when auto-starting sessions ([#641](https://github.com/callumalpass/tasknotes/issues/641), thanks to @RumiaKitinari)\n- Fixed all-day tasks not rendering properly across multiple days in calendar view (thanks to [Danny Talks Tech](https://www.youtube.com/watch?v=SRavkMUYWzo) for reporting this in his video review)\n\n### User Interface\n\n- Fixed mini calendar header overflow issue in sidebar view ([#459](https://github.com/callumalpass/tasknotes/issues/459), with CSS improvements suggested by @jsonshanks, thanks to @girisumit for the report)\n\n## New Features & Enhancements\n\n### Visual Improvements\n\n- Added file-text icon to note cards in agenda view for better visual distinction from headers and consistency with task and calendar event icons ([#662](https://github.com/callumalpass/tasknotes/issues/662), thanks to @ras0q for the suggestion)\n- Improved mini calendar styling, interactions, and legend display\n- Enhanced task dot visualization to reflect accurate matching dates\n\n### Settings Organization\n\n- Moved timeblocking settings to Features tab with improved usage instructions for better discoverability\n\n## Documentation\n\n- Updated documentation to fix auto-archiving settings reference ([#673](https://github.com/callumalpass/tasknotes/issues/673), thanks to @antonio for pointing out the inconsistency)\n\n## Contributors\n\nSpecial thanks to contributors:\n\n- @anareaty for reporting the Russian weekday scheduling conflict\n- @RumiaKitinari for detailed reports on natural language processing, timeblock editing, and Pomodoro timer issues\n- @jcromwell for reporting the scheduled task grouping UTC regression\n- @Yoav6 for identifying the excluded folders trailing comma issue\n- @mdbraber for reporting calendar refresh issues with time tracking changes\n- @girisumit for reporting the mini calendar header overflow issue\n- @jsonshanks for providing CSS improvement suggestions for the mini calendar\n- @ras0q for suggesting the file-text icon addition to agenda view\n- @antonio for pointing out the auto-archiving documentation inconsistency\n- [Danny Talks Tech](https://www.youtube.com/watch?v=SRavkMUYWzo) for reporting the all-day task rendering issue in his video review\n\n---\n\nThis release focuses primarily on bug fixes and stability improvements, particularly around calendar functionality, natural language processing, and user interface polish.","aliases":["/releases/3.23.4/","/releases/3.23.4/"],"toc":[{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"task-scheduling-natural-language-processing","text":"Task Scheduling & Natural Language Processing"},{"level":3,"id":"settings-configuration","text":"Settings & Configuration"},{"level":3,"id":"calendar-time-management","text":"Calendar & Time Management"},{"level":3,"id":"user-interface","text":"User Interface"},{"level":2,"id":"new-features-enhancements","text":"New Features & Enhancements"},{"level":3,"id":"visual-improvements","text":"Visual Improvements"},{"level":3,"id":"settings-organization","text":"Settings Organization"},{"level":2,"id":"documentation","text":"Documentation"},{"level":2,"id":"contributors","text":"Contributors"}],"html":"

Bug Fixes#

\n

Task Scheduling & Natural Language Processing#

\n
    \n
  • Fixed Russian weekday scheduling conflict where single weekdays (e.g., "воскресенье") were incorrectly interpreted as recurring tasks instead of single-day scheduling (#665, thanks to @anareaty for the report)
  • \n
  • Fixed issue where natural language processing failed to save parsed time estimates in task creation modal (#682, thanks to @RumiaKitinari for the detailed report)
  • \n
  • Fixed scheduled task grouping UTC anchor regression that caused today's tasks to appear under "Past Scheduled" instead of "Today" (#384, thanks to @jcromwell for the report)
  • \n
\n

Settings & Configuration#

\n
    \n
  • Fixed plugin failure when excluded folders setting contains trailing commas - the parsing logic now properly filters empty strings (#664, thanks to @Yoav6 for identifying this issue)
  • \n
\n

Calendar & Time Management#

\n
    \n
  • Fixed calendar not refreshing when task duration or time tracking changes (#382, thanks to @mdbraber)
  • \n
  • Fixed calendar not refreshing after task archive or move operations
  • \n
  • Fixed timeblock editing using stored date instead of current date for past day modifications (#647, thanks to @RumiaKitinari)
  • \n
  • Fixed Pomodoro timer not preserving task context when auto-starting sessions (#641, thanks to @RumiaKitinari)
  • \n
  • Fixed all-day tasks not rendering properly across multiple days in calendar view (thanks to Danny Talks Tech for reporting this in his video review)
  • \n
\n

User Interface#

\n
    \n
  • Fixed mini calendar header overflow issue in sidebar view (#459, with CSS improvements suggested by @jsonshanks, thanks to @girisumit for the report)
  • \n
\n

New Features & Enhancements#

\n

Visual Improvements#

\n
    \n
  • Added file-text icon to note cards in agenda view for better visual distinction from headers and consistency with task and calendar event icons (#662, thanks to @ras0q for the suggestion)
  • \n
  • Improved mini calendar styling, interactions, and legend display
  • \n
  • Enhanced task dot visualization to reflect accurate matching dates
  • \n
\n

Settings Organization#

\n
    \n
  • Moved timeblocking settings to Features tab with improved usage instructions for better discoverability
  • \n
\n

Documentation#

\n
    \n
  • Updated documentation to fix auto-archiving settings reference (#673, thanks to @antonio for pointing out the inconsistency)
  • \n
\n

Contributors#

\n

Special thanks to contributors:

\n
    \n
  • @anareaty for reporting the Russian weekday scheduling conflict
  • \n
  • @RumiaKitinari for detailed reports on natural language processing, timeblock editing, and Pomodoro timer issues
  • \n
  • @jcromwell for reporting the scheduled task grouping UTC regression
  • \n
  • @Yoav6 for identifying the excluded folders trailing comma issue
  • \n
  • @mdbraber for reporting calendar refresh issues with time tracking changes
  • \n
  • @girisumit for reporting the mini calendar header overflow issue
  • \n
  • @jsonshanks for providing CSS improvement suggestions for the mini calendar
  • \n
  • @ras0q for suggesting the file-text icon addition to agenda view
  • \n
  • @antonio for pointing out the auto-archiving documentation inconsistency
  • \n
  • Danny Talks Tech for reporting the all-day task rendering issue in his video review
  • \n
\n
\n

This release focuses primarily on bug fixes and stability improvements, particularly around calendar functionality, natural language processing, and user interface polish.

\n","text":"Bug Fixes# Task Scheduling & Natural Language Processing# Fixed Russian weekday scheduling conflict where single weekdays (e.g., \"воскресенье\") were incorrectly interpreted as recurring tasks instead of single-day scheduling (#665, thanks to @anareaty for the report) Fixed issue where natural language processing failed to save parsed time estimates in task creation modal (#682, thanks to @RumiaKitinari for the detailed report) Fixed scheduled task grouping UTC anchor regression that caused today's tasks to appear under \"Past Scheduled\" instead of \"Today\" (#384, thanks to @jcromwell for the report) Settings & Configuration# Fixed plugin failure when excluded folders setting contains trailing commas - the parsing logic now properly filters empty strings (#664, thanks to @Yoav6 for identifying this issue) Calendar & Time Management# Fixed calendar not refreshing when task duration or time tracking changes (#382, thanks to @mdbraber) Fixed calendar not refreshing after task archive or move operations Fixed timeblock editing using stored date instead of current date for past day modifications (#647, thanks to @RumiaKitinari) Fixed Pomodoro timer not preserving task context when auto-starting sessions (#641, thanks to @RumiaKitinari) Fixed all-day tasks not rendering properly across multiple days in calendar view (thanks to Danny Talks Tech for reporting this in his video review) User Interface# Fixed mini calendar header overflow issue in sidebar view (#459, with CSS improvements suggested by @jsonshanks, thanks to @girisumit for the report) New Features & Enhancements# Visual Improvements# Added file-text icon to note cards in agenda view for better visual distinction from headers and consistency with task and calendar event icons (#662, thanks to @ras0q for the suggestion) Improved mini calendar styling, interactions, and legend display Enhanced task dot visualization to reflect accurate matching dates Settings Organization# Moved timeblocking settings to Features tab with improved usage instructions for better discoverability Documentation# Updated documentation to fix auto-archiving settings reference (#673, thanks to @antonio for pointing out the inconsistency) Contributors# Special thanks to contributors: @anareaty for reporting the Russian weekday scheduling conflict @RumiaKitinari for detailed reports on natural language processing, timeblock editing, and Pomodoro timer issues @jcromwell for reporting the scheduled task grouping UTC regression @Yoav6 for identifying the excluded folders trailing comma issue @mdbraber for reporting calendar refresh issues with time tracking changes @girisumit for reporting the mini calendar header overflow issue @jsonshanks for providing CSS improvement suggestions for the mini calendar @ras0q for suggesting the file-text icon addition to agenda view @antonio for pointing out the auto-archiving documentation inconsistency Danny Talks Tech for reporting the all-day task rendering issue in his video review This release focuses primarily on bug fixes and stability improvements, particularly around calendar functionality, natural language processing, and user interface polish."},{"route":"/obsidian/releases/3.24.0/","title":"TaskNotes 3.24.0","description":"Special thanks to all this release's contributors:","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.24.0.md","namespace":"obsidian","relativePath":"releases/3.24.0.md","raw":"# TaskNotes 3.24.0\n\n## New Features\n\n### Agenda View Overdue Section\n\n- Added separate \"Overdue\" section in Agenda view instead of mixing overdue tasks with today's tasks ([#557](https://github.com/callumalpass/tasknotes/issues/557), thanks to @backyardbiomech for the detailed report)\n- Collapsible section with task completion statistics and proper internationalization support\n- Includes overdue recurring tasks based on their scheduled dates\n\n### Task Dependencies and Blocking Relationships\n\n- Implemented blocking/blocked task dependencies with persistent relationships ([#701](https://github.com/callumalpass/tasknotes/issues/701), thanks to @prayidae for the detailed feature request)\n- Tasks can be marked as blocking other tasks or blocked by other tasks\n- Dependency relationships persist in frontmatter as structural links\n- Dynamic blocked state computed based on blocking task completion status\n\n### Task Card Widget in Notes\n\n- Added configurable task card widget displaying at the top of task notes ([#576](https://github.com/callumalpass/tasknotes/issues/576), thanks to @jhedlund for the request)\n- Provides immediate access to task actions and context menus without requiring command palette\n- Uses CodeMirror widget system for integration\n- Appears above project subtasks widget when both enabled\n- Can be disabled via settings\n\n### Hierarchical Subgrouping\n\n- Implemented hierarchical subgrouping functionality for TaskListView and AgendaView (thanks to @renatomen for this major feature contribution)\n- Allows two-level task organization (e.g., Group by Status, Subgroup by Priority)\n- Cross-view support with consistent behavior\n- State persistence for expand/collapse preferences\n- Custom user fields supported as subgroup options\n\n### Internationalization Support\n\n- Added i18n framework with multi-language support\n- Support for German, Spanish, French, Russian, Chinese, and Japanese\n- Translation coverage for command palette entries and UI strings\n- Localized agenda and filter interface elements\n\n### Template Variables\n\n- Added `{{hashtags}}` template variable for space-separated hashtag rendering ([#612](https://github.com/callumalpass/tasknotes/issues/612), thanks to @strazto for the suggestion)\n- Added `{{currentNoteTitle}}` template variable for note-specific folder organization ([#637](https://github.com/callumalpass/tasknotes/issues/637), thanks to @Mara-Li for the request)\n- Added template variable support for archive folder paths ([#677](https://github.com/callumalpass/tasknotes/issues/677), thanks to @dsebastien for the request)\n- Fixed `{{project}}` variables to properly extract basenames from wikilinks ([#490](https://github.com/callumalpass/tasknotes/issues/490), thanks to @nsstrickland for the detailed bug report)\n\n### Project and Subtask Management\n\n- Enhanced task modals with project and subtask management capabilities\n- Added \"Add to project\" and \"Add subtasks\" sections in task creation/edit modals\n- Context menu options for assigning tasks to projects and adding subtasks\n- Collapsible lists with visual separators between form sections\n\n### View and Grouping Enhancements\n\n- Added \"Completed Date\" as grouping option for analyzing productivity ([#430](https://github.com/callumalpass/tasknotes/issues/430), thanks to @anareaty for the suggestion)\n- Added \"Status\" as sorting option in Kanban and Task List views ([#633](https://github.com/callumalpass/tasknotes/issues/633), thanks to @mdbraber for the report)\n- Implemented per-grouping column persistence for Kanban views\n- Smart default ordering respecting StatusManager and PriorityManager configurations\n\n## Bug Fixes\n\n### Calendar and Advanced Calendar\n\n- Fixed calendar not refreshing when task duration or time tracking changes\n- Fixed calendar not refreshing after task archive or move operations\n- Fixed agenda duplication for all-day ICS events ([#695](https://github.com/callumalpass/tasknotes/issues/695), thanks to @realJohnDoe for the report)\n- Added configurable `eventMinHeight` for Advanced Calendar to make short duration tasks readable ([#718](https://github.com/callumalpass/tasknotes/issues/718), thanks to @Ruboks-Cube for the detailed report)\n- Fixed multi-day task creation in month/year view to properly calculate time estimates ([#564](https://github.com/callumalpass/tasknotes/issues/564), thanks to @same774 for the report)\n\n### Kanban View\n\n- Fixed kanban view losing columns after upgrades ([#689](https://github.com/callumalpass/tasknotes/issues/689), thanks to @mikesale for the report)\n- Fixed clearing filters defaulting to \"none\" instead of \"status\" grouping ([#679](https://github.com/callumalpass/tasknotes/issues/679), thanks to @camara-tech-pro for the question)\n- Fixed column order changes when switching between views ([#710](https://github.com/callumalpass/tasknotes/issues/710), thanks to @phortx for the report)\n- Fixed kanban drag-and-drop for custom field grouping ([#494](https://github.com/callumalpass/tasknotes/issues/494), thanks to @anareaty for the report)\n- Enhanced save view modal functionality with improved styling and accessibility\n\n### Task Management\n\n- Fixed HTTP API task creation to return sanitized title matching stored content ([#635](https://github.com/callumalpass/tasknotes/issues/635), thanks to @nightroman for the detailed report)\n- Fixed `#task` tag being incorrectly added when using property-based task identification ([#570](https://github.com/callumalpass/tasknotes/issues/570), thanks to @RobbK17 for the report)\n- Fixed recurring task completion styling in Bases views ([#669](https://github.com/callumalpass/tasknotes/issues/669), thanks to @jordandrako for the report)\n\n### Hierarchical Tag Support\n\n- Added hierarchical tag support with exclusion patterns for Obsidian nested tags ([#584](https://github.com/callumalpass/tasknotes/issues/584), thanks to @renatomen for the detailed feature request)\n- Hierarchical matching allows searching for parent tags to match child tags (e.g., `t/ef` matches `t/ef/project`, `t/ef/task`)\n- Exclusion patterns support using `-` prefix to exclude specific tags and their children\n- Maintains backward compatibility with existing substring matching\n\n### Natural Language Processing and Tags\n\n- Fixed nested tags losing slashes in agenda view rendering ([#712](https://github.com/callumalpass/tasknotes/issues/712), thanks to @antonio for the report and fix)\n- Added support for hyphens in NLP tag parsing ([#568](https://github.com/callumalpass/tasknotes/issues/568), thanks to @jordandrako for the report)\n\n### Settings and Configuration\n\n- Fixed property value truncation in project autosuggest settings by adding input debouncing ([#705](https://github.com/callumalpass/tasknotes/issues/705), thanks to @aubreyz for the report)\n- Improved webhook transform error handling with detailed logging ([#719](https://github.com/callumalpass/tasknotes/issues/719), thanks to @stephen-netu for the detailed report)\n- Added save button disable logic to prevent duplicate task creation (thanks to @hamlim for the report and implementation)\n\n### Code Quality and Development\n\n- Configured Prettier formatter for consistent code formatting ([#717](https://github.com/callumalpass/tasknotes/issues/717), thanks to @ras0q for the request)\n- Applied ESLint fixes reducing problems from 209 to 97\n- Added format and format:check scripts for development workflow\n- Fixed browser extension repository URL in README (thanks to @elijahmanor for the correction)\n\n## Enhancements\n\n### Performance and Reliability\n\n- Added debouncing to project autosuggest property inputs\n- Improved error handling for webhook transform failures\n\n### User Interface\n\n- Added time display based on `timeEstimate` property in task statistics (thanks to Sergen Aras for the implementation)\n- Enhanced language selection display with native scripts\n\n### Settings Organization\n\n- Reorganized settings with improved categorization\n- Added collapsible functionality to various UI sections\n- Enhanced accessibility with proper button labeling\n\n## Documentation\n\n- Added documentation for task dependencies feature\n- Updated comprehensive subgrouping feature documentation\n- Enhanced template variable documentation\n- Updated various view documentation for new features\n\n## Contributors\n\nSpecial thanks to all this release's contributors:\n\n### Feature Contributors\n\n- **@renatomen** for implementing the major hierarchical subgrouping feature and hierarchical tag support feature request (#584)\n- **@antonio** for implementing nested tag slash preservation and providing the fix\n- **@elijahmanor** for fixing the browser extension repository URL\n- **@sergenaras** for implementing time display based on timeEstimate property in task statistics\n- **@hamlim** for implementing save button disable logic to prevent duplicate task creation\n\n### Issue Reporters and Feature Requesters\n\n- **@backyardbiomech** for the detailed overdue recurring tasks report (#557)\n- **@prayidae** for the detailed task dependencies feature request (#701)\n- **@jhedlund** for requesting task context menu in notes (#576)\n- **@anareaty** for requesting completed date grouping (#430) and reporting kanban custom field drag issues (#494)\n- **@mdbraber** for reporting missing status sorting option (#633)\n- **@strazto** for requesting hashtags template variable (#612)\n- **@Mara-Li** for requesting currentNoteTitle template variable (#637)\n- **@dsebastien** for requesting archive folder template support (#677)\n- **@nsstrickland** for the detailed project variable bug report (#490)\n- **@realJohnDoe** for reporting ICS all-day event duplication (#695)\n- **@Ruboks-Cube** for reporting short duration task rendering issues (#718)\n- **@same774** for reporting multi-day task creation issues (#564)\n- **@mikesale** for reporting kanban column loss (#689)\n- **@camara-tech-pro** for the kanban grouping question (#679)\n- **@phortx** for reporting column order changes (#710)\n- **@nightroman** for the detailed HTTP API title sanitization report (#635)\n- **@RobbK17** for reporting property identification tag issue (#570)\n- **@jordandrako** for reporting recurring task styling in Bases (#669) and NLP tag parsing with hyphens (#568)\n- **@aubreyz** for reporting project autosuggest truncation issue (#705)\n- **@ras0q** for requesting code formatting improvements (#717)\n- **@stephen-netu** for the detailed webhook transform script loading report (#719)\n","aliases":["/releases/3.24.0/","/releases/3.24.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"agenda-view-overdue-section","text":"Agenda View Overdue Section"},{"level":3,"id":"task-dependencies-and-blocking-relationships","text":"Task Dependencies and Blocking Relationships"},{"level":3,"id":"task-card-widget-in-notes","text":"Task Card Widget in Notes"},{"level":3,"id":"hierarchical-subgrouping","text":"Hierarchical Subgrouping"},{"level":3,"id":"internationalization-support","text":"Internationalization Support"},{"level":3,"id":"template-variables","text":"Template Variables"},{"level":3,"id":"project-and-subtask-management","text":"Project and Subtask Management"},{"level":3,"id":"view-and-grouping-enhancements","text":"View and Grouping Enhancements"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"calendar-and-advanced-calendar","text":"Calendar and Advanced Calendar"},{"level":3,"id":"kanban-view","text":"Kanban View"},{"level":3,"id":"task-management","text":"Task Management"},{"level":3,"id":"hierarchical-tag-support","text":"Hierarchical Tag Support"},{"level":3,"id":"natural-language-processing-and-tags","text":"Natural Language Processing and Tags"},{"level":3,"id":"settings-and-configuration","text":"Settings and Configuration"},{"level":3,"id":"code-quality-and-development","text":"Code Quality and Development"},{"level":2,"id":"enhancements","text":"Enhancements"},{"level":3,"id":"performance-and-reliability","text":"Performance and Reliability"},{"level":3,"id":"user-interface","text":"User Interface"},{"level":3,"id":"settings-organization","text":"Settings Organization"},{"level":2,"id":"documentation","text":"Documentation"},{"level":2,"id":"contributors","text":"Contributors"},{"level":3,"id":"feature-contributors","text":"Feature Contributors"},{"level":3,"id":"issue-reporters-and-feature-requesters","text":"Issue Reporters and Feature Requesters"}],"html":"

New Features#

\n

Agenda View Overdue Section#

\n
    \n
  • Added separate "Overdue" section in Agenda view instead of mixing overdue tasks with today's tasks (#557, thanks to @backyardbiomech for the detailed report)
  • \n
  • Collapsible section with task completion statistics and proper internationalization support
  • \n
  • Includes overdue recurring tasks based on their scheduled dates
  • \n
\n

Task Dependencies and Blocking Relationships#

\n
    \n
  • Implemented blocking/blocked task dependencies with persistent relationships (#701, thanks to @prayidae for the detailed feature request)
  • \n
  • Tasks can be marked as blocking other tasks or blocked by other tasks
  • \n
  • Dependency relationships persist in frontmatter as structural links
  • \n
  • Dynamic blocked state computed based on blocking task completion status
  • \n
\n

Task Card Widget in Notes#

\n
    \n
  • Added configurable task card widget displaying at the top of task notes (#576, thanks to @jhedlund for the request)
  • \n
  • Provides immediate access to task actions and context menus without requiring command palette
  • \n
  • Uses CodeMirror widget system for integration
  • \n
  • Appears above project subtasks widget when both enabled
  • \n
  • Can be disabled via settings
  • \n
\n

Hierarchical Subgrouping#

\n
    \n
  • Implemented hierarchical subgrouping functionality for TaskListView and AgendaView (thanks to @renatomen for this major feature contribution)
  • \n
  • Allows two-level task organization (e.g., Group by Status, Subgroup by Priority)
  • \n
  • Cross-view support with consistent behavior
  • \n
  • State persistence for expand/collapse preferences
  • \n
  • Custom user fields supported as subgroup options
  • \n
\n

Internationalization Support#

\n
    \n
  • Added i18n framework with multi-language support
  • \n
  • Support for German, Spanish, French, Russian, Chinese, and Japanese
  • \n
  • Translation coverage for command palette entries and UI strings
  • \n
  • Localized agenda and filter interface elements
  • \n
\n

Template Variables#

\n
    \n
  • Added {{hashtags}} template variable for space-separated hashtag rendering (#612, thanks to @strazto for the suggestion)
  • \n
  • Added {{currentNoteTitle}} template variable for note-specific folder organization (#637, thanks to @Mara-Li for the request)
  • \n
  • Added template variable support for archive folder paths (#677, thanks to @dsebastien for the request)
  • \n
  • Fixed {{project}} variables to properly extract basenames from wikilinks (#490, thanks to @nsstrickland for the detailed bug report)
  • \n
\n

Project and Subtask Management#

\n
    \n
  • Enhanced task modals with project and subtask management capabilities
  • \n
  • Added "Add to project" and "Add subtasks" sections in task creation/edit modals
  • \n
  • Context menu options for assigning tasks to projects and adding subtasks
  • \n
  • Collapsible lists with visual separators between form sections
  • \n
\n

View and Grouping Enhancements#

\n
    \n
  • Added "Completed Date" as grouping option for analyzing productivity (#430, thanks to @anareaty for the suggestion)
  • \n
  • Added "Status" as sorting option in Kanban and Task List views (#633, thanks to @mdbraber for the report)
  • \n
  • Implemented per-grouping column persistence for Kanban views
  • \n
  • Smart default ordering respecting StatusManager and PriorityManager configurations
  • \n
\n

Bug Fixes#

\n

Calendar and Advanced Calendar#

\n
    \n
  • Fixed calendar not refreshing when task duration or time tracking changes
  • \n
  • Fixed calendar not refreshing after task archive or move operations
  • \n
  • Fixed agenda duplication for all-day ICS events (#695, thanks to @realJohnDoe for the report)
  • \n
  • Added configurable eventMinHeight for Advanced Calendar to make short duration tasks readable (#718, thanks to @Ruboks-Cube for the detailed report)
  • \n
  • Fixed multi-day task creation in month/year view to properly calculate time estimates (#564, thanks to @same774 for the report)
  • \n
\n

Kanban View#

\n
    \n
  • Fixed kanban view losing columns after upgrades (#689, thanks to @mikesale for the report)
  • \n
  • Fixed clearing filters defaulting to "none" instead of "status" grouping (#679, thanks to @camara-tech-pro for the question)
  • \n
  • Fixed column order changes when switching between views (#710, thanks to @phortx for the report)
  • \n
  • Fixed kanban drag-and-drop for custom field grouping (#494, thanks to @anareaty for the report)
  • \n
  • Enhanced save view modal functionality with improved styling and accessibility
  • \n
\n

Task Management#

\n
    \n
  • Fixed HTTP API task creation to return sanitized title matching stored content (#635, thanks to @nightroman for the detailed report)
  • \n
  • Fixed #task tag being incorrectly added when using property-based task identification (#570, thanks to @RobbK17 for the report)
  • \n
  • Fixed recurring task completion styling in Bases views (#669, thanks to @jordandrako for the report)
  • \n
\n

Hierarchical Tag Support#

\n
    \n
  • Added hierarchical tag support with exclusion patterns for Obsidian nested tags (#584, thanks to @renatomen for the detailed feature request)
  • \n
  • Hierarchical matching allows searching for parent tags to match child tags (e.g., t/ef matches t/ef/project, t/ef/task)
  • \n
  • Exclusion patterns support using - prefix to exclude specific tags and their children
  • \n
  • Maintains backward compatibility with existing substring matching
  • \n
\n

Natural Language Processing and Tags#

\n
    \n
  • Fixed nested tags losing slashes in agenda view rendering (#712, thanks to @antonio for the report and fix)
  • \n
  • Added support for hyphens in NLP tag parsing (#568, thanks to @jordandrako for the report)
  • \n
\n

Settings and Configuration#

\n
    \n
  • Fixed property value truncation in project autosuggest settings by adding input debouncing (#705, thanks to @aubreyz for the report)
  • \n
  • Improved webhook transform error handling with detailed logging (#719, thanks to @stephen-netu for the detailed report)
  • \n
  • Added save button disable logic to prevent duplicate task creation (thanks to @hamlim for the report and implementation)
  • \n
\n

Code Quality and Development#

\n
    \n
  • Configured Prettier formatter for consistent code formatting (#717, thanks to @ras0q for the request)
  • \n
  • Applied ESLint fixes reducing problems from 209 to 97
  • \n
  • Added format and format:check scripts for development workflow
  • \n
  • Fixed browser extension repository URL in README (thanks to @elijahmanor for the correction)
  • \n
\n

Enhancements#

\n

Performance and Reliability#

\n
    \n
  • Added debouncing to project autosuggest property inputs
  • \n
  • Improved error handling for webhook transform failures
  • \n
\n

User Interface#

\n
    \n
  • Added time display based on timeEstimate property in task statistics (thanks to Sergen Aras for the implementation)
  • \n
  • Enhanced language selection display with native scripts
  • \n
\n

Settings Organization#

\n
    \n
  • Reorganized settings with improved categorization
  • \n
  • Added collapsible functionality to various UI sections
  • \n
  • Enhanced accessibility with proper button labeling
  • \n
\n

Documentation#

\n
    \n
  • Added documentation for task dependencies feature
  • \n
  • Updated comprehensive subgrouping feature documentation
  • \n
  • Enhanced template variable documentation
  • \n
  • Updated various view documentation for new features
  • \n
\n

Contributors#

\n

Special thanks to all this release's contributors:

\n

Feature Contributors#

\n
    \n
  • @renatomen for implementing the major hierarchical subgrouping feature and hierarchical tag support feature request (#584)
  • \n
  • @antonio for implementing nested tag slash preservation and providing the fix
  • \n
  • @elijahmanor for fixing the browser extension repository URL
  • \n
  • @sergenaras for implementing time display based on timeEstimate property in task statistics
  • \n
  • @hamlim for implementing save button disable logic to prevent duplicate task creation
  • \n
\n

Issue Reporters and Feature Requesters#

\n
    \n
  • @backyardbiomech for the detailed overdue recurring tasks report (#557)
  • \n
  • @prayidae for the detailed task dependencies feature request (#701)
  • \n
  • @jhedlund for requesting task context menu in notes (#576)
  • \n
  • @anareaty for requesting completed date grouping (#430) and reporting kanban custom field drag issues (#494)
  • \n
  • @mdbraber for reporting missing status sorting option (#633)
  • \n
  • @strazto for requesting hashtags template variable (#612)
  • \n
  • @Mara-Li for requesting currentNoteTitle template variable (#637)
  • \n
  • @dsebastien for requesting archive folder template support (#677)
  • \n
  • @nsstrickland for the detailed project variable bug report (#490)
  • \n
  • @realJohnDoe for reporting ICS all-day event duplication (#695)
  • \n
  • @Ruboks-Cube for reporting short duration task rendering issues (#718)
  • \n
  • @same774 for reporting multi-day task creation issues (#564)
  • \n
  • @mikesale for reporting kanban column loss (#689)
  • \n
  • @camara-tech-pro for the kanban grouping question (#679)
  • \n
  • @phortx for reporting column order changes (#710)
  • \n
  • @nightroman for the detailed HTTP API title sanitization report (#635)
  • \n
  • @RobbK17 for reporting property identification tag issue (#570)
  • \n
  • @jordandrako for reporting recurring task styling in Bases (#669) and NLP tag parsing with hyphens (#568)
  • \n
  • @aubreyz for reporting project autosuggest truncation issue (#705)
  • \n
  • @ras0q for requesting code formatting improvements (#717)
  • \n
  • @stephen-netu for the detailed webhook transform script loading report (#719)
  • \n
\n","text":"New Features# Agenda View Overdue Section# Added separate \"Overdue\" section in Agenda view instead of mixing overdue tasks with today's tasks (#557, thanks to @backyardbiomech for the detailed report) Collapsible section with task completion statistics and proper internationalization support Includes overdue recurring tasks based on their scheduled dates Task Dependencies and Blocking Relationships# Implemented blocking/blocked task dependencies with persistent relationships (#701, thanks to @prayidae for the detailed feature request) Tasks can be marked as blocking other tasks or blocked by other tasks Dependency relationships persist in frontmatter as structural links Dynamic blocked state computed based on blocking task completion status Task Card Widget in Notes# Added configurable task card widget displaying at the top of task notes (#576, thanks to @jhedlund for the request) Provides immediate access to task actions and context menus without requiring command palette Uses CodeMirror widget system for integration Appears above project subtasks widget when both enabled Can be disabled via settings Hierarchical Subgrouping# Implemented hierarchical subgrouping functionality for TaskListView and AgendaView (thanks to @renatomen for this major feature contribution) Allows two-level task organization (e.g., Group by Status, Subgroup by Priority) Cross-view support with consistent behavior State persistence for expand/collapse preferences Custom user fields supported as subgroup options Internationalization Support# Added i18n framework with multi-language support Support for German, Spanish, French, Russian, Chinese, and Japanese Translation coverage for command palette entries and UI strings Localized agenda and filter interface elements Template Variables# Added {{hashtags}} template variable for space-separated hashtag rendering (#612, thanks to @strazto for the suggestion) Added {{currentNoteTitle}} template variable for note-specific folder organization (#637, thanks to @Mara-Li for the request) Added template variable support for archive folder paths (#677, thanks to @dsebastien for the request) Fixed {{project}} variables to properly extract basenames from wikilinks (#490, thanks to @nsstrickland for the detailed bug report) Project and Subtask Management# Enhanced task modals with project and subtask management capabilities Added \"Add to project\" and \"Add subtasks\" sections in task creation/edit modals Context menu options for assigning tasks to projects and adding subtasks Collapsible lists with visual separators between form sections View and Grouping Enhancements# Added \"Completed Date\" as grouping option for analyzing productivity (#430, thanks to @anareaty for the suggestion) Added \"Status\" as sorting option in Kanban and Task List views (#633, thanks to @mdbraber for the report) Implemented per-grouping column persistence for Kanban views Smart default ordering respecting StatusManager and PriorityManager configurations Bug Fixes# Calendar and Advanced Calendar# Fixed calendar not refreshing when task duration or time tracking changes Fixed calendar not refreshing after task archive or move operations Fixed agenda duplication for all-day ICS events (#695, thanks to @realJohnDoe for the report) Added configurable eventMinHeight for Advanced Calendar to make short duration tasks readable (#718, thanks to @Ruboks-Cube for the detailed report) Fixed multi-day task creation in month/year view to properly calculate time estimates (#564, thanks to @same774 for the report) Kanban View# Fixed kanban view losing columns after upgrades (#689, thanks to @mikesale for the report) Fixed clearing filters defaulting to \"none\" instead of \"status\" grouping (#679, thanks to @camara-tech-pro for the question) Fixed column order changes when switching between views (#710, thanks to @phortx for the report) Fixed kanban drag-and-drop for custom field grouping (#494, thanks to @anareaty for the report) Enhanced save view modal functionality with improved styling and accessibility Task Management# Fixed HTTP API task creation to return sanitized title matching stored content (#635, thanks to @nightroman for the detailed report) Fixed #task tag being incorrectly added when using property-based task identification (#570, thanks to @RobbK17 for the report) Fixed recurring task completion styling in Bases views (#669, thanks to @jordandrako for the report) Hierarchical Tag Support# Added hierarchical tag support with exclusion patterns for Obsidian nested tags (#584, thanks to @renatomen for the detailed feature request) Hierarchical matching allows searching for parent tags to match child tags (e.g., t/ef matches t/ef/project, t/ef/task) Exclusion patterns support using - prefix to exclude specific tags and their children Maintains backward compatibility with existing substring matching Natural Language Processing and Tags# Fixed nested tags losing slashes in agenda view rendering (#712, thanks to @antonio for the report and fix) Added support for hyphens in NLP tag parsing (#568, thanks to @jordandrako for the report) Settings and Configuration# Fixed property value truncation in project autosuggest settings by adding input debouncing (#705, thanks to @aubreyz for the report) Improved webhook transform error handling with detailed logging (#719, thanks to @stephen-netu for the detailed report) Added save button disable logic to prevent duplicate task creation (thanks to @hamlim for the report and implementation) Code Quality and Development# Configured Prettier formatter for consistent code formatting (#717, thanks to @ras0q for the request) Applied ESLint fixes reducing problems from 209 to 97 Added format and format:check scripts for development workflow Fixed browser extension repository URL in README (thanks to @elijahmanor for the correction) Enhancements# Performance and Reliability# Added debouncing to project autosuggest property inputs Improved error handling for webhook transform failures User Interface# Added time display based on timeEstimate property in task statistics (thanks to Sergen Aras for the implementation) Enhanced language selection display with native scripts Settings Organization# Reorganized settings with improved categorization Added collapsible functionality to various UI sections Enhanced accessibility with proper button labeling Documentation# Added documentation for task dependencies feature Updated comprehensive subgrouping feature documentation Enhanced template variable documentation Updated various view documentation for new features Contributors# Special thanks to all this release's contributors: Feature Contributors# @renatomen for implementing the major hierarchical subgrouping feature and hierarchical tag support feature request (#584) @antonio for implementing nested tag slash preservation and providing the fix @elijahmanor for fixing the browser extension repository URL @sergenaras for implementing time display based on timeEstimate property in task statistics @hamlim for implementing save button disable logic to prevent duplicate task creation Issue Reporters and Feature Requesters# @backyardbiomech for the detailed overdue recurring tasks report (#557) @prayidae for the detailed task dependencies feature request (#701) @jhedlund for requesting task context menu in notes (#576) @anareaty for requesting completed date grouping (#430) and reporting kanban custom field drag issues (#494) @mdbraber for reporting missing status sorting option (#633) @strazto for requesting hashtags template variable (#612) @Mara-Li for requesting currentNoteTitle template variable (#637) @dsebastien for requesting archive folder template support (#677) @nsstrickland for the detailed project variable bug report (#490) @realJohnDoe for reporting ICS all-day event duplication (#695) @Ruboks-Cube for reporting short duration task rendering issues (#718) @same774 for reporting multi-day task creation issues (#564) @mikesale for reporting kanban column loss (#689) @camara-tech-pro for the kanban grouping question (#679) @phortx for reporting column order changes (#710) @nightroman for the detailed HTTP API title sanitization report (#635) @RobbK17 for reporting property identification tag issue (#570) @jordandrako for reporting recurring task styling in Bases (#669) and NLP tag parsing with hyphens (#568) @aubreyz for reporting project autosuggest truncation issue (#705) @ras0q for requesting code formatting improvements (#717) @stephen-netu for the detailed webhook transform script loading report (#719)"},{"route":"/obsidian/releases/3.24.1/","title":"TaskNotes 3.24.1","description":"This patch release fixes the task card widget introduced in 3.24.0 to only display on actual task notes.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.24.1.md","namespace":"obsidian","relativePath":"releases/3.24.1.md","raw":"# TaskNotes 3.24.1\n\n## Bug Fixes\n\n### Task Card Widget\n\n- Fixed task card widget appearing on all notes instead of only task notes\n- Widget now properly respects task identification settings (tag or property-based)\n\nThis patch release fixes the task card widget introduced in 3.24.0 to only display on actual task notes.","aliases":["/releases/3.24.1/","/releases/3.24.1/"],"toc":[{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"task-card-widget","text":"Task Card Widget"}],"html":"

Bug Fixes#

\n

Task Card Widget#

\n
    \n
  • Fixed task card widget appearing on all notes instead of only task notes
  • \n
  • Widget now properly respects task identification settings (tag or property-based)
  • \n
\n

This patch release fixes the task card widget introduced in 3.24.0 to only display on actual task notes.

\n","text":"Bug Fixes# Task Card Widget# Fixed task card widget appearing on all notes instead of only task notes Widget now properly respects task identification settings (tag or property-based) This patch release fixes the task card widget introduced in 3.24.0 to only display on actual task notes."},{"route":"/obsidian/releases/3.24.2/","title":"TaskNotes 3.24.2","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.24.2.md","namespace":"obsidian","relativePath":"releases/3.24.2.md","raw":"# TaskNotes 3.24.2 \n\n## Fixed\n\n- (#766) Fixed tag parsing incorrectly identifying notes with tags containing \"task\" (like \"pkm-task\") as task notes\n - Added exact hierarchical tag matching for task identification to prevent false positives\n - Preserved substring matching behavior for filter bar searches where it's desired\n - Only exact matches or hierarchical children (like \"task/work\") now identify notes as tasks\n - Thanks to @anareaty and @fastrick for reporting this issue\n- (#767) Fixed subgroups not rendering under the \"Overdue\" agenda group\n - Thanks to @renatomen for reporting this issue\n- (#768) Fixed calendar view appearing empty in week and day views due to invalid time configuration values\n - Added time validation in settings UI with proper error messages and debouncing\n - Added runtime sanitization in calendar with safe defaults (00:00:00, 24:00:00, 08:00:00)\n - Prevents \"Cannot read properties of null (reading 'years')\" error from FullCalendar\n - Thanks to @kmaustral for reporting\n- (#769) Fixed NLP processor incorrectly assigning hardcoded \"waiting\" status when \"blocked\" appears in task titles\n - NLP now only uses user-defined status configurations when available, ignoring hardcoded fallback patterns\n - Prevents unexpected status assignments for users with custom status workflows\n - Fallback patterns still work when no custom status configurations are defined\n - Thanks to @renatomen for reporting this issue\n","aliases":["/releases/3.24.2/","/releases/3.24.2/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Fixed#

\n
    \n
  • (#766) Fixed tag parsing incorrectly identifying notes with tags containing "task" (like "pkm-task") as task notes
      \n
    • Added exact hierarchical tag matching for task identification to prevent false positives
    • \n
    • Preserved substring matching behavior for filter bar searches where it's desired
    • \n
    • Only exact matches or hierarchical children (like "task/work") now identify notes as tasks
    • \n
    • Thanks to @anareaty and @fastrick for reporting this issue
    • \n
    \n
  • \n
  • (#767) Fixed subgroups not rendering under the "Overdue" agenda group
      \n
    • Thanks to @renatomen for reporting this issue
    • \n
    \n
  • \n
  • (#768) Fixed calendar view appearing empty in week and day views due to invalid time configuration values
      \n
    • Added time validation in settings UI with proper error messages and debouncing
    • \n
    • Added runtime sanitization in calendar with safe defaults (00:00:00, 24:00:00, 08:00:00)
    • \n
    • Prevents "Cannot read properties of null (reading 'years')" error from FullCalendar
    • \n
    • Thanks to @kmaustral for reporting
    • \n
    \n
  • \n
  • (#769) Fixed NLP processor incorrectly assigning hardcoded "waiting" status when "blocked" appears in task titles
      \n
    • NLP now only uses user-defined status configurations when available, ignoring hardcoded fallback patterns
    • \n
    • Prevents unexpected status assignments for users with custom status workflows
    • \n
    • Fallback patterns still work when no custom status configurations are defined
    • \n
    • Thanks to @renatomen for reporting this issue
    • \n
    \n
  • \n
\n","text":"Fixed# (#766) Fixed tag parsing incorrectly identifying notes with tags containing \"task\" (like \"pkm-task\") as task notes Added exact hierarchical tag matching for task identification to prevent false positives Preserved substring matching behavior for filter bar searches where it's desired Only exact matches or hierarchical children (like \"task/work\") now identify notes as tasks Thanks to @anareaty and @fastrick for reporting this issue (#767) Fixed subgroups not rendering under the \"Overdue\" agenda group Thanks to @renatomen for reporting this issue (#768) Fixed calendar view appearing empty in week and day views due to invalid time configuration values Added time validation in settings UI with proper error messages and debouncing Added runtime sanitization in calendar with safe defaults (00:00:00, 24:00:00, 08:00:00) Prevents \"Cannot read properties of null (reading 'years')\" error from FullCalendar Thanks to @kmaustral for reporting (#769) Fixed NLP processor incorrectly assigning hardcoded \"waiting\" status when \"blocked\" appears in task titles NLP now only uses user-defined status configurations when available, ignoring hardcoded fallback patterns Prevents unexpected status assignments for users with custom status workflows Fallback patterns still work when no custom status configurations are defined Thanks to @renatomen for reporting this issue"},{"route":"/obsidian/releases/3.24.3/","title":"TaskNotes 3.24.3","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.24.3.md","namespace":"obsidian","relativePath":"releases/3.24.3.md","raw":"# TaskNotes 3.24.3\n\n- (#776) Fixed screens failing to load with \"toLowerCase is not a function\" error\n - Issue occurred when frontmatter tags array contained non-string values (numbers, booleans, etc.)\n - Added type validation to filter out non-string values before processing tags\n - Valid string tags continue to work normally while invalid types are safely skipped\n - Thanks to @kmf and @Andre-Ioda for help debugging this issue\n","aliases":["/releases/3.24.3/","/releases/3.24.3/"],"toc":[],"html":"
    \n
  • (#776) Fixed screens failing to load with "toLowerCase is not a function" error
      \n
    • Issue occurred when frontmatter tags array contained non-string values (numbers, booleans, etc.)
    • \n
    • Added type validation to filter out non-string values before processing tags
    • \n
    • Valid string tags continue to work normally while invalid types are safely skipped
    • \n
    • Thanks to @kmf and @Andre-Ioda for help debugging this issue
    • \n
    \n
  • \n
\n","text":"(#776) Fixed screens failing to load with \"toLowerCase is not a function\" error Issue occurred when frontmatter tags array contained non-string values (numbers, booleans, etc.) Added type validation to filter out non-string values before processing tags Valid string tags continue to work normally while invalid types are safely skipped Thanks to @kmf and @Andre-Ioda for help debugging this issue"},{"route":"/obsidian/releases/3.24.4/","title":"TaskNotes 3.24.4","description":"(#768) Fixed calendar view crashes when tasks contain null values in grouping fields","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.24.4.md","namespace":"obsidian","relativePath":"releases/3.24.4.md","raw":"# TaskNotes 3.24.4\n\n## Fixed\n\n- (#768) Fixed calendar view crashes when tasks contain null values in grouping fields\n - Added null/undefined checks in sort comparisons to prevent localeCompare errors\n - Calendar now handles null values in tags, contexts, and custom fields gracefully\n - Thanks to @kmaustral for reporting\n\n- (#601) Fixed Unicode characters not displaying in tags and contexts\n - Unicode characters (Š, Ė, Ž, Ą, etc.) are now properly preserved in tags and contexts\n - Affects Agenda View, Task List View, and all other views displaying tags\n - Thanks to @Kapinekas for reporting\n\n- (#778) Fixed cursor artifacts in CodeMirror widgets\n - Thanks to @jhedlund for the fix\n\n- Fixed task card widgets in note editor not updating for archive and time tracking changes\n - Task card widgets now properly detect when tasks are archived/unarchived\n - Task card widgets now properly detect when time tracking starts/stops\n - Blue \"tracking\" border now appears/disappears correctly in live preview\n - Archive styling now updates correctly in live preview\n\n## Changed\n\n- (#751) Status bar tracked task click behavior now opens task notes directly\n - Single tracked task: opens the task note immediately\n - Multiple tracked tasks: shows selector modal to choose which task note to open\n - Provides faster access to tracked tasks compared to previous task list view\n\n- (#727) \"Create New Inline Task\" command now respects the \"Include Current Note in Project\" setting\n - When enabled, the current note is automatically added as a project to inline tasks\n - Provides consistency with instant convert functionality\n - Thanks to @chrisfeagles for the suggestion\n\n- Improved link handling throughout the plugin using Obsidian's native APIs\n - Replaced manual wikilink generation with `FileManager.generateMarkdownLink()`\n - Now respects user's link format settings (wikilink vs markdown, relative paths)\n - Replaced manual link parsing with `parseLinktext()` for proper alias handling\n - Better compatibility with future Obsidian updates\n - Added centralized link utilities in `linkUtils.ts`\n\n- Refactored widget cursor styles into reusable utility class\n - Consolidated shared CSS into .cm-widget-cursor-fix utility\n - Improved maintainability across widget components\n\n","aliases":["/releases/3.24.4/","/releases/3.24.4/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"changed","text":"Changed"}],"html":"

Fixed#

\n
    \n
  • (#768) Fixed calendar view crashes when tasks contain null values in grouping fields

    \n
      \n
    • Added null/undefined checks in sort comparisons to prevent localeCompare errors
    • \n
    • Calendar now handles null values in tags, contexts, and custom fields gracefully
    • \n
    • Thanks to @kmaustral for reporting
    • \n
    \n
  • \n
  • (#601) Fixed Unicode characters not displaying in tags and contexts

    \n
      \n
    • Unicode characters (Š, Ė, Ž, Ą, etc.) are now properly preserved in tags and contexts
    • \n
    • Affects Agenda View, Task List View, and all other views displaying tags
    • \n
    • Thanks to @Kapinekas for reporting
    • \n
    \n
  • \n
  • (#778) Fixed cursor artifacts in CodeMirror widgets

    \n
      \n
    • Thanks to @jhedlund for the fix
    • \n
    \n
  • \n
  • Fixed task card widgets in note editor not updating for archive and time tracking changes

    \n
      \n
    • Task card widgets now properly detect when tasks are archived/unarchived
    • \n
    • Task card widgets now properly detect when time tracking starts/stops
    • \n
    • Blue "tracking" border now appears/disappears correctly in live preview
    • \n
    • Archive styling now updates correctly in live preview
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • (#751) Status bar tracked task click behavior now opens task notes directly

    \n
      \n
    • Single tracked task: opens the task note immediately
    • \n
    • Multiple tracked tasks: shows selector modal to choose which task note to open
    • \n
    • Provides faster access to tracked tasks compared to previous task list view
    • \n
    \n
  • \n
  • (#727) "Create New Inline Task" command now respects the "Include Current Note in Project" setting

    \n
      \n
    • When enabled, the current note is automatically added as a project to inline tasks
    • \n
    • Provides consistency with instant convert functionality
    • \n
    • Thanks to @chrisfeagles for the suggestion
    • \n
    \n
  • \n
  • Improved link handling throughout the plugin using Obsidian's native APIs

    \n
      \n
    • Replaced manual wikilink generation with FileManager.generateMarkdownLink()
    • \n
    • Now respects user's link format settings (wikilink vs markdown, relative paths)
    • \n
    • Replaced manual link parsing with parseLinktext() for proper alias handling
    • \n
    • Better compatibility with future Obsidian updates
    • \n
    • Added centralized link utilities in linkUtils.ts
    • \n
    \n
  • \n
  • Refactored widget cursor styles into reusable utility class

    \n
      \n
    • Consolidated shared CSS into .cm-widget-cursor-fix utility
    • \n
    • Improved maintainability across widget components
    • \n
    \n
  • \n
\n","text":"Fixed# (#768) Fixed calendar view crashes when tasks contain null values in grouping fields Added null/undefined checks in sort comparisons to prevent localeCompare errors Calendar now handles null values in tags, contexts, and custom fields gracefully Thanks to @kmaustral for reporting (#601) Fixed Unicode characters not displaying in tags and contexts Unicode characters (Š, Ė, Ž, Ą, etc.) are now properly preserved in tags and contexts Affects Agenda View, Task List View, and all other views displaying tags Thanks to @Kapinekas for reporting (#778) Fixed cursor artifacts in CodeMirror widgets Thanks to @jhedlund for the fix Fixed task card widgets in note editor not updating for archive and time tracking changes Task card widgets now properly detect when tasks are archived/unarchived Task card widgets now properly detect when time tracking starts/stops Blue \"tracking\" border now appears/disappears correctly in live preview Archive styling now updates correctly in live preview Changed# (#751) Status bar tracked task click behavior now opens task notes directly Single tracked task: opens the task note immediately Multiple tracked tasks: shows selector modal to choose which task note to open Provides faster access to tracked tasks compared to previous task list view (#727) \"Create New Inline Task\" command now respects the \"Include Current Note in Project\" setting When enabled, the current note is automatically added as a project to inline tasks Provides consistency with instant convert functionality Thanks to @chrisfeagles for the suggestion Improved link handling throughout the plugin using Obsidian's native APIs Replaced manual wikilink generation with FileManager.generateMarkdownLink() Now respects user's link format settings (wikilink vs markdown, relative paths) Replaced manual link parsing with parseLinktext() for proper alias handling Better compatibility with future Obsidian updates Added centralized link utilities in linkUtils.ts Refactored widget cursor styles into reusable utility class Consolidated shared CSS into .cm-widget-cursor-fix utility Improved maintainability across widget components"},{"route":"/obsidian/releases/3.24.5/","title":"TaskNotes 3.24.5","description":"(#806) Fixed Bases views crashing on Obsidian 1.10.0 startup","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.24.5.md","namespace":"obsidian","relativePath":"releases/3.24.5.md","raw":"# TaskNotes 3.24.5\n\n## Fixed\n\n- (#806) Fixed Bases views crashing on Obsidian 1.10.0 startup\n - TaskNotes Bases views (Task List and Kanban) now restore correctly when already open at startup\n - Added defensive checks in `setEphemeralState` to handle early lifecycle calls\n - Added `focus()` method to view objects for proper restoration\n - Made root elements focusable to support Obsidian 1.10.0 view lifecycle\n\n- (#792, #800) Fixed markdown-style project and dependency links not being recognized in frontmatter\n - Added support for markdown link format `[text](path)` in projects and blockedBy fields\n - Handles URL-encoded paths like `[Car Maintenance](../../projects/Car%20Maintenance.md)`\n - Markdown links now render as clickable links showing display text instead of raw `[text](path)` format\n - Links are properly resolved for grouping, filtering, and project-task associations\n - Previously only wikilink format `[[path]]` was supported\n - Prevents automatic removal of project assignments when editing tasks\n - Thanks to @minchinweb for reporting\n\n- (#780) Fixed \"Cannot Create Timeblocks\" error when daily notes folder doesn't exist\n - Added proper error handling when `createDailyNote` fails due to missing folder\n - Improved error messages to guide users to check Daily Notes plugin configuration\n - Prevents uncaught errors from `obsidian-daily-notes-interface` package\n - Thanks to @uberunix for reporting\n\n","aliases":["/releases/3.24.5/","/releases/3.24.5/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Fixed#

\n
    \n
  • (#806) Fixed Bases views crashing on Obsidian 1.10.0 startup

    \n
      \n
    • TaskNotes Bases views (Task List and Kanban) now restore correctly when already open at startup
    • \n
    • Added defensive checks in setEphemeralState to handle early lifecycle calls
    • \n
    • Added focus() method to view objects for proper restoration
    • \n
    • Made root elements focusable to support Obsidian 1.10.0 view lifecycle
    • \n
    \n
  • \n
  • (#792, #800) Fixed markdown-style project and dependency links not being recognized in frontmatter

    \n
      \n
    • Added support for markdown link format [text](path) in projects and blockedBy fields
    • \n
    • Handles URL-encoded paths like [Car Maintenance](../../projects/Car%20Maintenance.md)
    • \n
    • Markdown links now render as clickable links showing display text instead of raw [text](path) format
    • \n
    • Links are properly resolved for grouping, filtering, and project-task associations
    • \n
    • Previously only wikilink format [[path]] was supported
    • \n
    • Prevents automatic removal of project assignments when editing tasks
    • \n
    • Thanks to @minchinweb for reporting
    • \n
    \n
  • \n
  • (#780) Fixed "Cannot Create Timeblocks" error when daily notes folder doesn't exist

    \n
      \n
    • Added proper error handling when createDailyNote fails due to missing folder
    • \n
    • Improved error messages to guide users to check Daily Notes plugin configuration
    • \n
    • Prevents uncaught errors from obsidian-daily-notes-interface package
    • \n
    • Thanks to @uberunix for reporting
    • \n
    \n
  • \n
\n","text":"Fixed# (#806) Fixed Bases views crashing on Obsidian 1.10.0 startup TaskNotes Bases views (Task List and Kanban) now restore correctly when already open at startup Added defensive checks in setEphemeralState to handle early lifecycle calls Added focus() method to view objects for proper restoration Made root elements focusable to support Obsidian 1.10.0 view lifecycle (#792, #800) Fixed markdown-style project and dependency links not being recognized in frontmatter Added support for markdown link format [text](path) in projects and blockedBy fields Handles URL-encoded paths like [Car Maintenance](../../projects/Car%20Maintenance.md) Markdown links now render as clickable links showing display text instead of raw [text](path) format Links are properly resolved for grouping, filtering, and project-task associations Previously only wikilink format [[path]] was supported Prevents automatic removal of project assignments when editing tasks Thanks to @minchinweb for reporting (#780) Fixed \"Cannot Create Timeblocks\" error when daily notes folder doesn't exist Added proper error handling when createDailyNote fails due to missing folder Improved error messages to guide users to check Daily Notes plugin configuration Prevents uncaught errors from obsidian-daily-notes-interface package Thanks to @uberunix for reporting"},{"route":"/obsidian/releases/3.24.6/","title":"TaskNotes 3.24.6","description":"(#440) Fixed inline task replacement not working for links with relative paths","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.24.6.md","namespace":"obsidian","relativePath":"releases/3.24.6.md","raw":"# TaskNotes 3.24.6\n\n## Added\n\n- Added release notes viewer\n - New view displays release notes in a dedicated tab when plugin updates\n - Automatically opens after updating to a new version\n - Access anytime via command palette \"TaskNotes: View release notes\" or Settings > General\n - Release notes are rendered using native Obsidian markdown rendering\n - Includes link to view all releases on GitHub\n - Fully internationalized with i18n support\n - Auto-generation system ensures correct version is loaded without manual updates\n\n## Fixed\n\n- (#440) Fixed inline task replacement not working for links with relative paths\n - Markdown links with relative paths like `[task](../../../GTD/tasks/task.md)` now display inline previews\n - Wikilinks with relative paths now work correctly\n - Removed overly aggressive path sanitization that was stripping `..` from all link paths\n - Works in both Live Preview and Reading Mode\n - Thanks to @minchinweb for reporting\n\n- (#814) Fixed markdown links in projects field not being recognized on Project notes\n - Tasks with markdown-style project links `[text](path)` now appear in project's Subtasks section\n - Updated project link detection to use `parseLinkToPath` utility which handles both wikilinks and markdown links\n - Handles URL-encoded paths like `[z Test Project](z%20Test%20Project.md)`\n - Thanks to @minchinweb for reporting\n\n- (#827) Fixed project links being generated as markdown links for users with markdown links enabled in Obsidian settings\n - Project links in frontmatter are now always generated as wikilinks `[[link]]` by default for Obsidian compatibility\n - Obsidian does not support markdown links in frontmatter properties without third-party plugins\n - Added optional setting to enable markdown links in frontmatter for users with `obsidian-frontmatter-markdown-links` plugin\n - Setting only appears when user has markdown links enabled globally in Obsidian\n - Thanks to @nightroman for reporting\n","aliases":["/releases/3.24.6/","/releases/3.24.6/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • Added release notes viewer
      \n
    • New view displays release notes in a dedicated tab when plugin updates
    • \n
    • Automatically opens after updating to a new version
    • \n
    • Access anytime via command palette "TaskNotes: View release notes" or Settings > General
    • \n
    • Release notes are rendered using native Obsidian markdown rendering
    • \n
    • Includes link to view all releases on GitHub
    • \n
    • Fully internationalized with i18n support
    • \n
    • Auto-generation system ensures correct version is loaded without manual updates
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#440) Fixed inline task replacement not working for links with relative paths

    \n
      \n
    • Markdown links with relative paths like [task](../../../GTD/tasks/task.md) now display inline previews
    • \n
    • Wikilinks with relative paths now work correctly
    • \n
    • Removed overly aggressive path sanitization that was stripping .. from all link paths
    • \n
    • Works in both Live Preview and Reading Mode
    • \n
    • Thanks to @minchinweb for reporting
    • \n
    \n
  • \n
  • (#814) Fixed markdown links in projects field not being recognized on Project notes

    \n
      \n
    • Tasks with markdown-style project links [text](path) now appear in project's Subtasks section
    • \n
    • Updated project link detection to use parseLinkToPath utility which handles both wikilinks and markdown links
    • \n
    • Handles URL-encoded paths like [z Test Project](z%20Test%20Project.md)
    • \n
    • Thanks to @minchinweb for reporting
    • \n
    \n
  • \n
  • (#827) Fixed project links being generated as markdown links for users with markdown links enabled in Obsidian settings

    \n
      \n
    • Project links in frontmatter are now always generated as wikilinks [[link]] by default for Obsidian compatibility
    • \n
    • Obsidian does not support markdown links in frontmatter properties without third-party plugins
    • \n
    • Added optional setting to enable markdown links in frontmatter for users with obsidian-frontmatter-markdown-links plugin
    • \n
    • Setting only appears when user has markdown links enabled globally in Obsidian
    • \n
    • Thanks to @nightroman for reporting
    • \n
    \n
  • \n
\n","text":"Added# Added release notes viewer New view displays release notes in a dedicated tab when plugin updates Automatically opens after updating to a new version Access anytime via command palette \"TaskNotes: View release notes\" or Settings > General Release notes are rendered using native Obsidian markdown rendering Includes link to view all releases on GitHub Fully internationalized with i18n support Auto-generation system ensures correct version is loaded without manual updates Fixed# (#440) Fixed inline task replacement not working for links with relative paths Markdown links with relative paths like [task](../../../GTD/tasks/task.md) now display inline previews Wikilinks with relative paths now work correctly Removed overly aggressive path sanitization that was stripping .. from all link paths Works in both Live Preview and Reading Mode Thanks to @minchinweb for reporting (#814) Fixed markdown links in projects field not being recognized on Project notes Tasks with markdown-style project links [text](path) now appear in project's Subtasks section Updated project link detection to use parseLinkToPath utility which handles both wikilinks and markdown links Handles URL-encoded paths like [z Test Project](z%20Test%20Project.md) Thanks to @minchinweb for reporting (#827) Fixed project links being generated as markdown links for users with markdown links enabled in Obsidian settings Project links in frontmatter are now always generated as wikilinks [[link]] by default for Obsidian compatibility Obsidian does not support markdown links in frontmatter properties without third-party plugins Added optional setting to enable markdown links in frontmatter for users with obsidian-frontmatter-markdown-links plugin Setting only appears when user has markdown links enabled globally in Obsidian Thanks to @nightroman for reporting"},{"route":"/obsidian/releases/3.25.0/","title":"TaskNotes 3.25.0","description":"Added Calendar view for Bases plugin integration (requires Bases 1.10.0+)","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.25.0.md","namespace":"obsidian","relativePath":"releases/3.25.0.md","raw":"# TaskNotes 3.25.0\n\n## Added\n\n- Added Calendar view for Bases plugin integration (requires Bases 1.10.0+)\n - Supports month, week, day, year, and list views\n - Property-based events from note date properties (configurable start date, end date, and title properties)\n - Custom card rendering in list view for tasks, timeblocks, ICS events, and property-based events\n - Layout options: time format, weekend visibility, all-day slot, today highlight, scroll time, event height\n - Visibility toggles for event types (scheduled, due, recurring, time entries, timeblocks, property-based)\n - Date validation to handle invalid property values\n - Drag-and-drop to update property-based event dates in frontmatter\n - Full internationalization support for calendar features in 7 languages (English, French, Spanish, German, Japanese, Russian, Chinese)\n\n- Added grouped rendering support for Bases integration list and kanban views\n - List view displays collapsible groups with toggle controls\n - Kanban view renders grouped columns with drag-drop support\n - Automatically detects ungrouped views and renders as flat list\n\n- (#842) Added keyboard navigation support for task forms\n - Action bar icons now focusable with proper tab order and ARIA attributes\n - Enter and Space keys trigger actions on focused elements\n - Added submenu support for reminders button for better keyboard accessibility\n - Improved focus indicators for better visual feedback\n - Thanks to @maybetm for this excellent contribution!\n\n## Changed\n\n- Migrated Bases integration to use public API (Bases 1.10.0+) with graceful fallback to internal API for older versions\n\n## Fixed\n\n- (#789) Fixed folder path truncation in settings causing tasks to be created in wrong paths\n - Changed debounce to trailing mode to ensure final value is saved instead of partial input\n - Fixes issue where rapid typing, paste, or autocomplete would save incomplete folder paths\n - Thanks to @sascha224 for reporting\n\n- (#806) Fixed Bases views crashing on Obsidian 1.10.0 startup\n - TaskNotes Bases views (Task List and Kanban) now restore correctly when already open at startup\n - Added defensive checks in `setEphemeralState` to handle early lifecycle calls\n - Added `focus()` method to view objects for proper restoration\n - Made root elements focusable to support Obsidian 1.10.0 view lifecycle\n\n- (#825) Fixed single/double click settings not applying to calendar views\n - Shared click handling now works consistently across Advanced Calendar and Bases Calendar\n - Ctrl/Cmd+click opens tasks in new tab as expected\n - Single and double-click actions respect user settings\n\n- (#699) Fixed Obsidian freezing when moving calendar tab to new window\n - Skip calendar resize during window transfer to prevent freeze\n - Calendar may display incorrectly after move but can be fixed by switching views\n - Prevents complete UI lockup during tab transfer\n\n- (#816) Fixed template variables not processing in ICS subscription note folder paths\n - Template variables like `{{year}}`, `{{month}}`, `{{date}}` now work in ICS note folder settings\n - Extracted folder template processing into shared utility for consistency\n - Added support for ICS-specific variables: `{{icsEventTitle}}`, `{{icsEventLocation}}`, `{{icsEventDescription}}`\n - Users can now organize ICS notes in date-based hierarchies (e.g., `Daily/{{year}}/{{month}}/`)\n - Thanks to @j-peeters for reporting\n\n- (#813) Fixed subscribed ICS calendars irregularly disappearing from calendar views\n - Added 5-minute grace period after cache expiration to keep events visible during refresh\n - Trigger automatic background refresh when cache is stale or missing\n - Initialize ICS service instances early so views can register event listeners before data loads\n - Prevents disappearance during network errors or when calendar opens at Obsidian startup\n - Thanks to @j-peeters for reporting\n\n- (#829) Fixed time estimates and recurrence patterns being lost during instant task conversion\n - Added `timeEstimate` field to `ParsedTaskData` interface\n - Time estimates from natural language parsing now properly transferred to task frontmatter\n - Parsed values now take priority over default settings\n - RRule strings passed directly without conversion (preferred format)\n - Thanks to @Justin-Burg for reporting\n\n- (#826) Fixed task card widget not appearing when Obsidian starts with task note open\n - Deferred dispatch calls to avoid \"EditorView.update not allowed during update\" error\n - Widget now renders correctly on startup without requiring workarounds\n - Thanks to @nightroman for reporting\n\n- (#781), (#841) Fixed ICS calendar events displaying incorrect times due to timezone conversion issues\n - Events with non-IANA timezone identifiers (e.g., `TZID=Zurich` without VTIMEZONE) now display at correct local times\n - Fixed Outlook/Exchange calendar events showing original timezone instead of user's local timezone\n - Replaced unreliable `toJSDate()` conversion with `toUnixTime()` for accurate UTC timestamp handling\n - Affects all ICS subscriptions including Infomaniak, Outlook, and other providers with non-standard timezone formats\n - Thanks to @chrlaney for reporting and @wilf80 for detailed analysis\n\n- (#810) Fixed recurring tasks with overdue due dates disappearing from agenda view\n - Recurring tasks now check both `due` and `scheduled` dates for overdue status\n - Previously only `scheduled` was checked for recurring tasks, causing tasks with overdue `due` dates to be hidden\n - Ensures consistent overdue detection logic between recurring and non-recurring tasks\n - Thanks to @skyrunner15 for reporting\n\n- (#822) Fixed mini calendar showing incorrect dates in negative UTC offset timezones\n - Calendar tooltips and month displays now show correct dates for users in Americas/Pacific timezones\n - UTC-anchored dates are now converted to local calendar dates before formatting\n - Fixes off-by-one day error that affected date selection and display\n - Thanks to @kenhsmith for reporting\n\n","aliases":["/releases/3.25.0/","/releases/3.25.0/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • Added Calendar view for Bases plugin integration (requires Bases 1.10.0+)

    \n
      \n
    • Supports month, week, day, year, and list views
    • \n
    • Property-based events from note date properties (configurable start date, end date, and title properties)
    • \n
    • Custom card rendering in list view for tasks, timeblocks, ICS events, and property-based events
    • \n
    • Layout options: time format, weekend visibility, all-day slot, today highlight, scroll time, event height
    • \n
    • Visibility toggles for event types (scheduled, due, recurring, time entries, timeblocks, property-based)
    • \n
    • Date validation to handle invalid property values
    • \n
    • Drag-and-drop to update property-based event dates in frontmatter
    • \n
    • Full internationalization support for calendar features in 7 languages (English, French, Spanish, German, Japanese, Russian, Chinese)
    • \n
    \n
  • \n
  • Added grouped rendering support for Bases integration list and kanban views

    \n
      \n
    • List view displays collapsible groups with toggle controls
    • \n
    • Kanban view renders grouped columns with drag-drop support
    • \n
    • Automatically detects ungrouped views and renders as flat list
    • \n
    \n
  • \n
  • (#842) Added keyboard navigation support for task forms

    \n
      \n
    • Action bar icons now focusable with proper tab order and ARIA attributes
    • \n
    • Enter and Space keys trigger actions on focused elements
    • \n
    • Added submenu support for reminders button for better keyboard accessibility
    • \n
    • Improved focus indicators for better visual feedback
    • \n
    • Thanks to @maybetm for this excellent contribution!
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Migrated Bases integration to use public API (Bases 1.10.0+) with graceful fallback to internal API for older versions
  • \n
\n

Fixed#

\n
    \n
  • (#789) Fixed folder path truncation in settings causing tasks to be created in wrong paths

    \n
      \n
    • Changed debounce to trailing mode to ensure final value is saved instead of partial input
    • \n
    • Fixes issue where rapid typing, paste, or autocomplete would save incomplete folder paths
    • \n
    • Thanks to @sascha224 for reporting
    • \n
    \n
  • \n
  • (#806) Fixed Bases views crashing on Obsidian 1.10.0 startup

    \n
      \n
    • TaskNotes Bases views (Task List and Kanban) now restore correctly when already open at startup
    • \n
    • Added defensive checks in setEphemeralState to handle early lifecycle calls
    • \n
    • Added focus() method to view objects for proper restoration
    • \n
    • Made root elements focusable to support Obsidian 1.10.0 view lifecycle
    • \n
    \n
  • \n
  • (#825) Fixed single/double click settings not applying to calendar views

    \n
      \n
    • Shared click handling now works consistently across Advanced Calendar and Bases Calendar
    • \n
    • Ctrl/Cmd+click opens tasks in new tab as expected
    • \n
    • Single and double-click actions respect user settings
    • \n
    \n
  • \n
  • (#699) Fixed Obsidian freezing when moving calendar tab to new window

    \n
      \n
    • Skip calendar resize during window transfer to prevent freeze
    • \n
    • Calendar may display incorrectly after move but can be fixed by switching views
    • \n
    • Prevents complete UI lockup during tab transfer
    • \n
    \n
  • \n
  • (#816) Fixed template variables not processing in ICS subscription note folder paths

    \n
      \n
    • Template variables like {{year}}, {{month}}, {{date}} now work in ICS note folder settings
    • \n
    • Extracted folder template processing into shared utility for consistency
    • \n
    • Added support for ICS-specific variables: {{icsEventTitle}}, {{icsEventLocation}}, {{icsEventDescription}}
    • \n
    • Users can now organize ICS notes in date-based hierarchies (e.g., Daily/{{year}}/{{month}}/)
    • \n
    • Thanks to @j-peeters for reporting
    • \n
    \n
  • \n
  • (#813) Fixed subscribed ICS calendars irregularly disappearing from calendar views

    \n
      \n
    • Added 5-minute grace period after cache expiration to keep events visible during refresh
    • \n
    • Trigger automatic background refresh when cache is stale or missing
    • \n
    • Initialize ICS service instances early so views can register event listeners before data loads
    • \n
    • Prevents disappearance during network errors or when calendar opens at Obsidian startup
    • \n
    • Thanks to @j-peeters for reporting
    • \n
    \n
  • \n
  • (#829) Fixed time estimates and recurrence patterns being lost during instant task conversion

    \n
      \n
    • Added timeEstimate field to ParsedTaskData interface
    • \n
    • Time estimates from natural language parsing now properly transferred to task frontmatter
    • \n
    • Parsed values now take priority over default settings
    • \n
    • RRule strings passed directly without conversion (preferred format)
    • \n
    • Thanks to @Justin-Burg for reporting
    • \n
    \n
  • \n
  • (#826) Fixed task card widget not appearing when Obsidian starts with task note open

    \n
      \n
    • Deferred dispatch calls to avoid "EditorView.update not allowed during update" error
    • \n
    • Widget now renders correctly on startup without requiring workarounds
    • \n
    • Thanks to @nightroman for reporting
    • \n
    \n
  • \n
  • (#781), (#841) Fixed ICS calendar events displaying incorrect times due to timezone conversion issues

    \n
      \n
    • Events with non-IANA timezone identifiers (e.g., TZID=Zurich without VTIMEZONE) now display at correct local times
    • \n
    • Fixed Outlook/Exchange calendar events showing original timezone instead of user's local timezone
    • \n
    • Replaced unreliable toJSDate() conversion with toUnixTime() for accurate UTC timestamp handling
    • \n
    • Affects all ICS subscriptions including Infomaniak, Outlook, and other providers with non-standard timezone formats
    • \n
    • Thanks to @chrlaney for reporting and @wilf80 for detailed analysis
    • \n
    \n
  • \n
  • (#810) Fixed recurring tasks with overdue due dates disappearing from agenda view

    \n
      \n
    • Recurring tasks now check both due and scheduled dates for overdue status
    • \n
    • Previously only scheduled was checked for recurring tasks, causing tasks with overdue due dates to be hidden
    • \n
    • Ensures consistent overdue detection logic between recurring and non-recurring tasks
    • \n
    • Thanks to @skyrunner15 for reporting
    • \n
    \n
  • \n
  • (#822) Fixed mini calendar showing incorrect dates in negative UTC offset timezones

    \n
      \n
    • Calendar tooltips and month displays now show correct dates for users in Americas/Pacific timezones
    • \n
    • UTC-anchored dates are now converted to local calendar dates before formatting
    • \n
    • Fixes off-by-one day error that affected date selection and display
    • \n
    • Thanks to @kenhsmith for reporting
    • \n
    \n
  • \n
\n","text":"Added# Added Calendar view for Bases plugin integration (requires Bases 1.10.0+) Supports month, week, day, year, and list views Property-based events from note date properties (configurable start date, end date, and title properties) Custom card rendering in list view for tasks, timeblocks, ICS events, and property-based events Layout options: time format, weekend visibility, all-day slot, today highlight, scroll time, event height Visibility toggles for event types (scheduled, due, recurring, time entries, timeblocks, property-based) Date validation to handle invalid property values Drag-and-drop to update property-based event dates in frontmatter Full internationalization support for calendar features in 7 languages (English, French, Spanish, German, Japanese, Russian, Chinese) Added grouped rendering support for Bases integration list and kanban views List view displays collapsible groups with toggle controls Kanban view renders grouped columns with drag-drop support Automatically detects ungrouped views and renders as flat list (#842) Added keyboard navigation support for task forms Action bar icons now focusable with proper tab order and ARIA attributes Enter and Space keys trigger actions on focused elements Added submenu support for reminders button for better keyboard accessibility Improved focus indicators for better visual feedback Thanks to @maybetm for this excellent contribution! Changed# Migrated Bases integration to use public API (Bases 1.10.0+) with graceful fallback to internal API for older versions Fixed# (#789) Fixed folder path truncation in settings causing tasks to be created in wrong paths Changed debounce to trailing mode to ensure final value is saved instead of partial input Fixes issue where rapid typing, paste, or autocomplete would save incomplete folder paths Thanks to @sascha224 for reporting (#806) Fixed Bases views crashing on Obsidian 1.10.0 startup TaskNotes Bases views (Task List and Kanban) now restore correctly when already open at startup Added defensive checks in setEphemeralState to handle early lifecycle calls Added focus() method to view objects for proper restoration Made root elements focusable to support Obsidian 1.10.0 view lifecycle (#825) Fixed single/double click settings not applying to calendar views Shared click handling now works consistently across Advanced Calendar and Bases Calendar Ctrl/Cmd+click opens tasks in new tab as expected Single and double-click actions respect user settings (#699) Fixed Obsidian freezing when moving calendar tab to new window Skip calendar resize during window transfer to prevent freeze Calendar may display incorrectly after move but can be fixed by switching views Prevents complete UI lockup during tab transfer (#816) Fixed template variables not processing in ICS subscription note folder paths Template variables like {{year}}, {{month}}, {{date}} now work in ICS note folder settings Extracted folder template processing into shared utility for consistency Added support for ICS-specific variables: {{icsEventTitle}}, {{icsEventLocation}}, {{icsEventDescription}} Users can now organize ICS notes in date-based hierarchies (e.g., Daily/{{year}}/{{month}}/) Thanks to @j-peeters for reporting (#813) Fixed subscribed ICS calendars irregularly disappearing from calendar views Added 5-minute grace period after cache expiration to keep events visible during refresh Trigger automatic background refresh when cache is stale or missing Initialize ICS service instances early so views can register event listeners before data loads Prevents disappearance during network errors or when calendar opens at Obsidian startup Thanks to @j-peeters for reporting (#829) Fixed time estimates and recurrence patterns being lost during instant task conversion Added timeEstimate field to ParsedTaskData interface Time estimates from natural language parsing now properly transferred to task frontmatter Parsed values now take priority over default settings RRule strings passed directly without conversion (preferred format) Thanks to @Justin-Burg for reporting (#826) Fixed task card widget not appearing when Obsidian starts with task note open Deferred dispatch calls to avoid \"EditorView.update not allowed during update\" error Widget now renders correctly on startup without requiring workarounds Thanks to @nightroman for reporting (#781), (#841) Fixed ICS calendar events displaying incorrect times due to timezone conversion issues Events with non-IANA timezone identifiers (e.g., TZID=Zurich without VTIMEZONE) now display at correct local times Fixed Outlook/Exchange calendar events showing original timezone instead of user's local timezone Replaced unreliable toJSDate() conversion with toUnixTime() for accurate UTC timestamp handling Affects all ICS subscriptions including Infomaniak, Outlook, and other providers with non-standard timezone formats Thanks to @chrlaney for reporting and @wilf80 for detailed analysis (#810) Fixed recurring tasks with overdue due dates disappearing from agenda view Recurring tasks now check both due and scheduled dates for overdue status Previously only scheduled was checked for recurring tasks, causing tasks with overdue due dates to be hidden Ensures consistent overdue detection logic between recurring and non-recurring tasks Thanks to @skyrunner15 for reporting (#822) Fixed mini calendar showing incorrect dates in negative UTC offset timezones Calendar tooltips and month displays now show correct dates for users in Americas/Pacific timezones UTC-anchored dates are now converted to local calendar dates before formatting Fixes off-by-one day error that affected date selection and display Thanks to @kenhsmith for reporting"},{"route":"/obsidian/releases/3.25.1/","title":"TaskNotes 3.25.1","description":"(#854) (#695) Fixed all-day ICS calendar events displaying on wrong day and appearing twice","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.25.1.md","namespace":"obsidian","relativePath":"releases/3.25.1.md","raw":"# TaskNotes 3.25.1\n\n## Fixed\n\n- (#854) (#695) Fixed all-day ICS calendar events displaying on wrong day and appearing twice\n - All-day events now stored as date-only strings (YYYY-MM-DD) instead of UTC timestamps\n - Events display on correct calendar date regardless of user timezone (fixes issue in PST, EST, and other negative UTC offset timezones)\n - All-day events no longer appear twice in Agenda view\n - Updated all date parsing throughout the codebase to handle date-only format correctly\n - Maintains compatibility with FullCalendar and preserves iCalendar RFC 5545 semantics for VALUE=DATE events\n - Thanks to @needo37 for reporting #854 and @realJohnDoe for reporting #695\n\n- (#859) Fixed multi-day task creation in Bases calendar view\n - Extracted shared task creation logic to `calendar-core.ts` for consistency between calendar views\n - Multi-day all-day selections now correctly set time estimate based on number of days dragged\n - Timed task selections (week view) now correctly calculate duration in minutes\n - Single-day clicks no longer override default time estimate settings\n - Both Bases calendar and AdvancedCalendarView now use same logic for consistent behavior\n - Fixed all-day task rendering to use 24-hour days (1440 minutes = 1 day on calendar)\n - Follows UTC Anchor principle for date-only strings\n - Thanks to @anareaty for reporting\n","aliases":["/releases/3.25.1/","/releases/3.25.1/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Fixed#

\n
    \n
  • (#854) (#695) Fixed all-day ICS calendar events displaying on wrong day and appearing twice

    \n
      \n
    • All-day events now stored as date-only strings (YYYY-MM-DD) instead of UTC timestamps
    • \n
    • Events display on correct calendar date regardless of user timezone (fixes issue in PST, EST, and other negative UTC offset timezones)
    • \n
    • All-day events no longer appear twice in Agenda view
    • \n
    • Updated all date parsing throughout the codebase to handle date-only format correctly
    • \n
    • Maintains compatibility with FullCalendar and preserves iCalendar RFC 5545 semantics for VALUE=DATE events
    • \n
    • Thanks to @needo37 for reporting #854 and @realJohnDoe for reporting #695
    • \n
    \n
  • \n
  • (#859) Fixed multi-day task creation in Bases calendar view

    \n
      \n
    • Extracted shared task creation logic to calendar-core.ts for consistency between calendar views
    • \n
    • Multi-day all-day selections now correctly set time estimate based on number of days dragged
    • \n
    • Timed task selections (week view) now correctly calculate duration in minutes
    • \n
    • Single-day clicks no longer override default time estimate settings
    • \n
    • Both Bases calendar and AdvancedCalendarView now use same logic for consistent behavior
    • \n
    • Fixed all-day task rendering to use 24-hour days (1440 minutes = 1 day on calendar)
    • \n
    • Follows UTC Anchor principle for date-only strings
    • \n
    • Thanks to @anareaty for reporting
    • \n
    \n
  • \n
\n","text":"Fixed# (#854) (#695) Fixed all-day ICS calendar events displaying on wrong day and appearing twice All-day events now stored as date-only strings (YYYY-MM-DD) instead of UTC timestamps Events display on correct calendar date regardless of user timezone (fixes issue in PST, EST, and other negative UTC offset timezones) All-day events no longer appear twice in Agenda view Updated all date parsing throughout the codebase to handle date-only format correctly Maintains compatibility with FullCalendar and preserves iCalendar RFC 5545 semantics for VALUE=DATE events Thanks to @needo37 for reporting #854 and @realJohnDoe for reporting #695 (#859) Fixed multi-day task creation in Bases calendar view Extracted shared task creation logic to calendar-core.ts for consistency between calendar views Multi-day all-day selections now correctly set time estimate based on number of days dragged Timed task selections (week view) now correctly calculate duration in minutes Single-day clicks no longer override default time estimate settings Both Bases calendar and AdvancedCalendarView now use same logic for consistent behavior Fixed all-day task rendering to use 24-hour days (1440 minutes = 1 day on calendar) Follows UTC Anchor principle for date-only strings Thanks to @anareaty for reporting"},{"route":"/obsidian/releases/3.25.2/","title":"TaskNotes 3.25.2","description":"(#857) Fixed Mini Calendar opening previous day's daily note when clicked","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.25.2.md","namespace":"obsidian","relativePath":"releases/3.25.2.md","raw":"# TaskNotes 3.25.2\n\n## Fixed\n\n- (#857) Fixed Mini Calendar opening previous day's daily note when clicked\n - Affects users in negative UTC offset timezones (Americas, Pacific)\n - Thanks to @tsweezy for reporting\n\n- (#871) Fixed Bases Kanban drag-and-drop updating wrong property when grouped by custom fields\n - Added support for both Bases 1.10.0+ format (`{property: string, direction: string}`) and legacy string format\n - Note: GroupBy is not exposed in the Bases public API (`config.get('groupBy')` returns undefined)\n - Known limitation: When grouping by projects, Bases groups by literal wikilink strings, not resolved file paths\n - Tasks with different wikilink formats pointing to the same project file will appear in separate columns\n - Example: `[[Project]]`, `[[path/to/Project]]`, and `[[Project|Alias]]` create separate columns\n - This differs from native TaskNotes Kanban which resolves all wikilinks to absolute paths\n - Thanks to @kmaustral for reporting\n\n## Added\n\n- Added date navigation configuration for Bases calendar views\n - Hardcoded date option: Set a specific date (YYYY-MM-DD format) for the calendar to display on load\n - Property-based navigation: Automatically navigate to dates from filtered note properties\n - Three navigation strategies: First result, Earliest date, or Latest date\n\n## Changed\n\n- Release notes now bundle all versions from current and previous minor series with collapsible sections\n - Added setting to disable automatic release notes display after updates\n","aliases":["/releases/3.25.2/","/releases/3.25.2/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"}],"html":"

Fixed#

\n
    \n
  • (#857) Fixed Mini Calendar opening previous day's daily note when clicked

    \n
      \n
    • Affects users in negative UTC offset timezones (Americas, Pacific)
    • \n
    • Thanks to @tsweezy for reporting
    • \n
    \n
  • \n
  • (#871) Fixed Bases Kanban drag-and-drop updating wrong property when grouped by custom fields

    \n
      \n
    • Added support for both Bases 1.10.0+ format ({property: string, direction: string}) and legacy string format
    • \n
    • Note: GroupBy is not exposed in the Bases public API (config.get('groupBy') returns undefined)
    • \n
    • Known limitation: When grouping by projects, Bases groups by literal wikilink strings, not resolved file paths
        \n
      • Tasks with different wikilink formats pointing to the same project file will appear in separate columns
      • \n
      • Example: [[Project]], [[path/to/Project]], and [[Project|Alias]] create separate columns
      • \n
      • This differs from native TaskNotes Kanban which resolves all wikilinks to absolute paths
      • \n
      \n
    • \n
    • Thanks to @kmaustral for reporting
    • \n
    \n
  • \n
\n

Added#

\n
    \n
  • Added date navigation configuration for Bases calendar views
      \n
    • Hardcoded date option: Set a specific date (YYYY-MM-DD format) for the calendar to display on load
    • \n
    • Property-based navigation: Automatically navigate to dates from filtered note properties
    • \n
    • Three navigation strategies: First result, Earliest date, or Latest date
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Release notes now bundle all versions from current and previous minor series with collapsible sections
      \n
    • Added setting to disable automatic release notes display after updates
    • \n
    \n
  • \n
\n","text":"Fixed# (#857) Fixed Mini Calendar opening previous day's daily note when clicked Affects users in negative UTC offset timezones (Americas, Pacific) Thanks to @tsweezy for reporting (#871) Fixed Bases Kanban drag-and-drop updating wrong property when grouped by custom fields Added support for both Bases 1.10.0+ format ({property: string, direction: string}) and legacy string format Note: GroupBy is not exposed in the Bases public API (config.get('groupBy') returns undefined) Known limitation: When grouping by projects, Bases groups by literal wikilink strings, not resolved file paths Tasks with different wikilink formats pointing to the same project file will appear in separate columns Example: [[Project]], [[path/to/Project]], and [[Project|Alias]] create separate columns This differs from native TaskNotes Kanban which resolves all wikilinks to absolute paths Thanks to @kmaustral for reporting Added# Added date navigation configuration for Bases calendar views Hardcoded date option: Set a specific date (YYYY-MM-DD format) for the calendar to display on load Property-based navigation: Automatically navigate to dates from filtered note properties Three navigation strategies: First result, Earliest date, or Latest date Changed# Release notes now bundle all versions from current and previous minor series with collapsible sections Added setting to disable automatic release notes display after updates"},{"route":"/obsidian/releases/3.25.3/","title":"TaskNotes 3.25.3","description":"(#899) Fixed \"Folder for converted tasks\" setting being hidden when convert button is disabled","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.25.3.md","namespace":"obsidian","relativePath":"releases/3.25.3.md","raw":"# TaskNotes 3.25.3\n\n## Added\n\n- (#877) Added standard Obsidian CSS classes to settings tab buttons for improved theme compatibility\n - Fixes issue where themes like Retroma couldn't distinguish active tabs\n - Thanks to @Bregor for the contribution\n\n## Fixed\n\n- (#899) Fixed \"Folder for converted tasks\" setting being hidden when convert button is disabled\n - Setting now always visible since it affects command palette task conversion\n - Resolves confusion for users who convert tasks via command palette\n - Thanks to @nnnell for the fix\n\n- (#905), (#907) Fixed project filter incorrectly affecting custom field suggestions\n - Custom field wikilink suggestions (`[[`) now show all vault files instead of only filtered projects\n - Task Edit modal now uses consistent hierarchical tag matching with Task Creation modal\n - Thanks to @renatomen for the thorough fix and tests\n","aliases":["/releases/3.25.3/","/releases/3.25.3/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • (#877) Added standard Obsidian CSS classes to settings tab buttons for improved theme compatibility
      \n
    • Fixes issue where themes like Retroma couldn't distinguish active tabs
    • \n
    • Thanks to @Bregor for the contribution
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#899) Fixed "Folder for converted tasks" setting being hidden when convert button is disabled

    \n
      \n
    • Setting now always visible since it affects command palette task conversion
    • \n
    • Resolves confusion for users who convert tasks via command palette
    • \n
    • Thanks to @nnnell for the fix
    • \n
    \n
  • \n
  • (#905), (#907) Fixed project filter incorrectly affecting custom field suggestions

    \n
      \n
    • Custom field wikilink suggestions ([[) now show all vault files instead of only filtered projects
    • \n
    • Task Edit modal now uses consistent hierarchical tag matching with Task Creation modal
    • \n
    • Thanks to @renatomen for the thorough fix and tests
    • \n
    \n
  • \n
\n","text":"Added# (#877) Added standard Obsidian CSS classes to settings tab buttons for improved theme compatibility Fixes issue where themes like Retroma couldn't distinguish active tabs Thanks to @Bregor for the contribution Fixed# (#899) Fixed \"Folder for converted tasks\" setting being hidden when convert button is disabled Setting now always visible since it affects command palette task conversion Resolves confusion for users who convert tasks via command palette Thanks to @nnnell for the fix (#905), (#907) Fixed project filter incorrectly affecting custom field suggestions Custom field wikilink suggestions ([[) now show all vault files instead of only filtered projects Task Edit modal now uses consistent hierarchical tag matching with Task Creation modal Thanks to @renatomen for the thorough fix and tests"},{"route":"/obsidian/releases/3.25.4/","title":"TaskNotes 3.25.4","description":"(#937), (#956) Added optional setting to hide identification tags in task cards","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.25.4.md","namespace":"obsidian","relativePath":"releases/3.25.4.md","raw":"# TaskNotes 3.25.4\n\n## Added\n\n- (#937), (#956) Added optional setting to hide identification tags in task cards\n - New \"Hide identification tags in task cards\" setting (only visible when using tag-based identification)\n - Hides exact matches (e.g., `#task`) and hierarchical children (e.g., `#task/project`, `#task/work/urgent`)\n - Reduces visual clutter while keeping tags in frontmatter for organizational purposes\n - Backward compatible - disabled by default\n - Thanks to @renatomen for implementing this feature and @edakimling for reporting\n\n- (#911) Added custom field suggestion filtering\n - New `autosuggestFilter` field to `UserMappedField` interface allows filtering suggestions by current filter context\n - Added collapsible filter section in settings with visual indicator\n - Comprehensive test coverage for custom field filtering feature\n - Thanks to @renatomen for this enhancement\n\n## Fixed\n\n- (#903) Fixed Edit Task modal not adding completedDate when marking tasks as done\n - Edit Task modal now correctly adds completedDate when changing status to completed\n - Fixed Edit Task modal adding empty contexts and projects arrays to frontmatter\n - Behavior now consistent with other completion methods (Agenda view, widget context menu, quick actions)\n - Thanks to @nightroman for reporting\n\n- (#969), (#967) Fixed Bases Kanban layout not displaying correctly when no groupBy is configured\n - All tasks were appearing in a single \"None\" column\n - Columns now appear in the order defined in TaskNotes settings (not alphabetical)\n - Detects invalid Bases grouping and falls back to status-based grouping\n - Tasks are properly distributed across status columns\n - Thanks to @mweichert for the fix and @PacoTaco2, @abuhammer for reporting\n\n","aliases":["/releases/3.25.4/","/releases/3.25.4/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • (#937), (#956) Added optional setting to hide identification tags in task cards

    \n
      \n
    • New "Hide identification tags in task cards" setting (only visible when using tag-based identification)
    • \n
    • Hides exact matches (e.g., #task) and hierarchical children (e.g., #task/project, #task/work/urgent)
    • \n
    • Reduces visual clutter while keeping tags in frontmatter for organizational purposes
    • \n
    • Backward compatible - disabled by default
    • \n
    • Thanks to @renatomen for implementing this feature and @edakimling for reporting
    • \n
    \n
  • \n
  • (#911) Added custom field suggestion filtering

    \n
      \n
    • New autosuggestFilter field to UserMappedField interface allows filtering suggestions by current filter context
    • \n
    • Added collapsible filter section in settings with visual indicator
    • \n
    • Comprehensive test coverage for custom field filtering feature
    • \n
    • Thanks to @renatomen for this enhancement
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#903) Fixed Edit Task modal not adding completedDate when marking tasks as done

    \n
      \n
    • Edit Task modal now correctly adds completedDate when changing status to completed
    • \n
    • Fixed Edit Task modal adding empty contexts and projects arrays to frontmatter
    • \n
    • Behavior now consistent with other completion methods (Agenda view, widget context menu, quick actions)
    • \n
    • Thanks to @nightroman for reporting
    • \n
    \n
  • \n
  • (#969), (#967) Fixed Bases Kanban layout not displaying correctly when no groupBy is configured

    \n
      \n
    • All tasks were appearing in a single "None" column
    • \n
    • Columns now appear in the order defined in TaskNotes settings (not alphabetical)
    • \n
    • Detects invalid Bases grouping and falls back to status-based grouping
    • \n
    • Tasks are properly distributed across status columns
    • \n
    • Thanks to @mweichert for the fix and @PacoTaco2, @abuhammer for reporting
    • \n
    \n
  • \n
\n","text":"Added# (#937), (#956) Added optional setting to hide identification tags in task cards New \"Hide identification tags in task cards\" setting (only visible when using tag-based identification) Hides exact matches (e.g., #task) and hierarchical children (e.g., #task/project, #task/work/urgent) Reduces visual clutter while keeping tags in frontmatter for organizational purposes Backward compatible - disabled by default Thanks to @renatomen for implementing this feature and @edakimling for reporting (#911) Added custom field suggestion filtering New autosuggestFilter field to UserMappedField interface allows filtering suggestions by current filter context Added collapsible filter section in settings with visual indicator Comprehensive test coverage for custom field filtering feature Thanks to @renatomen for this enhancement Fixed# (#903) Fixed Edit Task modal not adding completedDate when marking tasks as done Edit Task modal now correctly adds completedDate when changing status to completed Fixed Edit Task modal adding empty contexts and projects arrays to frontmatter Behavior now consistent with other completion methods (Agenda view, widget context menu, quick actions) Thanks to @nightroman for reporting (#969), (#967) Fixed Bases Kanban layout not displaying correctly when no groupBy is configured All tasks were appearing in a single \"None\" column Columns now appear in the order defined in TaskNotes settings (not alphabetical) Detects invalid Bases grouping and falls back to status-based grouping Tasks are properly distributed across status columns Thanks to @mweichert for the fix and @PacoTaco2, @abuhammer for reporting"},{"route":"/obsidian/releases/3.25.6/","title":"Tasknotes 3.25.6","description":"(#1013) Fixed inability to subscribe to Apple iCloud calendars","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.25.6.md","namespace":"obsidian","relativePath":"releases/3.25.6.md","raw":"# Tasknotes 3.25.6\n\n## Fixed\n\n- (#1013) Fixed inability to subscribe to Apple iCloud calendars\n - Calendar URLs copied from Apple Calendar (starting with webcal://) can now be pasted directly\n - Previously required manually changing the URL format before it would be accepted\n - Works with both standard and secure calendar URLs (webcal:// and webcals://)\n - Thanks to @nickbirch51 for reporting\n\n- (#1022) Fixed tasks randomly disappearing from views and not being recognized\n - Tasks would appear initially but disappear after a few seconds, especially during long sessions\n - Restarting Obsidian or using \"Refresh Cache\" would only temporarily fix the issue\n - Thanks to @seepage87 for reporting and @alejandrospoz for help debugging\n\n- (#968) Fixed timeEntries being duplicated when mapped to custom property name\n - When timeEntries was configured to use a custom property name in Metadata settings (e.g., time_entries), saving tasks would create duplicate entries in both the custom property and the default timeEntries property\n - FieldMapper now correctly uses only the configured property name for time tracking data\n - Thanks to @minchinweb for reporting this issue \n\n- (#953) Fixed non-task notes incorrectly appearing as subtasks in views\n - Notes with Parent or project properties but no task tag/property no longer show up as tasks\n - Views now update correctly when task tags are removed from files\n - Improved performance for large vaults by optimizing cache invalidation\n - Thanks to @renatomen for reporting and submitting PR #955\n","aliases":["/releases/3.25.6/","/releases/3.25.6/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Fixed#

\n
    \n
  • (#1013) Fixed inability to subscribe to Apple iCloud calendars

    \n
      \n
    • Calendar URLs copied from Apple Calendar (starting with webcal://) can now be pasted directly
    • \n
    • Previously required manually changing the URL format before it would be accepted
    • \n
    • Works with both standard and secure calendar URLs (webcal:// and webcals://)
    • \n
    • Thanks to @nickbirch51 for reporting
    • \n
    \n
  • \n
  • (#1022) Fixed tasks randomly disappearing from views and not being recognized

    \n
      \n
    • Tasks would appear initially but disappear after a few seconds, especially during long sessions
    • \n
    • Restarting Obsidian or using "Refresh Cache" would only temporarily fix the issue
    • \n
    • Thanks to @seepage87 for reporting and @alejandrospoz for help debugging
    • \n
    \n
  • \n
  • (#968) Fixed timeEntries being duplicated when mapped to custom property name

    \n
      \n
    • When timeEntries was configured to use a custom property name in Metadata settings (e.g., time_entries), saving tasks would create duplicate entries in both the custom property and the default timeEntries property
    • \n
    • FieldMapper now correctly uses only the configured property name for time tracking data
    • \n
    • Thanks to @minchinweb for reporting this issue
    • \n
    \n
  • \n
  • (#953) Fixed non-task notes incorrectly appearing as subtasks in views

    \n
      \n
    • Notes with Parent or project properties but no task tag/property no longer show up as tasks
    • \n
    • Views now update correctly when task tags are removed from files
    • \n
    • Improved performance for large vaults by optimizing cache invalidation
    • \n
    • Thanks to @renatomen for reporting and submitting PR #955
    • \n
    \n
  • \n
\n","text":"Fixed# (#1013) Fixed inability to subscribe to Apple iCloud calendars Calendar URLs copied from Apple Calendar (starting with webcal://) can now be pasted directly Previously required manually changing the URL format before it would be accepted Works with both standard and secure calendar URLs (webcal:// and webcals://) Thanks to @nickbirch51 for reporting (#1022) Fixed tasks randomly disappearing from views and not being recognized Tasks would appear initially but disappear after a few seconds, especially during long sessions Restarting Obsidian or using \"Refresh Cache\" would only temporarily fix the issue Thanks to @seepage87 for reporting and @alejandrospoz for help debugging (#968) Fixed timeEntries being duplicated when mapped to custom property name When timeEntries was configured to use a custom property name in Metadata settings (e.g., time_entries), saving tasks would create duplicate entries in both the custom property and the default timeEntries property FieldMapper now correctly uses only the configured property name for time tracking data Thanks to @minchinweb for reporting this issue (#953) Fixed non-task notes incorrectly appearing as subtasks in views Notes with Parent or project properties but no task tag/property no longer show up as tasks Views now update correctly when task tags are removed from files Improved performance for large vaults by optimizing cache invalidation Thanks to @renatomen for reporting and submitting PR #955"},{"route":"/obsidian/releases/3.3.0/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.1.1...3.3.0","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.3.0.md","namespace":"obsidian","relativePath":"releases/3.3.0.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.1.1...3.3.0\n","aliases":["/releases/3.3.0/","/releases/3.3.0/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.1.1...3.3.0

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.1.1...3.3.0"},{"route":"/obsidian/releases/3.4.0/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.3.0...3.4.0","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.4.0.md","namespace":"obsidian","relativePath":"releases/3.4.0.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.3.0...3.4.0\n","aliases":["/releases/3.4.0/","/releases/3.4.0/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.3.0...3.4.0

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.3.0...3.4.0"},{"route":"/obsidian/releases/3.4.1/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.0...3.4.1","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.4.1.md","namespace":"obsidian","relativePath":"releases/3.4.1.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.4.0...3.4.1\n","aliases":["/releases/3.4.1/","/releases/3.4.1/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.0...3.4.1

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.0...3.4.1"},{"route":"/obsidian/releases/3.4.2/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.1...3.4.2","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.4.2.md","namespace":"obsidian","relativePath":"releases/3.4.2.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.4.1...3.4.2\n","aliases":["/releases/3.4.2/","/releases/3.4.2/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.1...3.4.2

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.1...3.4.2"},{"route":"/obsidian/releases/3.5.1/","title":"Untitled","description":"This release focusses on significant performance improvements by migrating away from the baroque plugin caching system to Obsidian's native cache.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.5.1.md","namespace":"obsidian","relativePath":"releases/3.5.1.md","raw":"This release focusses on significant performance improvements by migrating away from the baroque plugin caching system to Obsidian's native cache.\r\n\r\n**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.4.0...3.5.1\n","aliases":["/releases/3.5.1/","/releases/3.5.1/"],"toc":[],"html":"

This release focusses on significant performance improvements by migrating away from the baroque plugin caching system to Obsidian's native cache.

\n

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.0...3.5.1

\n","text":"This release focusses on significant performance improvements by migrating away from the baroque plugin caching system to Obsidian's native cache. Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.0...3.5.1"},{"route":"/obsidian/releases/3.6.0/","title":"Untitled","description":"Fix task tag check. Add optional timeblocking.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.6.0.md","namespace":"obsidian","relativePath":"releases/3.6.0.md","raw":"Fix task tag check. \r\nAdd optional timeblocking. \n","aliases":["/releases/3.6.0/","/releases/3.6.0/"],"toc":[],"html":"

Fix task tag check. \nAdd optional timeblocking.

\n","text":"Fix task tag check. Add optional timeblocking."},{"route":"/obsidian/releases/3.7.0/","title":"TaskNotes v3.7.0 Release Notes","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.6.0...3.7.0","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.7.0.md","namespace":"obsidian","relativePath":"releases/3.7.0.md","raw":"# TaskNotes v3.7.0 Release Notes\r\n\r\n### Reading Mode Task Previews (thank you @amithkk)\r\n\r\n- Task link previews now work in Reading Mode in addition to Live Preview \r\n- Consistent interactive experience across all Obsidian view modes\r\n- Same functionality: click to edit, right-click for context menu, hover for file preview\r\n- New ReadingModeTaskLinkProcessor.ts with dedicated CSS styling\r\n\r\n### Task Action Palette\r\n\r\n- New quick-action command palette for rapid task management\r\n- Access via command palette: \"TaskNotes: Open Task Action Palette\"\r\n- Change status/priority with fuzzy search, set dates, start/stop timers, archive/delete tasks\r\n- Handles recurring task instances vs. series intelligently\r\n- Fully keyboard navigable with categorized actions\r\n\r\n### Natural Language Task Input\r\n\r\n- Parse natural language when creating tasks: \"Buy groceries tomorrow 3pm high priority @home #errands\"\r\n- Powered by chrono-node for robust date/time parsing\r\n- Extracts dates, priorities, status, contexts (@), tags (#), recurrence, and time estimates\r\n- Multi-line support: first line parsed, additional lines become task details\r\n- Toggle in Settings → Basic Defaults\r\n\r\n## UI/UX Improvements\r\n\r\n### Enhanced Task Creation Modal\r\n\r\n- Smart input mode with simplified interface when natural language is enabled\r\n- Progressive disclosure to detailed form when needed\r\n- Better conversion flow with pre-populated forms\r\n- Live filename preview as you type\r\n\r\n### Settings & Modal Improvements\r\n\r\n- Moved Natural Language Input to Basic Defaults section\r\n- Updated task link overlay description to mention both view modes\r\n- Reusable confirmation modal for consistent dialogs\r\n- Better error handling and accessibility improvements\r\n\r\n## Bug Fixes\r\n\r\n### Fixed: Inline Tasks Not Respecting Default Status & Priority (Issue #58)\r\n\r\n- Problem: Inline task conversion applied \"none\" instead of configured defaults\r\n- Solution: Changed useDefaultsOnInstantConvert default from false to true\r\n\r\n### Timer Function Standardization\r\n\r\n- Fixed browser compatibility by replacing Node.js timer types with browser-native timers\r\n- Resolved timing issues across different environments\r\n\r\n### Enhanced Task Link Overlays\r\n\r\n- Better path resolution with security enhancements\r\n- Graceful fallbacks for invalid or missing task files\r\n- Improved handling of rapid view changes\r\n\r\n## Technical Improvements\r\n\r\n### Enhanced Date Support\r\n\r\n- Full due date and scheduled date support in task creation and filename generation\r\n- New filename template variables: {dueDate} and {scheduledDate} (YYYY-MM-DD format)\r\n- Support for ISO dates, relative dates, named dates, and natural language\r\n\r\n### Performance & Code Quality\r\n\r\n- Improved event handling with better refresh logic\r\n- Layout change listeners for immediate overlay updates\r\n- Enhanced error handling with user-friendly messages\r\n- Better TypeScript types and modular design\r\n\r\n## New Files & Dependencies\r\n\r\n### New Files\r\n\r\n- src/editor/ReadingModeTaskLinkProcessor.ts\r\n- src/modals/TaskActionPaletteModal.ts\r\n- src/services/NaturalLanguageParser.ts\r\n- src/modals/ConfirmationModal.ts\r\n- styles/task-action-palette-modal.css\r\n\r\n### New Dependency\r\n\r\n- chrono-node: Natural language date parsing library\r\n\r\n## What's Changed\r\n* Feat/task previews in reading mode by @amithkk in https://github.com/callumalpass/tasknotes/pull/57\r\n\r\n## New Contributors\r\n* @amithkk made their first contribution in https://github.com/callumalpass/tasknotes/pull/57\r\n\r\n**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.6.0...3.7.0\n","aliases":["/releases/3.7.0/","/releases/3.7.0/"],"toc":[{"level":3,"id":"reading-mode-task-previews-thank-you-amithkk","text":"Reading Mode Task Previews (thank you @amithkk)"},{"level":3,"id":"task-action-palette","text":"Task Action Palette"},{"level":3,"id":"natural-language-task-input","text":"Natural Language Task Input"},{"level":2,"id":"uiux-improvements","text":"UI/UX Improvements"},{"level":3,"id":"enhanced-task-creation-modal","text":"Enhanced Task Creation Modal"},{"level":3,"id":"settings-modal-improvements","text":"Settings & Modal Improvements"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"fixed-inline-tasks-not-respecting-default-status-priority-issue-58","text":"Fixed: Inline Tasks Not Respecting Default Status & Priority (Issue #58)"},{"level":3,"id":"timer-function-standardization","text":"Timer Function Standardization"},{"level":3,"id":"enhanced-task-link-overlays","text":"Enhanced Task Link Overlays"},{"level":2,"id":"technical-improvements","text":"Technical Improvements"},{"level":3,"id":"enhanced-date-support","text":"Enhanced Date Support"},{"level":3,"id":"performance-code-quality","text":"Performance & Code Quality"},{"level":2,"id":"new-files-dependencies","text":"New Files & Dependencies"},{"level":3,"id":"new-files","text":"New Files"},{"level":3,"id":"new-dependency","text":"New Dependency"},{"level":2,"id":"what39s-changed","text":"What's Changed"},{"level":2,"id":"new-contributors","text":"New Contributors"}],"html":"

Reading Mode Task Previews (thank you @amithkk)#

\n
    \n
  • Task link previews now work in Reading Mode in addition to Live Preview
  • \n
  • Consistent interactive experience across all Obsidian view modes
  • \n
  • Same functionality: click to edit, right-click for context menu, hover for file preview
  • \n
  • New ReadingModeTaskLinkProcessor.ts with dedicated CSS styling
  • \n
\n

Task Action Palette#

\n
    \n
  • New quick-action command palette for rapid task management
  • \n
  • Access via command palette: "TaskNotes: Open Task Action Palette"
  • \n
  • Change status/priority with fuzzy search, set dates, start/stop timers, archive/delete tasks
  • \n
  • Handles recurring task instances vs. series intelligently
  • \n
  • Fully keyboard navigable with categorized actions
  • \n
\n

Natural Language Task Input#

\n
    \n
  • Parse natural language when creating tasks: "Buy groceries tomorrow 3pm high priority @home #errands"
  • \n
  • Powered by chrono-node for robust date/time parsing
  • \n
  • Extracts dates, priorities, status, contexts (@), tags (#), recurrence, and time estimates
  • \n
  • Multi-line support: first line parsed, additional lines become task details
  • \n
  • Toggle in Settings → Basic Defaults
  • \n
\n

UI/UX Improvements#

\n

Enhanced Task Creation Modal#

\n
    \n
  • Smart input mode with simplified interface when natural language is enabled
  • \n
  • Progressive disclosure to detailed form when needed
  • \n
  • Better conversion flow with pre-populated forms
  • \n
  • Live filename preview as you type
  • \n
\n

Settings & Modal Improvements#

\n
    \n
  • Moved Natural Language Input to Basic Defaults section
  • \n
  • Updated task link overlay description to mention both view modes
  • \n
  • Reusable confirmation modal for consistent dialogs
  • \n
  • Better error handling and accessibility improvements
  • \n
\n

Bug Fixes#

\n

Fixed: Inline Tasks Not Respecting Default Status & Priority (Issue #58)#

\n
    \n
  • Problem: Inline task conversion applied "none" instead of configured defaults
  • \n
  • Solution: Changed useDefaultsOnInstantConvert default from false to true
  • \n
\n

Timer Function Standardization#

\n
    \n
  • Fixed browser compatibility by replacing Node.js timer types with browser-native timers
  • \n
  • Resolved timing issues across different environments
  • \n
\n\n
    \n
  • Better path resolution with security enhancements
  • \n
  • Graceful fallbacks for invalid or missing task files
  • \n
  • Improved handling of rapid view changes
  • \n
\n

Technical Improvements#

\n

Enhanced Date Support#

\n
    \n
  • Full due date and scheduled date support in task creation and filename generation
  • \n
  • New filename template variables: {dueDate} and {scheduledDate} (YYYY-MM-DD format)
  • \n
  • Support for ISO dates, relative dates, named dates, and natural language
  • \n
\n

Performance & Code Quality#

\n
    \n
  • Improved event handling with better refresh logic
  • \n
  • Layout change listeners for immediate overlay updates
  • \n
  • Enhanced error handling with user-friendly messages
  • \n
  • Better TypeScript types and modular design
  • \n
\n

New Files & Dependencies#

\n

New Files#

\n
    \n
  • src/editor/ReadingModeTaskLinkProcessor.ts
  • \n
  • src/modals/TaskActionPaletteModal.ts
  • \n
  • src/services/NaturalLanguageParser.ts
  • \n
  • src/modals/ConfirmationModal.ts
  • \n
  • styles/task-action-palette-modal.css
  • \n
\n

New Dependency#

\n
    \n
  • chrono-node: Natural language date parsing library
  • \n
\n

What's Changed#

\n\n

New Contributors#

\n\n

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.6.0...3.7.0

\n","text":"Reading Mode Task Previews (thank you @amithkk)# Task link previews now work in Reading Mode in addition to Live Preview Consistent interactive experience across all Obsidian view modes Same functionality: click to edit, right-click for context menu, hover for file preview New ReadingModeTaskLinkProcessor.ts with dedicated CSS styling Task Action Palette# New quick-action command palette for rapid task management Access via command palette: \"TaskNotes: Open Task Action Palette\" Change status/priority with fuzzy search, set dates, start/stop timers, archive/delete tasks Handles recurring task instances vs. series intelligently Fully keyboard navigable with categorized actions Natural Language Task Input# Parse natural language when creating tasks: \"Buy groceries tomorrow 3pm high priority @home #errands\" Powered by chrono-node for robust date/time parsing Extracts dates, priorities, status, contexts (@), tags (#), recurrence, and time estimates Multi-line support: first line parsed, additional lines become task details Toggle in Settings → Basic Defaults UI/UX Improvements# Enhanced Task Creation Modal# Smart input mode with simplified interface when natural language is enabled Progressive disclosure to detailed form when needed Better conversion flow with pre-populated forms Live filename preview as you type Settings & Modal Improvements# Moved Natural Language Input to Basic Defaults section Updated task link overlay description to mention both view modes Reusable confirmation modal for consistent dialogs Better error handling and accessibility improvements Bug Fixes# Fixed: Inline Tasks Not Respecting Default Status & Priority (Issue #58)# Problem: Inline task conversion applied \"none\" instead of configured defaults Solution: Changed useDefaultsOnInstantConvert default from false to true Timer Function Standardization# Fixed browser compatibility by replacing Node.js timer types with browser-native timers Resolved timing issues across different environments Enhanced Task Link Overlays# Better path resolution with security enhancements Graceful fallbacks for invalid or missing task files Improved handling of rapid view changes Technical Improvements# Enhanced Date Support# Full due date and scheduled date support in task creation and filename generation New filename template variables: {dueDate} and {scheduledDate} (YYYY-MM-DD format) Support for ISO dates, relative dates, named dates, and natural language Performance & Code Quality# Improved event handling with better refresh logic Layout change listeners for immediate overlay updates Enhanced error handling with user-friendly messages Better TypeScript types and modular design New Files & Dependencies# New Files# src/editor/ReadingModeTaskLinkProcessor.ts src/modals/TaskActionPaletteModal.ts src/services/NaturalLanguageParser.ts src/modals/ConfirmationModal.ts styles/task-action-palette-modal.css New Dependency# chrono-node: Natural language date parsing library What's Changed# Feat/task previews in reading mode by @amithkk in https://github.com/callumalpass/tasknotes/pull/57 New Contributors# @amithkk made their first contribution in https://github.com/callumalpass/tasknotes/pull/57 Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.6.0...3.7.0"},{"route":"/obsidian/releases/3.7.1/","title":"Version 3.7.1","description":"Files with Major Changes:","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.7.1.md","namespace":"obsidian","relativePath":"releases/3.7.1.md","raw":"# Version 3.7.1\r\n\r\n## Major UI/UX Enhancements\r\n\r\n### Interactive Inline Task Previews\r\n\r\n- Clickable Status Dots: Status indicators in inline task previews are now interactive - click to cycle through task statuses directly from the preview\r\n- Clickable Date Fields: Due and scheduled dates are now clickable and open dedicated modals for quick editing\r\n- Enhanced Visual Design:\r\n - Redesigned with minimal styling\r\n - Improved spacing and vertical alignment between status dots, priority indicators, and task titles\r\n - Better hover effects with brightness and subtle animations\r\n - Status dots now use bordered design for better visibility\r\n\r\n### Modernized Task Card Design\r\n\r\n- Interactive Status Cycling: Click status dots on task cards to quickly change task status\r\n- Improved Mobile Support: Better touch targets and responsive behavior\r\n- Enhanced Animations: Smooth hover effects, scaling, and transition animations\r\n- Cleaner Layout: Streamlined design with better visual hierarchy\r\n\r\n### Enhanced Natural Language Processing\r\n\r\n#### Advanced Date Parsing\r\n\r\n- Explicit Trigger Recognition: Now recognizes specific phrases:\r\n - Due dates: \"due on\", \"deadline\", \"must be done by\", \"needs to be completed\"\r\n - Scheduled dates: \"scheduled for\", \"start on\", \"work on\", \"planned for\"\r\n- Configurable Defaults: New setting to choose whether ambiguous dates default to \"due\" or \"scheduled\"\r\n- Enhanced Recurrence Patterns:\r\n - \"every [weekday]\" patterns (every monday, every friday)\r\n - Plural day patterns (mondays, tuesdays, etc.)\r\n - \"Every other\" interval patterns (every other week, every 2 days)\r\n - Multiple days (\"every tuesday and thursday\")\r\n\r\n#### Improved Date/Time Handling\r\n\r\n- Better Time Component Support: Enhanced parsing of specific times with dates\r\n- Robust Validation: Improved handling of edge cases and malformed input\r\n- Smart Cleanup: Automatic removal of duplicate tags and contexts\r\n\r\n## Performance & Developer Experience\r\n\r\n### Instant Task Conversion Improvements\r\n\r\n- Real-time Updates: Task link overlays refresh immediately after task conversion\r\n- Smart Caching: Improved metadata cache management for newly created tasks\r\n- Better Error Handling: Enhanced validation with user-friendly error messages\r\n- Multi-line Support: Enhanced conversion of tasks with details from multiple selected lines\r\n\r\n### Technical Improvements\r\n\r\n- Improved Event Handling: Fixed n.dispatch is not a function error with proper validation\r\n- BEM CSS Methodology: Migrated to Block Element Modifier naming for better CSS organization\r\n- Performance Optimizations: Reduced unnecessary re-renders and improved widget caching\r\n- Enhanced State Management: Better synchronization between UI updates and task data\r\n\r\n## Modal & Interface Enhancements\r\n\r\n### Enhanced Date/Time Modals\r\n\r\n- Better Keyboard Navigation: Enter to save, Escape to cancel\r\n- Separate Time Inputs: Dedicated date and time fields for precision\r\n- Quick Date Buttons: Common date selections for faster input\r\n- Improved Accessibility: Proper ARIA labels and screen reader support\r\n\r\n### Better User Experience\r\n\r\n- One-Click Status Changes: Direct status cycling from any task preview\r\n- Direct Date Editing: Click any date to immediately edit it\r\n- Enhanced Visual Feedback: Better hover states, transitions, and loading animations\r\n- Accessibility Improvements: Enhanced keyboard navigation and screen reader support\r\n\r\n### Bug Fixes & Stability\r\n\r\n- Fixed: Inline task widget dispatch errors that caused console warnings\r\n- Fixed: Vertical alignment issues with different-sized status and priority indicators\r\n- Fixed: Layout conflicts between flexbox and inline display properties\r\n- Fixed: Spacing issues in inline task previews causing cramped appearance\r\n- Fixed: Missing task link overlay refreshes after instant task conversion\r\n\r\n## Configuration & Settings\r\n\r\n### New User Settings\r\n\r\n- Natural Language Default: Configure whether ambiguous dates default to \"due\" or \"scheduled\"\r\n- Enhanced Task Creation: Improved default value application for instant task conversion\r\n\r\n## Technical Details\r\n\r\nFiles with Major Changes:\r\n- Enhanced inline task previews (TaskLinkWidget.ts, TaskLinkOverlay.ts)\r\n- Modernized task card design (TaskCard.ts)\r\n- Advanced natural language processing (NaturalLanguageParser.ts)\r\n- Improved modal interfaces (DueDateModal.ts, ScheduledDateModal.ts)\r\n- Comprehensive CSS overhaul with BEM methodology\r\n","aliases":["/releases/3.7.1/","/releases/3.7.1/"],"toc":[{"level":2,"id":"major-uiux-enhancements","text":"Major UI/UX Enhancements"},{"level":3,"id":"interactive-inline-task-previews","text":"Interactive Inline Task Previews"},{"level":3,"id":"modernized-task-card-design","text":"Modernized Task Card Design"},{"level":3,"id":"enhanced-natural-language-processing","text":"Enhanced Natural Language Processing"},{"level":2,"id":"performance-developer-experience","text":"Performance & Developer Experience"},{"level":3,"id":"instant-task-conversion-improvements","text":"Instant Task Conversion Improvements"},{"level":3,"id":"technical-improvements","text":"Technical Improvements"},{"level":2,"id":"modal-interface-enhancements","text":"Modal & Interface Enhancements"},{"level":3,"id":"enhanced-datetime-modals","text":"Enhanced Date/Time Modals"},{"level":3,"id":"better-user-experience","text":"Better User Experience"},{"level":3,"id":"bug-fixes-stability","text":"Bug Fixes & Stability"},{"level":2,"id":"configuration-settings","text":"Configuration & Settings"},{"level":3,"id":"new-user-settings","text":"New User Settings"},{"level":2,"id":"technical-details","text":"Technical Details"}],"html":"

Major UI/UX Enhancements#

\n

Interactive Inline Task Previews#

\n
    \n
  • Clickable Status Dots: Status indicators in inline task previews are now interactive - click to cycle through task statuses directly from the preview
  • \n
  • Clickable Date Fields: Due and scheduled dates are now clickable and open dedicated modals for quick editing
  • \n
  • Enhanced Visual Design:
      \n
    • Redesigned with minimal styling
    • \n
    • Improved spacing and vertical alignment between status dots, priority indicators, and task titles
    • \n
    • Better hover effects with brightness and subtle animations
    • \n
    • Status dots now use bordered design for better visibility
    • \n
    \n
  • \n
\n

Modernized Task Card Design#

\n
    \n
  • Interactive Status Cycling: Click status dots on task cards to quickly change task status
  • \n
  • Improved Mobile Support: Better touch targets and responsive behavior
  • \n
  • Enhanced Animations: Smooth hover effects, scaling, and transition animations
  • \n
  • Cleaner Layout: Streamlined design with better visual hierarchy
  • \n
\n

Enhanced Natural Language Processing#

\n

Advanced Date Parsing#

\n
    \n
  • Explicit Trigger Recognition: Now recognizes specific phrases:
      \n
    • Due dates: "due on", "deadline", "must be done by", "needs to be completed"
    • \n
    • Scheduled dates: "scheduled for", "start on", "work on", "planned for"
    • \n
    \n
  • \n
  • Configurable Defaults: New setting to choose whether ambiguous dates default to "due" or "scheduled"
  • \n
  • Enhanced Recurrence Patterns:
      \n
    • "every [weekday]" patterns (every monday, every friday)
    • \n
    • Plural day patterns (mondays, tuesdays, etc.)
    • \n
    • "Every other" interval patterns (every other week, every 2 days)
    • \n
    • Multiple days ("every tuesday and thursday")
    • \n
    \n
  • \n
\n

Improved Date/Time Handling#

\n
    \n
  • Better Time Component Support: Enhanced parsing of specific times with dates
  • \n
  • Robust Validation: Improved handling of edge cases and malformed input
  • \n
  • Smart Cleanup: Automatic removal of duplicate tags and contexts
  • \n
\n

Performance & Developer Experience#

\n

Instant Task Conversion Improvements#

\n
    \n
  • Real-time Updates: Task link overlays refresh immediately after task conversion
  • \n
  • Smart Caching: Improved metadata cache management for newly created tasks
  • \n
  • Better Error Handling: Enhanced validation with user-friendly error messages
  • \n
  • Multi-line Support: Enhanced conversion of tasks with details from multiple selected lines
  • \n
\n

Technical Improvements#

\n
    \n
  • Improved Event Handling: Fixed n.dispatch is not a function error with proper validation
  • \n
  • BEM CSS Methodology: Migrated to Block Element Modifier naming for better CSS organization
  • \n
  • Performance Optimizations: Reduced unnecessary re-renders and improved widget caching
  • \n
  • Enhanced State Management: Better synchronization between UI updates and task data
  • \n
\n

Modal & Interface Enhancements#

\n

Enhanced Date/Time Modals#

\n
    \n
  • Better Keyboard Navigation: Enter to save, Escape to cancel
  • \n
  • Separate Time Inputs: Dedicated date and time fields for precision
  • \n
  • Quick Date Buttons: Common date selections for faster input
  • \n
  • Improved Accessibility: Proper ARIA labels and screen reader support
  • \n
\n

Better User Experience#

\n
    \n
  • One-Click Status Changes: Direct status cycling from any task preview
  • \n
  • Direct Date Editing: Click any date to immediately edit it
  • \n
  • Enhanced Visual Feedback: Better hover states, transitions, and loading animations
  • \n
  • Accessibility Improvements: Enhanced keyboard navigation and screen reader support
  • \n
\n

Bug Fixes & Stability#

\n
    \n
  • Fixed: Inline task widget dispatch errors that caused console warnings
  • \n
  • Fixed: Vertical alignment issues with different-sized status and priority indicators
  • \n
  • Fixed: Layout conflicts between flexbox and inline display properties
  • \n
  • Fixed: Spacing issues in inline task previews causing cramped appearance
  • \n
  • Fixed: Missing task link overlay refreshes after instant task conversion
  • \n
\n

Configuration & Settings#

\n

New User Settings#

\n
    \n
  • Natural Language Default: Configure whether ambiguous dates default to "due" or "scheduled"
  • \n
  • Enhanced Task Creation: Improved default value application for instant task conversion
  • \n
\n

Technical Details#

\n

Files with Major Changes:

\n
    \n
  • Enhanced inline task previews (TaskLinkWidget.ts, TaskLinkOverlay.ts)
  • \n
  • Modernized task card design (TaskCard.ts)
  • \n
  • Advanced natural language processing (NaturalLanguageParser.ts)
  • \n
  • Improved modal interfaces (DueDateModal.ts, ScheduledDateModal.ts)
  • \n
  • Comprehensive CSS overhaul with BEM methodology
  • \n
\n","text":"Major UI/UX Enhancements# Interactive Inline Task Previews# Clickable Status Dots: Status indicators in inline task previews are now interactive - click to cycle through task statuses directly from the preview Clickable Date Fields: Due and scheduled dates are now clickable and open dedicated modals for quick editing Enhanced Visual Design: Redesigned with minimal styling Improved spacing and vertical alignment between status dots, priority indicators, and task titles Better hover effects with brightness and subtle animations Status dots now use bordered design for better visibility Modernized Task Card Design# Interactive Status Cycling: Click status dots on task cards to quickly change task status Improved Mobile Support: Better touch targets and responsive behavior Enhanced Animations: Smooth hover effects, scaling, and transition animations Cleaner Layout: Streamlined design with better visual hierarchy Enhanced Natural Language Processing# Advanced Date Parsing# Explicit Trigger Recognition: Now recognizes specific phrases: Due dates: \"due on\", \"deadline\", \"must be done by\", \"needs to be completed\" Scheduled dates: \"scheduled for\", \"start on\", \"work on\", \"planned for\" Configurable Defaults: New setting to choose whether ambiguous dates default to \"due\" or \"scheduled\" Enhanced Recurrence Patterns: \"every [weekday]\" patterns (every monday, every friday) Plural day patterns (mondays, tuesdays, etc.) \"Every other\" interval patterns (every other week, every 2 days) Multiple days (\"every tuesday and thursday\") Improved Date/Time Handling# Better Time Component Support: Enhanced parsing of specific times with dates Robust Validation: Improved handling of edge cases and malformed input Smart Cleanup: Automatic removal of duplicate tags and contexts Performance & Developer Experience# Instant Task Conversion Improvements# Real-time Updates: Task link overlays refresh immediately after task conversion Smart Caching: Improved metadata cache management for newly created tasks Better Error Handling: Enhanced validation with user-friendly error messages Multi-line Support: Enhanced conversion of tasks with details from multiple selected lines Technical Improvements# Improved Event Handling: Fixed n.dispatch is not a function error with proper validation BEM CSS Methodology: Migrated to Block Element Modifier naming for better CSS organization Performance Optimizations: Reduced unnecessary re-renders and improved widget caching Enhanced State Management: Better synchronization between UI updates and task data Modal & Interface Enhancements# Enhanced Date/Time Modals# Better Keyboard Navigation: Enter to save, Escape to cancel Separate Time Inputs: Dedicated date and time fields for precision Quick Date Buttons: Common date selections for faster input Improved Accessibility: Proper ARIA labels and screen reader support Better User Experience# One-Click Status Changes: Direct status cycling from any task preview Direct Date Editing: Click any date to immediately edit it Enhanced Visual Feedback: Better hover states, transitions, and loading animations Accessibility Improvements: Enhanced keyboard navigation and screen reader support Bug Fixes & Stability# Fixed: Inline task widget dispatch errors that caused console warnings Fixed: Vertical alignment issues with different-sized status and priority indicators Fixed: Layout conflicts between flexbox and inline display properties Fixed: Spacing issues in inline task previews causing cramped appearance Fixed: Missing task link overlay refreshes after instant task conversion Configuration & Settings# New User Settings# Natural Language Default: Configure whether ambiguous dates default to \"due\" or \"scheduled\" Enhanced Task Creation: Improved default value application for instant task conversion Technical Details# Files with Major Changes: Enhanced inline task previews (TaskLinkWidget.ts, TaskLinkOverlay.ts) Modernized task card design (TaskCard.ts) Advanced natural language processing (NaturalLanguageParser.ts) Improved modal interfaces (DueDateModal.ts, ScheduledDateModal.ts) Comprehensive CSS overhaul with BEM methodology"},{"route":"/obsidian/releases/3.8.1/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.7.1...3.8.1","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.8.1.md","namespace":"obsidian","relativePath":"releases/3.8.1.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.7.1...3.8.1\n","aliases":["/releases/3.8.1/","/releases/3.8.1/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.7.1...3.8.1

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.7.1...3.8.1"},{"route":"/obsidian/releases/3.8.5/","title":"TaskNotes 3.8.5 Release Notes","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.1...3.8.5","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.8.5.md","namespace":"obsidian","relativePath":"releases/3.8.5.md","raw":"# TaskNotes 3.8.5 Release Notes\r\n\r\n## UI/UX Improvements\r\n\r\n### Compact Filter Bar (Special thanks to @amithkk :tada: )\r\n\r\n- Complete redesign of FilterBar component with compact, modern interface\r\n- Native Obsidian dropdowns replace basic HTML select elements for better consistency\r\n- Collapsible controls - settings are hidden by default with expandable controls via settings button\r\n- Visual indicators showing active filter count on settings button\r\n- Integrated search bar with search icon and improved visual hierarchy\r\n- Right-aligned control buttons for better layout organization\r\n\r\n### Advanced Calendar View Integration\r\n\r\n- Unified view options - calendar view toggles now integrated into FilterBar dropdown\r\n- Streamlined interface - removed separate toggle controls in favor of FilterBar integration\r\n- Consistent UX across different view types with shared filter/view controls\r\n- Dynamic option management with real-time updates and state synchronization\r\n\r\n## Enhanced Natural Language Processing\r\n\r\n### Improved Text Processing\r\n\r\n- Better whitespace handling with new cleanupWhitespace() function for consistent text normalization\r\n- Enhanced priority detection with improved pattern matching and conflict resolution\r\n- Completion status support - added isCompleted field to parsed task data\r\n- More robust text extraction across tags, contexts, priorities, and dates\r\n\r\n### Date and Time Handling Improvements\r\n\r\n- Enhanced date parsing with better timezone handling for date-only strings\r\n- Improved date normalization with direct Date constructor to avoid timezone issues\r\n- Better error handling for invalid date strings and edge cases\r\n- More robust timestamp formatting with validation checks\r\n\r\n## Testing Infrastructure\r\n\r\n### Comprehensive Test Suite\r\n\r\n- Complete testing infrastructure with Jest configuration for both unit and integration tests\r\n- Enhanced mocking system with improved Obsidian API mocks and better type safety\r\n- Integration test helpers with utilities for end-to-end workflow testing\r\n- Improved test coverage across core components and services\r\n\r\n### Mock Improvements\r\n\r\n- Updated mock factories with better type consistency and realistic data generation\r\n- Enhanced DOM simulation for better UI component testing\r\n- Improved date-fns mocking with support for \"MMM d, yyyy h:mm a\" format\r\n- Better Obsidian API compatibility in test mocks\r\n\r\n## Developer Experience\r\n\r\n### Type Safety Enhancements\r\n\r\n- Refactored type definitions for improved consistency across the codebase\r\n- Better TypeScript integration with enhanced type checking and inference\r\n- Improved callback types for better development experience\r\n\r\n## Build and Deployment\r\n\r\n- Updated GitHub Actions with artifact uploader v4 for improved CI/CD\r\n- Enhanced development workflow with better testing and build processes\r\n\r\n## User Interface Polish\r\n\r\n### Task Creation Modal\r\n\r\n- Improved placeholder text with more natural language examples\r\n- Better user guidance for natural language task input format\r\n- Clearer instruction formatting for enhanced user experience\r\n\r\n### Visual Consistency\r\n\r\n- Native Obsidian styling throughout filter and control components\r\n- Consistent iconography using Obsidian's icon system\r\n- Improved responsive design with better mobile and small screen support\r\n\r\n## Bug Fixes and Stability\r\n\r\n#### Error Handling\r\n\r\n- Improved error handling in date parsing and normalization functions\r\n- Better validation for user input and edge cases\r\n- Enhanced robustness in text processing and natural language parsing\r\n\r\n### Code Quality\r\n\r\n- Refactored components for better maintainability and performance\r\n- Simplified scheduled date logic with cleaner default handling\r\n- Enhanced code organization with better separation of concerns\r\n\r\n\r\n## What's Changed\r\n\r\n* Add compact filter bar by @amithkk in https://github.com/callumalpass/tasknotes/pull/73\r\n\r\n\r\n**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.8.1...3.8.5\n","aliases":["/releases/3.8.5/","/releases/3.8.5/"],"toc":[{"level":2,"id":"uiux-improvements","text":"UI/UX Improvements"},{"level":3,"id":"compact-filter-bar-special-thanks-to-amithkk-tada","text":"Compact Filter Bar (Special thanks to @amithkk :tada: )"},{"level":3,"id":"advanced-calendar-view-integration","text":"Advanced Calendar View Integration"},{"level":2,"id":"enhanced-natural-language-processing","text":"Enhanced Natural Language Processing"},{"level":3,"id":"improved-text-processing","text":"Improved Text Processing"},{"level":3,"id":"date-and-time-handling-improvements","text":"Date and Time Handling Improvements"},{"level":2,"id":"testing-infrastructure","text":"Testing Infrastructure"},{"level":3,"id":"comprehensive-test-suite","text":"Comprehensive Test Suite"},{"level":3,"id":"mock-improvements","text":"Mock Improvements"},{"level":2,"id":"developer-experience","text":"Developer Experience"},{"level":3,"id":"type-safety-enhancements","text":"Type Safety Enhancements"},{"level":2,"id":"build-and-deployment","text":"Build and Deployment"},{"level":2,"id":"user-interface-polish","text":"User Interface Polish"},{"level":3,"id":"task-creation-modal","text":"Task Creation Modal"},{"level":3,"id":"visual-consistency","text":"Visual Consistency"},{"level":2,"id":"bug-fixes-and-stability","text":"Bug Fixes and Stability"},{"level":3,"id":"code-quality","text":"Code Quality"},{"level":2,"id":"what39s-changed","text":"What's Changed"}],"html":"

UI/UX Improvements#

\n

Compact Filter Bar (Special thanks to @amithkk :tada: )#

\n
    \n
  • Complete redesign of FilterBar component with compact, modern interface
  • \n
  • Native Obsidian dropdowns replace basic HTML select elements for better consistency
  • \n
  • Collapsible controls - settings are hidden by default with expandable controls via settings button
  • \n
  • Visual indicators showing active filter count on settings button
  • \n
  • Integrated search bar with search icon and improved visual hierarchy
  • \n
  • Right-aligned control buttons for better layout organization
  • \n
\n

Advanced Calendar View Integration#

\n
    \n
  • Unified view options - calendar view toggles now integrated into FilterBar dropdown
  • \n
  • Streamlined interface - removed separate toggle controls in favor of FilterBar integration
  • \n
  • Consistent UX across different view types with shared filter/view controls
  • \n
  • Dynamic option management with real-time updates and state synchronization
  • \n
\n

Enhanced Natural Language Processing#

\n

Improved Text Processing#

\n
    \n
  • Better whitespace handling with new cleanupWhitespace() function for consistent text normalization
  • \n
  • Enhanced priority detection with improved pattern matching and conflict resolution
  • \n
  • Completion status support - added isCompleted field to parsed task data
  • \n
  • More robust text extraction across tags, contexts, priorities, and dates
  • \n
\n

Date and Time Handling Improvements#

\n
    \n
  • Enhanced date parsing with better timezone handling for date-only strings
  • \n
  • Improved date normalization with direct Date constructor to avoid timezone issues
  • \n
  • Better error handling for invalid date strings and edge cases
  • \n
  • More robust timestamp formatting with validation checks
  • \n
\n

Testing Infrastructure#

\n

Comprehensive Test Suite#

\n
    \n
  • Complete testing infrastructure with Jest configuration for both unit and integration tests
  • \n
  • Enhanced mocking system with improved Obsidian API mocks and better type safety
  • \n
  • Integration test helpers with utilities for end-to-end workflow testing
  • \n
  • Improved test coverage across core components and services
  • \n
\n

Mock Improvements#

\n
    \n
  • Updated mock factories with better type consistency and realistic data generation
  • \n
  • Enhanced DOM simulation for better UI component testing
  • \n
  • Improved date-fns mocking with support for "MMM d, yyyy h:mm a" format
  • \n
  • Better Obsidian API compatibility in test mocks
  • \n
\n

Developer Experience#

\n

Type Safety Enhancements#

\n
    \n
  • Refactored type definitions for improved consistency across the codebase
  • \n
  • Better TypeScript integration with enhanced type checking and inference
  • \n
  • Improved callback types for better development experience
  • \n
\n

Build and Deployment#

\n
    \n
  • Updated GitHub Actions with artifact uploader v4 for improved CI/CD
  • \n
  • Enhanced development workflow with better testing and build processes
  • \n
\n

User Interface Polish#

\n

Task Creation Modal#

\n
    \n
  • Improved placeholder text with more natural language examples
  • \n
  • Better user guidance for natural language task input format
  • \n
  • Clearer instruction formatting for enhanced user experience
  • \n
\n

Visual Consistency#

\n
    \n
  • Native Obsidian styling throughout filter and control components
  • \n
  • Consistent iconography using Obsidian's icon system
  • \n
  • Improved responsive design with better mobile and small screen support
  • \n
\n

Bug Fixes and Stability#

\n

Error Handling#

\n
    \n
  • Improved error handling in date parsing and normalization functions
  • \n
  • Better validation for user input and edge cases
  • \n
  • Enhanced robustness in text processing and natural language parsing
  • \n
\n

Code Quality#

\n
    \n
  • Refactored components for better maintainability and performance
  • \n
  • Simplified scheduled date logic with cleaner default handling
  • \n
  • Enhanced code organization with better separation of concerns
  • \n
\n

What's Changed#

\n\n

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.1...3.8.5

\n","text":"UI/UX Improvements# Compact Filter Bar (Special thanks to @amithkk :tada: )# Complete redesign of FilterBar component with compact, modern interface Native Obsidian dropdowns replace basic HTML select elements for better consistency Collapsible controls - settings are hidden by default with expandable controls via settings button Visual indicators showing active filter count on settings button Integrated search bar with search icon and improved visual hierarchy Right-aligned control buttons for better layout organization Advanced Calendar View Integration# Unified view options - calendar view toggles now integrated into FilterBar dropdown Streamlined interface - removed separate toggle controls in favor of FilterBar integration Consistent UX across different view types with shared filter/view controls Dynamic option management with real-time updates and state synchronization Enhanced Natural Language Processing# Improved Text Processing# Better whitespace handling with new cleanupWhitespace() function for consistent text normalization Enhanced priority detection with improved pattern matching and conflict resolution Completion status support - added isCompleted field to parsed task data More robust text extraction across tags, contexts, priorities, and dates Date and Time Handling Improvements# Enhanced date parsing with better timezone handling for date-only strings Improved date normalization with direct Date constructor to avoid timezone issues Better error handling for invalid date strings and edge cases More robust timestamp formatting with validation checks Testing Infrastructure# Comprehensive Test Suite# Complete testing infrastructure with Jest configuration for both unit and integration tests Enhanced mocking system with improved Obsidian API mocks and better type safety Integration test helpers with utilities for end-to-end workflow testing Improved test coverage across core components and services Mock Improvements# Updated mock factories with better type consistency and realistic data generation Enhanced DOM simulation for better UI component testing Improved date-fns mocking with support for \"MMM d, yyyy h:mm a\" format Better Obsidian API compatibility in test mocks Developer Experience# Type Safety Enhancements# Refactored type definitions for improved consistency across the codebase Better TypeScript integration with enhanced type checking and inference Improved callback types for better development experience Build and Deployment# Updated GitHub Actions with artifact uploader v4 for improved CI/CD Enhanced development workflow with better testing and build processes User Interface Polish# Task Creation Modal# Improved placeholder text with more natural language examples Better user guidance for natural language task input format Clearer instruction formatting for enhanced user experience Visual Consistency# Native Obsidian styling throughout filter and control components Consistent iconography using Obsidian's icon system Improved responsive design with better mobile and small screen support Bug Fixes and Stability# Error Handling# Improved error handling in date parsing and normalization functions Better validation for user input and edge cases Enhanced robustness in text processing and natural language parsing Code Quality# Refactored components for better maintainability and performance Simplified scheduled date logic with cleaner default handling Enhanced code organization with better separation of concerns What's Changed# Add compact filter bar by @amithkk in https://github.com/callumalpass/tasknotes/pull/73 Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.1...3.8.5"},{"route":"/obsidian/releases/3.8.6/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.5...3.8.6","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.8.6.md","namespace":"obsidian","relativePath":"releases/3.8.6.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.8.5...3.8.6\n","aliases":["/releases/3.8.6/","/releases/3.8.6/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.5...3.8.6

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.5...3.8.6"},{"route":"/obsidian/releases/3.8.7/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.6...3.8.7","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.8.7.md","namespace":"obsidian","relativePath":"releases/3.8.7.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.8.6...3.8.7\n","aliases":["/releases/3.8.7/","/releases/3.8.7/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.6...3.8.7

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.6...3.8.7"},{"route":"/obsidian/releases/3.9.0/","title":"Release Notes v3.9.0","description":"This release introduces a host of new features, bug fixes, and significant enhancements to improve your task and time management experience. Key updates include a more powerful...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.9.0.md","namespace":"obsidian","relativePath":"releases/3.9.0.md","raw":"# Release Notes v3.9.0\r\n\r\nThis release introduces a host of new features, bug fixes, and significant enhancements to improve your task and time management experience.\r\nKey updates include a more powerful and standards-compliant recurrence system, a streamlined user interface, and improved performance.\r\n\r\nA special thank you to amithkk (https://github.com/amithkk) for their contributions to this release!\r\n\r\n## New Features\r\n\r\n * RRule-Based Recurrence: Task recurrence is now powered by the iCalendar standard (RFC 5545), allowing for more complex and flexible\r\n recurring task schedules. A migration assistant will help you update your existing tasks to the new format.\r\n * Interactive Recurring Task Calendar: An interactive calendar has been added to the task edit modal, allowing you to visualize and manage\r\n individual completions of recurring tasks.\r\n * \"Show\" Dropdown in Filter Bar: A unified \"Show\" dropdown has been added to the filter bar, providing enhanced filtering options for your\r\n tasks.\r\n * Insert Tasknote Link Command: A new command has been added to insert a link to a tasknote, streamlining your workflow.\r\n * Dedicated Inline Task Folder Setting: You can now specify a dedicated folder for inline tasks, with support for {{currentNotePath}} to save\r\n tasks in the same folder as the current note.\r\n * \"Show Due Dates When Scheduled\" Setting: A new setting allows you to display due dates for scheduled tasks in the calendar view.\r\n * Compact Filter Bar: A more compact filter bar option is now available for a cleaner interface. (Thanks, amithkk!)\r\n * Multiple New Ribbon Icons: New ribbon icons have been added for extended views and actions, providing quicker access to features.\r\n * \"Highlight Today\" in Calendar View: The calendar view now highlights the current day for better visibility.\r\n * New Documentation Site: A new documentation site, built with MkDocs, is now available with improved structure and searchability.\r\n * CI/CD and Testing:\r\n * A comprehensive testing suite using Jest has been added to improve code quality and prevent regressions.\r\n * GitHub Actions workflows have been implemented for automated testing, documentation deployment, and releases.\r\n\r\n## Enhancements\r\n\r\n * UI/UX Improvements:\r\n * The task edit and creation modals have been redesigned for a more minimalist and intuitive experience.\r\n * Task-related icons have been updated for better clarity.\r\n * Context menus have been added to task cards for quick actions.\r\n * The agenda view sorting options have been fixed.\r\n * The recurring calendar widget is now centered and on a separate line from its label.\r\n * Dropdown menus now handle clicks on text labels more reliably.\r\n * Performance and Reliability:\r\n * The task link overlay has been refactored to use a ViewPlugin for better performance.\r\n * The Advanced Calendar view now handles resizing and being moved to a new window more gracefully.\r\n * The natural language processing for task creation has been improved with a fallback mechanism.\r\n * Date parsing and handling have been made more robust, especially for UTC and different date formats.\r\n * Development Workflow:\r\n * ESLint configuration has been updated with new rules and plugins for better code consistency.\r\n * The build process for CSS has been improved.\r\n * The development guidelines have been updated to reflect the new architecture.\r\n\r\n## Bug Fixes\r\n\r\n\r\n * Fixed an issue where agenda view sorting options were not working correctly.\r\n * Fixed a bug that caused a forced reflow when moving the Advanced Calendar to a new window.\r\n * Resolved a TypeError in the task modal's suggestion filtering.\r\n * Fixed an issue where the Pomodoro task selector did not show all un-archived tasks.\r\n * Corrected the filtering of daily notes in the getNotesForDate function.\r\n * Fixed a bug where the underlying markdown of a task link was not revealed on hover.\r\n * Removed misleading placeholder symbols from the settings.\r\n * Addressed various linting issues and improved code quality.\r\n\r\n**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.7.1...3.9.0\n","aliases":["/releases/3.9.0/","/releases/3.9.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":2,"id":"enhancements","text":"Enhancements"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"}],"html":"

This release introduces a host of new features, bug fixes, and significant enhancements to improve your task and time management experience.\nKey updates include a more powerful and standards-compliant recurrence system, a streamlined user interface, and improved performance.

\n

A special thank you to amithkk (https://github.com/amithkk) for their contributions to this release!

\n

New Features#

\n
    \n
  • RRule-Based Recurrence: Task recurrence is now powered by the iCalendar standard (RFC 5545), allowing for more complex and flexible\nrecurring task schedules. A migration assistant will help you update your existing tasks to the new format.
  • \n
  • Interactive Recurring Task Calendar: An interactive calendar has been added to the task edit modal, allowing you to visualize and manage\nindividual completions of recurring tasks.
  • \n
  • "Show" Dropdown in Filter Bar: A unified "Show" dropdown has been added to the filter bar, providing enhanced filtering options for your\ntasks.
  • \n
  • Insert Tasknote Link Command: A new command has been added to insert a link to a tasknote, streamlining your workflow.
  • \n
  • Dedicated Inline Task Folder Setting: You can now specify a dedicated folder for inline tasks, with support for {{currentNotePath}} to save\ntasks in the same folder as the current note.
  • \n
  • "Show Due Dates When Scheduled" Setting: A new setting allows you to display due dates for scheduled tasks in the calendar view.
  • \n
  • Compact Filter Bar: A more compact filter bar option is now available for a cleaner interface. (Thanks, amithkk!)
  • \n
  • Multiple New Ribbon Icons: New ribbon icons have been added for extended views and actions, providing quicker access to features.
  • \n
  • "Highlight Today" in Calendar View: The calendar view now highlights the current day for better visibility.
  • \n
  • New Documentation Site: A new documentation site, built with MkDocs, is now available with improved structure and searchability.
  • \n
  • CI/CD and Testing:
      \n
    • A comprehensive testing suite using Jest has been added to improve code quality and prevent regressions.
    • \n
    • GitHub Actions workflows have been implemented for automated testing, documentation deployment, and releases.
    • \n
    \n
  • \n
\n

Enhancements#

\n
    \n
  • UI/UX Improvements:
      \n
    • The task edit and creation modals have been redesigned for a more minimalist and intuitive experience.
    • \n
    • Task-related icons have been updated for better clarity.
    • \n
    • Context menus have been added to task cards for quick actions.
    • \n
    • The agenda view sorting options have been fixed.
    • \n
    • The recurring calendar widget is now centered and on a separate line from its label.
    • \n
    • Dropdown menus now handle clicks on text labels more reliably.
    • \n
    \n
  • \n
  • Performance and Reliability:
      \n
    • The task link overlay has been refactored to use a ViewPlugin for better performance.
    • \n
    • The Advanced Calendar view now handles resizing and being moved to a new window more gracefully.
    • \n
    • The natural language processing for task creation has been improved with a fallback mechanism.
    • \n
    • Date parsing and handling have been made more robust, especially for UTC and different date formats.
    • \n
    \n
  • \n
  • Development Workflow:
      \n
    • ESLint configuration has been updated with new rules and plugins for better code consistency.
    • \n
    • The build process for CSS has been improved.
    • \n
    • The development guidelines have been updated to reflect the new architecture.
    • \n
    \n
  • \n
\n

Bug Fixes#

\n
    \n
  • Fixed an issue where agenda view sorting options were not working correctly.
  • \n
  • Fixed a bug that caused a forced reflow when moving the Advanced Calendar to a new window.
  • \n
  • Resolved a TypeError in the task modal's suggestion filtering.
  • \n
  • Fixed an issue where the Pomodoro task selector did not show all un-archived tasks.
  • \n
  • Corrected the filtering of daily notes in the getNotesForDate function.
  • \n
  • Fixed a bug where the underlying markdown of a task link was not revealed on hover.
  • \n
  • Removed misleading placeholder symbols from the settings.
  • \n
  • Addressed various linting issues and improved code quality.
  • \n
\n

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.7.1...3.9.0

\n","text":"This release introduces a host of new features, bug fixes, and significant enhancements to improve your task and time management experience. Key updates include a more powerful and standards-compliant recurrence system, a streamlined user interface, and improved performance. A special thank you to amithkk (https://github.com/amithkk) for their contributions to this release! New Features# RRule-Based Recurrence: Task recurrence is now powered by the iCalendar standard (RFC 5545), allowing for more complex and flexible recurring task schedules. A migration assistant will help you update your existing tasks to the new format. Interactive Recurring Task Calendar: An interactive calendar has been added to the task edit modal, allowing you to visualize and manage individual completions of recurring tasks. \"Show\" Dropdown in Filter Bar: A unified \"Show\" dropdown has been added to the filter bar, providing enhanced filtering options for your tasks. Insert Tasknote Link Command: A new command has been added to insert a link to a tasknote, streamlining your workflow. Dedicated Inline Task Folder Setting: You can now specify a dedicated folder for inline tasks, with support for {{currentNotePath}} to save tasks in the same folder as the current note. \"Show Due Dates When Scheduled\" Setting: A new setting allows you to display due dates for scheduled tasks in the calendar view. Compact Filter Bar: A more compact filter bar option is now available for a cleaner interface. (Thanks, amithkk!) Multiple New Ribbon Icons: New ribbon icons have been added for extended views and actions, providing quicker access to features. \"Highlight Today\" in Calendar View: The calendar view now highlights the current day for better visibility. New Documentation Site: A new documentation site, built with MkDocs, is now available with improved structure and searchability. CI/CD and Testing: A comprehensive testing suite using Jest has been added to improve code quality and prevent regressions. GitHub Actions workflows have been implemented for automated testing, documentation deployment, and releases. Enhancements# UI/UX Improvements: The task edit and creation modals have been redesigned for a more minimalist and intuitive experience. Task-related icons have been updated for better clarity. Context menus have been added to task cards for quick actions. The agenda view sorting options have been fixed. The recurring calendar widget is now centered and on a separate line from its label. Dropdown menus now handle clicks on text labels more reliably. Performance and Reliability: The task link overlay has been refactored to use a ViewPlugin for better performance. The Advanced Calendar view now handles resizing and being moved to a new window more gracefully. The natural language processing for task creation has been improved with a fallback mechanism. Date parsing and handling have been made more robust, especially for UTC and different date formats. Development Workflow: ESLint configuration has been updated with new rules and plugins for better code consistency. The build process for CSS has been improved. The development guidelines have been updated to reflect the new architecture. Bug Fixes# Fixed an issue where agenda view sorting options were not working correctly. Fixed a bug that caused a forced reflow when moving the Advanced Calendar to a new window. Resolved a TypeError in the task modal's suggestion filtering. Fixed an issue where the Pomodoro task selector did not show all un-archived tasks. Corrected the filtering of daily notes in the getNotesForDate function. Fixed a bug where the underlying markdown of a task link was not revealed on hover. Removed misleading placeholder symbols from the settings. Addressed various linting issues and improved code quality. Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.7.1...3.9.0"},{"route":"/obsidian/releases/3.9.1/","title":"Release Notes: 3.9.1","description":"New Features","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.9.1.md","namespace":"obsidian","relativePath":"releases/3.9.1.md","raw":"# Release Notes: 3.9.1\r\n\r\nNew Features\r\n\r\n * GitHub Issue Templates: Added templates for bug reports and feature requests to streamline issue submission and ensure all necessary information is provided.\r\n\r\nBug Fixes\r\n\r\n * Pomodoro Timer: Fixed an issue where a long break would incorrectly start after the first work session. The timer now correctly schedules a short break as intended.\r\n * Task Creation: The \"Magic Wand\" (Natural Language Processing) now properly fills the context and tag fields in the task creation modal. Default contexts and tags are preserved if none are found in the natural language input.\r\n\r\n\r\n\r\n## What's Changed\r\n* Add github issue templates by @amithkk in https://github.com/callumalpass/tasknotes/pull/101\r\n\r\n\r\n**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.9.0...3.9.1\n","aliases":["/releases/3.9.1/","/releases/3.9.1/"],"toc":[{"level":2,"id":"what39s-changed","text":"What's Changed"}],"html":"

New Features

\n
    \n
  • GitHub Issue Templates: Added templates for bug reports and feature requests to streamline issue submission and ensure all necessary information is provided.
  • \n
\n

Bug Fixes

\n
    \n
  • Pomodoro Timer: Fixed an issue where a long break would incorrectly start after the first work session. The timer now correctly schedules a short break as intended.
  • \n
  • Task Creation: The "Magic Wand" (Natural Language Processing) now properly fills the context and tag fields in the task creation modal. Default contexts and tags are preserved if none are found in the natural language input.
  • \n
\n

What's Changed#

\n\n

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.9.0...3.9.1

\n","text":"New Features GitHub Issue Templates: Added templates for bug reports and feature requests to streamline issue submission and ensure all necessary information is provided. Bug Fixes Pomodoro Timer: Fixed an issue where a long break would incorrectly start after the first work session. The timer now correctly schedules a short break as intended. Task Creation: The \"Magic Wand\" (Natural Language Processing) now properly fills the context and tag fields in the task creation modal. Default contexts and tags are preserved if none are found in the natural language input. What's Changed# Add github issue templates by @amithkk in https://github.com/callumalpass/tasknotes/pull/101 Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.9.0...3.9.1"},{"route":"/obsidian/releases/4.0.0-beta.0/","title":"TaskNotes 4.0.0-beta.0","description":"Beta Release","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.0.0-beta.0.md","namespace":"obsidian","relativePath":"releases/4.0.0-beta.0.md","raw":"# TaskNotes 4.0.0-beta.0\n\n> **Beta Release**\n>\n> You may encounter issues. Report problems on [GitHub Issues](https://github.com/callumalpass/tasknotes/issues).\n\n## What's New in v4\n\nTaskNotes v4 migrates all views to the Bases system.\n\n### Breaking Changes\n\n- **Minimum Obsidian version: 1.10.1**\n- **View commands now use Bases files** - Ribbon icons and command palette commands (Calendar, Kanban, Tasks, Agenda, Project Subtasks) now open `.base` files created automatically in your vault\n- **Saved filter views** - Custom saved views can be converted to `.base` files using a conversion button in settings\n\n## Added\n\n### OAuth Calendar Integration\n\n- Google Calendar and Microsoft Outlook integration via OAuth 2.0\n - View and sync calendar events in Bases calendar\n - Drag events in the TaskNotes bases calendar to change the event's time online\n - Events sync every 15 minutes or upon local change\n - Requires creating your own OAuth application (approximately 15 minutes)\n - See [Calendar Setup Guide](https://tasknotes.dev/calendar-setup)\n\n### Time Entry Editor Modal\n\n- Dedicated interface for managing time entries\n - Alt-drag on Bases calendar to create time entries\n - View total tracked time per task\n - Edit and delete time entries\n - Access via Task Action Palette (Alt/Opt + Enter)\n\n### Kanban Swimlane Layout\n\n- Horizontal swimlane grouping option for Bases Kanban\n - Group tasks by status, priority, or other fields\n - Hide empty columns\n - Configurable column widths\n - Improved drag-and-drop in swimlane mode\n\n### Saved View Converter\n\n- Conversion button in settings to convert saved filter views to `.base` files\n- Original settings preserved\n- Converted views created in `TaskNotes/Views/`\n\n## Changed\n\n### View System Architecture\n\n- All views now use Bases architecture\n - Calendar, Kanban, Tasks, Agenda, and Project Subtasks are `.base` files\n - Views stored in `TaskNotes/Views/`\n - Keyboard shortcuts and ribbon icons map to `.base` files\n - Configure file paths in Settings → Integrations → Bases Integration\n\n### Calendar\n\n- Control which calendar sources display\n - Toggle Google Calendar, Microsoft Calendar, and ICS events independently\n - Configurable list view with custom day count (2-10 days)\n - Improved timezone handling for recurring events\n\n### Settings\n\n- Reorganized settings tabs\n - OAuth calendar settings in Integrations tab\n - Updated help text\n\n## Fixed\n\n- (#843) Fixed task tag being added when \"Identify tasks by\" is set to \"Property\"\n - TaskCreationModal, TaskEditModal, and InstantTaskConvertService now respect taskIdentificationMethod setting\n - Thanks to @jack2game\n- Fixed dark mode calendar borders\n- Fixed Bases Kanban column ordering - Thanks to @mweichert\n- Fixed state management bug in FilterSettingsComponent\n- Fixed timezone handling for recurring events\n\n## Migration Guide\n\n### First Launch\n\n1. Default view files are created automatically in `TaskNotes/Views/`\n2. Ribbon and command palette commands now open `.base` files\n3. Review Settings → General to customize view file paths\n\n### Converting Saved Filter Views\n\n1. Go to Settings → General\n2. Click the conversion button to convert saved filter views to `.base` files\n3. Converted views appear in a file in `TaskNotes/Views/`\n\n### Calendar Integration (Optional)\n\n1. Go to Settings → Integrations → OAuth Calendar Integration\n2. Follow the [Calendar Setup Guide](https://tasknotes.dev/calendar-setup)\n3. Create OAuth applications with Google and/or Microsoft (approximately 15 minutes)\n4. Enter Client ID and Secret in calendar cards\n5. Click Connect\n\n## Known Limitations\n\n- Quick OAuth setup is disabled - only advanced setup (your own credentials) is available\n- Saved filter views require manual conversion using the button in settings\n- Migration is one-way - downgrading to v3 may require manual reconfiguration\n- OAuth setup requires creating applications with Google/Microsoft\n\n## Feedback\n\nReport issues on [GitHub](https://github.com/callumalpass/tasknotes/issues). Include:\n\n- Obsidian version\n- Steps to reproduce\n- Console errors (Ctrl/Cmd + Shift + I)\n- Whether issue occurs after migration or fresh install\n","aliases":["/releases/4.0.0-beta.0/","/releases/4.0.0-beta.0/"],"toc":[{"level":2,"id":"what39s-new-in-v4","text":"What's New in v4"},{"level":3,"id":"breaking-changes","text":"Breaking Changes"},{"level":2,"id":"added","text":"Added"},{"level":3,"id":"oauth-calendar-integration","text":"OAuth Calendar Integration"},{"level":3,"id":"time-entry-editor-modal","text":"Time Entry Editor Modal"},{"level":3,"id":"kanban-swimlane-layout","text":"Kanban Swimlane Layout"},{"level":3,"id":"saved-view-converter","text":"Saved View Converter"},{"level":2,"id":"changed","text":"Changed"},{"level":3,"id":"view-system-architecture","text":"View System Architecture"},{"level":3,"id":"calendar","text":"Calendar"},{"level":3,"id":"settings","text":"Settings"},{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"migration-guide","text":"Migration Guide"},{"level":3,"id":"first-launch","text":"First Launch"},{"level":3,"id":"converting-saved-filter-views","text":"Converting Saved Filter Views"},{"level":3,"id":"calendar-integration-optional","text":"Calendar Integration (Optional)"},{"level":2,"id":"known-limitations","text":"Known Limitations"},{"level":2,"id":"feedback","text":"Feedback"}],"html":"
\n

Beta Release

\n

You may encounter issues. Report problems on GitHub Issues.

\n
\n

What's New in v4#

\n

TaskNotes v4 migrates all views to the Bases system.

\n

Breaking Changes#

\n
    \n
  • Minimum Obsidian version: 1.10.1
  • \n
  • View commands now use Bases files - Ribbon icons and command palette commands (Calendar, Kanban, Tasks, Agenda, Project Subtasks) now open .base files created automatically in your vault
  • \n
  • Saved filter views - Custom saved views can be converted to .base files using a conversion button in settings
  • \n
\n

Added#

\n

OAuth Calendar Integration#

\n
    \n
  • Google Calendar and Microsoft Outlook integration via OAuth 2.0
      \n
    • View and sync calendar events in Bases calendar
    • \n
    • Drag events in the TaskNotes bases calendar to change the event's time online
    • \n
    • Events sync every 15 minutes or upon local change
    • \n
    • Requires creating your own OAuth application (approximately 15 minutes)
    • \n
    • See Calendar Setup Guide
    • \n
    \n
  • \n
\n

Time Entry Editor Modal#

\n
    \n
  • Dedicated interface for managing time entries
      \n
    • Alt-drag on Bases calendar to create time entries
    • \n
    • View total tracked time per task
    • \n
    • Edit and delete time entries
    • \n
    • Access via Task Action Palette (Alt/Opt + Enter)
    • \n
    \n
  • \n
\n

Kanban Swimlane Layout#

\n
    \n
  • Horizontal swimlane grouping option for Bases Kanban
      \n
    • Group tasks by status, priority, or other fields
    • \n
    • Hide empty columns
    • \n
    • Configurable column widths
    • \n
    • Improved drag-and-drop in swimlane mode
    • \n
    \n
  • \n
\n

Saved View Converter#

\n
    \n
  • Conversion button in settings to convert saved filter views to .base files
  • \n
  • Original settings preserved
  • \n
  • Converted views created in TaskNotes/Views/
  • \n
\n

Changed#

\n

View System Architecture#

\n
    \n
  • All views now use Bases architecture
      \n
    • Calendar, Kanban, Tasks, Agenda, and Project Subtasks are .base files
    • \n
    • Views stored in TaskNotes/Views/
    • \n
    • Keyboard shortcuts and ribbon icons map to .base files
    • \n
    • Configure file paths in Settings → Integrations → Bases Integration
    • \n
    \n
  • \n
\n

Calendar#

\n
    \n
  • Control which calendar sources display
      \n
    • Toggle Google Calendar, Microsoft Calendar, and ICS events independently
    • \n
    • Configurable list view with custom day count (2-10 days)
    • \n
    • Improved timezone handling for recurring events
    • \n
    \n
  • \n
\n

Settings#

\n
    \n
  • Reorganized settings tabs
      \n
    • OAuth calendar settings in Integrations tab
    • \n
    • Updated help text
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#843) Fixed task tag being added when "Identify tasks by" is set to "Property"
      \n
    • TaskCreationModal, TaskEditModal, and InstantTaskConvertService now respect taskIdentificationMethod setting
    • \n
    • Thanks to @jack2game
    • \n
    \n
  • \n
  • Fixed dark mode calendar borders
  • \n
  • Fixed Bases Kanban column ordering - Thanks to @mweichert
  • \n
  • Fixed state management bug in FilterSettingsComponent
  • \n
  • Fixed timezone handling for recurring events
  • \n
\n

Migration Guide#

\n

First Launch#

\n
    \n
  1. Default view files are created automatically in TaskNotes/Views/
  2. \n
  3. Ribbon and command palette commands now open .base files
  4. \n
  5. Review Settings → General to customize view file paths
  6. \n
\n

Converting Saved Filter Views#

\n
    \n
  1. Go to Settings → General
  2. \n
  3. Click the conversion button to convert saved filter views to .base files
  4. \n
  5. Converted views appear in a file in TaskNotes/Views/
  6. \n
\n

Calendar Integration (Optional)#

\n
    \n
  1. Go to Settings → Integrations → OAuth Calendar Integration
  2. \n
  3. Follow the Calendar Setup Guide
  4. \n
  5. Create OAuth applications with Google and/or Microsoft (approximately 15 minutes)
  6. \n
  7. Enter Client ID and Secret in calendar cards
  8. \n
  9. Click Connect
  10. \n
\n

Known Limitations#

\n
    \n
  • Quick OAuth setup is disabled - only advanced setup (your own credentials) is available
  • \n
  • Saved filter views require manual conversion using the button in settings
  • \n
  • Migration is one-way - downgrading to v3 may require manual reconfiguration
  • \n
  • OAuth setup requires creating applications with Google/Microsoft
  • \n
\n

Feedback#

\n

Report issues on GitHub. Include:

\n
    \n
  • Obsidian version
  • \n
  • Steps to reproduce
  • \n
  • Console errors (Ctrl/Cmd + Shift + I)
  • \n
  • Whether issue occurs after migration or fresh install
  • \n
\n","text":"Beta Release You may encounter issues. Report problems on GitHub Issues. What's New in v4# TaskNotes v4 migrates all views to the Bases system. Breaking Changes# Minimum Obsidian version: 1.10.1 View commands now use Bases files - Ribbon icons and command palette commands (Calendar, Kanban, Tasks, Agenda, Project Subtasks) now open .base files created automatically in your vault Saved filter views - Custom saved views can be converted to .base files using a conversion button in settings Added# OAuth Calendar Integration# Google Calendar and Microsoft Outlook integration via OAuth 2.0 View and sync calendar events in Bases calendar Drag events in the TaskNotes bases calendar to change the event's time online Events sync every 15 minutes or upon local change Requires creating your own OAuth application (approximately 15 minutes) See Calendar Setup Guide Time Entry Editor Modal# Dedicated interface for managing time entries Alt-drag on Bases calendar to create time entries View total tracked time per task Edit and delete time entries Access via Task Action Palette (Alt/Opt + Enter) Kanban Swimlane Layout# Horizontal swimlane grouping option for Bases Kanban Group tasks by status, priority, or other fields Hide empty columns Configurable column widths Improved drag-and-drop in swimlane mode Saved View Converter# Conversion button in settings to convert saved filter views to .base files Original settings preserved Converted views created in TaskNotes/Views/ Changed# View System Architecture# All views now use Bases architecture Calendar, Kanban, Tasks, Agenda, and Project Subtasks are .base files Views stored in TaskNotes/Views/ Keyboard shortcuts and ribbon icons map to .base files Configure file paths in Settings → Integrations → Bases Integration Calendar# Control which calendar sources display Toggle Google Calendar, Microsoft Calendar, and ICS events independently Configurable list view with custom day count (2-10 days) Improved timezone handling for recurring events Settings# Reorganized settings tabs OAuth calendar settings in Integrations tab Updated help text Fixed# (#843) Fixed task tag being added when \"Identify tasks by\" is set to \"Property\" TaskCreationModal, TaskEditModal, and InstantTaskConvertService now respect taskIdentificationMethod setting Thanks to @jack2game Fixed dark mode calendar borders Fixed Bases Kanban column ordering - Thanks to @mweichert Fixed state management bug in FilterSettingsComponent Fixed timezone handling for recurring events Migration Guide# First Launch# Default view files are created automatically in TaskNotes/Views/ Ribbon and command palette commands now open .base files Review Settings → General to customize view file paths Converting Saved Filter Views# Go to Settings → General Click the conversion button to convert saved filter views to .base files Converted views appear in a file in TaskNotes/Views/ Calendar Integration (Optional)# Go to Settings → Integrations → OAuth Calendar Integration Follow the Calendar Setup Guide Create OAuth applications with Google and/or Microsoft (approximately 15 minutes) Enter Client ID and Secret in calendar cards Click Connect Known Limitations# Quick OAuth setup is disabled - only advanced setup (your own credentials) is available Saved filter views require manual conversion using the button in settings Migration is one-way - downgrading to v3 may require manual reconfiguration OAuth setup requires creating applications with Google/Microsoft Feedback# Report issues on GitHub. Include: Obsidian version Steps to reproduce Console errors (Ctrl/Cmd + Shift + I) Whether issue occurs after migration or fresh install"},{"route":"/obsidian/releases/4.0.0-beta.1/","title":"TaskNotes 4.0.0-beta.1","description":"Beta Release","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.0.0-beta.1.md","namespace":"obsidian","relativePath":"releases/4.0.0-beta.1.md","raw":"# TaskNotes 4.0.0-beta.1\n\n> **Beta Release**\n>\n> You may encounter issues. Report problems on [GitHub Issues](https://github.com/callumalpass/tasknotes/issues).\n\n## Added\n\n- Added context menus for time entries and ICS events in calendar\n - Time entries: Right-click shows task context menu, left-click opens time entry editor modal\n - ICS/Google/Microsoft Calendar events: Right-click shows ICS event context menu with options to show details, create task/note, link note, and copy info\n- Added calendar icon to ICS event titles for better visual distinction\n- Added hover tooltips for timeblocks in calendar views\n- Added **MiniCalendar view** for Bases integration\n - Monthly calendar grid with dot indicators on days with notes\n - Configurable date property (file.ctime, note.dateCreated, etc.)\n - Fuzzy selector modal for selecting notes on clicked days\n - Ctrl+click (or Cmd+click on Mac) on any day opens/creates daily note\n- Added virtual scrolling and lazy rendering to Bases views for high-performance handling of large datasets\n - TaskListView: Virtual scrolling for 100+ tasks in flat and grouped views with collapsible groups\n - KanbanView: Virtual scrolling for regular columns (30+ tasks) and swimlane cells (30+ tasks per cell)\n - Tested with up to **30,000 notes** with no performance degradation\n - Thanks to @aubreyz and @turingexmachina for their reports of performance issues and diagnosis help\n\n\n## Changed\n\n- Refactored Bases integration to use public API and trust pre-sorted data\n - Migrated all three views (Task List, Kanban, Calendar) to clean class-based architecture\n - Removed legacy view files and ~500 lines of redundant sorting/grouping logic\n - Introduced BasesDataAdapter, PropertyMappingService, and BasesViewBase abstractions\n - Trusts Bases plugin to provide pre-sorted and pre-grouped data via public API\n - Reduced code duplication by 40% while maintaining full feature parity\n- Refactored calendar modules to use ES6 imports instead of lazy require() calls\n - Removed all dynamic require() calls from calendar-core.ts and calendar-view.ts\n - Consolidated all imports at module top level\n - Improves code maintainability, makes dependencies explicit, and follows modern TypeScript best practices\n- Time entry events now show task context menu on right-click (previously had no context menu)\n- Replaced MinimalNativeCache with just-in-time TaskManager for improved reliability\n - Removed complex index synchronization in favor of direct MetadataCache queries\n - Eliminated 7 internal indexes (tasksByDate, tasksByStatus, overdueTasks, etc.)\n - Added minimal DependencyCache for task dependencies and project references only\n - Zero startup time (no index building required)\n - Always provides fresh, accurate task data from Obsidian's MetadataCache\n- Completed internationalization with 100% translation coverage across all supported languages\n - Added 90 missing translation keys to English base\n - Completed 829 translations across 6 languages (German, Spanish, French, Japanese, Russian, Chinese)\n - All locales now have complete coverage (1745/1745 keys)\n - Improved translation quality for migration system, calendar settings, statistics, ICS events, and filter components\n- Migrated to i18n-state-manager CLI tool for translation management\n - Replaced custom scripts with more robust i18n-state-manager package\n - Added i18n-state.config.json for project-specific patterns\n - New features: find-unused, check-duplicates, improved stale detection\n - Hash-based state tracking and ripgrep-based scanning for performance\n- Bases view templates now generate dynamically based on user settings\n - Task filters adapt to user's task identification method (tag or property)\n - Property ordering reflects defaultVisibleProperties setting\n - Uses correct YAML object notation for Bases filters\n - Maintains backward compatibility with legacy static templates\n- Updated Bases CalendarView to show TaskNotes in property-based events\n - Tasks can now be visualized on calendar via any date property (dateCreated, scheduled, due, etc.)\n - Previously all TaskNotes were filtered out from property-based events\n\n## Fixed\n\n- (#1022, #684) Fixed tasks randomly disappearing when Smart Connections plugin is enabled\n - Eliminated race condition caused by index synchronization delays\n - TaskManager now reads directly from Obsidian's MetadataCache instead of maintaining separate indexes\n - No more timing-sensitive code that could conflict with other plugins' metadata processing\n - Tasks will always be visible regardless of other plugins' processing times\n - Thanks to @alejandrospoz, @seepage87, @amarjt, @luckb0x, camara-tech for reporting and help debugging. \n- (#992) Fixed \"Failed to resolve module specifier 'obsidian'\" error when moving recurring task instances in calendar\n - Removed unnecessary dynamic imports that were causing module resolution failures\n - Consolidated imports at top of calendar-core.ts module\n - Thanks to @jalooc for reporting this issue\n- Fixed task dependencies not displaying on task cards\n - TaskManager now properly calculates isBlocked and isBlocking flags from dependency data\n - Added missing property extractors and renderers in TaskCard for all dependency-related fields\n - Dependency information now shows correctly in Bases views, task note widgets, and other views\n - Shows \"Blocked (n)\" and \"Blocking (n)\" pills, plus detailed task links\n- Fixed Bases property mapping for user-configured field names\n - PropertyMappingService now correctly strips prefixes and applies FieldMapper transformations\n - Example: User configures \"state\" → \"status\", Bases provides \"note.state\", now correctly maps to \"status\"\n - Ensures TaskCard properly recognizes and renders user-configured properties\n- Fixed Bases views not respecting user-configured visible properties\n - Now prioritizes Bases 1.10.0+ public API config.getOrder() method\n - Removed reliance on internal API paths that no longer work\n - Filters out blocked/blocking properties when using defaults (only shown when explicitly requested via blockedBy)\n- Fixed MiniCalendar UTC anchoring for consistent timezone-independent date handling\n- Fixed DateValue conversion in BasesDataAdapter\n - DateValue objects have {date: Date, time: boolean} structure\n - Now properly checks for value.date instanceof Date before legacy conversion methods\n - Fixes property-based events in CalendarView\n\n","aliases":["/releases/4.0.0-beta.1/","/releases/4.0.0-beta.1/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"
\n

Beta Release

\n

You may encounter issues. Report problems on GitHub Issues.

\n
\n

Added#

\n
    \n
  • Added context menus for time entries and ICS events in calendar
      \n
    • Time entries: Right-click shows task context menu, left-click opens time entry editor modal
    • \n
    • ICS/Google/Microsoft Calendar events: Right-click shows ICS event context menu with options to show details, create task/note, link note, and copy info
    • \n
    \n
  • \n
  • Added calendar icon to ICS event titles for better visual distinction
  • \n
  • Added hover tooltips for timeblocks in calendar views
  • \n
  • Added MiniCalendar view for Bases integration
      \n
    • Monthly calendar grid with dot indicators on days with notes
    • \n
    • Configurable date property (file.ctime, note.dateCreated, etc.)
    • \n
    • Fuzzy selector modal for selecting notes on clicked days
    • \n
    • Ctrl+click (or Cmd+click on Mac) on any day opens/creates daily note
    • \n
    \n
  • \n
  • Added virtual scrolling and lazy rendering to Bases views for high-performance handling of large datasets
      \n
    • TaskListView: Virtual scrolling for 100+ tasks in flat and grouped views with collapsible groups
    • \n
    • KanbanView: Virtual scrolling for regular columns (30+ tasks) and swimlane cells (30+ tasks per cell)
    • \n
    • Tested with up to 30,000 notes with no performance degradation
    • \n
    • Thanks to @aubreyz and @turingexmachina for their reports of performance issues and diagnosis help
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Refactored Bases integration to use public API and trust pre-sorted data
      \n
    • Migrated all three views (Task List, Kanban, Calendar) to clean class-based architecture
    • \n
    • Removed legacy view files and ~500 lines of redundant sorting/grouping logic
    • \n
    • Introduced BasesDataAdapter, PropertyMappingService, and BasesViewBase abstractions
    • \n
    • Trusts Bases plugin to provide pre-sorted and pre-grouped data via public API
    • \n
    • Reduced code duplication by 40% while maintaining full feature parity
    • \n
    \n
  • \n
  • Refactored calendar modules to use ES6 imports instead of lazy require() calls
      \n
    • Removed all dynamic require() calls from calendar-core.ts and calendar-view.ts
    • \n
    • Consolidated all imports at module top level
    • \n
    • Improves code maintainability, makes dependencies explicit, and follows modern TypeScript best practices
    • \n
    \n
  • \n
  • Time entry events now show task context menu on right-click (previously had no context menu)
  • \n
  • Replaced MinimalNativeCache with just-in-time TaskManager for improved reliability
      \n
    • Removed complex index synchronization in favor of direct MetadataCache queries
    • \n
    • Eliminated 7 internal indexes (tasksByDate, tasksByStatus, overdueTasks, etc.)
    • \n
    • Added minimal DependencyCache for task dependencies and project references only
    • \n
    • Zero startup time (no index building required)
    • \n
    • Always provides fresh, accurate task data from Obsidian's MetadataCache
    • \n
    \n
  • \n
  • Completed internationalization with 100% translation coverage across all supported languages
      \n
    • Added 90 missing translation keys to English base
    • \n
    • Completed 829 translations across 6 languages (German, Spanish, French, Japanese, Russian, Chinese)
    • \n
    • All locales now have complete coverage (1745/1745 keys)
    • \n
    • Improved translation quality for migration system, calendar settings, statistics, ICS events, and filter components
    • \n
    \n
  • \n
  • Migrated to i18n-state-manager CLI tool for translation management
      \n
    • Replaced custom scripts with more robust i18n-state-manager package
    • \n
    • Added i18n-state.config.json for project-specific patterns
    • \n
    • New features: find-unused, check-duplicates, improved stale detection
    • \n
    • Hash-based state tracking and ripgrep-based scanning for performance
    • \n
    \n
  • \n
  • Bases view templates now generate dynamically based on user settings
      \n
    • Task filters adapt to user's task identification method (tag or property)
    • \n
    • Property ordering reflects defaultVisibleProperties setting
    • \n
    • Uses correct YAML object notation for Bases filters
    • \n
    • Maintains backward compatibility with legacy static templates
    • \n
    \n
  • \n
  • Updated Bases CalendarView to show TaskNotes in property-based events
      \n
    • Tasks can now be visualized on calendar via any date property (dateCreated, scheduled, due, etc.)
    • \n
    • Previously all TaskNotes were filtered out from property-based events
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1022, #684) Fixed tasks randomly disappearing when Smart Connections plugin is enabled
      \n
    • Eliminated race condition caused by index synchronization delays
    • \n
    • TaskManager now reads directly from Obsidian's MetadataCache instead of maintaining separate indexes
    • \n
    • No more timing-sensitive code that could conflict with other plugins' metadata processing
    • \n
    • Tasks will always be visible regardless of other plugins' processing times
    • \n
    • Thanks to @alejandrospoz, @seepage87, @amarjt, @luckb0x, camara-tech for reporting and help debugging.
    • \n
    \n
  • \n
  • (#992) Fixed "Failed to resolve module specifier 'obsidian'" error when moving recurring task instances in calendar
      \n
    • Removed unnecessary dynamic imports that were causing module resolution failures
    • \n
    • Consolidated imports at top of calendar-core.ts module
    • \n
    • Thanks to @jalooc for reporting this issue
    • \n
    \n
  • \n
  • Fixed task dependencies not displaying on task cards
      \n
    • TaskManager now properly calculates isBlocked and isBlocking flags from dependency data
    • \n
    • Added missing property extractors and renderers in TaskCard for all dependency-related fields
    • \n
    • Dependency information now shows correctly in Bases views, task note widgets, and other views
    • \n
    • Shows "Blocked (n)" and "Blocking (n)" pills, plus detailed task links
    • \n
    \n
  • \n
  • Fixed Bases property mapping for user-configured field names
      \n
    • PropertyMappingService now correctly strips prefixes and applies FieldMapper transformations
    • \n
    • Example: User configures "state" → "status", Bases provides "note.state", now correctly maps to "status"
    • \n
    • Ensures TaskCard properly recognizes and renders user-configured properties
    • \n
    \n
  • \n
  • Fixed Bases views not respecting user-configured visible properties
      \n
    • Now prioritizes Bases 1.10.0+ public API config.getOrder() method
    • \n
    • Removed reliance on internal API paths that no longer work
    • \n
    • Filters out blocked/blocking properties when using defaults (only shown when explicitly requested via blockedBy)
    • \n
    \n
  • \n
  • Fixed MiniCalendar UTC anchoring for consistent timezone-independent date handling
  • \n
  • Fixed DateValue conversion in BasesDataAdapter
      \n
    • DateValue objects have {date: Date, time: boolean} structure
    • \n
    • Now properly checks for value.date instanceof Date before legacy conversion methods
    • \n
    • Fixes property-based events in CalendarView
    • \n
    \n
  • \n
\n","text":"Beta Release You may encounter issues. Report problems on GitHub Issues. Added# Added context menus for time entries and ICS events in calendar Time entries: Right-click shows task context menu, left-click opens time entry editor modal ICS/Google/Microsoft Calendar events: Right-click shows ICS event context menu with options to show details, create task/note, link note, and copy info Added calendar icon to ICS event titles for better visual distinction Added hover tooltips for timeblocks in calendar views Added MiniCalendar view for Bases integration Monthly calendar grid with dot indicators on days with notes Configurable date property (file.ctime, note.dateCreated, etc.) Fuzzy selector modal for selecting notes on clicked days Ctrl+click (or Cmd+click on Mac) on any day opens/creates daily note Added virtual scrolling and lazy rendering to Bases views for high-performance handling of large datasets TaskListView: Virtual scrolling for 100+ tasks in flat and grouped views with collapsible groups KanbanView: Virtual scrolling for regular columns (30+ tasks) and swimlane cells (30+ tasks per cell) Tested with up to 30,000 notes with no performance degradation Thanks to @aubreyz and @turingexmachina for their reports of performance issues and diagnosis help Changed# Refactored Bases integration to use public API and trust pre-sorted data Migrated all three views (Task List, Kanban, Calendar) to clean class-based architecture Removed legacy view files and ~500 lines of redundant sorting/grouping logic Introduced BasesDataAdapter, PropertyMappingService, and BasesViewBase abstractions Trusts Bases plugin to provide pre-sorted and pre-grouped data via public API Reduced code duplication by 40% while maintaining full feature parity Refactored calendar modules to use ES6 imports instead of lazy require() calls Removed all dynamic require() calls from calendar-core.ts and calendar-view.ts Consolidated all imports at module top level Improves code maintainability, makes dependencies explicit, and follows modern TypeScript best practices Time entry events now show task context menu on right-click (previously had no context menu) Replaced MinimalNativeCache with just-in-time TaskManager for improved reliability Removed complex index synchronization in favor of direct MetadataCache queries Eliminated 7 internal indexes (tasksByDate, tasksByStatus, overdueTasks, etc.) Added minimal DependencyCache for task dependencies and project references only Zero startup time (no index building required) Always provides fresh, accurate task data from Obsidian's MetadataCache Completed internationalization with 100% translation coverage across all supported languages Added 90 missing translation keys to English base Completed 829 translations across 6 languages (German, Spanish, French, Japanese, Russian, Chinese) All locales now have complete coverage (1745/1745 keys) Improved translation quality for migration system, calendar settings, statistics, ICS events, and filter components Migrated to i18n-state-manager CLI tool for translation management Replaced custom scripts with more robust i18n-state-manager package Added i18n-state.config.json for project-specific patterns New features: find-unused, check-duplicates, improved stale detection Hash-based state tracking and ripgrep-based scanning for performance Bases view templates now generate dynamically based on user settings Task filters adapt to user's task identification method (tag or property) Property ordering reflects defaultVisibleProperties setting Uses correct YAML object notation for Bases filters Maintains backward compatibility with legacy static templates Updated Bases CalendarView to show TaskNotes in property-based events Tasks can now be visualized on calendar via any date property (dateCreated, scheduled, due, etc.) Previously all TaskNotes were filtered out from property-based events Fixed# (#1022, #684) Fixed tasks randomly disappearing when Smart Connections plugin is enabled Eliminated race condition caused by index synchronization delays TaskManager now reads directly from Obsidian's MetadataCache instead of maintaining separate indexes No more timing-sensitive code that could conflict with other plugins' metadata processing Tasks will always be visible regardless of other plugins' processing times Thanks to @alejandrospoz, @seepage87, @amarjt, @luckb0x, camara-tech for reporting and help debugging. (#992) Fixed \"Failed to resolve module specifier 'obsidian'\" error when moving recurring task instances in calendar Removed unnecessary dynamic imports that were causing module resolution failures Consolidated imports at top of calendar-core.ts module Thanks to @jalooc for reporting this issue Fixed task dependencies not displaying on task cards TaskManager now properly calculates isBlocked and isBlocking flags from dependency data Added missing property extractors and renderers in TaskCard for all dependency-related fields Dependency information now shows correctly in Bases views, task note widgets, and other views Shows \"Blocked (n)\" and \"Blocking (n)\" pills, plus detailed task links Fixed Bases property mapping for user-configured field names PropertyMappingService now correctly strips prefixes and applies FieldMapper transformations Example: User configures \"state\" → \"status\", Bases provides \"note.state\", now correctly maps to \"status\" Ensures TaskCard properly recognizes and renders user-configured properties Fixed Bases views not respecting user-configured visible properties Now prioritizes Bases 1.10.0+ public API config.getOrder() method Removed reliance on internal API paths that no longer work Filters out blocked/blocking properties when using defaults (only shown when explicitly requested via blockedBy) Fixed MiniCalendar UTC anchoring for consistent timezone-independent date handling Fixed DateValue conversion in BasesDataAdapter DateValue objects have {date: Date, time: boolean} structure Now properly checks for value.date instanceof Date before legacy conversion methods Fixes property-based events in CalendarView"},{"route":"/obsidian/releases/4.0.0-beta.2/","title":"TaskNotes 4.0.0-beta.2","description":"Beta Release","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.0.0-beta.2.md","namespace":"obsidian","relativePath":"releases/4.0.0-beta.2.md","raw":"# TaskNotes 4.0.0-beta.2\n\n> **Beta Release**\n>\n> You may encounter issues. Report problems on [GitHub Issues](https://github.com/callumalpass/tasknotes/issues).\n\n## Added\n\n- (#1090) Portuguese (Brazil) translation\n - Full Portuguese (pt-BR) localization support\n - A big thanks to @andysteel for the contribution\n- **Configurable task modal fields** \n - New \"Modal Fields\" settings tab for complete control over task creation and edit modals\n - Configure which fields appear in creation vs edit modals independently\n - Drag-and-drop reordering of fields within groups (metadata, organization, dependencies, custom)\n - Enable/disable individual fields (including core fields like contexts, tags, time estimate)\n - Organize fields into groups \n - Automatic migration of existing user-defined fields\n - Title and details fields support visibility toggling (ordering fixed for consistency)\n- **Rich markdown editor for NLP task creation**\n - Replaced plain textarea with full CodeMirror markdown editor\n - Live preview, syntax highlighting, and wikilink support\n - Ctrl/Cmd+Enter keyboard shortcut to save task\n - Esc/Tab keyboard shortcuts for modal control\n- **Customizable NLP triggers with autocomplete**\n - Configure custom trigger characters/strings for each property type (tags, contexts, projects, status, priority)\n - Supports user-defined field triggers\n - CodeMirror-based autocomplete with keyboard navigation (arrow keys, Enter, Tab)\n - Quote support for multi-word values in user fields\n - Native tag suggester integration when using # trigger\n- **Inline task link overlay enhancements**\n - Configurable visible properties for inline task cards\n - PropertySelectorModal for selecting which properties to display\n - Improved layout: title prioritized, horizontal scrolling for metadata\n - Real-time updates when task data changes\n- **New utility services**\n - `TriggerConfigService` - manages NLP trigger configurations\n - `PropertySelectorModal` - reusable multi-select property picker\n - Property helpers for consistent property handling across views\n- Kanban column reordering via drag and drop\n - Drag column headers to reorder columns\n - Column order is saved per grouping property\n - Visual feedback during drag operations\n- Mini calendar enhancements (in progress)\n - Week numbers column\n - Heat map intensity visualization\n - Note preview tooltips on hover\n - Keyboard navigation\n- **Unified Relationships widget**\n - Consolidated project subtasks, task dependencies, and blocking relationships into a single dynamic widget\n - Four automatic tabs: Subtasks (Kanban), Projects (List), Blocked By (List), Blocking (Kanban)\n - Tabs automatically show/hide based on available relationship data\n - Bases views handle all data updates reactively - no manual refresh needed\n - Single configuration setting: show/hide and position (top/bottom)\n - Significantly reduced code complexity (430 fewer lines)\n\n## Fixed\n\n- (#1084) Fixed word wrapping in NLP preview items\n - Thanks to @maybetm for the fix\n- (#975) Fixed advanced calendar list headers not respecting theme colors\n - Thanks to @hugohil for the fix\n- (#1089) Fixed embedded task list bases growing unbounded and leaving large empty space\n - Embedded bases now scroll internally instead of expanding to show all tasks\n - Consistent behavior between task list and kanban embedded views\n - Thanks to @same774 for reporting with screenshot\n- **Bases Calendar view options now working correctly**\n - Fixed \"Highlight today\" toggle not applying - now properly adds/removes CSS class when toggled\n - Fixed calendar view type (month/week/day/etc) not being saved when changed via calendar buttons\n - View type is now persisted when users click month/week/day buttons in the calendar UI\n- (#1050) Task modal no longer adds unwanted empty contexts and projects arrays\n - FieldMapper now checks if arrays are empty before writing to frontmatter\n - Thanks to @nightroman for reporting this issue\n- **Inline task link overlay fixes**\n - Fixed layout prioritization: title now prioritized over metadata\n - Added horizontal scrolling for metadata to prevent overflow\n - Fixed real-time update listeners for task data changes\n- Fixed group collapse/expand functionality in TaskListView\n - Re-registered click event listener for group headers using Component API\n - Groups can now be properly collapsed and expanded\n- Fixed config loading race condition in KanbanView and CalendarView\n - Config is now properly loaded in onload() lifecycle method\n - Views wait for config before rendering options\n- Fixed MiniCalendarView to use direct Bases API like other views\n - Consistent use of Component lifecycle methods\n - Proper cleanup in onunload()\n\n## Changed\n\n- **NLP system overhaul**\n - Replaced `StatusSuggestionService` wrapper with direct `NaturalLanguageParser` usage\n - Consolidated trigger configuration into unified `TriggerConfigService`\n - Enhanced `NaturalLanguageParser` with full trigger and user field support\n - Removed custom # tag autocomplete in favor of Obsidian's native tag suggester (when using # trigger)\n- **Task card and editor improvements**\n - Simplified `TaskCard` interface - removed unused options (showCheckbox, showArchiveButton, groupByDate)\n - Refactored `TaskLinkWidget` to use unified `TaskCard` component for consistency\n - Added support for inline vs. block layout modes in task cards\n - Improved task card BEM CSS with better styling for inline mode\n- **Settings UI enhancements**\n - NLP triggers now configurable through Settings > Features tab\n - Added settings for inline task card visible properties\n - Improved appearance tab with property selector integration\n - Better organization of NLP-related settings\n- Refactored Bases views to use Component lifecycle properly\n - Views now extend Component and use onload()/onunload()\n - Automatic cleanup of event listeners via Component.registerDomEvent()\n - Improved state management and ephemeral state handling\n- Improved development experience\n - Converted ESLint errors to warnings for non-blocking development\n - Fixed various linting issues and unused imports\n\n## Removed\n\n- Removed `StatusSuggestionService` (functionality consolidated into `NaturalLanguageParser`)\n\n## Breaking Changes\n\n- **Relationships widget settings consolidated** (automatic migration)\n - Old settings removed: `showProjectSubtasks`, `projectSubtasksPosition`, `showTaskDependencies`, `taskDependenciesPosition`\n - New unified settings: `showRelationships`, `relationshipsPosition`\n - Widget now appears on ALL notes (tasks, projects, regular notes) - Bases filtering controls which tabs are visible\n - **Migration**: Existing users will see the new unified widget automatically. If you had project subtasks enabled, relationships widget will be enabled by default\n - **Bases file change**: The command mapping changed from `'project-subtasks': 'TaskNotes/Views/project-subtasks.base'` to `'relationships': 'TaskNotes/Views/relationships.base'`\n - Run \"Create Default Files\" in Settings > General to create the new `relationships.base` file\n\n","aliases":["/releases/4.0.0-beta.2/","/releases/4.0.0-beta.2/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"removed","text":"Removed"},{"level":2,"id":"breaking-changes","text":"Breaking Changes"}],"html":"
\n

Beta Release

\n

You may encounter issues. Report problems on GitHub Issues.

\n
\n

Added#

\n
    \n
  • (#1090) Portuguese (Brazil) translation
      \n
    • Full Portuguese (pt-BR) localization support
    • \n
    • A big thanks to @andysteel for the contribution
    • \n
    \n
  • \n
  • Configurable task modal fields
      \n
    • New "Modal Fields" settings tab for complete control over task creation and edit modals
    • \n
    • Configure which fields appear in creation vs edit modals independently
    • \n
    • Drag-and-drop reordering of fields within groups (metadata, organization, dependencies, custom)
    • \n
    • Enable/disable individual fields (including core fields like contexts, tags, time estimate)
    • \n
    • Organize fields into groups
    • \n
    • Automatic migration of existing user-defined fields
    • \n
    • Title and details fields support visibility toggling (ordering fixed for consistency)
    • \n
    \n
  • \n
  • Rich markdown editor for NLP task creation
      \n
    • Replaced plain textarea with full CodeMirror markdown editor
    • \n
    • Live preview, syntax highlighting, and wikilink support
    • \n
    • Ctrl/Cmd+Enter keyboard shortcut to save task
    • \n
    • Esc/Tab keyboard shortcuts for modal control
    • \n
    \n
  • \n
  • Customizable NLP triggers with autocomplete
      \n
    • Configure custom trigger characters/strings for each property type (tags, contexts, projects, status, priority)
    • \n
    • Supports user-defined field triggers
    • \n
    • CodeMirror-based autocomplete with keyboard navigation (arrow keys, Enter, Tab)
    • \n
    • Quote support for multi-word values in user fields
    • \n
    • Native tag suggester integration when using # trigger
    • \n
    \n
  • \n
  • Inline task link overlay enhancements
      \n
    • Configurable visible properties for inline task cards
    • \n
    • PropertySelectorModal for selecting which properties to display
    • \n
    • Improved layout: title prioritized, horizontal scrolling for metadata
    • \n
    • Real-time updates when task data changes
    • \n
    \n
  • \n
  • New utility services
      \n
    • TriggerConfigService - manages NLP trigger configurations
    • \n
    • PropertySelectorModal - reusable multi-select property picker
    • \n
    • Property helpers for consistent property handling across views
    • \n
    \n
  • \n
  • Kanban column reordering via drag and drop
      \n
    • Drag column headers to reorder columns
    • \n
    • Column order is saved per grouping property
    • \n
    • Visual feedback during drag operations
    • \n
    \n
  • \n
  • Mini calendar enhancements (in progress)
      \n
    • Week numbers column
    • \n
    • Heat map intensity visualization
    • \n
    • Note preview tooltips on hover
    • \n
    • Keyboard navigation
    • \n
    \n
  • \n
  • Unified Relationships widget
      \n
    • Consolidated project subtasks, task dependencies, and blocking relationships into a single dynamic widget
    • \n
    • Four automatic tabs: Subtasks (Kanban), Projects (List), Blocked By (List), Blocking (Kanban)
    • \n
    • Tabs automatically show/hide based on available relationship data
    • \n
    • Bases views handle all data updates reactively - no manual refresh needed
    • \n
    • Single configuration setting: show/hide and position (top/bottom)
    • \n
    • Significantly reduced code complexity (430 fewer lines)
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1084) Fixed word wrapping in NLP preview items
      \n
    • Thanks to @maybetm for the fix
    • \n
    \n
  • \n
  • (#975) Fixed advanced calendar list headers not respecting theme colors
      \n
    • Thanks to @hugohil for the fix
    • \n
    \n
  • \n
  • (#1089) Fixed embedded task list bases growing unbounded and leaving large empty space
      \n
    • Embedded bases now scroll internally instead of expanding to show all tasks
    • \n
    • Consistent behavior between task list and kanban embedded views
    • \n
    • Thanks to @same774 for reporting with screenshot
    • \n
    \n
  • \n
  • Bases Calendar view options now working correctly
      \n
    • Fixed "Highlight today" toggle not applying - now properly adds/removes CSS class when toggled
    • \n
    • Fixed calendar view type (month/week/day/etc) not being saved when changed via calendar buttons
    • \n
    • View type is now persisted when users click month/week/day buttons in the calendar UI
    • \n
    \n
  • \n
  • (#1050) Task modal no longer adds unwanted empty contexts and projects arrays
      \n
    • FieldMapper now checks if arrays are empty before writing to frontmatter
    • \n
    • Thanks to @nightroman for reporting this issue
    • \n
    \n
  • \n
  • Inline task link overlay fixes
      \n
    • Fixed layout prioritization: title now prioritized over metadata
    • \n
    • Added horizontal scrolling for metadata to prevent overflow
    • \n
    • Fixed real-time update listeners for task data changes
    • \n
    \n
  • \n
  • Fixed group collapse/expand functionality in TaskListView
      \n
    • Re-registered click event listener for group headers using Component API
    • \n
    • Groups can now be properly collapsed and expanded
    • \n
    \n
  • \n
  • Fixed config loading race condition in KanbanView and CalendarView
      \n
    • Config is now properly loaded in onload() lifecycle method
    • \n
    • Views wait for config before rendering options
    • \n
    \n
  • \n
  • Fixed MiniCalendarView to use direct Bases API like other views
      \n
    • Consistent use of Component lifecycle methods
    • \n
    • Proper cleanup in onunload()
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • NLP system overhaul
      \n
    • Replaced StatusSuggestionService wrapper with direct NaturalLanguageParser usage
    • \n
    • Consolidated trigger configuration into unified TriggerConfigService
    • \n
    • Enhanced NaturalLanguageParser with full trigger and user field support
    • \n
    • Removed custom # tag autocomplete in favor of Obsidian's native tag suggester (when using # trigger)
    • \n
    \n
  • \n
  • Task card and editor improvements
      \n
    • Simplified TaskCard interface - removed unused options (showCheckbox, showArchiveButton, groupByDate)
    • \n
    • Refactored TaskLinkWidget to use unified TaskCard component for consistency
    • \n
    • Added support for inline vs. block layout modes in task cards
    • \n
    • Improved task card BEM CSS with better styling for inline mode
    • \n
    \n
  • \n
  • Settings UI enhancements
      \n
    • NLP triggers now configurable through Settings > Features tab
    • \n
    • Added settings for inline task card visible properties
    • \n
    • Improved appearance tab with property selector integration
    • \n
    • Better organization of NLP-related settings
    • \n
    \n
  • \n
  • Refactored Bases views to use Component lifecycle properly
      \n
    • Views now extend Component and use onload()/onunload()
    • \n
    • Automatic cleanup of event listeners via Component.registerDomEvent()
    • \n
    • Improved state management and ephemeral state handling
    • \n
    \n
  • \n
  • Improved development experience
      \n
    • Converted ESLint errors to warnings for non-blocking development
    • \n
    • Fixed various linting issues and unused imports
    • \n
    \n
  • \n
\n

Removed#

\n
    \n
  • Removed StatusSuggestionService (functionality consolidated into NaturalLanguageParser)
  • \n
\n

Breaking Changes#

\n
    \n
  • Relationships widget settings consolidated (automatic migration)
      \n
    • Old settings removed: showProjectSubtasks, projectSubtasksPosition, showTaskDependencies, taskDependenciesPosition
    • \n
    • New unified settings: showRelationships, relationshipsPosition
    • \n
    • Widget now appears on ALL notes (tasks, projects, regular notes) - Bases filtering controls which tabs are visible
    • \n
    • Migration: Existing users will see the new unified widget automatically. If you had project subtasks enabled, relationships widget will be enabled by default
    • \n
    • Bases file change: The command mapping changed from 'project-subtasks': 'TaskNotes/Views/project-subtasks.base' to 'relationships': 'TaskNotes/Views/relationships.base'
    • \n
    • Run "Create Default Files" in Settings > General to create the new relationships.base file
    • \n
    \n
  • \n
\n","text":"Beta Release You may encounter issues. Report problems on GitHub Issues. Added# (#1090) Portuguese (Brazil) translation Full Portuguese (pt-BR) localization support A big thanks to @andysteel for the contribution Configurable task modal fields New \"Modal Fields\" settings tab for complete control over task creation and edit modals Configure which fields appear in creation vs edit modals independently Drag-and-drop reordering of fields within groups (metadata, organization, dependencies, custom) Enable/disable individual fields (including core fields like contexts, tags, time estimate) Organize fields into groups Automatic migration of existing user-defined fields Title and details fields support visibility toggling (ordering fixed for consistency) Rich markdown editor for NLP task creation Replaced plain textarea with full CodeMirror markdown editor Live preview, syntax highlighting, and wikilink support Ctrl/Cmd+Enter keyboard shortcut to save task Esc/Tab keyboard shortcuts for modal control Customizable NLP triggers with autocomplete Configure custom trigger characters/strings for each property type (tags, contexts, projects, status, priority) Supports user-defined field triggers CodeMirror-based autocomplete with keyboard navigation (arrow keys, Enter, Tab) Quote support for multi-word values in user fields Native tag suggester integration when using # trigger Inline task link overlay enhancements Configurable visible properties for inline task cards PropertySelectorModal for selecting which properties to display Improved layout: title prioritized, horizontal scrolling for metadata Real-time updates when task data changes New utility services TriggerConfigService - manages NLP trigger configurations PropertySelectorModal - reusable multi-select property picker Property helpers for consistent property handling across views Kanban column reordering via drag and drop Drag column headers to reorder columns Column order is saved per grouping property Visual feedback during drag operations Mini calendar enhancements (in progress) Week numbers column Heat map intensity visualization Note preview tooltips on hover Keyboard navigation Unified Relationships widget Consolidated project subtasks, task dependencies, and blocking relationships into a single dynamic widget Four automatic tabs: Subtasks (Kanban), Projects (List), Blocked By (List), Blocking (Kanban) Tabs automatically show/hide based on available relationship data Bases views handle all data updates reactively - no manual refresh needed Single configuration setting: show/hide and position (top/bottom) Significantly reduced code complexity (430 fewer lines) Fixed# (#1084) Fixed word wrapping in NLP preview items Thanks to @maybetm for the fix (#975) Fixed advanced calendar list headers not respecting theme colors Thanks to @hugohil for the fix (#1089) Fixed embedded task list bases growing unbounded and leaving large empty space Embedded bases now scroll internally instead of expanding to show all tasks Consistent behavior between task list and kanban embedded views Thanks to @same774 for reporting with screenshot Bases Calendar view options now working correctly Fixed \"Highlight today\" toggle not applying - now properly adds/removes CSS class when toggled Fixed calendar view type (month/week/day/etc) not being saved when changed via calendar buttons View type is now persisted when users click month/week/day buttons in the calendar UI (#1050) Task modal no longer adds unwanted empty contexts and projects arrays FieldMapper now checks if arrays are empty before writing to frontmatter Thanks to @nightroman for reporting this issue Inline task link overlay fixes Fixed layout prioritization: title now prioritized over metadata Added horizontal scrolling for metadata to prevent overflow Fixed real-time update listeners for task data changes Fixed group collapse/expand functionality in TaskListView Re-registered click event listener for group headers using Component API Groups can now be properly collapsed and expanded Fixed config loading race condition in KanbanView and CalendarView Config is now properly loaded in onload() lifecycle method Views wait for config before rendering options Fixed MiniCalendarView to use direct Bases API like other views Consistent use of Component lifecycle methods Proper cleanup in onunload() Changed# NLP system overhaul Replaced StatusSuggestionService wrapper with direct NaturalLanguageParser usage Consolidated trigger configuration into unified TriggerConfigService Enhanced NaturalLanguageParser with full trigger and user field support Removed custom # tag autocomplete in favor of Obsidian's native tag suggester (when using # trigger) Task card and editor improvements Simplified TaskCard interface - removed unused options (showCheckbox, showArchiveButton, groupByDate) Refactored TaskLinkWidget to use unified TaskCard component for consistency Added support for inline vs. block layout modes in task cards Improved task card BEM CSS with better styling for inline mode Settings UI enhancements NLP triggers now configurable through Settings > Features tab Added settings for inline task card visible properties Improved appearance tab with property selector integration Better organization of NLP-related settings Refactored Bases views to use Component lifecycle properly Views now extend Component and use onload()/onunload() Automatic cleanup of event listeners via Component.registerDomEvent() Improved state management and ephemeral state handling Improved development experience Converted ESLint errors to warnings for non-blocking development Fixed various linting issues and unused imports Removed# Removed StatusSuggestionService (functionality consolidated into NaturalLanguageParser) Breaking Changes# Relationships widget settings consolidated (automatic migration) Old settings removed: showProjectSubtasks, projectSubtasksPosition, showTaskDependencies, taskDependenciesPosition New unified settings: showRelationships, relationshipsPosition Widget now appears on ALL notes (tasks, projects, regular notes) - Bases filtering controls which tabs are visible Migration: Existing users will see the new unified widget automatically. If you had project subtasks enabled, relationships widget will be enabled by default Bases file change: The command mapping changed from 'project-subtasks': 'TaskNotes/Views/project-subtasks.base' to 'relationships': 'TaskNotes/Views/relationships.base' Run \"Create Default Files\" in Settings > General to create the new relationships.base file"},{"route":"/obsidian/releases/4.0.0-beta.3/","title":"TaskNotes 4.0.0-beta.3","description":"Beta Release","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.0.0-beta.3.md","namespace":"obsidian","relativePath":"releases/4.0.0-beta.3.md","raw":"# TaskNotes 4.0.0-beta.3\n\n> **Beta Release**\n>\n> You may encounter issues. Report problems on [GitHub Issues](https://github.com/callumalpass/tasknotes/issues).\n\n## Added\n\n- Updated task card styling\n - Increased status dot size from 16px to 18px\n - Added subtle shadows and transitions to card hover states\n - Updated hover effects on status and priority dots with scaling and removed glow\n - Modified metadata pills with backdrop blur and adjusted spacing\n - Added box shadows to interactive elements (dates, projects, tags) on hover\n - Updated animations to use cubic-bezier easing\n - Added gradient accents to subtask and blocking task borders\n - Fixed subtasks appearing behind parent card hover backgrounds\n - Fixed subtask click and context menu events bubbling to parent cards\n - Fixed subtasks inheriting parent priority and status colors\n\n- (#361) Added completion-based recurrence support with `recurrence_anchor` field\n - Tasks can now recur based on completion date instead of scheduled date\n - Set `recurrence_anchor: completion` in task frontmatter to enable this behavior\n - When completing a recurring task, the next occurrence will be scheduled relative to the completion date\n - The DTSTART in the RRULE automatically updates to the completion date, ensuring calendar views show future occurrences at the correct dates\n - Defaults to `scheduled` (original behavior) if not specified\n - Useful for tasks like \"Exercise weekly\" where you want the next occurrence 7 days after you actually complete it, not 7 days after it was scheduled\n - Example: Complete a weekly task 2 days late, and the next occurrence will be 7 days from the completion date (not the original scheduled date)\n - Thanks to @luciolebrillante for the original feature request, and @jhedlund, @nschenone, @BryanWall, @realJohnDoe, and @kazerniel for additional input and interest\n\n- (#416) Added support for skipped recurrence instances with `skipped_instances` field\n - Recurring tasks can now have individual instances marked as \"skipped\" without completing them\n - Skipped instances are stored in the `skipped_instances` frontmatter array (e.g., `[\"2025-11-15\", \"2025-11-22\"]`)\n - Right-click on a recurring task instance in calendar views to skip/unskip it\n - Visual styling differentiates skipped instances:\n - Calendar views: Gray background with muted appearance\n - Task cards: Strike-through text with gray styling\n - Skipped instances don't affect the recurrence pattern - future instances continue as scheduled\n - Useful for holidays, vacations, or other planned exceptions to recurring tasks\n - Thanks to @mdbraber for the suggestion to use an array similar to `complete_instances`, and @jerzy-dudzic for reporting the issue\n\n\n## Fixed\n\n- (#893) Fixed yearly recurring tasks not always updating scheduled date to next occurrence when completed\n - Increased look-ahead period for yearly recurrence from 365 days to 800 days (~2.2 years)\n - Also optimized look-ahead periods for other frequencies: daily (30 days), weekly (90 days), monthly (400 days)\n - Ensures the next occurrence is always found when completing recurring task instances\n - Thanks to @VenturaNotes for reporting\n\n- (#951) Fixed yearly recurring tasks not showing up in calendar's weekly, 3-day, or day views\n - Extended the look-ahead period for yearly recurring tasks when generating calendar instances\n - Calendar views now look ahead ~2.2 years for yearly tasks to ensure occurrences appear even in short date ranges\n - Only displays instances that fall within the actual visible calendar range\n - Weekly recurring tasks were unaffected and continued to work correctly\n - Thanks to @bespokecomp for reporting\n\n- (#889) Fixed git merge conflicts in calendar subscription metadata\n - Calendar subscription `lastFetched` and `lastError` fields are now stored in memory instead of being saved to disk\n - Prevents git conflicts when syncing vaults across multiple computers that independently fetch calendar subscriptions\n - The \"last synced\" timestamp in settings will reset on plugin reload, but subscriptions will re-fetch automatically\n - Thanks to @karlfrohlich for reporting\n\n- Fixed recurrence modal not loading DTSTART date/time when editing existing recurrence rules\n - The custom recurrence modal now correctly parses and displays the start date and time fields\n - Fixed parser that was splitting on `=` instead of `:` for DTSTART values\n\n- (#1097) Fixed custom properties and formulas not displaying in Bases views\n - Updated TaskCard to use Bases API's getValue() method for formulas and custom note properties\n - Formulas now work correctly using `formula.NAME` syntax\n - Custom note properties now work correctly using `note.PROPERTY` syntax\n - Thanks to @cathywu for reporting\n\n- (#1099) Fixed issues with default Bases file creation\n - Fixed double-prefix bug in relationships template that generated invalid filter expressions like `note.note.projects`\n - Fixed race condition where files created during plugin load wouldn't appear in file explorer\n - Default Bases files now generate with correct property paths and appear reliably in the file explorer\n - Thanks to @kmaustral for reporting\n\n- (#1110) Fixed open recurring tasks appearing crossed out in Tasks view\n - Removed stale `selectedDate` property that was never updated in v4\n - Tasks view now uses fresh UTC-anchored \"today\" for correct recurring task completion status\n - Fixes issue where tasks completed yesterday would appear crossed out today for users in positive UTC offset timezones\n - Also fixed KanbanView to use UTC-anchored dates for consistency\n - Thanks to @kmaustral for reporting\n\n- (#1118) Fixed user-defined fields not working in inline task conversion\n - User-defined fields like `>customfield value` now properly convert to frontmatter when using the \"TaskNote: Convert task to TaskNote\" command\n - Fixed fields appearing with internal IDs (e.g., `field_1761435101864`) instead of configured frontmatter key names\n - Array values are now properly joined with commas\n - Added `userFields` property to `ParsedTaskData` interface to support custom fields throughout the conversion flow\n - Thanks to @guncav for reporting\n\n- Fixed kanban column width CSS constraints not matching settings\n - Updated CSS min-width from 280px to 200px and max-width from 350px to 500px to match slider range\n - Column width slider now works correctly across the full 200-500px range\n\n- Kanban view now shows empty columns for all user-defined statuses when grouping by status\n - Empty columns appear for custom statuses defined in settings, even when no tasks have that status\n - Allows users to drag tasks into empty status columns\n - Works in both flat kanban view and swimlane mode\n - Respects the existing \"Hide empty columns\" setting\n - Thanks to @williamcheuk03 for reporting this issue\n","aliases":["/releases/4.0.0-beta.3/","/releases/4.0.0-beta.3/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"
\n

Beta Release

\n

You may encounter issues. Report problems on GitHub Issues.

\n
\n

Added#

\n
    \n
  • Updated task card styling

    \n
      \n
    • Increased status dot size from 16px to 18px
    • \n
    • Added subtle shadows and transitions to card hover states
    • \n
    • Updated hover effects on status and priority dots with scaling and removed glow
    • \n
    • Modified metadata pills with backdrop blur and adjusted spacing
    • \n
    • Added box shadows to interactive elements (dates, projects, tags) on hover
    • \n
    • Updated animations to use cubic-bezier easing
    • \n
    • Added gradient accents to subtask and blocking task borders
    • \n
    • Fixed subtasks appearing behind parent card hover backgrounds
    • \n
    • Fixed subtask click and context menu events bubbling to parent cards
    • \n
    • Fixed subtasks inheriting parent priority and status colors
    • \n
    \n
  • \n
  • (#361) Added completion-based recurrence support with recurrence_anchor field

    \n
      \n
    • Tasks can now recur based on completion date instead of scheduled date
    • \n
    • Set recurrence_anchor: completion in task frontmatter to enable this behavior
    • \n
    • When completing a recurring task, the next occurrence will be scheduled relative to the completion date
    • \n
    • The DTSTART in the RRULE automatically updates to the completion date, ensuring calendar views show future occurrences at the correct dates
    • \n
    • Defaults to scheduled (original behavior) if not specified
    • \n
    • Useful for tasks like "Exercise weekly" where you want the next occurrence 7 days after you actually complete it, not 7 days after it was scheduled
    • \n
    • Example: Complete a weekly task 2 days late, and the next occurrence will be 7 days from the completion date (not the original scheduled date)
    • \n
    • Thanks to @luciolebrillante for the original feature request, and @jhedlund, @nschenone, @BryanWall, @realJohnDoe, and @kazerniel for additional input and interest
    • \n
    \n
  • \n
  • (#416) Added support for skipped recurrence instances with skipped_instances field

    \n
      \n
    • Recurring tasks can now have individual instances marked as "skipped" without completing them
    • \n
    • Skipped instances are stored in the skipped_instances frontmatter array (e.g., ["2025-11-15", "2025-11-22"])
    • \n
    • Right-click on a recurring task instance in calendar views to skip/unskip it
    • \n
    • Visual styling differentiates skipped instances:
        \n
      • Calendar views: Gray background with muted appearance
      • \n
      • Task cards: Strike-through text with gray styling
      • \n
      \n
    • \n
    • Skipped instances don't affect the recurrence pattern - future instances continue as scheduled
    • \n
    • Useful for holidays, vacations, or other planned exceptions to recurring tasks
    • \n
    • Thanks to @mdbraber for the suggestion to use an array similar to complete_instances, and @jerzy-dudzic for reporting the issue
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#893) Fixed yearly recurring tasks not always updating scheduled date to next occurrence when completed

    \n
      \n
    • Increased look-ahead period for yearly recurrence from 365 days to 800 days (~2.2 years)
    • \n
    • Also optimized look-ahead periods for other frequencies: daily (30 days), weekly (90 days), monthly (400 days)
    • \n
    • Ensures the next occurrence is always found when completing recurring task instances
    • \n
    • Thanks to @VenturaNotes for reporting
    • \n
    \n
  • \n
  • (#951) Fixed yearly recurring tasks not showing up in calendar's weekly, 3-day, or day views

    \n
      \n
    • Extended the look-ahead period for yearly recurring tasks when generating calendar instances
    • \n
    • Calendar views now look ahead ~2.2 years for yearly tasks to ensure occurrences appear even in short date ranges
    • \n
    • Only displays instances that fall within the actual visible calendar range
    • \n
    • Weekly recurring tasks were unaffected and continued to work correctly
    • \n
    • Thanks to @bespokecomp for reporting
    • \n
    \n
  • \n
  • (#889) Fixed git merge conflicts in calendar subscription metadata

    \n
      \n
    • Calendar subscription lastFetched and lastError fields are now stored in memory instead of being saved to disk
    • \n
    • Prevents git conflicts when syncing vaults across multiple computers that independently fetch calendar subscriptions
    • \n
    • The "last synced" timestamp in settings will reset on plugin reload, but subscriptions will re-fetch automatically
    • \n
    • Thanks to @karlfrohlich for reporting
    • \n
    \n
  • \n
  • Fixed recurrence modal not loading DTSTART date/time when editing existing recurrence rules

    \n
      \n
    • The custom recurrence modal now correctly parses and displays the start date and time fields
    • \n
    • Fixed parser that was splitting on = instead of : for DTSTART values
    • \n
    \n
  • \n
  • (#1097) Fixed custom properties and formulas not displaying in Bases views

    \n
      \n
    • Updated TaskCard to use Bases API's getValue() method for formulas and custom note properties
    • \n
    • Formulas now work correctly using formula.NAME syntax
    • \n
    • Custom note properties now work correctly using note.PROPERTY syntax
    • \n
    • Thanks to @cathywu for reporting
    • \n
    \n
  • \n
  • (#1099) Fixed issues with default Bases file creation

    \n
      \n
    • Fixed double-prefix bug in relationships template that generated invalid filter expressions like note.note.projects
    • \n
    • Fixed race condition where files created during plugin load wouldn't appear in file explorer
    • \n
    • Default Bases files now generate with correct property paths and appear reliably in the file explorer
    • \n
    • Thanks to @kmaustral for reporting
    • \n
    \n
  • \n
  • (#1110) Fixed open recurring tasks appearing crossed out in Tasks view

    \n
      \n
    • Removed stale selectedDate property that was never updated in v4
    • \n
    • Tasks view now uses fresh UTC-anchored "today" for correct recurring task completion status
    • \n
    • Fixes issue where tasks completed yesterday would appear crossed out today for users in positive UTC offset timezones
    • \n
    • Also fixed KanbanView to use UTC-anchored dates for consistency
    • \n
    • Thanks to @kmaustral for reporting
    • \n
    \n
  • \n
  • (#1118) Fixed user-defined fields not working in inline task conversion

    \n
      \n
    • User-defined fields like >customfield value now properly convert to frontmatter when using the "TaskNote: Convert task to TaskNote" command
    • \n
    • Fixed fields appearing with internal IDs (e.g., field_1761435101864) instead of configured frontmatter key names
    • \n
    • Array values are now properly joined with commas
    • \n
    • Added userFields property to ParsedTaskData interface to support custom fields throughout the conversion flow
    • \n
    • Thanks to @guncav for reporting
    • \n
    \n
  • \n
  • Fixed kanban column width CSS constraints not matching settings

    \n
      \n
    • Updated CSS min-width from 280px to 200px and max-width from 350px to 500px to match slider range
    • \n
    • Column width slider now works correctly across the full 200-500px range
    • \n
    \n
  • \n
  • Kanban view now shows empty columns for all user-defined statuses when grouping by status

    \n
      \n
    • Empty columns appear for custom statuses defined in settings, even when no tasks have that status
    • \n
    • Allows users to drag tasks into empty status columns
    • \n
    • Works in both flat kanban view and swimlane mode
    • \n
    • Respects the existing "Hide empty columns" setting
    • \n
    • Thanks to @williamcheuk03 for reporting this issue
    • \n
    \n
  • \n
\n","text":"Beta Release You may encounter issues. Report problems on GitHub Issues. Added# Updated task card styling Increased status dot size from 16px to 18px Added subtle shadows and transitions to card hover states Updated hover effects on status and priority dots with scaling and removed glow Modified metadata pills with backdrop blur and adjusted spacing Added box shadows to interactive elements (dates, projects, tags) on hover Updated animations to use cubic-bezier easing Added gradient accents to subtask and blocking task borders Fixed subtasks appearing behind parent card hover backgrounds Fixed subtask click and context menu events bubbling to parent cards Fixed subtasks inheriting parent priority and status colors (#361) Added completion-based recurrence support with recurrence_anchor field Tasks can now recur based on completion date instead of scheduled date Set recurrence_anchor: completion in task frontmatter to enable this behavior When completing a recurring task, the next occurrence will be scheduled relative to the completion date The DTSTART in the RRULE automatically updates to the completion date, ensuring calendar views show future occurrences at the correct dates Defaults to scheduled (original behavior) if not specified Useful for tasks like \"Exercise weekly\" where you want the next occurrence 7 days after you actually complete it, not 7 days after it was scheduled Example: Complete a weekly task 2 days late, and the next occurrence will be 7 days from the completion date (not the original scheduled date) Thanks to @luciolebrillante for the original feature request, and @jhedlund, @nschenone, @BryanWall, @realJohnDoe, and @kazerniel for additional input and interest (#416) Added support for skipped recurrence instances with skipped_instances field Recurring tasks can now have individual instances marked as \"skipped\" without completing them Skipped instances are stored in the skipped_instances frontmatter array (e.g., [\"2025-11-15\", \"2025-11-22\"]) Right-click on a recurring task instance in calendar views to skip/unskip it Visual styling differentiates skipped instances: Calendar views: Gray background with muted appearance Task cards: Strike-through text with gray styling Skipped instances don't affect the recurrence pattern - future instances continue as scheduled Useful for holidays, vacations, or other planned exceptions to recurring tasks Thanks to @mdbraber for the suggestion to use an array similar to complete_instances, and @jerzy-dudzic for reporting the issue Fixed# (#893) Fixed yearly recurring tasks not always updating scheduled date to next occurrence when completed Increased look-ahead period for yearly recurrence from 365 days to 800 days (~2.2 years) Also optimized look-ahead periods for other frequencies: daily (30 days), weekly (90 days), monthly (400 days) Ensures the next occurrence is always found when completing recurring task instances Thanks to @VenturaNotes for reporting (#951) Fixed yearly recurring tasks not showing up in calendar's weekly, 3-day, or day views Extended the look-ahead period for yearly recurring tasks when generating calendar instances Calendar views now look ahead ~2.2 years for yearly tasks to ensure occurrences appear even in short date ranges Only displays instances that fall within the actual visible calendar range Weekly recurring tasks were unaffected and continued to work correctly Thanks to @bespokecomp for reporting (#889) Fixed git merge conflicts in calendar subscription metadata Calendar subscription lastFetched and lastError fields are now stored in memory instead of being saved to disk Prevents git conflicts when syncing vaults across multiple computers that independently fetch calendar subscriptions The \"last synced\" timestamp in settings will reset on plugin reload, but subscriptions will re-fetch automatically Thanks to @karlfrohlich for reporting Fixed recurrence modal not loading DTSTART date/time when editing existing recurrence rules The custom recurrence modal now correctly parses and displays the start date and time fields Fixed parser that was splitting on = instead of : for DTSTART values (#1097) Fixed custom properties and formulas not displaying in Bases views Updated TaskCard to use Bases API's getValue() method for formulas and custom note properties Formulas now work correctly using formula.NAME syntax Custom note properties now work correctly using note.PROPERTY syntax Thanks to @cathywu for reporting (#1099) Fixed issues with default Bases file creation Fixed double-prefix bug in relationships template that generated invalid filter expressions like note.note.projects Fixed race condition where files created during plugin load wouldn't appear in file explorer Default Bases files now generate with correct property paths and appear reliably in the file explorer Thanks to @kmaustral for reporting (#1110) Fixed open recurring tasks appearing crossed out in Tasks view Removed stale selectedDate property that was never updated in v4 Tasks view now uses fresh UTC-anchored \"today\" for correct recurring task completion status Fixes issue where tasks completed yesterday would appear crossed out today for users in positive UTC offset timezones Also fixed KanbanView to use UTC-anchored dates for consistency Thanks to @kmaustral for reporting (#1118) Fixed user-defined fields not working in inline task conversion User-defined fields like >customfield value now properly convert to frontmatter when using the \"TaskNote: Convert task to TaskNote\" command Fixed fields appearing with internal IDs (e.g., field_1761435101864) instead of configured frontmatter key names Array values are now properly joined with commas Added userFields property to ParsedTaskData interface to support custom fields throughout the conversion flow Thanks to @guncav for reporting Fixed kanban column width CSS constraints not matching settings Updated CSS min-width from 280px to 200px and max-width from 350px to 500px to match slider range Column width slider now works correctly across the full 200-500px range Kanban view now shows empty columns for all user-defined statuses when grouping by status Empty columns appear for custom statuses defined in settings, even when no tasks have that status Allows users to drag tasks into empty status columns Works in both flat kanban view and swimlane mode Respects the existing \"Hide empty columns\" setting Thanks to @williamcheuk03 for reporting this issue"},{"route":"/obsidian/releases/4.0.1/","title":"TaskNotes 4","description":"TaskNotes 4.0.1 is a stability-focused major release that finishes the migration to Obsidian's Bases core plugin. Every task-facing view (Task List, Kanban, Calendar, Agenda...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.0.1.md","namespace":"obsidian","relativePath":"releases/4.0.1.md","raw":"# TaskNotes 4\n\nTaskNotes 4.0.1 is a stability-focused major release that finishes the migration to Obsidian's Bases core plugin. Every task-facing view (Task List, Kanban, Calendar, Agenda, Mini Calendar, and the embedded Relationships widget) now runs on `.base` files. This refactor simplifies the plugin codebase, removes bespoke UI logic, and lets workflows feel native to Obsidian—views are just files in your vault.\n\n## Highlights\n\n**New features and improvements:**\n\n- Performance improvements\n - Virtual scrolling in Task List and Kanban views handles **30,000+ tasks** without performance degradation\n- **OAuth calendar integration**\n - Google Calendar and Microsoft Outlook bi-directional sync\n - Drag calendar events in the TaskNotes calendar to update them online\n- **Configurable modals and NLP**\n - New Modal Fields settings tab for moving, hiding, or requiring fields in create/edit modals\n - Rich markdown editor and customizable NLP triggers, including autocomplete for user fields\n- **Time management features**\n - Time Entry Editor Modal \n - Improved Timeblock creation and management\n - Completion-based recurrence with `recurrence_anchor` field\n - Skippable recurrence instances\n\n**Bases architecture changes:**\n\n- **Bases-first architecture**\n - Task views ship as `.base` files inside `TaskNotes/Views/`\n - Commands and ribbon buttons now open files you control\n - Filtering/grouping/sorting uses Bases YAML instead of TaskNotes-specific UI\n - Agenda is a dedicated list-mode calendar `.base` file for fast daily/weekly reviews\n- **Inline workflows stay in sync**\n - Unified Relationships widget embeds a Bases view so project subtasks, dependencies, and blocking tasks stay in one place\n - Task cards inside notes honor the same Bases filtering/grouping rules as standalone views\n\n## Why Bases?\n\nMoving everything to Bases allowed us to delete thousands of lines of bespoke filtering logic, state management, and widget code. The plugin now leans on Obsidian's supported API, which:\n\n- Reduces maintenance overhead and improves reliability\n- Lets advanced users version-control and audit their view definitions\n- Makes saved views portable between vaults\n- Keeps TaskNotes behavior consistent with other Obsidian-native workflows\n\n## Upgrade Notes\n\n- Obsidian **1.10.1 or later** is required (Bases public API with group-by support)\n- Enable the **Bases** core plugin before opening TaskNotes views\n- Run **Settings → TaskNotes → General → Create Default Files** if you need fresh `.base` files\n- Use **Export All Saved Views to Bases** to convert any legacy FilterBar saved views into `.base` files\n- The Relationships widget uses `TaskNotes/Views/relationships.base`; adjust that file to change what appears inside notes\n\n## Breaking Changes\n\n- The old FilterBar UI has been removed—all filtering and saved views live in `.base` files\n- Legacy widget settings (`showProjectSubtasks`, `showTaskDependencies`, etc.) were replaced with `showRelationships` and `relationshipsPosition`\n- Task view commands now fail if their mapped `.base` file is missing; configure paths under **Settings → TaskNotes → General → View Commands**\n- **Priority sorting now uses alphabetical order instead of custom weights**\n - In v3, TaskNotes used priority \"weights\" to determine sort order (higher weight = higher priority)\n - In v4, Obsidian's Bases plugin sorts priorities alphabetically by their value\n - The weight field has been removed from the settings UI\n - **Workaround**: Name your priority values to sort alphabetically in your desired order\n - Example: `1-urgent`, `2-high`, `3-medium`, `4-normal`, `5-low`\n - Or: `a-urgent`, `b-high`, `c-medium`, `d-normal`, `e-low`\n- Agenda view has been replaced by the list view in Calendar\n - Grouping is not supported in this view, so the \"Overdue\" group is no longer provided\n - A separate \"Overdue\" view is available in the \"Task List\" base file\n\n## Known Issues\n\n- Users upgrading from versions prior to 3.x should export saved views to Bases before deleting old plugin data\n- Embedded Bases views still require the Bases plugin to remain enabled; disabling Bases will hide TaskNotes task views\n\n## Details\n\n### Added\n\n- Virtual scrolling and lazy rendering to Bases views for handling thousands of notes without performance degradation - Thanks to @aubreyz and @turingexmachina for reporting performance issues and help with diagnosis\n- Google Calendar and Microsoft Outlook integration via OAuth 2.0 with automatic syncing\n- Time Entry Editor Modal for managing time entries (Alt-drag on calendar to create)\n- Kanban Swimlane Layout with horizontal grouping and configurable column widths\n- Saved View Converter button in settings to convert v3 saved filter views to `.base` files\n- Context menus for time entries and ICS events in calendar views\n- Calendar icon to ICS event titles for better visual distinction\n- Hover tooltips for timeblocks in calendar views\n- MiniCalendar view for Bases integration with monthly grid and dot indicators - Thanks to @aubreyz and @turingexmachina for reporting performance issues and help with diagnosis\n- (#1090) Portuguese (Brazil) translation - Thanks to @andysteel for the contribution\n- Configurable task modal fields with drag-and-drop reordering in new \"Modal Fields\" settings tab\n- Rich markdown editor for NLP task creation with syntax highlighting and wikilink support\n- Customizable NLP triggers with autocomplete and keyboard navigation\n- Inline task link overlay enhancements with configurable visible properties\n- Kanban column reordering via drag and drop with saved order per grouping property\n- Mini calendar enhancements including week numbers, heat map visualization, note preview tooltips, and keyboard navigation\n- Unified Relationships widget consolidating project subtasks, dependencies, and blocking relationships with automatic tabs\n- Updated task card styling with improved hover effects, shadows, and gradient accents\n- (#361) Completion-based recurrence support with `recurrence_anchor` field for tasks that recur based on completion date - Thanks to @luciolebrillante for the original feature request, and @jhedlund, @nschenone, @BryanWall, @realJohnDoe, and @kazerniel for additional input and interest\n- (#416) Support for skipped recurrence instances with `skipped_instances` field and right-click skip/unskip in calendar - Thanks to @mdbraber for suggesting the array approach and @jerzy-dudzic for reporting the issue\n- Sub-grouping support to Bases Task List view with nested grouping by any property and collapsible groups\n- Documentation for default Bases templates showing all default `.base` file templates with examples\n\n### Changed\n\n- All views (Calendar, MiniCalendar, Kanban, Tasks, Agenda, Project Subtasks) now use Bases architecture with `.base` files\n- Calendar sources (Google, Microsoft, ICS events) can be toggled independently with improved timezone handling\n- Reorganized settings tabs with OAuth calendar settings in Integrations tab\n- Refactored Bases integration to use public API and trust pre-sorted data\n- Refactored calendar modules to use ES6 imports instead of lazy require() calls\n- Time entry events now show task context menu on right-click\n- Replaced MinimalNativeCache with just-in-time TaskManager for zero startup time and always-fresh task data\n- Completed internationalization with 100% translation coverage across all 6 supported languages\n- Migrated to i18n-state-manager CLI tool for improved translation management\n- Bases view templates now generate dynamically based on user settings with adaptive task filters\n- Updated Bases CalendarView to show TaskNotes in property-based events\n- NLP system overhaul with consolidated trigger configuration and direct NaturalLanguageParser usage\n- Simplified TaskCard interface and refactored TaskLinkWidget for consistency\n- Settings UI enhancements with NLP triggers configurable through Features tab\n- Refactored Bases views to use Component lifecycle properly with automatic cleanup\n- Improved development experience by converting ESLint errors to warnings\n- Renamed \"Advanced Calendar\" to \"Calendar\" throughout the UI\n- Improved timeblock visual styling in calendar views with reduced border width and softer shadows\n- Updated \"Export All Views\" button to \"Export V3 Views\" to clarify it migrates v3 saved views\n- Improved internationalization (i18n) support in General settings tab with all Bases integration settings using translation keys\n- Changed default Tasks List template view order with \"All Tasks\" first and added \"Unscheduled\" view\n\n### Fixed\n\n- (#843) Fixed task tag being added when \"Identify tasks by\" is set to \"Property\" - Thanks to @jack2game for reporting\n- Fixed dark mode calendar borders\n- Fixed Bases Kanban column ordering - Thanks to @mweichert for reporting\n- Fixed state management bug in FilterSettingsComponent\n- Fixed timezone handling for recurring events\n- (#1022, #684) Fixed tasks randomly disappearing when Smart Connections plugin is enabled by eliminating race condition - Thanks to @alejandrospoz, @seepage87, @amarjt, @luckb0x, and camara-tech for reporting and help debugging\n- (#992) Fixed \"Failed to resolve module specifier 'obsidian'\" error when moving recurring task instances in calendar - Thanks to @jalooc for reporting\n- Fixed task dependencies not displaying on task cards with proper isBlocked and isBlocking flags\n- Fixed Bases property mapping for user-configured field names\n- Fixed Bases views not respecting user-configured visible properties\n- Fixed MiniCalendar UTC anchoring for consistent timezone-independent date handling\n- Fixed DateValue conversion in BasesDataAdapter for property-based events in CalendarView\n- (#1084) Fixed word wrapping in NLP preview items - Thanks to @maybetm for the fix\n- (#975) Fixed advanced calendar list headers not respecting theme colors - Thanks to @hugohil for the fix\n- (#1089) Fixed embedded task list bases growing unbounded and leaving large empty space - Thanks to @same774 for reporting with screenshot\n- Fixed \"Highlight today\" toggle and calendar view type persistence in Bases Calendar view options\n- (#1050) Fixed task modal adding unwanted empty contexts and projects arrays - Thanks to @nightroman for reporting\n- Fixed inline task link overlay layout prioritization and horizontal scrolling for metadata\n- Fixed group collapse/expand functionality in TaskListView\n- Fixed config loading race condition in KanbanView and CalendarView\n- Fixed MiniCalendarView to use direct Bases API like other views\n- (#893) Fixed yearly recurring tasks not always updating scheduled date to next occurrence when completed - Thanks to @VenturaNotes for reporting\n- (#951) Fixed yearly recurring tasks not showing up in calendar's weekly, 3-day, or day views - Thanks to @bespokecomp for reporting\n- (#889) Fixed git merge conflicts in calendar subscription metadata by storing in memory instead of disk - Thanks to @karlfrohlich for reporting\n- Fixed recurrence modal not loading DTSTART date/time when editing existing recurrence rules\n- (#1097) Fixed custom properties and formulas not displaying in Bases views using getValue() method - Thanks to @cathywu for reporting\n- (#1099) Fixed issues with default Bases file creation including double-prefix bug and race condition - Thanks to @kmaustral for reporting\n- (#1110) Fixed open recurring tasks appearing crossed out in Tasks view by using UTC-anchored dates - Thanks to @kmaustral for reporting\n- (#1118) Fixed user-defined fields not working in inline task conversion to TaskNote - Thanks to @guncav for reporting\n- Fixed kanban column width CSS constraints not matching settings slider range\n- Fixed Kanban view showing empty columns for all user-defined statuses when grouping by status - Thanks to @williamcheuk03 for reporting\n- (#1103) Fixed TaskNotes/Views folder being created unnecessarily on startup - Thanks to @Wayment9504 for reporting\n- (#1133) Fixed empty priority columns not showing in Kanban view when \"Hide empty columns\" is disabled - Thanks to @luckb0x for reporting\n- Fixed OAuth calendar cards showing \"Unknown account\" by removing non-functional Account field - Thanks to @Oblique for reporting\n- Fixed incorrect Bases syntax in default template files with correct parameter naming\n- Fixed incorrect Bases syntax in \"Export V3 Views\" feature with correct YAML structure\n- (#1127) Fixed custom priority colors not being respected in Task List and Subtasks sections - Thanks to @HPmattsloper for reporting\n- (#1043) Fixed inability to set \"at time of event\" (0 offset) as default reminder in settings - Thanks to @dblinnikov for reporting\n- (#1055) Fixed break sessions being logged as `type: work` when started via command/hotkey - Thanks to @0-BSCode for reporting and debugging\n- (#1024) Fixed date/time picker immediately closing when selecting time on iPhone by refactoring to native Modal components - Thanks to @3zra47 for reporting\n- (#1122) Fixed inline task titles being truncated too aggressively with increased max-width - Thanks to @jacorvillo for reporting\n- Fixed Obsidian crashes when invalid time values entered in Bases calendar view configuration\n- (#1120) Fixed custom field mappings not being respected throughout the application - Thanks to @kmaustral for reporting\n- (#1121) Fixed custom user fields being saved with auto-generated IDs instead of user-defined property keys - Thanks to @guncav for reporting\n- (#1123) Fixed relationships widget only displaying on task notes, now appears on both task and project notes - Thanks to @dblinnikov for reporting\n- Fixed time entries not showing in calendar view for tasks without scheduled or due dates\n- (#1091) Fixed task card and relationships widgets appearing inside footnote editors - Thanks to @3zra47 for reporting\n- (#1086) Fixed calendar \"+more\" popover showing white text on white background in dark mode - Thanks to @same774 for reporting\n- (#1076) Fixed inability to create timeblocks ending at midnight (00:00) - Thanks to @skoove for reporting\n- (#958) Fixed cursor jumping and layout shifts when typing near task card or relationships widgets in live preview - Thanks to @thesmithmode for detailed debugging information\n- (#513) Fixed task card and relationships widgets not appearing in reading mode and fixed critical memory leak - Thanks to @berzernberg for reporting\n\n### Removed\n\n- Removed StatusSuggestionService (functionality consolidated into NaturalLanguageParser)\n- Removed legacy FilterBar UI - all filtering now lives in `.base` files\n- Removed legacy views\n\n","aliases":["/releases/4.0.1/","/releases/4.0.1/"],"toc":[{"level":2,"id":"highlights","text":"Highlights"},{"level":2,"id":"why-bases","text":"Why Bases?"},{"level":2,"id":"upgrade-notes","text":"Upgrade Notes"},{"level":2,"id":"breaking-changes","text":"Breaking Changes"},{"level":2,"id":"known-issues","text":"Known Issues"},{"level":2,"id":"details","text":"Details"},{"level":3,"id":"added","text":"Added"},{"level":3,"id":"changed","text":"Changed"},{"level":3,"id":"fixed","text":"Fixed"},{"level":3,"id":"removed","text":"Removed"}],"html":"

TaskNotes 4.0.1 is a stability-focused major release that finishes the migration to Obsidian's Bases core plugin. Every task-facing view (Task List, Kanban, Calendar, Agenda, Mini Calendar, and the embedded Relationships widget) now runs on .base files. This refactor simplifies the plugin codebase, removes bespoke UI logic, and lets workflows feel native to Obsidian—views are just files in your vault.

\n

Highlights#

\n

New features and improvements:

\n
    \n
  • Performance improvements
      \n
    • Virtual scrolling in Task List and Kanban views handles 30,000+ tasks without performance degradation
    • \n
    \n
  • \n
  • OAuth calendar integration
      \n
    • Google Calendar and Microsoft Outlook bi-directional sync
    • \n
    • Drag calendar events in the TaskNotes calendar to update them online
    • \n
    \n
  • \n
  • Configurable modals and NLP
      \n
    • New Modal Fields settings tab for moving, hiding, or requiring fields in create/edit modals
    • \n
    • Rich markdown editor and customizable NLP triggers, including autocomplete for user fields
    • \n
    \n
  • \n
  • Time management features
      \n
    • Time Entry Editor Modal
    • \n
    • Improved Timeblock creation and management
    • \n
    • Completion-based recurrence with recurrence_anchor field
    • \n
    • Skippable recurrence instances
    • \n
    \n
  • \n
\n

Bases architecture changes:

\n
    \n
  • Bases-first architecture
      \n
    • Task views ship as .base files inside TaskNotes/Views/
    • \n
    • Commands and ribbon buttons now open files you control
    • \n
    • Filtering/grouping/sorting uses Bases YAML instead of TaskNotes-specific UI
    • \n
    • Agenda is a dedicated list-mode calendar .base file for fast daily/weekly reviews
    • \n
    \n
  • \n
  • Inline workflows stay in sync
      \n
    • Unified Relationships widget embeds a Bases view so project subtasks, dependencies, and blocking tasks stay in one place
    • \n
    • Task cards inside notes honor the same Bases filtering/grouping rules as standalone views
    • \n
    \n
  • \n
\n

Why Bases?#

\n

Moving everything to Bases allowed us to delete thousands of lines of bespoke filtering logic, state management, and widget code. The plugin now leans on Obsidian's supported API, which:

\n
    \n
  • Reduces maintenance overhead and improves reliability
  • \n
  • Lets advanced users version-control and audit their view definitions
  • \n
  • Makes saved views portable between vaults
  • \n
  • Keeps TaskNotes behavior consistent with other Obsidian-native workflows
  • \n
\n

Upgrade Notes#

\n
    \n
  • Obsidian 1.10.1 or later is required (Bases public API with group-by support)
  • \n
  • Enable the Bases core plugin before opening TaskNotes views
  • \n
  • Run Settings → TaskNotes → General → Create Default Files if you need fresh .base files
  • \n
  • Use Export All Saved Views to Bases to convert any legacy FilterBar saved views into .base files
  • \n
  • The Relationships widget uses TaskNotes/Views/relationships.base; adjust that file to change what appears inside notes
  • \n
\n

Breaking Changes#

\n
    \n
  • The old FilterBar UI has been removed—all filtering and saved views live in .base files
  • \n
  • Legacy widget settings (showProjectSubtasks, showTaskDependencies, etc.) were replaced with showRelationships and relationshipsPosition
  • \n
  • Task view commands now fail if their mapped .base file is missing; configure paths under Settings → TaskNotes → General → View Commands
  • \n
  • Priority sorting now uses alphabetical order instead of custom weights
      \n
    • In v3, TaskNotes used priority "weights" to determine sort order (higher weight = higher priority)
    • \n
    • In v4, Obsidian's Bases plugin sorts priorities alphabetically by their value
    • \n
    • The weight field has been removed from the settings UI
    • \n
    • Workaround: Name your priority values to sort alphabetically in your desired order
        \n
      • Example: 1-urgent, 2-high, 3-medium, 4-normal, 5-low
      • \n
      • Or: a-urgent, b-high, c-medium, d-normal, e-low
      • \n
      \n
    • \n
    \n
  • \n
  • Agenda view has been replaced by the list view in Calendar
      \n
    • Grouping is not supported in this view, so the "Overdue" group is no longer provided
    • \n
    • A separate "Overdue" view is available in the "Task List" base file
    • \n
    \n
  • \n
\n

Known Issues#

\n
    \n
  • Users upgrading from versions prior to 3.x should export saved views to Bases before deleting old plugin data
  • \n
  • Embedded Bases views still require the Bases plugin to remain enabled; disabling Bases will hide TaskNotes task views
  • \n
\n

Details#

\n

Added#

\n
    \n
  • Virtual scrolling and lazy rendering to Bases views for handling thousands of notes without performance degradation - Thanks to @aubreyz and @turingexmachina for reporting performance issues and help with diagnosis
  • \n
  • Google Calendar and Microsoft Outlook integration via OAuth 2.0 with automatic syncing
  • \n
  • Time Entry Editor Modal for managing time entries (Alt-drag on calendar to create)
  • \n
  • Kanban Swimlane Layout with horizontal grouping and configurable column widths
  • \n
  • Saved View Converter button in settings to convert v3 saved filter views to .base files
  • \n
  • Context menus for time entries and ICS events in calendar views
  • \n
  • Calendar icon to ICS event titles for better visual distinction
  • \n
  • Hover tooltips for timeblocks in calendar views
  • \n
  • MiniCalendar view for Bases integration with monthly grid and dot indicators - Thanks to @aubreyz and @turingexmachina for reporting performance issues and help with diagnosis
  • \n
  • (#1090) Portuguese (Brazil) translation - Thanks to @andysteel for the contribution
  • \n
  • Configurable task modal fields with drag-and-drop reordering in new "Modal Fields" settings tab
  • \n
  • Rich markdown editor for NLP task creation with syntax highlighting and wikilink support
  • \n
  • Customizable NLP triggers with autocomplete and keyboard navigation
  • \n
  • Inline task link overlay enhancements with configurable visible properties
  • \n
  • Kanban column reordering via drag and drop with saved order per grouping property
  • \n
  • Mini calendar enhancements including week numbers, heat map visualization, note preview tooltips, and keyboard navigation
  • \n
  • Unified Relationships widget consolidating project subtasks, dependencies, and blocking relationships with automatic tabs
  • \n
  • Updated task card styling with improved hover effects, shadows, and gradient accents
  • \n
  • (#361) Completion-based recurrence support with recurrence_anchor field for tasks that recur based on completion date - Thanks to @luciolebrillante for the original feature request, and @jhedlund, @nschenone, @BryanWall, @realJohnDoe, and @kazerniel for additional input and interest
  • \n
  • (#416) Support for skipped recurrence instances with skipped_instances field and right-click skip/unskip in calendar - Thanks to @mdbraber for suggesting the array approach and @jerzy-dudzic for reporting the issue
  • \n
  • Sub-grouping support to Bases Task List view with nested grouping by any property and collapsible groups
  • \n
  • Documentation for default Bases templates showing all default .base file templates with examples
  • \n
\n

Changed#

\n
    \n
  • All views (Calendar, MiniCalendar, Kanban, Tasks, Agenda, Project Subtasks) now use Bases architecture with .base files
  • \n
  • Calendar sources (Google, Microsoft, ICS events) can be toggled independently with improved timezone handling
  • \n
  • Reorganized settings tabs with OAuth calendar settings in Integrations tab
  • \n
  • Refactored Bases integration to use public API and trust pre-sorted data
  • \n
  • Refactored calendar modules to use ES6 imports instead of lazy require() calls
  • \n
  • Time entry events now show task context menu on right-click
  • \n
  • Replaced MinimalNativeCache with just-in-time TaskManager for zero startup time and always-fresh task data
  • \n
  • Completed internationalization with 100% translation coverage across all 6 supported languages
  • \n
  • Migrated to i18n-state-manager CLI tool for improved translation management
  • \n
  • Bases view templates now generate dynamically based on user settings with adaptive task filters
  • \n
  • Updated Bases CalendarView to show TaskNotes in property-based events
  • \n
  • NLP system overhaul with consolidated trigger configuration and direct NaturalLanguageParser usage
  • \n
  • Simplified TaskCard interface and refactored TaskLinkWidget for consistency
  • \n
  • Settings UI enhancements with NLP triggers configurable through Features tab
  • \n
  • Refactored Bases views to use Component lifecycle properly with automatic cleanup
  • \n
  • Improved development experience by converting ESLint errors to warnings
  • \n
  • Renamed "Advanced Calendar" to "Calendar" throughout the UI
  • \n
  • Improved timeblock visual styling in calendar views with reduced border width and softer shadows
  • \n
  • Updated "Export All Views" button to "Export V3 Views" to clarify it migrates v3 saved views
  • \n
  • Improved internationalization (i18n) support in General settings tab with all Bases integration settings using translation keys
  • \n
  • Changed default Tasks List template view order with "All Tasks" first and added "Unscheduled" view
  • \n
\n

Fixed#

\n
    \n
  • (#843) Fixed task tag being added when "Identify tasks by" is set to "Property" - Thanks to @jack2game for reporting
  • \n
  • Fixed dark mode calendar borders
  • \n
  • Fixed Bases Kanban column ordering - Thanks to @mweichert for reporting
  • \n
  • Fixed state management bug in FilterSettingsComponent
  • \n
  • Fixed timezone handling for recurring events
  • \n
  • (#1022, #684) Fixed tasks randomly disappearing when Smart Connections plugin is enabled by eliminating race condition - Thanks to @alejandrospoz, @seepage87, @amarjt, @luckb0x, and camara-tech for reporting and help debugging
  • \n
  • (#992) Fixed "Failed to resolve module specifier 'obsidian'" error when moving recurring task instances in calendar - Thanks to @jalooc for reporting
  • \n
  • Fixed task dependencies not displaying on task cards with proper isBlocked and isBlocking flags
  • \n
  • Fixed Bases property mapping for user-configured field names
  • \n
  • Fixed Bases views not respecting user-configured visible properties
  • \n
  • Fixed MiniCalendar UTC anchoring for consistent timezone-independent date handling
  • \n
  • Fixed DateValue conversion in BasesDataAdapter for property-based events in CalendarView
  • \n
  • (#1084) Fixed word wrapping in NLP preview items - Thanks to @maybetm for the fix
  • \n
  • (#975) Fixed advanced calendar list headers not respecting theme colors - Thanks to @hugohil for the fix
  • \n
  • (#1089) Fixed embedded task list bases growing unbounded and leaving large empty space - Thanks to @same774 for reporting with screenshot
  • \n
  • Fixed "Highlight today" toggle and calendar view type persistence in Bases Calendar view options
  • \n
  • (#1050) Fixed task modal adding unwanted empty contexts and projects arrays - Thanks to @nightroman for reporting
  • \n
  • Fixed inline task link overlay layout prioritization and horizontal scrolling for metadata
  • \n
  • Fixed group collapse/expand functionality in TaskListView
  • \n
  • Fixed config loading race condition in KanbanView and CalendarView
  • \n
  • Fixed MiniCalendarView to use direct Bases API like other views
  • \n
  • (#893) Fixed yearly recurring tasks not always updating scheduled date to next occurrence when completed - Thanks to @VenturaNotes for reporting
  • \n
  • (#951) Fixed yearly recurring tasks not showing up in calendar's weekly, 3-day, or day views - Thanks to @bespokecomp for reporting
  • \n
  • (#889) Fixed git merge conflicts in calendar subscription metadata by storing in memory instead of disk - Thanks to @karlfrohlich for reporting
  • \n
  • Fixed recurrence modal not loading DTSTART date/time when editing existing recurrence rules
  • \n
  • (#1097) Fixed custom properties and formulas not displaying in Bases views using getValue() method - Thanks to @cathywu for reporting
  • \n
  • (#1099) Fixed issues with default Bases file creation including double-prefix bug and race condition - Thanks to @kmaustral for reporting
  • \n
  • (#1110) Fixed open recurring tasks appearing crossed out in Tasks view by using UTC-anchored dates - Thanks to @kmaustral for reporting
  • \n
  • (#1118) Fixed user-defined fields not working in inline task conversion to TaskNote - Thanks to @guncav for reporting
  • \n
  • Fixed kanban column width CSS constraints not matching settings slider range
  • \n
  • Fixed Kanban view showing empty columns for all user-defined statuses when grouping by status - Thanks to @williamcheuk03 for reporting
  • \n
  • (#1103) Fixed TaskNotes/Views folder being created unnecessarily on startup - Thanks to @Wayment9504 for reporting
  • \n
  • (#1133) Fixed empty priority columns not showing in Kanban view when "Hide empty columns" is disabled - Thanks to @luckb0x for reporting
  • \n
  • Fixed OAuth calendar cards showing "Unknown account" by removing non-functional Account field - Thanks to @Oblique for reporting
  • \n
  • Fixed incorrect Bases syntax in default template files with correct parameter naming
  • \n
  • Fixed incorrect Bases syntax in "Export V3 Views" feature with correct YAML structure
  • \n
  • (#1127) Fixed custom priority colors not being respected in Task List and Subtasks sections - Thanks to @HPmattsloper for reporting
  • \n
  • (#1043) Fixed inability to set "at time of event" (0 offset) as default reminder in settings - Thanks to @dblinnikov for reporting
  • \n
  • (#1055) Fixed break sessions being logged as type: work when started via command/hotkey - Thanks to @0-BSCode for reporting and debugging
  • \n
  • (#1024) Fixed date/time picker immediately closing when selecting time on iPhone by refactoring to native Modal components - Thanks to @3zra47 for reporting
  • \n
  • (#1122) Fixed inline task titles being truncated too aggressively with increased max-width - Thanks to @jacorvillo for reporting
  • \n
  • Fixed Obsidian crashes when invalid time values entered in Bases calendar view configuration
  • \n
  • (#1120) Fixed custom field mappings not being respected throughout the application - Thanks to @kmaustral for reporting
  • \n
  • (#1121) Fixed custom user fields being saved with auto-generated IDs instead of user-defined property keys - Thanks to @guncav for reporting
  • \n
  • (#1123) Fixed relationships widget only displaying on task notes, now appears on both task and project notes - Thanks to @dblinnikov for reporting
  • \n
  • Fixed time entries not showing in calendar view for tasks without scheduled or due dates
  • \n
  • (#1091) Fixed task card and relationships widgets appearing inside footnote editors - Thanks to @3zra47 for reporting
  • \n
  • (#1086) Fixed calendar "+more" popover showing white text on white background in dark mode - Thanks to @same774 for reporting
  • \n
  • (#1076) Fixed inability to create timeblocks ending at midnight (00:00) - Thanks to @skoove for reporting
  • \n
  • (#958) Fixed cursor jumping and layout shifts when typing near task card or relationships widgets in live preview - Thanks to @thesmithmode for detailed debugging information
  • \n
  • (#513) Fixed task card and relationships widgets not appearing in reading mode and fixed critical memory leak - Thanks to @berzernberg for reporting
  • \n
\n

Removed#

\n
    \n
  • Removed StatusSuggestionService (functionality consolidated into NaturalLanguageParser)
  • \n
  • Removed legacy FilterBar UI - all filtering now lives in .base files
  • \n
  • Removed legacy views
  • \n
\n","text":"TaskNotes 4.0.1 is a stability-focused major release that finishes the migration to Obsidian's Bases core plugin. Every task-facing view (Task List, Kanban, Calendar, Agenda, Mini Calendar, and the embedded Relationships widget) now runs on .base files. This refactor simplifies the plugin codebase, removes bespoke UI logic, and lets workflows feel native to Obsidian—views are just files in your vault. Highlights# New features and improvements: Performance improvements Virtual scrolling in Task List and Kanban views handles 30,000+ tasks without performance degradation OAuth calendar integration Google Calendar and Microsoft Outlook bi-directional sync Drag calendar events in the TaskNotes calendar to update them online Configurable modals and NLP New Modal Fields settings tab for moving, hiding, or requiring fields in create/edit modals Rich markdown editor and customizable NLP triggers, including autocomplete for user fields Time management features Time Entry Editor Modal Improved Timeblock creation and management Completion-based recurrence with recurrence_anchor field Skippable recurrence instances Bases architecture changes: Bases-first architecture Task views ship as .base files inside TaskNotes/Views/ Commands and ribbon buttons now open files you control Filtering/grouping/sorting uses Bases YAML instead of TaskNotes-specific UI Agenda is a dedicated list-mode calendar .base file for fast daily/weekly reviews Inline workflows stay in sync Unified Relationships widget embeds a Bases view so project subtasks, dependencies, and blocking tasks stay in one place Task cards inside notes honor the same Bases filtering/grouping rules as standalone views Why Bases?# Moving everything to Bases allowed us to delete thousands of lines of bespoke filtering logic, state management, and widget code. The plugin now leans on Obsidian's supported API, which: Reduces maintenance overhead and improves reliability Lets advanced users version-control and audit their view definitions Makes saved views portable between vaults Keeps TaskNotes behavior consistent with other Obsidian-native workflows Upgrade Notes# Obsidian 1.10.1 or later is required (Bases public API with group-by support) Enable the Bases core plugin before opening TaskNotes views Run Settings → TaskNotes → General → Create Default Files if you need fresh .base files Use Export All Saved Views to Bases to convert any legacy FilterBar saved views into .base files The Relationships widget uses TaskNotes/Views/relationships.base; adjust that file to change what appears inside notes Breaking Changes# The old FilterBar UI has been removed—all filtering and saved views live in .base files Legacy widget settings (showProjectSubtasks, showTaskDependencies, etc.) were replaced with showRelationships and relationshipsPosition Task view commands now fail if their mapped .base file is missing; configure paths under Settings → TaskNotes → General → View Commands Priority sorting now uses alphabetical order instead of custom weights In v3, TaskNotes used priority \"weights\" to determine sort order (higher weight = higher priority) In v4, Obsidian's Bases plugin sorts priorities alphabetically by their value The weight field has been removed from the settings UI Workaround: Name your priority values to sort alphabetically in your desired order Example: 1-urgent, 2-high, 3-medium, 4-normal, 5-low Or: a-urgent, b-high, c-medium, d-normal, e-low Agenda view has been replaced by the list view in Calendar Grouping is not supported in this view, so the \"Overdue\" group is no longer provided A separate \"Overdue\" view is available in the \"Task List\" base file Known Issues# Users upgrading from versions prior to 3.x should export saved views to Bases before deleting old plugin data Embedded Bases views still require the Bases plugin to remain enabled; disabling Bases will hide TaskNotes task views Details# Added# Virtual scrolling and lazy rendering to Bases views for handling thousands of notes without performance degradation - Thanks to @aubreyz and @turingexmachina for reporting performance issues and help with diagnosis Google Calendar and Microsoft Outlook integration via OAuth 2.0 with automatic syncing Time Entry Editor Modal for managing time entries (Alt-drag on calendar to create) Kanban Swimlane Layout with horizontal grouping and configurable column widths Saved View Converter button in settings to convert v3 saved filter views to .base files Context menus for time entries and ICS events in calendar views Calendar icon to ICS event titles for better visual distinction Hover tooltips for timeblocks in calendar views MiniCalendar view for Bases integration with monthly grid and dot indicators - Thanks to @aubreyz and @turingexmachina for reporting performance issues and help with diagnosis (#1090) Portuguese (Brazil) translation - Thanks to @andysteel for the contribution Configurable task modal fields with drag-and-drop reordering in new \"Modal Fields\" settings tab Rich markdown editor for NLP task creation with syntax highlighting and wikilink support Customizable NLP triggers with autocomplete and keyboard navigation Inline task link overlay enhancements with configurable visible properties Kanban column reordering via drag and drop with saved order per grouping property Mini calendar enhancements including week numbers, heat map visualization, note preview tooltips, and keyboard navigation Unified Relationships widget consolidating project subtasks, dependencies, and blocking relationships with automatic tabs Updated task card styling with improved hover effects, shadows, and gradient accents (#361) Completion-based recurrence support with recurrence_anchor field for tasks that recur based on completion date - Thanks to @luciolebrillante for the original feature request, and @jhedlund, @nschenone, @BryanWall, @realJohnDoe, and @kazerniel for additional input and interest (#416) Support for skipped recurrence instances with skipped_instances field and right-click skip/unskip in calendar - Thanks to @mdbraber for suggesting the array approach and @jerzy-dudzic for reporting the issue Sub-grouping support to Bases Task List view with nested grouping by any property and collapsible groups Documentation for default Bases templates showing all default .base file templates with examples Changed# All views (Calendar, MiniCalendar, Kanban, Tasks, Agenda, Project Subtasks) now use Bases architecture with .base files Calendar sources (Google, Microsoft, ICS events) can be toggled independently with improved timezone handling Reorganized settings tabs with OAuth calendar settings in Integrations tab Refactored Bases integration to use public API and trust pre-sorted data Refactored calendar modules to use ES6 imports instead of lazy require() calls Time entry events now show task context menu on right-click Replaced MinimalNativeCache with just-in-time TaskManager for zero startup time and always-fresh task data Completed internationalization with 100% translation coverage across all 6 supported languages Migrated to i18n-state-manager CLI tool for improved translation management Bases view templates now generate dynamically based on user settings with adaptive task filters Updated Bases CalendarView to show TaskNotes in property-based events NLP system overhaul with consolidated trigger configuration and direct NaturalLanguageParser usage Simplified TaskCard interface and refactored TaskLinkWidget for consistency Settings UI enhancements with NLP triggers configurable through Features tab Refactored Bases views to use Component lifecycle properly with automatic cleanup Improved development experience by converting ESLint errors to warnings Renamed \"Advanced Calendar\" to \"Calendar\" throughout the UI Improved timeblock visual styling in calendar views with reduced border width and softer shadows Updated \"Export All Views\" button to \"Export V3 Views\" to clarify it migrates v3 saved views Improved internationalization (i18n) support in General settings tab with all Bases integration settings using translation keys Changed default Tasks List template view order with \"All Tasks\" first and added \"Unscheduled\" view Fixed# (#843) Fixed task tag being added when \"Identify tasks by\" is set to \"Property\" - Thanks to @jack2game for reporting Fixed dark mode calendar borders Fixed Bases Kanban column ordering - Thanks to @mweichert for reporting Fixed state management bug in FilterSettingsComponent Fixed timezone handling for recurring events (#1022, #684) Fixed tasks randomly disappearing when Smart Connections plugin is enabled by eliminating race condition - Thanks to @alejandrospoz, @seepage87, @amarjt, @luckb0x, and camara-tech for reporting and help debugging (#992) Fixed \"Failed to resolve module specifier 'obsidian'\" error when moving recurring task instances in calendar - Thanks to @jalooc for reporting Fixed task dependencies not displaying on task cards with proper isBlocked and isBlocking flags Fixed Bases property mapping for user-configured field names Fixed Bases views not respecting user-configured visible properties Fixed MiniCalendar UTC anchoring for consistent timezone-independent date handling Fixed DateValue conversion in BasesDataAdapter for property-based events in CalendarView (#1084) Fixed word wrapping in NLP preview items - Thanks to @maybetm for the fix (#975) Fixed advanced calendar list headers not respecting theme colors - Thanks to @hugohil for the fix (#1089) Fixed embedded task list bases growing unbounded and leaving large empty space - Thanks to @same774 for reporting with screenshot Fixed \"Highlight today\" toggle and calendar view type persistence in Bases Calendar view options (#1050) Fixed task modal adding unwanted empty contexts and projects arrays - Thanks to @nightroman for reporting Fixed inline task link overlay layout prioritization and horizontal scrolling for metadata Fixed group collapse/expand functionality in TaskListView Fixed config loading race condition in KanbanView and CalendarView Fixed MiniCalendarView to use direct Bases API like other views (#893) Fixed yearly recurring tasks not always updating scheduled date to next occurrence when completed - Thanks to @VenturaNotes for reporting (#951) Fixed yearly recurring tasks not showing up in calendar's weekly, 3-day, or day views - Thanks to @bespokecomp for reporting (#889) Fixed git merge conflicts in calendar subscription metadata by storing in memory instead of disk - Thanks to @karlfrohlich for reporting Fixed recurrence modal not loading DTSTART date/time when editing existing recurrence rules (#1097) Fixed custom properties and formulas not displaying in Bases views using getValue() method - Thanks to @cathywu for reporting (#1099) Fixed issues with default Bases file creation including double-prefix bug and race condition - Thanks to @kmaustral for reporting (#1110) Fixed open recurring tasks appearing crossed out in Tasks view by using UTC-anchored dates - Thanks to @kmaustral for reporting (#1118) Fixed user-defined fields not working in inline task conversion to TaskNote - Thanks to @guncav for reporting Fixed kanban column width CSS constraints not matching settings slider range Fixed Kanban view showing empty columns for all user-defined statuses when grouping by status - Thanks to @williamcheuk03 for reporting (#1103) Fixed TaskNotes/Views folder being created unnecessarily on startup - Thanks to @Wayment9504 for reporting (#1133) Fixed empty priority columns not showing in Kanban view when \"Hide empty columns\" is disabled - Thanks to @luckb0x for reporting Fixed OAuth calendar cards showing \"Unknown account\" by removing non-functional Account field - Thanks to @Oblique for reporting Fixed incorrect Bases syntax in default template files with correct parameter naming Fixed incorrect Bases syntax in \"Export V3 Views\" feature with correct YAML structure (#1127) Fixed custom priority colors not being respected in Task List and Subtasks sections - Thanks to @HPmattsloper for reporting (#1043) Fixed inability to set \"at time of event\" (0 offset) as default reminder in settings - Thanks to @dblinnikov for reporting (#1055) Fixed break sessions being logged as type: work when started via command/hotkey - Thanks to @0-BSCode for reporting and debugging (#1024) Fixed date/time picker immediately closing when selecting time on iPhone by refactoring to native Modal components - Thanks to @3zra47 for reporting (#1122) Fixed inline task titles being truncated too aggressively with increased max-width - Thanks to @jacorvillo for reporting Fixed Obsidian crashes when invalid time values entered in Bases calendar view configuration (#1120) Fixed custom field mappings not being respected throughout the application - Thanks to @kmaustral for reporting (#1121) Fixed custom user fields being saved with auto-generated IDs instead of user-defined property keys - Thanks to @guncav for reporting (#1123) Fixed relationships widget only displaying on task notes, now appears on both task and project notes - Thanks to @dblinnikov for reporting Fixed time entries not showing in calendar view for tasks without scheduled or due dates (#1091) Fixed task card and relationships widgets appearing inside footnote editors - Thanks to @3zra47 for reporting (#1086) Fixed calendar \"+more\" popover showing white text on white background in dark mode - Thanks to @same774 for reporting (#1076) Fixed inability to create timeblocks ending at midnight (00:00) - Thanks to @skoove for reporting (#958) Fixed cursor jumping and layout shifts when typing near task card or relationships widgets in live preview - Thanks to @thesmithmode for detailed debugging information (#513) Fixed task card and relationships widgets not appearing in reading mode and fixed critical memory leak - Thanks to @berzernberg for reporting Removed# Removed StatusSuggestionService (functionality consolidated into NaturalLanguageParser) Removed legacy FilterBar UI - all filtering now lives in .base files Removed legacy views"},{"route":"/obsidian/releases/4.0.2/","title":"TaskNotes 4.0.2","description":"This release fixes some of the more urgent (and easy-to-fix) bugs that were introduced in the v4 major release. Thanks to everyone for your patience, and to those who have repor...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.0.2.md","namespace":"obsidian","relativePath":"releases/4.0.2.md","raw":"# TaskNotes 4.0.2\n\nThis release fixes some of the more urgent (and easy-to-fix) bugs that were introduced in the v4 major release. Thanks to everyone for your patience, and to those who have reported issues, for taking the time to do so. There will be more releases over the coming weeks to iron out some of v4's kinks.\n\n## Added\n\n- Added \"Not Blocked\" view to default task list template\n - Shows incomplete tasks that are ready to work on (not blocked by incomplete dependencies)\n - Uses Bases `list.filter()` to check completion status of each blocking task\n - This new view can be accessed by regenerating the Task List view, or by copying the filters from the [default base templates documentation](https://tasknotes.dev/views/default-base-templates)\n\n## Fixed\n\n- (#1145, #1156) Fixed default Kanban view requiring manual 'Group by' configuration\n - Default Kanban template now automatically includes `groupBy` property set to status\n - Resolves \"Kanban requires a 'Group by' property to be configured\" error on first use\n - Users no longer need to manually configure grouping through the Sort menu\n - Thanks to @randomness42 and @seepage87 for reporting\n- Fixed user-defined custom fields appearing as `user:field_xxx` in generated base templates\n - Custom fields now use their actual property names (e.g., `effort` instead of `user:field_1761435303709`)\n - Ensures Bases can properly query user-defined properties\n - Also fixed `totalTrackedTime` to correctly map to the configured `timeEntries` property name\n- (#1145) Improved Kanban error message when no 'Group by' property is configured\n - Now includes instructions: \"Click the 'Sort' button and select a property under 'Group by'\"\n - Thanks to @randomness42 for the suggestion\n- (#1139, #1141) Fixed relationships widget not appearing in project notes\n - Project references are now resolved to full file paths when indexing\n - Uses Obsidian's link resolution API to handle wikilinks, markdown links, and relative paths\n - Restores v3.x behavior where subtasks appear in parent project notes\n - Thanks to @jhedlund, @n1njaznutz, and @luckb0x for reporting and testing\n- Fixed dependency blocking status to be status-aware\n - \"Blocked (x)\" pill now only appears when tasks have **incomplete** blocking dependencies\n - Tasks with all completed blocking dependencies no longer show as blocked\n- Fixed cache invalidation bug causing blocking/blocked pills to disappear when editing tasks\n - When a task is modified, only forward dependencies are cleared (stored in its frontmatter)\n - Reverse dependencies are preserved (stored in other tasks' frontmatter)\n\n## Changed\n\n- Removed custom TaskNotes icon from task modals\n - Task creation and edit modals now use Obsidian's standard title styling \n - Thanks to @kepano for the suggestion\n- Moved default base templates documentation to `docs/views/`\n - Location: `docs/views/default-base-templates.md`\n - Added cross-references to official Obsidian Bases documentation\n - Updated code comments to reference new documentation path\n- Fixed incorrect quote escaping in default base templates documentation\n - YAML examples now use proper single quotes for strings containing double quotes\n","aliases":["/releases/4.0.2/","/releases/4.0.2/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"changed","text":"Changed"}],"html":"

This release fixes some of the more urgent (and easy-to-fix) bugs that were introduced in the v4 major release. Thanks to everyone for your patience, and to those who have reported issues, for taking the time to do so. There will be more releases over the coming weeks to iron out some of v4's kinks.

\n

Added#

\n
    \n
  • Added "Not Blocked" view to default task list template
      \n
    • Shows incomplete tasks that are ready to work on (not blocked by incomplete dependencies)
    • \n
    • Uses Bases list.filter() to check completion status of each blocking task
    • \n
    • This new view can be accessed by regenerating the Task List view, or by copying the filters from the default base templates documentation
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1145, #1156) Fixed default Kanban view requiring manual 'Group by' configuration
      \n
    • Default Kanban template now automatically includes groupBy property set to status
    • \n
    • Resolves "Kanban requires a 'Group by' property to be configured" error on first use
    • \n
    • Users no longer need to manually configure grouping through the Sort menu
    • \n
    • Thanks to @randomness42 and @seepage87 for reporting
    • \n
    \n
  • \n
  • Fixed user-defined custom fields appearing as user:field_xxx in generated base templates
      \n
    • Custom fields now use their actual property names (e.g., effort instead of user:field_1761435303709)
    • \n
    • Ensures Bases can properly query user-defined properties
    • \n
    • Also fixed totalTrackedTime to correctly map to the configured timeEntries property name
    • \n
    \n
  • \n
  • (#1145) Improved Kanban error message when no 'Group by' property is configured
      \n
    • Now includes instructions: "Click the 'Sort' button and select a property under 'Group by'"
    • \n
    • Thanks to @randomness42 for the suggestion
    • \n
    \n
  • \n
  • (#1139, #1141) Fixed relationships widget not appearing in project notes
      \n
    • Project references are now resolved to full file paths when indexing
    • \n
    • Uses Obsidian's link resolution API to handle wikilinks, markdown links, and relative paths
    • \n
    • Restores v3.x behavior where subtasks appear in parent project notes
    • \n
    • Thanks to @jhedlund, @n1njaznutz, and @luckb0x for reporting and testing
    • \n
    \n
  • \n
  • Fixed dependency blocking status to be status-aware
      \n
    • "Blocked (x)" pill now only appears when tasks have incomplete blocking dependencies
    • \n
    • Tasks with all completed blocking dependencies no longer show as blocked
    • \n
    \n
  • \n
  • Fixed cache invalidation bug causing blocking/blocked pills to disappear when editing tasks
      \n
    • When a task is modified, only forward dependencies are cleared (stored in its frontmatter)
    • \n
    • Reverse dependencies are preserved (stored in other tasks' frontmatter)
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Removed custom TaskNotes icon from task modals
      \n
    • Task creation and edit modals now use Obsidian's standard title styling
    • \n
    • Thanks to @kepano for the suggestion
    • \n
    \n
  • \n
  • Moved default base templates documentation to docs/views/
      \n
    • Location: docs/views/default-base-templates.md
    • \n
    • Added cross-references to official Obsidian Bases documentation
    • \n
    • Updated code comments to reference new documentation path
    • \n
    \n
  • \n
  • Fixed incorrect quote escaping in default base templates documentation
      \n
    • YAML examples now use proper single quotes for strings containing double quotes
    • \n
    \n
  • \n
\n","text":"This release fixes some of the more urgent (and easy-to-fix) bugs that were introduced in the v4 major release. Thanks to everyone for your patience, and to those who have reported issues, for taking the time to do so. There will be more releases over the coming weeks to iron out some of v4's kinks. Added# Added \"Not Blocked\" view to default task list template Shows incomplete tasks that are ready to work on (not blocked by incomplete dependencies) Uses Bases list.filter() to check completion status of each blocking task This new view can be accessed by regenerating the Task List view, or by copying the filters from the default base templates documentation Fixed# (#1145, #1156) Fixed default Kanban view requiring manual 'Group by' configuration Default Kanban template now automatically includes groupBy property set to status Resolves \"Kanban requires a 'Group by' property to be configured\" error on first use Users no longer need to manually configure grouping through the Sort menu Thanks to @randomness42 and @seepage87 for reporting Fixed user-defined custom fields appearing as user:field_xxx in generated base templates Custom fields now use their actual property names (e.g., effort instead of user:field_1761435303709) Ensures Bases can properly query user-defined properties Also fixed totalTrackedTime to correctly map to the configured timeEntries property name (#1145) Improved Kanban error message when no 'Group by' property is configured Now includes instructions: \"Click the 'Sort' button and select a property under 'Group by'\" Thanks to @randomness42 for the suggestion (#1139, #1141) Fixed relationships widget not appearing in project notes Project references are now resolved to full file paths when indexing Uses Obsidian's link resolution API to handle wikilinks, markdown links, and relative paths Restores v3.x behavior where subtasks appear in parent project notes Thanks to @jhedlund, @n1njaznutz, and @luckb0x for reporting and testing Fixed dependency blocking status to be status-aware \"Blocked (x)\" pill now only appears when tasks have incomplete blocking dependencies Tasks with all completed blocking dependencies no longer show as blocked Fixed cache invalidation bug causing blocking/blocked pills to disappear when editing tasks When a task is modified, only forward dependencies are cleared (stored in its frontmatter) Reverse dependencies are preserved (stored in other tasks' frontmatter) Changed# Removed custom TaskNotes icon from task modals Task creation and edit modals now use Obsidian's standard title styling Thanks to @kepano for the suggestion Moved default base templates documentation to docs/views/ Location: docs/views/default-base-templates.md Added cross-references to official Obsidian Bases documentation Updated code comments to reference new documentation path Fixed incorrect quote escaping in default base templates documentation YAML examples now use proper single quotes for strings containing double quotes"},{"route":"/obsidian/releases/4.0.3/","title":"TaskNotes 4.0.3","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.0.3.md","namespace":"obsidian","relativePath":"releases/4.0.3.md","raw":"# TaskNotes 4.0.3\n\n## Fixed\n\n- (#1157) Fixed task embeds appearing on new line instead of inline with bullets in lists\n - Changed inline task cards to use span elements instead of divs for proper inline flow\n - Added max-width constraint to prevent wrapping when tasks are wider than editor\n - Task embeds now display correctly inline with bullet points during live preview\n - Thanks to @3zra47 for reporting\n- (#1168) Fixed mini calendar stealing focus every few seconds when pinned to sidebar\n - Thanks to @DearHaruHaru for reporting\n- (#1161, #1162) Fixed \"unexpected scalar\" YAML parsing error in generated tasks-default.base template\n - Changed nested quotes in \"Not Blocked\" filter from double to single quotes\n - Thanks to @benschifman and @InterstellarRaccoon for reporting, @GarrettKaupp for identifying the fix\n\n## Changed\n\n- Updated task modal UI to use native Obsidian patterns for better theme compatibility\n - Thanks to @kepano for feedback\n\n","aliases":["/releases/4.0.3/","/releases/4.0.3/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"changed","text":"Changed"}],"html":"

Fixed#

\n
    \n
  • (#1157) Fixed task embeds appearing on new line instead of inline with bullets in lists
      \n
    • Changed inline task cards to use span elements instead of divs for proper inline flow
    • \n
    • Added max-width constraint to prevent wrapping when tasks are wider than editor
    • \n
    • Task embeds now display correctly inline with bullet points during live preview
    • \n
    • Thanks to @3zra47 for reporting
    • \n
    \n
  • \n
  • (#1168) Fixed mini calendar stealing focus every few seconds when pinned to sidebar
      \n
    • Thanks to @DearHaruHaru for reporting
    • \n
    \n
  • \n
  • (#1161, #1162) Fixed "unexpected scalar" YAML parsing error in generated tasks-default.base template
      \n
    • Changed nested quotes in "Not Blocked" filter from double to single quotes
    • \n
    • Thanks to @benschifman and @InterstellarRaccoon for reporting, @GarrettKaupp for identifying the fix
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Updated task modal UI to use native Obsidian patterns for better theme compatibility
      \n
    • Thanks to @kepano for feedback
    • \n
    \n
  • \n
\n","text":"Fixed# (#1157) Fixed task embeds appearing on new line instead of inline with bullets in lists Changed inline task cards to use span elements instead of divs for proper inline flow Added max-width constraint to prevent wrapping when tasks are wider than editor Task embeds now display correctly inline with bullet points during live preview Thanks to @3zra47 for reporting (#1168) Fixed mini calendar stealing focus every few seconds when pinned to sidebar Thanks to @DearHaruHaru for reporting (#1161, #1162) Fixed \"unexpected scalar\" YAML parsing error in generated tasks-default.base template Changed nested quotes in \"Not Blocked\" filter from double to single quotes Thanks to @benschifman and @InterstellarRaccoon for reporting, @GarrettKaupp for identifying the fix Changed# Updated task modal UI to use native Obsidian patterns for better theme compatibility Thanks to @kepano for feedback"},{"route":"/obsidian/releases/4.0.4/","title":"TaskNotes 4.0.4","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.0.4.md","namespace":"obsidian","relativePath":"releases/4.0.4.md","raw":"# TaskNotes 4.0.4\n\n## Added\n\n- (#1134, #779) Added CMD+Enter (Mac) / Ctrl+Enter (Windows/Linux) keyboard shortcut support for saving in all modals\n - Works from any input field in task creation, task edit, time entry, timeblock, and property selector modals\n - Thanks to @luckb0x, @hamlim and @nightroman for the feature requests\n\n## Fixed\n\n- (#1181) Fixed vertical overflow in Kanban view columns with fewer than 15 tasks\n - Prevents cards from extending beyond column boundaries before virtualization activates\n - Thanks to @lomarcanys for reporting\n- (#1177) Bases views now anchor recurring completion and calendar navigation to the right date\n - Recurring completion from Bases Task List/Kanban uses the task's scheduled/due date instead of \"today\" (fixes complete_instances)\n - Bases calendar navigation and property-based events use UTC anchors to avoid previous-day jumps\n - Thanks to @nslee123 for flagging the issue\n- Bases calendar navigation now respects UTC-anchored dates to avoid landing on the previous day\n - Corrected all-day end date calculation to prevent off-by-one spans\n - Added regression test for the UTC anchor behavior\n - Thanks to KaCii for [flagging the issue](https://discord.com/channels/686053708261228577/1433165116702199880/1439757826380660767)\n\n## Changed\n\n- Refactored plugin styling to better align with Obsidian's native UI conventions\n - Replaced all `cursor: pointer` with `cursor: var(--cursor)` (100+ instances) to follow Obsidian's cursor convention\n - Removed forced `border: none; box-shadow: none` rules that were fighting against Obsidian's native button styling\n - Scoped custom `.tn-btn` button system to settings modal only (`.mod-settings`), allowing Obsidian's native button styles to work elsewhere\n - Thanks to @kepano for guidance\n","aliases":["/releases/4.0.4/","/releases/4.0.4/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"changed","text":"Changed"}],"html":"

Added#

\n
    \n
  • (#1134, #779) Added CMD+Enter (Mac) / Ctrl+Enter (Windows/Linux) keyboard shortcut support for saving in all modals
      \n
    • Works from any input field in task creation, task edit, time entry, timeblock, and property selector modals
    • \n
    • Thanks to @luckb0x, @hamlim and @nightroman for the feature requests
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1181) Fixed vertical overflow in Kanban view columns with fewer than 15 tasks
      \n
    • Prevents cards from extending beyond column boundaries before virtualization activates
    • \n
    • Thanks to @lomarcanys for reporting
    • \n
    \n
  • \n
  • (#1177) Bases views now anchor recurring completion and calendar navigation to the right date
      \n
    • Recurring completion from Bases Task List/Kanban uses the task's scheduled/due date instead of "today" (fixes complete_instances)
    • \n
    • Bases calendar navigation and property-based events use UTC anchors to avoid previous-day jumps
    • \n
    • Thanks to @nslee123 for flagging the issue
    • \n
    \n
  • \n
  • Bases calendar navigation now respects UTC-anchored dates to avoid landing on the previous day
      \n
    • Corrected all-day end date calculation to prevent off-by-one spans
    • \n
    • Added regression test for the UTC anchor behavior
    • \n
    • Thanks to KaCii for flagging the issue
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Refactored plugin styling to better align with Obsidian's native UI conventions
      \n
    • Replaced all cursor: pointer with cursor: var(--cursor) (100+ instances) to follow Obsidian's cursor convention
    • \n
    • Removed forced border: none; box-shadow: none rules that were fighting against Obsidian's native button styling
    • \n
    • Scoped custom .tn-btn button system to settings modal only (.mod-settings), allowing Obsidian's native button styles to work elsewhere
    • \n
    • Thanks to @kepano for guidance
    • \n
    \n
  • \n
\n","text":"Added# (#1134, #779) Added CMD+Enter (Mac) / Ctrl+Enter (Windows/Linux) keyboard shortcut support for saving in all modals Works from any input field in task creation, task edit, time entry, timeblock, and property selector modals Thanks to @luckb0x, @hamlim and @nightroman for the feature requests Fixed# (#1181) Fixed vertical overflow in Kanban view columns with fewer than 15 tasks Prevents cards from extending beyond column boundaries before virtualization activates Thanks to @lomarcanys for reporting (#1177) Bases views now anchor recurring completion and calendar navigation to the right date Recurring completion from Bases Task List/Kanban uses the task's scheduled/due date instead of \"today\" (fixes complete_instances) Bases calendar navigation and property-based events use UTC anchors to avoid previous-day jumps Thanks to @nslee123 for flagging the issue Bases calendar navigation now respects UTC-anchored dates to avoid landing on the previous day Corrected all-day end date calculation to prevent off-by-one spans Added regression test for the UTC anchor behavior Thanks to KaCii for flagging the issue Changed# Refactored plugin styling to better align with Obsidian's native UI conventions Replaced all cursor: pointer with cursor: var(--cursor) (100+ instances) to follow Obsidian's cursor convention Removed forced border: none; box-shadow: none rules that were fighting against Obsidian's native button styling Scoped custom .tn-btn button system to settings modal only (.mod-settings), allowing Obsidian's native button styles to work elsewhere Thanks to @kepano for guidance"},{"route":"/obsidian/releases/4.0.5/","title":"TaskNotes 4.0.5","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.0.5.md","namespace":"obsidian","relativePath":"releases/4.0.5.md","raw":"# TaskNotes 4.0.5\n\n## Changed\n\n- (#790) Task edit modal now shows unresolved project links with appropriate styling\n\t- Similar to how dependencies are displayed, unresolved projects now appear with visual indication\n\t- Hovering over an unresolved project shows a tooltip explaining it couldn't be resolved\n\t- Thanks to @aubreyz for reporting\n\n## Fixed\n\n- (#1011) Fixed chevrons incorrectly showing on tasks with no subtasks\n\t- Project index was incorrectly adding all linked files instead of only files referenced in the projects field\n\t- Now properly parses the projects field and only indexes those specific files as projects\n\t- Also fixed alias handling in project and dependency links - aliases are now correctly stripped before link resolution\n\t- Thanks to @craziedde for reporting\n- (#1200) Fixed kanban drag & drop not updating task properties correctly\n\t- Dragging tasks to different columns now properly triggers business logic (completedDate, auto-archive, webhooks)\n\t- Previously, kanban updates bypassed `updateProperty` and directly modified frontmatter\n\t- Thanks very much to @tvoklov for the PR\n- (#1203) Fixed autocomplete dropdown being clipped inside NLP field boundaries\n\t- Configure CodeMirror tooltips to render in document.body instead of constrained editor container\n\t- Prevents suggestion dropdown from being hidden when it extends beyond the NLP field height\n\t- Thanks to @Andrei-Ioda for reporting\n- (#1172) Fixed task lists and checkboxes rendering incorrectly in task details editor\n\t- Remove padding-left override on `.cm-line` to allow CodeMirror decorations (checkboxes, indentation) to render properly\n\t- Content padding is now handled by `.cm-content` while `.cm-line` uses natural spacing\n\t- Thanks to @nightroman for reporting\n- Fixed relationships widget not appearing on project notes without frontmatter\n\t- Widget now correctly shows on any note referenced as a project by tasks, regardless of whether the note has frontmatter\n- Fixed task card and relationships widgets not appearing when opening notes in source mode\n\t- Removed live preview mode restriction to allow widgets to render in both source and live preview modes\n- (#901) Fixed calendar view toolbar buttons overflowing on narrow screens\n - Added `flex-wrap: wrap` to calendar header toolbar to allow buttons to wrap to multiple lines\n - Thanks to @RumiaKitinari for reporting\n- (#1193), (#1194), (#1185) Fixed new calendar views not respecting user's default calendar settings\n\t- Previously, new Bases calendar views used hardcoded inline defaults instead of user-configured preferences\n\t- Calendar view initialization now correctly uses `plugin.settings.calendarViewSettings` as the fallback\n\t- Thanks @ki5ck, @minchinweb and @ThamirysOlv for reporting \n- Fixed calendar to ensure that it respects user's locale\n - Tries to use calendar locale, then tries UI language, then system language, then falls back to English\n- (#1043) Fixed default reminders with \"at time of event\" (0 offset) not being applied to tasks\n\t- UI was displaying \"1\" instead of \"0\" for zero-offset reminders in settings\n\t- Thanks to @dblinnikov for reporting\n- (#1206) Fixed NLP status parsing regressions with trigger prefixes and temporal keywords\n\t- Manually typing status trigger + label now correctly parses (e.g., `*Done` when label is `Done`)\n\t- Status values containing temporal keywords no longer misparsed as dates (e.g., `Expedite = Now`)\n\t- Thanks very much to @renatomen for the PR\n- (#1212) Fixed \"Show release notes on update\" toggle not saving correctly\n - Thanks to @Jon-dog for reporting\n- (#1197) Add Portuguese language to list of translations in general tab settings\n - Allows users to select the Portuguese translation option\n - Thanks to @andysteel for the PR\n- Fixed file properties displaying incorrectly in Bases views\n\t- File properties like `file.name`, `file.basename`, `file.size`, etc. were showing as \"Title\" or returning null\n\t- Now correctly extracts and displays all file properties from Obsidian's file metadata\n\t- Supports both direct TFile properties (name, basename, extension, path, size, ctime, mtime) and computed properties (links, embeds, tags, backlinks, aliases)\n","aliases":["/releases/4.0.5/","/releases/4.0.5/"],"toc":[{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Changed#

\n
    \n
  • (#790) Task edit modal now shows unresolved project links with appropriate styling
      \n
    • Similar to how dependencies are displayed, unresolved projects now appear with visual indication
    • \n
    • Hovering over an unresolved project shows a tooltip explaining it couldn't be resolved
    • \n
    • Thanks to @aubreyz for reporting
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1011) Fixed chevrons incorrectly showing on tasks with no subtasks
      \n
    • Project index was incorrectly adding all linked files instead of only files referenced in the projects field
    • \n
    • Now properly parses the projects field and only indexes those specific files as projects
    • \n
    • Also fixed alias handling in project and dependency links - aliases are now correctly stripped before link resolution
    • \n
    • Thanks to @craziedde for reporting
    • \n
    \n
  • \n
  • (#1200) Fixed kanban drag & drop not updating task properties correctly
      \n
    • Dragging tasks to different columns now properly triggers business logic (completedDate, auto-archive, webhooks)
    • \n
    • Previously, kanban updates bypassed updateProperty and directly modified frontmatter
    • \n
    • Thanks very much to @tvoklov for the PR
    • \n
    \n
  • \n
  • (#1203) Fixed autocomplete dropdown being clipped inside NLP field boundaries
      \n
    • Configure CodeMirror tooltips to render in document.body instead of constrained editor container
    • \n
    • Prevents suggestion dropdown from being hidden when it extends beyond the NLP field height
    • \n
    • Thanks to @Andrei-Ioda for reporting
    • \n
    \n
  • \n
  • (#1172) Fixed task lists and checkboxes rendering incorrectly in task details editor
      \n
    • Remove padding-left override on .cm-line to allow CodeMirror decorations (checkboxes, indentation) to render properly
    • \n
    • Content padding is now handled by .cm-content while .cm-line uses natural spacing
    • \n
    • Thanks to @nightroman for reporting
    • \n
    \n
  • \n
  • Fixed relationships widget not appearing on project notes without frontmatter
      \n
    • Widget now correctly shows on any note referenced as a project by tasks, regardless of whether the note has frontmatter
    • \n
    \n
  • \n
  • Fixed task card and relationships widgets not appearing when opening notes in source mode
      \n
    • Removed live preview mode restriction to allow widgets to render in both source and live preview modes
    • \n
    \n
  • \n
  • (#901) Fixed calendar view toolbar buttons overflowing on narrow screens
      \n
    • Added flex-wrap: wrap to calendar header toolbar to allow buttons to wrap to multiple lines
    • \n
    • Thanks to @RumiaKitinari for reporting
    • \n
    \n
  • \n
  • (#1193), (#1194), (#1185) Fixed new calendar views not respecting user's default calendar settings
      \n
    • Previously, new Bases calendar views used hardcoded inline defaults instead of user-configured preferences
    • \n
    • Calendar view initialization now correctly uses plugin.settings.calendarViewSettings as the fallback
    • \n
    • Thanks @ki5ck, @minchinweb and @ThamirysOlv for reporting
    • \n
    \n
  • \n
  • Fixed calendar to ensure that it respects user's locale
      \n
    • Tries to use calendar locale, then tries UI language, then system language, then falls back to English
    • \n
    \n
  • \n
  • (#1043) Fixed default reminders with "at time of event" (0 offset) not being applied to tasks
      \n
    • UI was displaying "1" instead of "0" for zero-offset reminders in settings
    • \n
    • Thanks to @dblinnikov for reporting
    • \n
    \n
  • \n
  • (#1206) Fixed NLP status parsing regressions with trigger prefixes and temporal keywords
      \n
    • Manually typing status trigger + label now correctly parses (e.g., *Done when label is Done)
    • \n
    • Status values containing temporal keywords no longer misparsed as dates (e.g., Expedite = Now)
    • \n
    • Thanks very much to @renatomen for the PR
    • \n
    \n
  • \n
  • (#1212) Fixed "Show release notes on update" toggle not saving correctly
      \n
    • Thanks to @Jon-dog for reporting
    • \n
    \n
  • \n
  • (#1197) Add Portuguese language to list of translations in general tab settings
      \n
    • Allows users to select the Portuguese translation option
    • \n
    • Thanks to @andysteel for the PR
    • \n
    \n
  • \n
  • Fixed file properties displaying incorrectly in Bases views
      \n
    • File properties like file.name, file.basename, file.size, etc. were showing as "Title" or returning null
    • \n
    • Now correctly extracts and displays all file properties from Obsidian's file metadata
    • \n
    • Supports both direct TFile properties (name, basename, extension, path, size, ctime, mtime) and computed properties (links, embeds, tags, backlinks, aliases)
    • \n
    \n
  • \n
\n","text":"Changed# (#790) Task edit modal now shows unresolved project links with appropriate styling Similar to how dependencies are displayed, unresolved projects now appear with visual indication Hovering over an unresolved project shows a tooltip explaining it couldn't be resolved Thanks to @aubreyz for reporting Fixed# (#1011) Fixed chevrons incorrectly showing on tasks with no subtasks Project index was incorrectly adding all linked files instead of only files referenced in the projects field Now properly parses the projects field and only indexes those specific files as projects Also fixed alias handling in project and dependency links - aliases are now correctly stripped before link resolution Thanks to @craziedde for reporting (#1200) Fixed kanban drag & drop not updating task properties correctly Dragging tasks to different columns now properly triggers business logic (completedDate, auto-archive, webhooks) Previously, kanban updates bypassed updateProperty and directly modified frontmatter Thanks very much to @tvoklov for the PR (#1203) Fixed autocomplete dropdown being clipped inside NLP field boundaries Configure CodeMirror tooltips to render in document.body instead of constrained editor container Prevents suggestion dropdown from being hidden when it extends beyond the NLP field height Thanks to @Andrei-Ioda for reporting (#1172) Fixed task lists and checkboxes rendering incorrectly in task details editor Remove padding-left override on .cm-line to allow CodeMirror decorations (checkboxes, indentation) to render properly Content padding is now handled by .cm-content while .cm-line uses natural spacing Thanks to @nightroman for reporting Fixed relationships widget not appearing on project notes without frontmatter Widget now correctly shows on any note referenced as a project by tasks, regardless of whether the note has frontmatter Fixed task card and relationships widgets not appearing when opening notes in source mode Removed live preview mode restriction to allow widgets to render in both source and live preview modes (#901) Fixed calendar view toolbar buttons overflowing on narrow screens Added flex-wrap: wrap to calendar header toolbar to allow buttons to wrap to multiple lines Thanks to @RumiaKitinari for reporting (#1193), (#1194), (#1185) Fixed new calendar views not respecting user's default calendar settings Previously, new Bases calendar views used hardcoded inline defaults instead of user-configured preferences Calendar view initialization now correctly uses plugin.settings.calendarViewSettings as the fallback Thanks @ki5ck, @minchinweb and @ThamirysOlv for reporting Fixed calendar to ensure that it respects user's locale Tries to use calendar locale, then tries UI language, then system language, then falls back to English (#1043) Fixed default reminders with \"at time of event\" (0 offset) not being applied to tasks UI was displaying \"1\" instead of \"0\" for zero-offset reminders in settings Thanks to @dblinnikov for reporting (#1206) Fixed NLP status parsing regressions with trigger prefixes and temporal keywords Manually typing status trigger + label now correctly parses (e.g., *Done when label is Done) Status values containing temporal keywords no longer misparsed as dates (e.g., Expedite = Now) Thanks very much to @renatomen for the PR (#1212) Fixed \"Show release notes on update\" toggle not saving correctly Thanks to @Jon-dog for reporting (#1197) Add Portuguese language to list of translations in general tab settings Allows users to select the Portuguese translation option Thanks to @andysteel for the PR Fixed file properties displaying incorrectly in Bases views File properties like file.name, file.basename, file.size, etc. were showing as \"Title\" or returning null Now correctly extracts and displays all file properties from Obsidian's file metadata Supports both direct TFile properties (name, basename, extension, path, size, ctime, mtime) and computed properties (links, embeds, tags, backlinks, aliases)"},{"route":"/obsidian/releases/4.1.0/","title":"TaskNotes 4.1.0","description":"(#1245), (#793) Added custom icon support for task statuses","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.1.0.md","namespace":"obsidian","relativePath":"releases/4.1.0.md","raw":"# TaskNotes 4.1.0\n\n## Added\n\n- (#1245), (#793) Added custom icon support for task statuses\n - Configure a Lucide icon name (e.g., `check`, `circle`, `clock`) per status in Settings → Task Properties → Task Statuses\n - Icons display instead of the colored dot, inheriting the status color\n - Browse available icons at [lucide.dev](https://lucide.dev)\n - Improves accessibility by allowing shape-based status differentiation\n - Thanks to @3Fish for the feature request and @Raonmir2, @aubreyz, @prayidae, and @anareaty for the discussion on accessibility and icon-based indicators\n\n- (#1259) Added [Property Types Reference](../settings/property-types-reference.md) documentation\n - Documents expected data types (text, list, date, number) for all frontmatter properties\n - Includes format specifications, examples, and a complete YAML reference\n - Thanks to @Oblique82 for the suggestion\n\n- (#1248) Added formula property support for sub-grouping in Bases Task List view\n - Formula properties (e.g., `formula.myFormula`) now appear in the Sub-group by dropdown\n - Supports all Bases Value types including strings, numbers, booleans, dates, and lists\n - Thanks to @prayidae for the feature request\n\n- (#1070) Added formula property support for swimlanes in Bases Kanban view\n - Formula properties now appear in the Swim Lane dropdown\n - Fixed swimlanes displaying empty when grouping by formula properties\n - Note: Dragging tasks between formula-based columns/swimlanes is disabled (formulas are computed values)\n - Thanks to @cathywu for reporting\n\n- (#1010), (#1126) Added batch task selection and editing in Task List and Kanban views\n - Shift+click to select multiple tasks\n - Right-click selected tasks to open batch context menu\n - Batch operations: change status, priority, due date, scheduled date, archive, delete\n - Drag multiple selected cards in Kanban to move them together\n - Click the selection count indicator to clear selection\n - Thanks to @jalooc and @solidabstract for the feature requests\n\n- (#1207) Added inline search box to Bases views (Task List, Kanban, Calendar)\n - Enable via \"Enable search box\" toggle in view settings\n - Searches across title, status, priority, tags, contexts, projects, and visible custom properties\n - Press Escape or click × to clear search\n - Thanks to @renatomen for the PR\n\n- (#363) Added \"Create or open task\" command with NLP-based quick task creation\n - Open via command palette or assign a hotkey\n - Search existing tasks or type natural language to create new tasks (e.g., \"Buy groceries tomorrow #shopping\")\n - Press Enter to select an existing task, Shift+Enter to create a new task\n - Real-time preview shows parsed title, due date, priority, tags, and other metadata\n - Can be used when adding sub-tasks to create sub-tasks on-the-fly\n - Thanks to @luciolebrillante for the feature request\n\n- (#1044), (#1222) Added unsaved changes confirmation when closing task edit modal\n - Detects modifications to any field (title, dates, priority, tags, etc.)\n - Shows confirmation dialog with Save/Discard/Keep Editing options\n - Prevents accidental data loss from clicking outside the modal or pressing Escape\n - Thanks to @renatomen for the PR and @0-BSCode for the feature request\n\n- (#904) Added visual highlighting for overdue and past dates on task cards\n - Overdue due dates now display in red text\n - Past scheduled dates now display in blue text\n - Thanks to @ras0q for the suggestion\n\n- (#1164) Added `priorityWeight` formula to all default Bases templates for priority-based sorting\n - Formula maps each priority value to a numeric weight based on your custom priority configuration\n - Sort by `formula.priorityWeight` in ascending order to get highest priority tasks first\n - Example: `if(priority==\"high\",0,if(priority==\"normal\",1,if(priority==\"low\",2,999)))`\n - Thanks to @jhedlund for the suggestion\n\n- (#1257), (#1064) Added configurable event stacking options for Bases Calendar view\n - **Allow events to overlap**: Toggle whether timed events visually overlap or display side-by-side in week/day views\n - **Max stacked events**: Limit horizontal event stacking in week/day views (0 = unlimited)\n - **Max events per day**: Limit events shown per day cell in month view (0 = auto based on cell height)\n - **Max event rows per day**: Limit event rows per day cell in month view (0 = unlimited)\n - Configure per-view in the Bases Calendar view settings under Layout\n - Thanks to @3zra47 and @hasanyilmaz for the feature requests\n\n## Changed\n\n- Improved inline task conversion to merge TasksPlugin and NLP parsing results\n - Previously, if a task had hashtags (e.g., `- [ ] Buy milk tomorrow #groceries`), NLP parsing was skipped entirely\n - Now NLP always parses the clean title to extract dates/times, then merges with TasksPlugin-extracted metadata\n - TasksPlugin explicit values (emoji dates like 📅) take priority over NLP-inferred values\n - Tags, contexts, and projects from both sources are combined and deduplicated\n\n- Polished task card styling for a more native Obsidian look\n - Simplified hover and focus states to use native Obsidian colors\n - Removed blur filter and shadows from metadata pills\n - Fixed subtask chevron vertical alignment with status dot\n - Reduced swimlane label column width in Kanban view\n\n- (#1151) Increased mini calendar heatmap color intensity for better visibility\n - Days with notes now show more noticeable colors, especially with low note counts\n - Intensity levels increased from 10/25/45/65% to 25/40/55/70%\n - Thanks to @arreme for the suggestion\n\n## Fixed\n\n- (#1271) Fixed custom user fields not appearing in task modals after creation\n - New custom fields are now automatically added to both creation and edit modals\n - Deleting a custom field also removes it from modal configuration\n - Updating a field's display name syncs to the modal configuration\n - Thanks to @craziedde for reporting\n\n- (#1256) Fixed links in custom properties not rendering as clickable in task cards\n - Wikilinks (`[[Note]]`) now render correctly in Bases views\n - Markdown links (`[text](url)`) now render correctly in all views\n - Links in list-type properties are also properly rendered\n - Thanks to @3zra47 for reporting\n\n- (#1157) Fixed inline task embeds breaking layout when placed in indented bullet lists\n - Task titles now wrap naturally within line boundaries instead of forcing the entire card to a new line\n - Metadata (dates, tags, etc.) stays inline when space permits, with horizontal scrolling on hover when needed\n - Thanks to @3zra47 for reporting\n\n- (#1241) Fixed deleting custom priorities in settings removing the wrong priority when multiple priorities exist\n - Thanks to @Anthonyhunter100 for reporting\n\n- (#1165) Fixed Kanban view grouping by list properties (contexts, tags, projects) treating multiple values as a single combined column\n - Tasks with multiple values now appear in each individual column (e.g., a task with `contexts: [work, call]` appears in both \"work\" and \"call\" columns)\n - Added \"Show items in multiple columns\" option (enabled by default) to control this behavior\n - Fixed drag-and-drop to properly add/remove individual values instead of replacing the entire list\n - Fixed swimlane mode to also respect list property explosion\n - Thanks to @dictionarymouse for reporting\n\n- (#1217) Fixed inconsistent Ctrl+Click/Cmd+Click behavior for opening notes in new tabs\n - Note cards and internal links now properly support Ctrl/Cmd+Click to open in new tab\n - Added middle-click support for opening in new tab\n - Thanks to @diegomarzaa for reporting\n\n- (#1265) Fixed task edit modal corrupting markdown-style project links on save\n - Links like `[Project Name](path.md)` were being wrapped in extra brackets: `[[[Project Name](path.md)]]`\n - Plain text project names are now preserved as-is instead of being converted to wikilinks\n - Markdown-style project links now resolve properly and display as linked (not orange/unresolved)\n - Thanks to @minchinweb for reporting\n\n- (#1266) Fixed Kanban view scroll position resetting to top of column after any change\n - Clicking status dots, priority, or other task properties no longer jumps the column back to top\n - Scroll position is now preserved for both regular columns and swimlane cells\n - Thanks to @essouflenfer for reporting\n\n- (#485), (#1221), (#1262) Fixed NLP parser not recognizing non-ASCII characters in tags, contexts, and projects\n - Tags like `#investigación` were being truncated at accented characters (e.g., `#investigaci`)\n - Non-Latin scripts (Chinese, Cyrillic, Japanese, etc.) were not recognized at all (e.g., `@家`, `#杂事`, `@ознакомиться`)\n - Parser now uses Unicode-aware regex patterns to support all languages and scripts\n - Thanks to @Arachnidai, @fidelaznar, and @qian1ing for reporting\n\n- (#1249) Fixed project preview in task creation modal showing quadruple brackets (`[[[[Project]]]]`)\n - Projects selected from autocomplete were being wrapped in extra wikilink brackets in the preview display\n - Thanks to @2vzqwz8tvg-png for reporting\n\n- (#1249) Fixed custom priority ordering in settings being unclear and non-intuitive\n - Priority cards are now draggable to reorder (like statuses)\n - Priorities are displayed in weight order (lowest to highest priority)\n - New priorities are added at the end (highest priority) instead of with a fixed weight\n - Thanks to @2vzqwz8tvg-png for reporting\n\n- (#1272) Fixed recurrence anchor not being saved when set to \"completion\" during task creation\n - Selecting \"completion\" as the recurrence anchor now correctly persists to the task frontmatter\n - Thanks to @blaxcky for reporting\n\n- (#1128) Fixed NLP parser not allowing slashes in context names\n - Contexts like `@shopping/groceries` were being split into `@shopping` and `/groceries`\n - Hierarchical context names now work the same as tags and projects\n - Thanks to @wealthychef1 for reporting\n\n- (#1170) Fixed `dateCreated` and `dateModified` not using custom property names when creating notes from calendar events\n - Notes created from ICS events now respect the field mapping configured in settings\n - Thanks to @maddie-m for reporting\n\n- (#1171) Fixed calendar event toggles not responding to changes after initial load\n - Toggling \"Show scheduled tasks\", \"Show due tasks\", and other event filters now correctly updates the calendar\n - Previously, changing these toggles had no effect until the view was reloaded\n - Thanks to @hangryscribe3 for reporting\n\n- (#1198) Fixed project links being created relative to the wrong file when editing from Bases views\n - Relative paths in project links are now correctly resolved relative to the task note file\n - Previously, editing a task from a Bases view would create project links relative to the `.base` file\n - Thanks to @minchinweb for reporting\n\n","aliases":["/releases/4.1.0/","/releases/4.1.0/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • (#1245), (#793) Added custom icon support for task statuses

    \n
      \n
    • Configure a Lucide icon name (e.g., check, circle, clock) per status in Settings → Task Properties → Task Statuses
    • \n
    • Icons display instead of the colored dot, inheriting the status color
    • \n
    • Browse available icons at lucide.dev
    • \n
    • Improves accessibility by allowing shape-based status differentiation
    • \n
    • Thanks to @3Fish for the feature request and @Raonmir2, @aubreyz, @prayidae, and @anareaty for the discussion on accessibility and icon-based indicators
    • \n
    \n
  • \n
  • (#1259) Added Property Types Reference documentation

    \n
      \n
    • Documents expected data types (text, list, date, number) for all frontmatter properties
    • \n
    • Includes format specifications, examples, and a complete YAML reference
    • \n
    • Thanks to @Oblique82 for the suggestion
    • \n
    \n
  • \n
  • (#1248) Added formula property support for sub-grouping in Bases Task List view

    \n
      \n
    • Formula properties (e.g., formula.myFormula) now appear in the Sub-group by dropdown
    • \n
    • Supports all Bases Value types including strings, numbers, booleans, dates, and lists
    • \n
    • Thanks to @prayidae for the feature request
    • \n
    \n
  • \n
  • (#1070) Added formula property support for swimlanes in Bases Kanban view

    \n
      \n
    • Formula properties now appear in the Swim Lane dropdown
    • \n
    • Fixed swimlanes displaying empty when grouping by formula properties
    • \n
    • Note: Dragging tasks between formula-based columns/swimlanes is disabled (formulas are computed values)
    • \n
    • Thanks to @cathywu for reporting
    • \n
    \n
  • \n
  • (#1010), (#1126) Added batch task selection and editing in Task List and Kanban views

    \n
      \n
    • Shift+click to select multiple tasks
    • \n
    • Right-click selected tasks to open batch context menu
    • \n
    • Batch operations: change status, priority, due date, scheduled date, archive, delete
    • \n
    • Drag multiple selected cards in Kanban to move them together
    • \n
    • Click the selection count indicator to clear selection
    • \n
    • Thanks to @jalooc and @solidabstract for the feature requests
    • \n
    \n
  • \n
  • (#1207) Added inline search box to Bases views (Task List, Kanban, Calendar)

    \n
      \n
    • Enable via "Enable search box" toggle in view settings
    • \n
    • Searches across title, status, priority, tags, contexts, projects, and visible custom properties
    • \n
    • Press Escape or click × to clear search
    • \n
    • Thanks to @renatomen for the PR
    • \n
    \n
  • \n
  • (#363) Added "Create or open task" command with NLP-based quick task creation

    \n
      \n
    • Open via command palette or assign a hotkey
    • \n
    • Search existing tasks or type natural language to create new tasks (e.g., "Buy groceries tomorrow #shopping")
    • \n
    • Press Enter to select an existing task, Shift+Enter to create a new task
    • \n
    • Real-time preview shows parsed title, due date, priority, tags, and other metadata
    • \n
    • Can be used when adding sub-tasks to create sub-tasks on-the-fly
    • \n
    • Thanks to @luciolebrillante for the feature request
    • \n
    \n
  • \n
  • (#1044), (#1222) Added unsaved changes confirmation when closing task edit modal

    \n
      \n
    • Detects modifications to any field (title, dates, priority, tags, etc.)
    • \n
    • Shows confirmation dialog with Save/Discard/Keep Editing options
    • \n
    • Prevents accidental data loss from clicking outside the modal or pressing Escape
    • \n
    • Thanks to @renatomen for the PR and @0-BSCode for the feature request
    • \n
    \n
  • \n
  • (#904) Added visual highlighting for overdue and past dates on task cards

    \n
      \n
    • Overdue due dates now display in red text
    • \n
    • Past scheduled dates now display in blue text
    • \n
    • Thanks to @ras0q for the suggestion
    • \n
    \n
  • \n
  • (#1164) Added priorityWeight formula to all default Bases templates for priority-based sorting

    \n
      \n
    • Formula maps each priority value to a numeric weight based on your custom priority configuration
    • \n
    • Sort by formula.priorityWeight in ascending order to get highest priority tasks first
    • \n
    • Example: if(priority=="high",0,if(priority=="normal",1,if(priority=="low",2,999)))
    • \n
    • Thanks to @jhedlund for the suggestion
    • \n
    \n
  • \n
  • (#1257), (#1064) Added configurable event stacking options for Bases Calendar view

    \n
      \n
    • Allow events to overlap: Toggle whether timed events visually overlap or display side-by-side in week/day views
    • \n
    • Max stacked events: Limit horizontal event stacking in week/day views (0 = unlimited)
    • \n
    • Max events per day: Limit events shown per day cell in month view (0 = auto based on cell height)
    • \n
    • Max event rows per day: Limit event rows per day cell in month view (0 = unlimited)
    • \n
    • Configure per-view in the Bases Calendar view settings under Layout
    • \n
    • Thanks to @3zra47 and @hasanyilmaz for the feature requests
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Improved inline task conversion to merge TasksPlugin and NLP parsing results

    \n
      \n
    • Previously, if a task had hashtags (e.g., - [ ] Buy milk tomorrow #groceries), NLP parsing was skipped entirely
    • \n
    • Now NLP always parses the clean title to extract dates/times, then merges with TasksPlugin-extracted metadata
    • \n
    • TasksPlugin explicit values (emoji dates like 📅) take priority over NLP-inferred values
    • \n
    • Tags, contexts, and projects from both sources are combined and deduplicated
    • \n
    \n
  • \n
  • Polished task card styling for a more native Obsidian look

    \n
      \n
    • Simplified hover and focus states to use native Obsidian colors
    • \n
    • Removed blur filter and shadows from metadata pills
    • \n
    • Fixed subtask chevron vertical alignment with status dot
    • \n
    • Reduced swimlane label column width in Kanban view
    • \n
    \n
  • \n
  • (#1151) Increased mini calendar heatmap color intensity for better visibility

    \n
      \n
    • Days with notes now show more noticeable colors, especially with low note counts
    • \n
    • Intensity levels increased from 10/25/45/65% to 25/40/55/70%
    • \n
    • Thanks to @arreme for the suggestion
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1271) Fixed custom user fields not appearing in task modals after creation

    \n
      \n
    • New custom fields are now automatically added to both creation and edit modals
    • \n
    • Deleting a custom field also removes it from modal configuration
    • \n
    • Updating a field's display name syncs to the modal configuration
    • \n
    • Thanks to @craziedde for reporting
    • \n
    \n
  • \n
  • (#1256) Fixed links in custom properties not rendering as clickable in task cards

    \n
      \n
    • Wikilinks ([[Note]]) now render correctly in Bases views
    • \n
    • Markdown links ([text](url)) now render correctly in all views
    • \n
    • Links in list-type properties are also properly rendered
    • \n
    • Thanks to @3zra47 for reporting
    • \n
    \n
  • \n
  • (#1157) Fixed inline task embeds breaking layout when placed in indented bullet lists

    \n
      \n
    • Task titles now wrap naturally within line boundaries instead of forcing the entire card to a new line
    • \n
    • Metadata (dates, tags, etc.) stays inline when space permits, with horizontal scrolling on hover when needed
    • \n
    • Thanks to @3zra47 for reporting
    • \n
    \n
  • \n
  • (#1241) Fixed deleting custom priorities in settings removing the wrong priority when multiple priorities exist

    \n
      \n
    • Thanks to @Anthonyhunter100 for reporting
    • \n
    \n
  • \n
  • (#1165) Fixed Kanban view grouping by list properties (contexts, tags, projects) treating multiple values as a single combined column

    \n
      \n
    • Tasks with multiple values now appear in each individual column (e.g., a task with contexts: [work, call] appears in both "work" and "call" columns)
    • \n
    • Added "Show items in multiple columns" option (enabled by default) to control this behavior
    • \n
    • Fixed drag-and-drop to properly add/remove individual values instead of replacing the entire list
    • \n
    • Fixed swimlane mode to also respect list property explosion
    • \n
    • Thanks to @dictionarymouse for reporting
    • \n
    \n
  • \n
  • (#1217) Fixed inconsistent Ctrl+Click/Cmd+Click behavior for opening notes in new tabs

    \n
      \n
    • Note cards and internal links now properly support Ctrl/Cmd+Click to open in new tab
    • \n
    • Added middle-click support for opening in new tab
    • \n
    • Thanks to @diegomarzaa for reporting
    • \n
    \n
  • \n
  • (#1265) Fixed task edit modal corrupting markdown-style project links on save

    \n
      \n
    • Links like [Project Name](path.md) were being wrapped in extra brackets: [[[Project Name](path.md)]]
    • \n
    • Plain text project names are now preserved as-is instead of being converted to wikilinks
    • \n
    • Markdown-style project links now resolve properly and display as linked (not orange/unresolved)
    • \n
    • Thanks to @minchinweb for reporting
    • \n
    \n
  • \n
  • (#1266) Fixed Kanban view scroll position resetting to top of column after any change

    \n
      \n
    • Clicking status dots, priority, or other task properties no longer jumps the column back to top
    • \n
    • Scroll position is now preserved for both regular columns and swimlane cells
    • \n
    • Thanks to @essouflenfer for reporting
    • \n
    \n
  • \n
  • (#485), (#1221), (#1262) Fixed NLP parser not recognizing non-ASCII characters in tags, contexts, and projects

    \n
      \n
    • Tags like #investigación were being truncated at accented characters (e.g., #investigaci)
    • \n
    • Non-Latin scripts (Chinese, Cyrillic, Japanese, etc.) were not recognized at all (e.g., @家, #杂事, @ознакомиться)
    • \n
    • Parser now uses Unicode-aware regex patterns to support all languages and scripts
    • \n
    • Thanks to @Arachnidai, @fidelaznar, and @qian1ing for reporting
    • \n
    \n
  • \n
  • (#1249) Fixed project preview in task creation modal showing quadruple brackets ([[[[Project]]]])

    \n
      \n
    • Projects selected from autocomplete were being wrapped in extra wikilink brackets in the preview display
    • \n
    • Thanks to @2vzqwz8tvg-png for reporting
    • \n
    \n
  • \n
  • (#1249) Fixed custom priority ordering in settings being unclear and non-intuitive

    \n
      \n
    • Priority cards are now draggable to reorder (like statuses)
    • \n
    • Priorities are displayed in weight order (lowest to highest priority)
    • \n
    • New priorities are added at the end (highest priority) instead of with a fixed weight
    • \n
    • Thanks to @2vzqwz8tvg-png for reporting
    • \n
    \n
  • \n
  • (#1272) Fixed recurrence anchor not being saved when set to "completion" during task creation

    \n
      \n
    • Selecting "completion" as the recurrence anchor now correctly persists to the task frontmatter
    • \n
    • Thanks to @blaxcky for reporting
    • \n
    \n
  • \n
  • (#1128) Fixed NLP parser not allowing slashes in context names

    \n
      \n
    • Contexts like @shopping/groceries were being split into @shopping and /groceries
    • \n
    • Hierarchical context names now work the same as tags and projects
    • \n
    • Thanks to @wealthychef1 for reporting
    • \n
    \n
  • \n
  • (#1170) Fixed dateCreated and dateModified not using custom property names when creating notes from calendar events

    \n
      \n
    • Notes created from ICS events now respect the field mapping configured in settings
    • \n
    • Thanks to @maddie-m for reporting
    • \n
    \n
  • \n
  • (#1171) Fixed calendar event toggles not responding to changes after initial load

    \n
      \n
    • Toggling "Show scheduled tasks", "Show due tasks", and other event filters now correctly updates the calendar
    • \n
    • Previously, changing these toggles had no effect until the view was reloaded
    • \n
    • Thanks to @hangryscribe3 for reporting
    • \n
    \n
  • \n
  • (#1198) Fixed project links being created relative to the wrong file when editing from Bases views

    \n
      \n
    • Relative paths in project links are now correctly resolved relative to the task note file
    • \n
    • Previously, editing a task from a Bases view would create project links relative to the .base file
    • \n
    • Thanks to @minchinweb for reporting
    • \n
    \n
  • \n
\n","text":"Added# (#1245), (#793) Added custom icon support for task statuses Configure a Lucide icon name (e.g., check, circle, clock) per status in Settings → Task Properties → Task Statuses Icons display instead of the colored dot, inheriting the status color Browse available icons at lucide.dev Improves accessibility by allowing shape-based status differentiation Thanks to @3Fish for the feature request and @Raonmir2, @aubreyz, @prayidae, and @anareaty for the discussion on accessibility and icon-based indicators (#1259) Added Property Types Reference documentation Documents expected data types (text, list, date, number) for all frontmatter properties Includes format specifications, examples, and a complete YAML reference Thanks to @Oblique82 for the suggestion (#1248) Added formula property support for sub-grouping in Bases Task List view Formula properties (e.g., formula.myFormula) now appear in the Sub-group by dropdown Supports all Bases Value types including strings, numbers, booleans, dates, and lists Thanks to @prayidae for the feature request (#1070) Added formula property support for swimlanes in Bases Kanban view Formula properties now appear in the Swim Lane dropdown Fixed swimlanes displaying empty when grouping by formula properties Note: Dragging tasks between formula-based columns/swimlanes is disabled (formulas are computed values) Thanks to @cathywu for reporting (#1010), (#1126) Added batch task selection and editing in Task List and Kanban views Shift+click to select multiple tasks Right-click selected tasks to open batch context menu Batch operations: change status, priority, due date, scheduled date, archive, delete Drag multiple selected cards in Kanban to move them together Click the selection count indicator to clear selection Thanks to @jalooc and @solidabstract for the feature requests (#1207) Added inline search box to Bases views (Task List, Kanban, Calendar) Enable via \"Enable search box\" toggle in view settings Searches across title, status, priority, tags, contexts, projects, and visible custom properties Press Escape or click × to clear search Thanks to @renatomen for the PR (#363) Added \"Create or open task\" command with NLP-based quick task creation Open via command palette or assign a hotkey Search existing tasks or type natural language to create new tasks (e.g., \"Buy groceries tomorrow #shopping\") Press Enter to select an existing task, Shift+Enter to create a new task Real-time preview shows parsed title, due date, priority, tags, and other metadata Can be used when adding sub-tasks to create sub-tasks on-the-fly Thanks to @luciolebrillante for the feature request (#1044), (#1222) Added unsaved changes confirmation when closing task edit modal Detects modifications to any field (title, dates, priority, tags, etc.) Shows confirmation dialog with Save/Discard/Keep Editing options Prevents accidental data loss from clicking outside the modal or pressing Escape Thanks to @renatomen for the PR and @0-BSCode for the feature request (#904) Added visual highlighting for overdue and past dates on task cards Overdue due dates now display in red text Past scheduled dates now display in blue text Thanks to @ras0q for the suggestion (#1164) Added priorityWeight formula to all default Bases templates for priority-based sorting Formula maps each priority value to a numeric weight based on your custom priority configuration Sort by formula.priorityWeight in ascending order to get highest priority tasks first Example: if(priority==\"high\",0,if(priority==\"normal\",1,if(priority==\"low\",2,999))) Thanks to @jhedlund for the suggestion (#1257), (#1064) Added configurable event stacking options for Bases Calendar view Allow events to overlap: Toggle whether timed events visually overlap or display side-by-side in week/day views Max stacked events: Limit horizontal event stacking in week/day views (0 = unlimited) Max events per day: Limit events shown per day cell in month view (0 = auto based on cell height) Max event rows per day: Limit event rows per day cell in month view (0 = unlimited) Configure per-view in the Bases Calendar view settings under Layout Thanks to @3zra47 and @hasanyilmaz for the feature requests Changed# Improved inline task conversion to merge TasksPlugin and NLP parsing results Previously, if a task had hashtags (e.g., - [ ] Buy milk tomorrow #groceries), NLP parsing was skipped entirely Now NLP always parses the clean title to extract dates/times, then merges with TasksPlugin-extracted metadata TasksPlugin explicit values (emoji dates like 📅) take priority over NLP-inferred values Tags, contexts, and projects from both sources are combined and deduplicated Polished task card styling for a more native Obsidian look Simplified hover and focus states to use native Obsidian colors Removed blur filter and shadows from metadata pills Fixed subtask chevron vertical alignment with status dot Reduced swimlane label column width in Kanban view (#1151) Increased mini calendar heatmap color intensity for better visibility Days with notes now show more noticeable colors, especially with low note counts Intensity levels increased from 10/25/45/65% to 25/40/55/70% Thanks to @arreme for the suggestion Fixed# (#1271) Fixed custom user fields not appearing in task modals after creation New custom fields are now automatically added to both creation and edit modals Deleting a custom field also removes it from modal configuration Updating a field's display name syncs to the modal configuration Thanks to @craziedde for reporting (#1256) Fixed links in custom properties not rendering as clickable in task cards Wikilinks ([[Note]]) now render correctly in Bases views Markdown links ([text](url)) now render correctly in all views Links in list-type properties are also properly rendered Thanks to @3zra47 for reporting (#1157) Fixed inline task embeds breaking layout when placed in indented bullet lists Task titles now wrap naturally within line boundaries instead of forcing the entire card to a new line Metadata (dates, tags, etc.) stays inline when space permits, with horizontal scrolling on hover when needed Thanks to @3zra47 for reporting (#1241) Fixed deleting custom priorities in settings removing the wrong priority when multiple priorities exist Thanks to @Anthonyhunter100 for reporting (#1165) Fixed Kanban view grouping by list properties (contexts, tags, projects) treating multiple values as a single combined column Tasks with multiple values now appear in each individual column (e.g., a task with contexts: [work, call] appears in both \"work\" and \"call\" columns) Added \"Show items in multiple columns\" option (enabled by default) to control this behavior Fixed drag-and-drop to properly add/remove individual values instead of replacing the entire list Fixed swimlane mode to also respect list property explosion Thanks to @dictionarymouse for reporting (#1217) Fixed inconsistent Ctrl+Click/Cmd+Click behavior for opening notes in new tabs Note cards and internal links now properly support Ctrl/Cmd+Click to open in new tab Added middle-click support for opening in new tab Thanks to @diegomarzaa for reporting (#1265) Fixed task edit modal corrupting markdown-style project links on save Links like [Project Name](path.md) were being wrapped in extra brackets: [[[Project Name](path.md)]] Plain text project names are now preserved as-is instead of being converted to wikilinks Markdown-style project links now resolve properly and display as linked (not orange/unresolved) Thanks to @minchinweb for reporting (#1266) Fixed Kanban view scroll position resetting to top of column after any change Clicking status dots, priority, or other task properties no longer jumps the column back to top Scroll position is now preserved for both regular columns and swimlane cells Thanks to @essouflenfer for reporting (#485), (#1221), (#1262) Fixed NLP parser not recognizing non-ASCII characters in tags, contexts, and projects Tags like #investigación were being truncated at accented characters (e.g., #investigaci) Non-Latin scripts (Chinese, Cyrillic, Japanese, etc.) were not recognized at all (e.g., @家, #杂事, @ознакомиться) Parser now uses Unicode-aware regex patterns to support all languages and scripts Thanks to @Arachnidai, @fidelaznar, and @qian1ing for reporting (#1249) Fixed project preview in task creation modal showing quadruple brackets ([[[[Project]]]]) Projects selected from autocomplete were being wrapped in extra wikilink brackets in the preview display Thanks to @2vzqwz8tvg-png for reporting (#1249) Fixed custom priority ordering in settings being unclear and non-intuitive Priority cards are now draggable to reorder (like statuses) Priorities are displayed in weight order (lowest to highest priority) New priorities are added at the end (highest priority) instead of with a fixed weight Thanks to @2vzqwz8tvg-png for reporting (#1272) Fixed recurrence anchor not being saved when set to \"completion\" during task creation Selecting \"completion\" as the recurrence anchor now correctly persists to the task frontmatter Thanks to @blaxcky for reporting (#1128) Fixed NLP parser not allowing slashes in context names Contexts like @shopping/groceries were being split into @shopping and /groceries Hierarchical context names now work the same as tags and projects Thanks to @wealthychef1 for reporting (#1170) Fixed dateCreated and dateModified not using custom property names when creating notes from calendar events Notes created from ICS events now respect the field mapping configured in settings Thanks to @maddie-m for reporting (#1171) Fixed calendar event toggles not responding to changes after initial load Toggling \"Show scheduled tasks\", \"Show due tasks\", and other event filters now correctly updates the calendar Previously, changing these toggles had no effect until the view was reloaded Thanks to @hangryscribe3 for reporting (#1198) Fixed project links being created relative to the wrong file when editing from Bases views Relative paths in project links are now correctly resolved relative to the task note file Previously, editing a task from a Bases view would create project links relative to the .base file Thanks to @minchinweb for reporting"},{"route":"/obsidian/releases/4.1.1/","title":"TaskNotes 4.1.1","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.1.1.md","namespace":"obsidian","relativePath":"releases/4.1.1.md","raw":"# TaskNotes 4.1.1\n\n## Added\n\n- (#1277) Icon autosuggestion for custom status settings\n - Type to search through all available Lucide icons\n - Thanks to @Arachnidai for the suggestion\n- New formula properties in default Base templates\n - **Date calculations**: `daysUntilDue`, `daysUntilScheduled`, `daysSinceCreated`, `daysSinceModified`\n - **Boolean helpers**: `isOverdue`, `isDueToday`, `isDueThisWeek`, `isScheduledToday`, `isRecurring`, `hasTimeEstimate`\n - **Time tracking**: `timeRemaining`, `efficiencyRatio`, `timeTrackedThisWeek`, `timeTrackedToday`, `timeTrackedFormatted`\n - **Grouping**: `dueMonth`, `dueWeek`, `scheduledMonth`, `scheduledWeek`, `dueDateCategory`, `timeEstimateCategory`, `ageCategory`, `createdMonth`, `modifiedMonth`, `priorityCategory`, `projectCount`, `contextCount`, `trackingStatus`\n - **Combined due/scheduled**: `nextDate`, `daysUntilNext`, `hasDate`, `isToday`, `isThisWeek`, `nextDateCategory`, `nextDateMonth`, `nextDateWeek` - work with whichever date comes first\n - **Sorting**: `priorityWeight`, `urgencyScore` (combines priority with date proximity)\n - **Display**: `dueDateDisplay` (relative dates like \"Today\", \"Tomorrow\", \"3d ago\")\n - Action-oriented views (Not Blocked, Today, Overdue, This Week) now sort by urgency score, showing most important tasks first\n - See [Default Base Templates documentation](https://tasknotes.dev/views/default-base-templates) for full details\n - **Note**: To get these new formulas, either copy them from the documentation, or delete your `.base` files in `TaskNotes/Views/` and restart Obsidian to regenerate them\n\n## Changed\n\n- (#1282) Added spacing between task title and metadata in inline task widgets for improved readability\n - Thanks to @3zra47 for the suggestion\n- Custom status icons now display in all context menus (task context menu, batch operations menu, and task creation/edit modals)\n- Added embedded video guide for Google Calendar OAuth setup in documentation\n - Thanks to [@antoneheyward](https://www.youtube.com/@antoneheyward) for the tutorial\n\n## Fixed\n\n- (#1279) Fixed Kanban column width setting not being respected on mobile devices\n - Thanks to @guncav for reporting\n- (#1026), (#1177) Fixed recurring task completion from Base views recording the wrong date for users in negative UTC offset timezones (e.g., PST/PDT) when completing tasks in the evening\n - The bug caused `complete_instances` to record the next day instead of the user's current calendar day\n - Thanks to @3zra47 and @nslee123 for reporting and providing detailed reproduction steps\n\n","aliases":["/releases/4.1.1/","/releases/4.1.1/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • (#1277) Icon autosuggestion for custom status settings
      \n
    • Type to search through all available Lucide icons
    • \n
    • Thanks to @Arachnidai for the suggestion
    • \n
    \n
  • \n
  • New formula properties in default Base templates
      \n
    • Date calculations: daysUntilDue, daysUntilScheduled, daysSinceCreated, daysSinceModified
    • \n
    • Boolean helpers: isOverdue, isDueToday, isDueThisWeek, isScheduledToday, isRecurring, hasTimeEstimate
    • \n
    • Time tracking: timeRemaining, efficiencyRatio, timeTrackedThisWeek, timeTrackedToday, timeTrackedFormatted
    • \n
    • Grouping: dueMonth, dueWeek, scheduledMonth, scheduledWeek, dueDateCategory, timeEstimateCategory, ageCategory, createdMonth, modifiedMonth, priorityCategory, projectCount, contextCount, trackingStatus
    • \n
    • Combined due/scheduled: nextDate, daysUntilNext, hasDate, isToday, isThisWeek, nextDateCategory, nextDateMonth, nextDateWeek - work with whichever date comes first
    • \n
    • Sorting: priorityWeight, urgencyScore (combines priority with date proximity)
    • \n
    • Display: dueDateDisplay (relative dates like "Today", "Tomorrow", "3d ago")
    • \n
    • Action-oriented views (Not Blocked, Today, Overdue, This Week) now sort by urgency score, showing most important tasks first
    • \n
    • See Default Base Templates documentation for full details
    • \n
    • Note: To get these new formulas, either copy them from the documentation, or delete your .base files in TaskNotes/Views/ and restart Obsidian to regenerate them
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • (#1282) Added spacing between task title and metadata in inline task widgets for improved readability
      \n
    • Thanks to @3zra47 for the suggestion
    • \n
    \n
  • \n
  • Custom status icons now display in all context menus (task context menu, batch operations menu, and task creation/edit modals)
  • \n
  • Added embedded video guide for Google Calendar OAuth setup in documentation\n
  • \n
\n

Fixed#

\n
    \n
  • (#1279) Fixed Kanban column width setting not being respected on mobile devices
      \n
    • Thanks to @guncav for reporting
    • \n
    \n
  • \n
  • (#1026), (#1177) Fixed recurring task completion from Base views recording the wrong date for users in negative UTC offset timezones (e.g., PST/PDT) when completing tasks in the evening
      \n
    • The bug caused complete_instances to record the next day instead of the user's current calendar day
    • \n
    • Thanks to @3zra47 and @nslee123 for reporting and providing detailed reproduction steps
    • \n
    \n
  • \n
\n","text":"Added# (#1277) Icon autosuggestion for custom status settings Type to search through all available Lucide icons Thanks to @Arachnidai for the suggestion New formula properties in default Base templates Date calculations: daysUntilDue, daysUntilScheduled, daysSinceCreated, daysSinceModified Boolean helpers: isOverdue, isDueToday, isDueThisWeek, isScheduledToday, isRecurring, hasTimeEstimate Time tracking: timeRemaining, efficiencyRatio, timeTrackedThisWeek, timeTrackedToday, timeTrackedFormatted Grouping: dueMonth, dueWeek, scheduledMonth, scheduledWeek, dueDateCategory, timeEstimateCategory, ageCategory, createdMonth, modifiedMonth, priorityCategory, projectCount, contextCount, trackingStatus Combined due/scheduled: nextDate, daysUntilNext, hasDate, isToday, isThisWeek, nextDateCategory, nextDateMonth, nextDateWeek - work with whichever date comes first Sorting: priorityWeight, urgencyScore (combines priority with date proximity) Display: dueDateDisplay (relative dates like \"Today\", \"Tomorrow\", \"3d ago\") Action-oriented views (Not Blocked, Today, Overdue, This Week) now sort by urgency score, showing most important tasks first See Default Base Templates documentation for full details Note: To get these new formulas, either copy them from the documentation, or delete your .base files in TaskNotes/Views/ and restart Obsidian to regenerate them Changed# (#1282) Added spacing between task title and metadata in inline task widgets for improved readability Thanks to @3zra47 for the suggestion Custom status icons now display in all context menus (task context menu, batch operations menu, and task creation/edit modals) Added embedded video guide for Google Calendar OAuth setup in documentation Thanks to @antoneheyward for the tutorial Fixed# (#1279) Fixed Kanban column width setting not being respected on mobile devices Thanks to @guncav for reporting (#1026), (#1177) Fixed recurring task completion from Base views recording the wrong date for users in negative UTC offset timezones (e.g., PST/PDT) when completing tasks in the evening The bug caused complete_instances to record the next day instead of the user's current calendar day Thanks to @3zra47 and @nslee123 for reporting and providing detailed reproduction steps"},{"route":"/obsidian/releases/4.1.2/","title":"TaskNotes 4.1.2","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.1.2.md","namespace":"obsidian","relativePath":"releases/4.1.2.md","raw":"# TaskNotes 4.1.2\n\n## Fixed\n\n- Significant performance improvements for Bases views (TaskList, Kanban, Calendar)\n - Reduced `extractDataItems` time from ~4 seconds to ~5-10ms for large vaults (6000+ tasks)\n - Computed file properties (`file.backlinks`, `file.links`, etc.) are now fetched lazily during render instead of upfront\n - Only visible items (with virtualization) trigger expensive property computations\n - Added debouncing to `onDataUpdated` to prevent UI freezes during typing\n - Timeblock generation now uses Obsidian's metadataCache instead of file reads\n - Added date range filtering for calendar events to skip events outside visible range\n - (#1285) Calendar view uses 5-second debounce to prevent flickering while typing\n\t - Thanks to @steven-murray for reporting\n- Calendar view switching (month/week/day/list) is now much faster\n - View type is now saved on unload instead of on every change\n- Fixed task edit modal archive button being too narrow on mobile devices\n- (#1319) Added missing properties to Field Mapping settings\n - `recurrence_anchor` - now in Settings > Task Properties > Task Details\n - `skipped_instances` - now in Settings > Task Properties > Metadata Properties\n - Thanks to @kazerniel for reporting\n- (#1310) Fixed inline task conversion deleting text when task title exceeds filename limits\n - Text that cannot fit in the filename is now preserved in the task note's body\n - Thanks to @prayidae for reporting\n- (#1301) Fixed inline task wikilinks leaving blank space when no metadata properties are visible\n - Thanks to @Richard-UMPV for reporting\n- (#1317) Fixed project autosuggest filters not working correctly when only \"Required Property Key\" is configured\n - NLP `+` trigger now properly filters by property existence when no property value is specified\n - Modal \"Add to project\" button now shows consistent results with inline autosuggest\n - Thanks to @JacksonMcDonaldDev for reporting\n- (#1287), (#1307) The \"New\" button in Bases views now opens the TaskNotes creation modal\n - Tasks created from Bases views now respect default properties (status, priority, etc.)\n - Tasks are now created in the configured default folder instead of the views folder\n - Thanks to @anareaty and @sylvainfct-dot for reporting\n- (#1291) Fixed Microsoft Calendar OAuth documentation using wrong redirect URI\n - Added instructions for configuring via Azure manifest editor\n - Thanks to @PlecotusAustriacus for reporting\n\n## Added\n\n- (#803) New command \"Convert current note to task\" to add task properties to an existing note\n - Thanks to @GardarikanetS and @diegomarzaa for suggesting\n- (#1080) Custom user fields now support default values\n - Each field type has an appropriate input: text field, number input, toggle, date preset dropdown, or comma-separated list\n - Defaults are applied when creating tasks via modal, instant conversion, \"Create or open task\" command, or HTTP API\n - Thanks to @bradyrx for suggesting\n\n## Changed\n\n- Added documentation link to settings panel (links to tasknotes.dev)\n- Reorganized settings panel for improved discoverability\n - Removed \"Defaults\" tab - default values are now configured alongside each property in the Task Properties tab\n - Moved task filename format settings to the Title property section\n - Moved project autosuggest settings to the Projects property section\n - Body template setting moved to the Features tab\n - Added descriptions to each property explaining its purpose\n - Moved \"Folder for converted tasks\" setting to General tab under Task Storage for better discoverability\n - Updated setting description to clarify that leaving empty uses the default tasks folder\n\n","aliases":["/releases/4.1.2/","/releases/4.1.2/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"}],"html":"

Fixed#

\n
    \n
  • Significant performance improvements for Bases views (TaskList, Kanban, Calendar)
      \n
    • Reduced extractDataItems time from ~4 seconds to ~5-10ms for large vaults (6000+ tasks)
    • \n
    • Computed file properties (file.backlinks, file.links, etc.) are now fetched lazily during render instead of upfront
    • \n
    • Only visible items (with virtualization) trigger expensive property computations
    • \n
    • Added debouncing to onDataUpdated to prevent UI freezes during typing
    • \n
    • Timeblock generation now uses Obsidian's metadataCache instead of file reads
    • \n
    • Added date range filtering for calendar events to skip events outside visible range
    • \n
    • (#1285) Calendar view uses 5-second debounce to prevent flickering while typing
        \n
      • Thanks to @steven-murray for reporting
      • \n
      \n
    • \n
    \n
  • \n
  • Calendar view switching (month/week/day/list) is now much faster
      \n
    • View type is now saved on unload instead of on every change
    • \n
    \n
  • \n
  • Fixed task edit modal archive button being too narrow on mobile devices
  • \n
  • (#1319) Added missing properties to Field Mapping settings
      \n
    • recurrence_anchor - now in Settings > Task Properties > Task Details
    • \n
    • skipped_instances - now in Settings > Task Properties > Metadata Properties
    • \n
    • Thanks to @kazerniel for reporting
    • \n
    \n
  • \n
  • (#1310) Fixed inline task conversion deleting text when task title exceeds filename limits
      \n
    • Text that cannot fit in the filename is now preserved in the task note's body
    • \n
    • Thanks to @prayidae for reporting
    • \n
    \n
  • \n
  • (#1301) Fixed inline task wikilinks leaving blank space when no metadata properties are visible
      \n
    • Thanks to @Richard-UMPV for reporting
    • \n
    \n
  • \n
  • (#1317) Fixed project autosuggest filters not working correctly when only "Required Property Key" is configured
      \n
    • NLP + trigger now properly filters by property existence when no property value is specified
    • \n
    • Modal "Add to project" button now shows consistent results with inline autosuggest
    • \n
    • Thanks to @JacksonMcDonaldDev for reporting
    • \n
    \n
  • \n
  • (#1287), (#1307) The "New" button in Bases views now opens the TaskNotes creation modal
      \n
    • Tasks created from Bases views now respect default properties (status, priority, etc.)
    • \n
    • Tasks are now created in the configured default folder instead of the views folder
    • \n
    • Thanks to @anareaty and @sylvainfct-dot for reporting
    • \n
    \n
  • \n
  • (#1291) Fixed Microsoft Calendar OAuth documentation using wrong redirect URI
      \n
    • Added instructions for configuring via Azure manifest editor
    • \n
    • Thanks to @PlecotusAustriacus for reporting
    • \n
    \n
  • \n
\n

Added#

\n
    \n
  • (#803) New command "Convert current note to task" to add task properties to an existing note
      \n
    • Thanks to @GardarikanetS and @diegomarzaa for suggesting
    • \n
    \n
  • \n
  • (#1080) Custom user fields now support default values
      \n
    • Each field type has an appropriate input: text field, number input, toggle, date preset dropdown, or comma-separated list
    • \n
    • Defaults are applied when creating tasks via modal, instant conversion, "Create or open task" command, or HTTP API
    • \n
    • Thanks to @bradyrx for suggesting
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Added documentation link to settings panel (links to tasknotes.dev)
  • \n
  • Reorganized settings panel for improved discoverability
      \n
    • Removed "Defaults" tab - default values are now configured alongside each property in the Task Properties tab
    • \n
    • Moved task filename format settings to the Title property section
    • \n
    • Moved project autosuggest settings to the Projects property section
    • \n
    • Body template setting moved to the Features tab
    • \n
    • Added descriptions to each property explaining its purpose
    • \n
    • Moved "Folder for converted tasks" setting to General tab under Task Storage for better discoverability
    • \n
    • Updated setting description to clarify that leaving empty uses the default tasks folder
    • \n
    \n
  • \n
\n","text":"Fixed# Significant performance improvements for Bases views (TaskList, Kanban, Calendar) Reduced extractDataItems time from ~4 seconds to ~5-10ms for large vaults (6000+ tasks) Computed file properties (file.backlinks, file.links, etc.) are now fetched lazily during render instead of upfront Only visible items (with virtualization) trigger expensive property computations Added debouncing to onDataUpdated to prevent UI freezes during typing Timeblock generation now uses Obsidian's metadataCache instead of file reads Added date range filtering for calendar events to skip events outside visible range (#1285) Calendar view uses 5-second debounce to prevent flickering while typing Thanks to @steven-murray for reporting Calendar view switching (month/week/day/list) is now much faster View type is now saved on unload instead of on every change Fixed task edit modal archive button being too narrow on mobile devices (#1319) Added missing properties to Field Mapping settings recurrence_anchor - now in Settings > Task Properties > Task Details skipped_instances - now in Settings > Task Properties > Metadata Properties Thanks to @kazerniel for reporting (#1310) Fixed inline task conversion deleting text when task title exceeds filename limits Text that cannot fit in the filename is now preserved in the task note's body Thanks to @prayidae for reporting (#1301) Fixed inline task wikilinks leaving blank space when no metadata properties are visible Thanks to @Richard-UMPV for reporting (#1317) Fixed project autosuggest filters not working correctly when only \"Required Property Key\" is configured NLP + trigger now properly filters by property existence when no property value is specified Modal \"Add to project\" button now shows consistent results with inline autosuggest Thanks to @JacksonMcDonaldDev for reporting (#1287), (#1307) The \"New\" button in Bases views now opens the TaskNotes creation modal Tasks created from Bases views now respect default properties (status, priority, etc.) Tasks are now created in the configured default folder instead of the views folder Thanks to @anareaty and @sylvainfct-dot for reporting (#1291) Fixed Microsoft Calendar OAuth documentation using wrong redirect URI Added instructions for configuring via Azure manifest editor Thanks to @PlecotusAustriacus for reporting Added# (#803) New command \"Convert current note to task\" to add task properties to an existing note Thanks to @GardarikanetS and @diegomarzaa for suggesting (#1080) Custom user fields now support default values Each field type has an appropriate input: text field, number input, toggle, date preset dropdown, or comma-separated list Defaults are applied when creating tasks via modal, instant conversion, \"Create or open task\" command, or HTTP API Thanks to @bradyrx for suggesting Changed# Added documentation link to settings panel (links to tasknotes.dev) Reorganized settings panel for improved discoverability Removed \"Defaults\" tab - default values are now configured alongside each property in the Task Properties tab Moved task filename format settings to the Title property section Moved project autosuggest settings to the Projects property section Body template setting moved to the Features tab Added descriptions to each property explaining its purpose Moved \"Folder for converted tasks\" setting to General tab under Task Storage for better discoverability Updated setting description to clarify that leaving empty uses the default tasks folder"},{"route":"/obsidian/releases/4.1.3/","title":"TaskNotes 4.1.3","description":"This patch fixes a critical performance issue affecting the Calendar views. As a bonus, it adds a configurable \"split\" view to the task creation/edit modals.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.1.3.md","namespace":"obsidian","relativePath":"releases/4.1.3.md","raw":"# TaskNotes 4.1.3\n\nThis patch fixes a critical performance issue affecting the Calendar views. As a bonus, it adds a configurable \"split\" view to the task creation/edit modals. \n\n## Added\n\n- Split layout for task modals on wide screens (900px+)\n - Details editor appears in a dedicated right column when the modal is expanded\n - New setting \"Split layout on wide screens\" in Modal Fields settings tab to toggle this behavior\n - Improves usability by showing form fields and details side-by-side\n\n## Fixed\n\n- (#1330) Fixed calendar view regression taking 5 seconds to load and respond to user interactions\n - Initial calendar load is now immediate again\n - User interactions (drag/drop, creating timeblocks, etc.) respond instantly\n - Removed redundant date filtering (FullCalendar handles this more efficiently)\n - Thanks to @ysafonov, @kmaustral, @sunjiawe, @Мизгирь, and @FiliusIcari for reporting\n","aliases":["/releases/4.1.3/","/releases/4.1.3/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

This patch fixes a critical performance issue affecting the Calendar views. As a bonus, it adds a configurable "split" view to the task creation/edit modals.

\n

Added#

\n
    \n
  • Split layout for task modals on wide screens (900px+)
      \n
    • Details editor appears in a dedicated right column when the modal is expanded
    • \n
    • New setting "Split layout on wide screens" in Modal Fields settings tab to toggle this behavior
    • \n
    • Improves usability by showing form fields and details side-by-side
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1330) Fixed calendar view regression taking 5 seconds to load and respond to user interactions
      \n
    • Initial calendar load is now immediate again
    • \n
    • User interactions (drag/drop, creating timeblocks, etc.) respond instantly
    • \n
    • Removed redundant date filtering (FullCalendar handles this more efficiently)
    • \n
    • Thanks to @ysafonov, @kmaustral, @sunjiawe, @Мизгирь, and @FiliusIcari for reporting
    • \n
    \n
  • \n
\n","text":"This patch fixes a critical performance issue affecting the Calendar views. As a bonus, it adds a configurable \"split\" view to the task creation/edit modals. Added# Split layout for task modals on wide screens (900px+) Details editor appears in a dedicated right column when the modal is expanded New setting \"Split layout on wide screens\" in Modal Fields settings tab to toggle this behavior Improves usability by showing form fields and details side-by-side Fixed# (#1330) Fixed calendar view regression taking 5 seconds to load and respond to user interactions Initial calendar load is now immediate again User interactions (drag/drop, creating timeblocks, etc.) respond instantly Removed redundant date filtering (FullCalendar handles this more efficiently) Thanks to @ysafonov, @kmaustral, @sunjiawe, @Мизгирь, and @FiliusIcari for reporting"},{"route":"/obsidian/releases/4.10.0/","title":"TaskNotes 4.10.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.10.0.md","namespace":"obsidian","relativePath":"releases/4.10.0.md","raw":"# TaskNotes 4.10.0\n\n## Added\n\n- **New companion plugin:** TaskNotes Workflows adds Markdown-defined automation for TaskNotes tasks, events, schedules, and manual commands. It keeps automation workflows outside TaskNotes core while using the runtime API for safe task reads, writes, queries, events, and relationship resolution. See [TaskNotes Workflows](https://tasknotes.dev/companion-plugins/tasknotes-workflows/).\n - (#1530) `Auto-start time tracking` starts a timer when a task moves into active work. Thanks to @Jendrik0 and @benmartinek for the request and follow-up.\n - (#222, #184) `Stop time tracking on complete` stops active timers when a task is completed. Thanks to @bcohen44 and @cathywu for the requests, and @amarjt for the follow-up.\n - (#265) `Stamp started timestamp` records a custom started timestamp when a task first moves into active work. Thanks to @cathywu, @digitaldoctors, and @Leo310 for the request and discussion.\n - (#1703) `Clear scheduled when started` clears the scheduled date when a task moves into active work. Thanks to @kmaustral for the request.\n - (#1293) `Rollover overdue scheduled tasks` moves incomplete tasks with past scheduled dates back to today. Thanks to @grosserfrank for the request.\n - (#1896) `Escalate upcoming due tasks` raises priority as due dates approach. Thanks to @Neptune-Illusion for the request.\n - (#214, #518, #1785, #1855) The subtask inheritance workflows can copy parent contexts, tags, priority, planning dates, and dependencies into new subtasks. Thanks to @timfidd, @bepolymathe, @AndyEveritt, @lindsaylearns, @tomsymonds, @wedgen, @poulpoulsen, and @misolex for the related requests and discussion.\n - (#1166) `Blocked task review` provides a reminder-style review for blocked tasks without automatically deleting dependency links. Thanks to @jpmoo and @jortscity for the request and follow-up.\n- Added a versioned TaskNotes JavaScript runtime API for companion plugins, with namespaced model validation, canonical task query validation/normalization/explain helpers, catalogs, query/support helpers, lifecycle events, typed errors/results, task, time-tracking, Pomodoro, recurring-task, settings, NLP, event, and extension-registry surfaces. Runtime API mutations carry source and correlation metadata so companion plugins can debug and coordinate workflow runs. See [JavaScript API](https://tasknotes.dev/javascript-api/).\n- Added documentation for the companion-plugin model. See [Companion Plugins](https://tasknotes.dev/companion-plugins/).\n- (#288, #345, #361, #523, #573, #703, #925, #929, #1115, #1137, #1260, #1303, #1324, #1394, #1445, #1509, #1735, #1736, #1743, #1780, #1874, #1951, #1974) Added support for TaskNotes spec 0.2.0 materialized occurrences, including recurrence parent/date fields, generated mdbase schema roles, parent reconciliation when occurrence notes are completed, occurrence notes that inherit parent planning metadata without copying history, occurrence note controls in task, calendar, and edit-modal completion menus, and visible occurrence identity on task cards. This gives recurring tasks a concrete occurrence-note path for per-instance state, related notes, subtasks, templates, scheduling changes, completion history, and calendar behavior without forcing every recurring task to create files. See [Recurring Tasks](https://tasknotes.dev/features/recurring-tasks/#materialized-occurrence-notes) and [Property Types Reference](https://tasknotes.dev/settings/property-types-reference/#materialized-occurrence-properties). Thanks to @LuxBetancourt, @jerzy-dudzic, @luciolebrillante, @BryanWall, @jhedlund, @kazerniel, @nschenone, @realJohnDoe, @cathywu, @Lorite, @EllenGYY, @JcMinarro, @gsssr, @slipstyle, @3zra47, @Leonard-44, @ak-42, @RumiaKitinari, @atos2212-blip, @kmaustral, @eugenedefox, @notDavid, @zitongcharliedeng, and @Jomo94 for the related recurrence, occurrence, completion, and calendar requests.\n- (#1951) Added Calendar support for recurring tasks stretched between scheduled and due dates when the existing stretch option is enabled. Date-only ranges stay as all-day spans, and timed ranges render once per day in the range. Thanks to @atos2212-blip for the request.\n- (#1751, #1792, #1969) Added a Task List and Kanban view option to hide top-level subtasks when their parent task is also in the filtered view, while still allowing inherited expanded relationships to show the subtasks under the parent. Thanks to @Glint-Eye and @Proxybat for the request and follow-up, and @stanley-910 and @Spencerduran for the earlier PRs.\n\n## Changed\n\n- Moved core TaskNotes model behavior for field mapping, dates, recurrence, time-tracking, and adapter operation planning into a shared package used by the plugin and companion tooling.\n- Calendar views now coalesce materialized occurrence notes with their matching virtual recurring instances. Dragging a materialized occurrence reschedules that occurrence note without changing the parent recurrence rule or the note's `occurrence_date` identity. See [Recurring Tasks](https://tasknotes.dev/features/recurring-tasks/#calendar-drag-and-drop).\n- Improved the Calendar Bases View Options menu by splitting settings into clearer groups and hiding view-specific controls until they apply to the selected calendar mode.\n\n## Fixed\n\n- (#1976) Fixed embedded Calendar and Agenda Bases so \"Navigate to date from property\" can use the containing note's date property when the Base rows do not have that property. Thanks to @matesvecenik for reporting this.\n- (#1977) Fixed Calendar and Agenda views showing duplicate all-day entries when a task's scheduled date and due date are the same day. Timed due dates on the same day still show as separate deadline markers. Thanks to @pdgBC for reporting this.\n- Fixed the release notes view using cramped interface typography instead of regular reading typography.\n- (#216) Improved inline conversion for Tasks plugin task lines, including Dataview-style fields, priority markers, recurrence text, date aliases, block links, and safer trailing-field parsing. Thanks to @ksdavidc for the request, @natleahh for the Dataview example, and @hangryscribe3 and @nayatiuh for the discussion.\n- (#1974) Stopped Calendar and Agenda property-based events from logging date parse errors for entries that do not have the selected date property. Thanks to @Jomo94 for suggesting completed-date Agenda events.\n- (#1973) Reduced unnecessary Calendar view recreations when external calendar providers are reported in a different order, and preserved Calendar scroll position when a config-driven refresh has to recreate the view. Thanks to @e-zz for reporting this.\n- (#1972) Fixed ICS calendar event related notes so standalone events with similar numeric IDs no longer show unrelated notes or tasks on every event. Thanks to @ks-studio-net for reporting this.\n- (#1970) Fixed generated default Base filters so updating default files applies configured excluded folders to TaskNotes task views. Thanks to @henrim01 for reporting that templates could still appear in regenerated views.\n- (#1968) Fixed inline task link overlays collapsing on Obsidian mobile, which could hide the task title and leave a tall empty gap after the widget. Thanks to @renatomen for reporting and diagnosing the containment issue.\n","aliases":["/releases/4.10.0/","/releases/4.10.0/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • New companion plugin: TaskNotes Workflows adds Markdown-defined automation for TaskNotes tasks, events, schedules, and manual commands. It keeps automation workflows outside TaskNotes core while using the runtime API for safe task reads, writes, queries, events, and relationship resolution. See TaskNotes Workflows.
      \n
    • (#1530) Auto-start time tracking starts a timer when a task moves into active work. Thanks to @Jendrik0 and @benmartinek for the request and follow-up.
    • \n
    • (#222, #184) Stop time tracking on complete stops active timers when a task is completed. Thanks to @bcohen44 and @cathywu for the requests, and @amarjt for the follow-up.
    • \n
    • (#265) Stamp started timestamp records a custom started timestamp when a task first moves into active work. Thanks to @cathywu, @digitaldoctors, and @Leo310 for the request and discussion.
    • \n
    • (#1703) Clear scheduled when started clears the scheduled date when a task moves into active work. Thanks to @kmaustral for the request.
    • \n
    • (#1293) Rollover overdue scheduled tasks moves incomplete tasks with past scheduled dates back to today. Thanks to @grosserfrank for the request.
    • \n
    • (#1896) Escalate upcoming due tasks raises priority as due dates approach. Thanks to @Neptune-Illusion for the request.
    • \n
    • (#214, #518, #1785, #1855) The subtask inheritance workflows can copy parent contexts, tags, priority, planning dates, and dependencies into new subtasks. Thanks to @timfidd, @bepolymathe, @AndyEveritt, @lindsaylearns, @tomsymonds, @wedgen, @poulpoulsen, and @misolex for the related requests and discussion.
    • \n
    • (#1166) Blocked task review provides a reminder-style review for blocked tasks without automatically deleting dependency links. Thanks to @jpmoo and @jortscity for the request and follow-up.
    • \n
    \n
  • \n
  • Added a versioned TaskNotes JavaScript runtime API for companion plugins, with namespaced model validation, canonical task query validation/normalization/explain helpers, catalogs, query/support helpers, lifecycle events, typed errors/results, task, time-tracking, Pomodoro, recurring-task, settings, NLP, event, and extension-registry surfaces. Runtime API mutations carry source and correlation metadata so companion plugins can debug and coordinate workflow runs. See JavaScript API.
  • \n
  • Added documentation for the companion-plugin model. See Companion Plugins.
  • \n
  • (#288, #345, #361, #523, #573, #703, #925, #929, #1115, #1137, #1260, #1303, #1324, #1394, #1445, #1509, #1735, #1736, #1743, #1780, #1874, #1951, #1974) Added support for TaskNotes spec 0.2.0 materialized occurrences, including recurrence parent/date fields, generated mdbase schema roles, parent reconciliation when occurrence notes are completed, occurrence notes that inherit parent planning metadata without copying history, occurrence note controls in task, calendar, and edit-modal completion menus, and visible occurrence identity on task cards. This gives recurring tasks a concrete occurrence-note path for per-instance state, related notes, subtasks, templates, scheduling changes, completion history, and calendar behavior without forcing every recurring task to create files. See Recurring Tasks and Property Types Reference. Thanks to @LuxBetancourt, @jerzy-dudzic, @luciolebrillante, @BryanWall, @jhedlund, @kazerniel, @nschenone, @realJohnDoe, @cathywu, @Lorite, @EllenGYY, @JcMinarro, @gsssr, @slipstyle, @3zra47, @Leonard-44, @ak-42, @RumiaKitinari, @atos2212-blip, @kmaustral, @eugenedefox, @notDavid, @zitongcharliedeng, and @Jomo94 for the related recurrence, occurrence, completion, and calendar requests.
  • \n
  • (#1951) Added Calendar support for recurring tasks stretched between scheduled and due dates when the existing stretch option is enabled. Date-only ranges stay as all-day spans, and timed ranges render once per day in the range. Thanks to @atos2212-blip for the request.
  • \n
  • (#1751, #1792, #1969) Added a Task List and Kanban view option to hide top-level subtasks when their parent task is also in the filtered view, while still allowing inherited expanded relationships to show the subtasks under the parent. Thanks to @Glint-Eye and @Proxybat for the request and follow-up, and @stanley-910 and @Spencerduran for the earlier PRs.
  • \n
\n

Changed#

\n
    \n
  • Moved core TaskNotes model behavior for field mapping, dates, recurrence, time-tracking, and adapter operation planning into a shared package used by the plugin and companion tooling.
  • \n
  • Calendar views now coalesce materialized occurrence notes with their matching virtual recurring instances. Dragging a materialized occurrence reschedules that occurrence note without changing the parent recurrence rule or the note's occurrence_date identity. See Recurring Tasks.
  • \n
  • Improved the Calendar Bases View Options menu by splitting settings into clearer groups and hiding view-specific controls until they apply to the selected calendar mode.
  • \n
\n

Fixed#

\n
    \n
  • (#1976) Fixed embedded Calendar and Agenda Bases so "Navigate to date from property" can use the containing note's date property when the Base rows do not have that property. Thanks to @matesvecenik for reporting this.
  • \n
  • (#1977) Fixed Calendar and Agenda views showing duplicate all-day entries when a task's scheduled date and due date are the same day. Timed due dates on the same day still show as separate deadline markers. Thanks to @pdgBC for reporting this.
  • \n
  • Fixed the release notes view using cramped interface typography instead of regular reading typography.
  • \n
  • (#216) Improved inline conversion for Tasks plugin task lines, including Dataview-style fields, priority markers, recurrence text, date aliases, block links, and safer trailing-field parsing. Thanks to @ksdavidc for the request, @natleahh for the Dataview example, and @hangryscribe3 and @nayatiuh for the discussion.
  • \n
  • (#1974) Stopped Calendar and Agenda property-based events from logging date parse errors for entries that do not have the selected date property. Thanks to @Jomo94 for suggesting completed-date Agenda events.
  • \n
  • (#1973) Reduced unnecessary Calendar view recreations when external calendar providers are reported in a different order, and preserved Calendar scroll position when a config-driven refresh has to recreate the view. Thanks to @e-zz for reporting this.
  • \n
  • (#1972) Fixed ICS calendar event related notes so standalone events with similar numeric IDs no longer show unrelated notes or tasks on every event. Thanks to @ks-studio-net for reporting this.
  • \n
  • (#1970) Fixed generated default Base filters so updating default files applies configured excluded folders to TaskNotes task views. Thanks to @henrim01 for reporting that templates could still appear in regenerated views.
  • \n
  • (#1968) Fixed inline task link overlays collapsing on Obsidian mobile, which could hide the task title and leave a tall empty gap after the widget. Thanks to @renatomen for reporting and diagnosing the containment issue.
  • \n
\n","text":"Added# New companion plugin: TaskNotes Workflows adds Markdown-defined automation for TaskNotes tasks, events, schedules, and manual commands. It keeps automation workflows outside TaskNotes core while using the runtime API for safe task reads, writes, queries, events, and relationship resolution. See TaskNotes Workflows. (#1530) Auto-start time tracking starts a timer when a task moves into active work. Thanks to @Jendrik0 and @benmartinek for the request and follow-up. (#222, #184) Stop time tracking on complete stops active timers when a task is completed. Thanks to @bcohen44 and @cathywu for the requests, and @amarjt for the follow-up. (#265) Stamp started timestamp records a custom started timestamp when a task first moves into active work. Thanks to @cathywu, @digitaldoctors, and @Leo310 for the request and discussion. (#1703) Clear scheduled when started clears the scheduled date when a task moves into active work. Thanks to @kmaustral for the request. (#1293) Rollover overdue scheduled tasks moves incomplete tasks with past scheduled dates back to today. Thanks to @grosserfrank for the request. (#1896) Escalate upcoming due tasks raises priority as due dates approach. Thanks to @Neptune-Illusion for the request. (#214, #518, #1785, #1855) The subtask inheritance workflows can copy parent contexts, tags, priority, planning dates, and dependencies into new subtasks. Thanks to @timfidd, @bepolymathe, @AndyEveritt, @lindsaylearns, @tomsymonds, @wedgen, @poulpoulsen, and @misolex for the related requests and discussion. (#1166) Blocked task review provides a reminder-style review for blocked tasks without automatically deleting dependency links. Thanks to @jpmoo and @jortscity for the request and follow-up. Added a versioned TaskNotes JavaScript runtime API for companion plugins, with namespaced model validation, canonical task query validation/normalization/explain helpers, catalogs, query/support helpers, lifecycle events, typed errors/results, task, time-tracking, Pomodoro, recurring-task, settings, NLP, event, and extension-registry surfaces. Runtime API mutations carry source and correlation metadata so companion plugins can debug and coordinate workflow runs. See JavaScript API. Added documentation for the companion-plugin model. See Companion Plugins. (#288, #345, #361, #523, #573, #703, #925, #929, #1115, #1137, #1260, #1303, #1324, #1394, #1445, #1509, #1735, #1736, #1743, #1780, #1874, #1951, #1974) Added support for TaskNotes spec 0.2.0 materialized occurrences, including recurrence parent/date fields, generated mdbase schema roles, parent reconciliation when occurrence notes are completed, occurrence notes that inherit parent planning metadata without copying history, occurrence note controls in task, calendar, and edit-modal completion menus, and visible occurrence identity on task cards. This gives recurring tasks a concrete occurrence-note path for per-instance state, related notes, subtasks, templates, scheduling changes, completion history, and calendar behavior without forcing every recurring task to create files. See Recurring Tasks and Property Types Reference. Thanks to @LuxBetancourt, @jerzy-dudzic, @luciolebrillante, @BryanWall, @jhedlund, @kazerniel, @nschenone, @realJohnDoe, @cathywu, @Lorite, @EllenGYY, @JcMinarro, @gsssr, @slipstyle, @3zra47, @Leonard-44, @ak-42, @RumiaKitinari, @atos2212-blip, @kmaustral, @eugenedefox, @notDavid, @zitongcharliedeng, and @Jomo94 for the related recurrence, occurrence, completion, and calendar requests. (#1951) Added Calendar support for recurring tasks stretched between scheduled and due dates when the existing stretch option is enabled. Date-only ranges stay as all-day spans, and timed ranges render once per day in the range. Thanks to @atos2212-blip for the request. (#1751, #1792, #1969) Added a Task List and Kanban view option to hide top-level subtasks when their parent task is also in the filtered view, while still allowing inherited expanded relationships to show the subtasks under the parent. Thanks to @Glint-Eye and @Proxybat for the request and follow-up, and @stanley-910 and @Spencerduran for the earlier PRs. Changed# Moved core TaskNotes model behavior for field mapping, dates, recurrence, time-tracking, and adapter operation planning into a shared package used by the plugin and companion tooling. Calendar views now coalesce materialized occurrence notes with their matching virtual recurring instances. Dragging a materialized occurrence reschedules that occurrence note without changing the parent recurrence rule or the note's occurrence_date identity. See Recurring Tasks. Improved the Calendar Bases View Options menu by splitting settings into clearer groups and hiding view-specific controls until they apply to the selected calendar mode. Fixed# (#1976) Fixed embedded Calendar and Agenda Bases so \"Navigate to date from property\" can use the containing note's date property when the Base rows do not have that property. Thanks to @matesvecenik for reporting this. (#1977) Fixed Calendar and Agenda views showing duplicate all-day entries when a task's scheduled date and due date are the same day. Timed due dates on the same day still show as separate deadline markers. Thanks to @pdgBC for reporting this. Fixed the release notes view using cramped interface typography instead of regular reading typography. (#216) Improved inline conversion for Tasks plugin task lines, including Dataview-style fields, priority markers, recurrence text, date aliases, block links, and safer trailing-field parsing. Thanks to @ksdavidc for the request, @natleahh for the Dataview example, and @hangryscribe3 and @nayatiuh for the discussion. (#1974) Stopped Calendar and Agenda property-based events from logging date parse errors for entries that do not have the selected date property. Thanks to @Jomo94 for suggesting completed-date Agenda events. (#1973) Reduced unnecessary Calendar view recreations when external calendar providers are reported in a different order, and preserved Calendar scroll position when a config-driven refresh has to recreate the view. Thanks to @e-zz for reporting this. (#1972) Fixed ICS calendar event related notes so standalone events with similar numeric IDs no longer show unrelated notes or tasks on every event. Thanks to @ks-studio-net for reporting this. (#1970) Fixed generated default Base filters so updating default files applies configured excluded folders to TaskNotes task views. Thanks to @henrim01 for reporting that templates could still appear in regenerated views. (#1968) Fixed inline task link overlays collapsing on Obsidian mobile, which could hide the task title and leave a tall empty gap after the widget. Thanks to @renatomen for reporting and diagnosing the containment issue."},{"route":"/obsidian/releases/4.10.1/","title":"TaskNotes 4.10.1","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.10.1.md","namespace":"obsidian","relativePath":"releases/4.10.1.md","raw":"# TaskNotes 4.10.1\n\n## Added\n\n- Added a startup check for new compatible TaskNotes releases. When a new release is available, TaskNotes shows a notice that opens the TaskNotes entry in Obsidian's Community Plugins browser.\n- (#1989) Added a command-palette action plus runtime and HTTP API actions for updating configured default `.base` files from the current TaskNotes templates. Thanks to @businessBoris for the request.\n- (#1115) Added API and MCP support for creating materialized occurrence notes from recurring tasks, and made headless recurring-instance completion respect occurrence notes when the parent uses Create next after completion. Thanks to @gsssr for the original request, @slipstyle for the follow-up, and @martin-forge for identifying the API/MCP gap.\n\n## Fixed\n\n- (#1985) Fixed embedded Calendar and Agenda time-grid views drifting out of alignment inside callouts and Reading mode. Thanks to @matesvecenik for reporting and sharing screenshots.\n- (#1986) Fixed the local HTTP API rejecting requests from the TaskNotes browser extension's Chrome extension origin. Thanks to @n1njaznutz for reporting this.\n- (#1980) Added mobile bottom spacing to Agenda Calendar views so the last visible tasks can scroll above Obsidian's bottom navigation bar. Thanks to @Jomo94 for reporting and sharing the screenshot.\n- (#1984) Fixed mobile task link overlays hiding configured inline task card properties such as scheduled date, due date, contexts, and projects. Thanks to @stil-sudo for reporting.\n- (#1979) Kept the left-positioned subtask chevron from overlapping the task status control on mobile task cards. Thanks to @Jomo94 for reporting and sharing the screenshot.\n- (#1903) Reduced the Edit Task modal's mobile action-button footer so Open note, Archive, Delete, Save, and Cancel take two rows instead of three on iPhone-sized screens. Thanks to @3zra47 for the original report and @krzyfu for the follow-up about the button area crowding the editor.\n- (#1982) Preserved scroll position in TaskNotes Bases after task edits and data refreshes, avoiding jumps back to the top on mobile. Thanks to @3zra47 for reporting.\n- (#1978) Restored Obsidian editor shortcuts such as insert link, headings, and list toggles inside the Edit Task modal's Details editor. Thanks to @krzyfu for reporting this.\n","aliases":["/releases/4.10.1/","/releases/4.10.1/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • Added a startup check for new compatible TaskNotes releases. When a new release is available, TaskNotes shows a notice that opens the TaskNotes entry in Obsidian's Community Plugins browser.
  • \n
  • (#1989) Added a command-palette action plus runtime and HTTP API actions for updating configured default .base files from the current TaskNotes templates. Thanks to @businessBoris for the request.
  • \n
  • (#1115) Added API and MCP support for creating materialized occurrence notes from recurring tasks, and made headless recurring-instance completion respect occurrence notes when the parent uses Create next after completion. Thanks to @gsssr for the original request, @slipstyle for the follow-up, and @martin-forge for identifying the API/MCP gap.
  • \n
\n

Fixed#

\n
    \n
  • (#1985) Fixed embedded Calendar and Agenda time-grid views drifting out of alignment inside callouts and Reading mode. Thanks to @matesvecenik for reporting and sharing screenshots.
  • \n
  • (#1986) Fixed the local HTTP API rejecting requests from the TaskNotes browser extension's Chrome extension origin. Thanks to @n1njaznutz for reporting this.
  • \n
  • (#1980) Added mobile bottom spacing to Agenda Calendar views so the last visible tasks can scroll above Obsidian's bottom navigation bar. Thanks to @Jomo94 for reporting and sharing the screenshot.
  • \n
  • (#1984) Fixed mobile task link overlays hiding configured inline task card properties such as scheduled date, due date, contexts, and projects. Thanks to @stil-sudo for reporting.
  • \n
  • (#1979) Kept the left-positioned subtask chevron from overlapping the task status control on mobile task cards. Thanks to @Jomo94 for reporting and sharing the screenshot.
  • \n
  • (#1903) Reduced the Edit Task modal's mobile action-button footer so Open note, Archive, Delete, Save, and Cancel take two rows instead of three on iPhone-sized screens. Thanks to @3zra47 for the original report and @krzyfu for the follow-up about the button area crowding the editor.
  • \n
  • (#1982) Preserved scroll position in TaskNotes Bases after task edits and data refreshes, avoiding jumps back to the top on mobile. Thanks to @3zra47 for reporting.
  • \n
  • (#1978) Restored Obsidian editor shortcuts such as insert link, headings, and list toggles inside the Edit Task modal's Details editor. Thanks to @krzyfu for reporting this.
  • \n
\n","text":"Added# Added a startup check for new compatible TaskNotes releases. When a new release is available, TaskNotes shows a notice that opens the TaskNotes entry in Obsidian's Community Plugins browser. (#1989) Added a command-palette action plus runtime and HTTP API actions for updating configured default .base files from the current TaskNotes templates. Thanks to @businessBoris for the request. (#1115) Added API and MCP support for creating materialized occurrence notes from recurring tasks, and made headless recurring-instance completion respect occurrence notes when the parent uses Create next after completion. Thanks to @gsssr for the original request, @slipstyle for the follow-up, and @martin-forge for identifying the API/MCP gap. Fixed# (#1985) Fixed embedded Calendar and Agenda time-grid views drifting out of alignment inside callouts and Reading mode. Thanks to @matesvecenik for reporting and sharing screenshots. (#1986) Fixed the local HTTP API rejecting requests from the TaskNotes browser extension's Chrome extension origin. Thanks to @n1njaznutz for reporting this. (#1980) Added mobile bottom spacing to Agenda Calendar views so the last visible tasks can scroll above Obsidian's bottom navigation bar. Thanks to @Jomo94 for reporting and sharing the screenshot. (#1984) Fixed mobile task link overlays hiding configured inline task card properties such as scheduled date, due date, contexts, and projects. Thanks to @stil-sudo for reporting. (#1979) Kept the left-positioned subtask chevron from overlapping the task status control on mobile task cards. Thanks to @Jomo94 for reporting and sharing the screenshot. (#1903) Reduced the Edit Task modal's mobile action-button footer so Open note, Archive, Delete, Save, and Cancel take two rows instead of three on iPhone-sized screens. Thanks to @3zra47 for the original report and @krzyfu for the follow-up about the button area crowding the editor. (#1982) Preserved scroll position in TaskNotes Bases after task edits and data refreshes, avoiding jumps back to the top on mobile. Thanks to @3zra47 for reporting. (#1978) Restored Obsidian editor shortcuts such as insert link, headings, and list toggles inside the Edit Task modal's Details editor. Thanks to @krzyfu for reporting this."},{"route":"/obsidian/releases/4.10.2/","title":"TaskNotes 4.10.2","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.10.2.md","namespace":"obsidian","relativePath":"releases/4.10.2.md","raw":"# TaskNotes 4.10.2\n\n## Fixed\n\n- (#1995) Fixed Bases Calendar views showing both a materialized occurrence note and its matching virtual recurring task instance. Thanks to @rdefaccio for reporting this.\n- (Discussion #1994) Fixed timed recurring tasks failing to advance their due dates when due-date offset preservation is enabled. Thanks to @mgrecar for raising this.\n","aliases":["/releases/4.10.2/","/releases/4.10.2/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Fixed#

\n
    \n
  • (#1995) Fixed Bases Calendar views showing both a materialized occurrence note and its matching virtual recurring task instance. Thanks to @rdefaccio for reporting this.
  • \n
  • (Discussion #1994) Fixed timed recurring tasks failing to advance their due dates when due-date offset preservation is enabled. Thanks to @mgrecar for raising this.
  • \n
\n","text":"Fixed# (#1995) Fixed Bases Calendar views showing both a materialized occurrence note and its matching virtual recurring task instance. Thanks to @rdefaccio for reporting this. (Discussion #1994) Fixed timed recurring tasks failing to advance their due dates when due-date offset preservation is enabled. Thanks to @mgrecar for raising this."},{"route":"/obsidian/releases/4.11.0/","title":"TaskNotes 4.11.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.11.0.md","namespace":"obsidian","relativePath":"releases/4.11.0.md","raw":"# TaskNotes 4.11.0\n\n## Added\n\n- (#730, #1897, #1942, #1998) Added [Canvas Bases](https://github.com/callumalpass/canvas-bases), an optional companion plugin that turns Obsidian Bases views into canvas-style boards and reusable JSON Canvas snapshots, with TaskNotes badges, task menus, dependency and subtask edges, and assignment zones for supported TaskNotes actions. See [Canvas Bases](https://tasknotes.dev/companion-plugins/canvas-bases/) for setup details. Thanks to @DillPickle80, @BradGaddis, @Hyadhuad, and @AlinaWithAFace for the visual planning requests, and to @renatomen, @prayidae, and @maranqz for the related discussion.\n- Added a TaskNotes starter note that is created and opened automatically on first install to introduce task creation, inline conversion, and embedded Bases views.\n- Added a runtime API surface for companion plugins to show or populate the standard TaskNotes task context menu.\n- (#2000) Added separate settings for using the active note as a project during normal task creation and during inline task creation or instant conversion. Thanks to @BlueScreen32 for suggesting the split.\n- (#1303, #2001) Added separate templates for materialized occurrence notes, including parent-level `occurrence_template` support and a global fallback setting. Thanks to @BrucePlumb for suggesting a separate occurrence-note template and @ak-42 for the related per-recurrence template request.\n- (#2006) Added the projected local finish time beside the remaining duration while a Pomodoro is running. See [Pomodoro View](https://tasknotes.dev/views/pomodoro-view/) for the timer behavior. Thanks to @abbiefalls90 for suggesting this.\n- (#2016) Added a setting for recurring external calendar event related notes, so Google, Microsoft, and ICS recurrences can either share notes across the series or keep notes limited to the selected instance. See [Integrations Settings](https://tasknotes.dev/settings/integrations/#calendar-subscriptions-ics) for the setting. Thanks to @akhtsang for reporting this, and to @cathywu and @mdbraber for the earlier series-linking discussion.\n\n## Changed\n\n- (#1737) Clarified that changing the task tag does not automatically update existing Base view filters. Thanks to @goldorak00 for reporting this, and to @Domcoppinger and @imsuck for the first-time setup feedback.\n- (#2005) Excluded archived task notes and archived project-note references from Task & Project Statistics. Thanks to @Xiarno for suggesting this.\n- Added a local review-type lint check that catches dependency-resolution warnings from Obsidian's online review before submission.\n- Improved dependency and project relationship cache updates so ordinary note edits avoid unnecessary relationship recalculation, while blocked and blocking state stays current when dependency status changes.\n- Improved filter and view query caching so filter options update immediately after relevant task-field changes while large Task List, Kanban, and Calendar queries avoid repeated vault scans.\n- Extended the in-app release notes bundle to include the current major release, with collapsed versions rendered only when opened.\n\n## Fixed\n\n- (#2015) Fixed Google Calendar events from the previous six months disappearing from Calendar and Mini Calendar views after a fresh sync. Thanks to @akhtsang for reporting this.\n- (#2013) Fixed task-card status and priority dots becoming oversized on touch-capable desktop devices. Thanks to @RumiaKitinari for reporting this.\n- (#2009) Restored Tab and Shift+Tab focus movement in the Create new task modal's natural language input instead of letting the markdown editor indent the title. Thanks to @prepare4robots for reporting this.\n- (#2007) Fixed status autocomplete in the task creation modal leaving status value fragments in the task title when the editor auto-paired the status trigger. Thanks to @prepare4robots for reporting this.\n- (#2004) Fixed the Pomodoro start command forgetting the selected task after it was completed, so reopening the task lets it be picked up again. Thanks to @MPourjam for reporting this.\n- (#1996) Made Kanban card drag-and-drop show a clear drop slot marker while cards are being repositioned, so the landing position remains visible during sorting. Thanks to @phillipadsmith for reporting this.\n- Fixed runtime API dependency removal so removing the last dependency from a task also clears the mapped `blockedBy` property from the note.\n","aliases":["/releases/4.11.0/","/releases/4.11.0/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • (#730, #1897, #1942, #1998) Added Canvas Bases, an optional companion plugin that turns Obsidian Bases views into canvas-style boards and reusable JSON Canvas snapshots, with TaskNotes badges, task menus, dependency and subtask edges, and assignment zones for supported TaskNotes actions. See Canvas Bases for setup details. Thanks to @DillPickle80, @BradGaddis, @Hyadhuad, and @AlinaWithAFace for the visual planning requests, and to @renatomen, @prayidae, and @maranqz for the related discussion.
  • \n
  • Added a TaskNotes starter note that is created and opened automatically on first install to introduce task creation, inline conversion, and embedded Bases views.
  • \n
  • Added a runtime API surface for companion plugins to show or populate the standard TaskNotes task context menu.
  • \n
  • (#2000) Added separate settings for using the active note as a project during normal task creation and during inline task creation or instant conversion. Thanks to @BlueScreen32 for suggesting the split.
  • \n
  • (#1303, #2001) Added separate templates for materialized occurrence notes, including parent-level occurrence_template support and a global fallback setting. Thanks to @BrucePlumb for suggesting a separate occurrence-note template and @ak-42 for the related per-recurrence template request.
  • \n
  • (#2006) Added the projected local finish time beside the remaining duration while a Pomodoro is running. See Pomodoro View for the timer behavior. Thanks to @abbiefalls90 for suggesting this.
  • \n
  • (#2016) Added a setting for recurring external calendar event related notes, so Google, Microsoft, and ICS recurrences can either share notes across the series or keep notes limited to the selected instance. See Integrations Settings for the setting. Thanks to @akhtsang for reporting this, and to @cathywu and @mdbraber for the earlier series-linking discussion.
  • \n
\n

Changed#

\n
    \n
  • (#1737) Clarified that changing the task tag does not automatically update existing Base view filters. Thanks to @goldorak00 for reporting this, and to @Domcoppinger and @imsuck for the first-time setup feedback.
  • \n
  • (#2005) Excluded archived task notes and archived project-note references from Task & Project Statistics. Thanks to @Xiarno for suggesting this.
  • \n
  • Added a local review-type lint check that catches dependency-resolution warnings from Obsidian's online review before submission.
  • \n
  • Improved dependency and project relationship cache updates so ordinary note edits avoid unnecessary relationship recalculation, while blocked and blocking state stays current when dependency status changes.
  • \n
  • Improved filter and view query caching so filter options update immediately after relevant task-field changes while large Task List, Kanban, and Calendar queries avoid repeated vault scans.
  • \n
  • Extended the in-app release notes bundle to include the current major release, with collapsed versions rendered only when opened.
  • \n
\n

Fixed#

\n
    \n
  • (#2015) Fixed Google Calendar events from the previous six months disappearing from Calendar and Mini Calendar views after a fresh sync. Thanks to @akhtsang for reporting this.
  • \n
  • (#2013) Fixed task-card status and priority dots becoming oversized on touch-capable desktop devices. Thanks to @RumiaKitinari for reporting this.
  • \n
  • (#2009) Restored Tab and Shift+Tab focus movement in the Create new task modal's natural language input instead of letting the markdown editor indent the title. Thanks to @prepare4robots for reporting this.
  • \n
  • (#2007) Fixed status autocomplete in the task creation modal leaving status value fragments in the task title when the editor auto-paired the status trigger. Thanks to @prepare4robots for reporting this.
  • \n
  • (#2004) Fixed the Pomodoro start command forgetting the selected task after it was completed, so reopening the task lets it be picked up again. Thanks to @MPourjam for reporting this.
  • \n
  • (#1996) Made Kanban card drag-and-drop show a clear drop slot marker while cards are being repositioned, so the landing position remains visible during sorting. Thanks to @phillipadsmith for reporting this.
  • \n
  • Fixed runtime API dependency removal so removing the last dependency from a task also clears the mapped blockedBy property from the note.
  • \n
\n","text":"Added# (#730, #1897, #1942, #1998) Added Canvas Bases, an optional companion plugin that turns Obsidian Bases views into canvas-style boards and reusable JSON Canvas snapshots, with TaskNotes badges, task menus, dependency and subtask edges, and assignment zones for supported TaskNotes actions. See Canvas Bases for setup details. Thanks to @DillPickle80, @BradGaddis, @Hyadhuad, and @AlinaWithAFace for the visual planning requests, and to @renatomen, @prayidae, and @maranqz for the related discussion. Added a TaskNotes starter note that is created and opened automatically on first install to introduce task creation, inline conversion, and embedded Bases views. Added a runtime API surface for companion plugins to show or populate the standard TaskNotes task context menu. (#2000) Added separate settings for using the active note as a project during normal task creation and during inline task creation or instant conversion. Thanks to @BlueScreen32 for suggesting the split. (#1303, #2001) Added separate templates for materialized occurrence notes, including parent-level occurrence_template support and a global fallback setting. Thanks to @BrucePlumb for suggesting a separate occurrence-note template and @ak-42 for the related per-recurrence template request. (#2006) Added the projected local finish time beside the remaining duration while a Pomodoro is running. See Pomodoro View for the timer behavior. Thanks to @abbiefalls90 for suggesting this. (#2016) Added a setting for recurring external calendar event related notes, so Google, Microsoft, and ICS recurrences can either share notes across the series or keep notes limited to the selected instance. See Integrations Settings for the setting. Thanks to @akhtsang for reporting this, and to @cathywu and @mdbraber for the earlier series-linking discussion. Changed# (#1737) Clarified that changing the task tag does not automatically update existing Base view filters. Thanks to @goldorak00 for reporting this, and to @Domcoppinger and @imsuck for the first-time setup feedback. (#2005) Excluded archived task notes and archived project-note references from Task & Project Statistics. Thanks to @Xiarno for suggesting this. Added a local review-type lint check that catches dependency-resolution warnings from Obsidian's online review before submission. Improved dependency and project relationship cache updates so ordinary note edits avoid unnecessary relationship recalculation, while blocked and blocking state stays current when dependency status changes. Improved filter and view query caching so filter options update immediately after relevant task-field changes while large Task List, Kanban, and Calendar queries avoid repeated vault scans. Extended the in-app release notes bundle to include the current major release, with collapsed versions rendered only when opened. Fixed# (#2015) Fixed Google Calendar events from the previous six months disappearing from Calendar and Mini Calendar views after a fresh sync. Thanks to @akhtsang for reporting this. (#2013) Fixed task-card status and priority dots becoming oversized on touch-capable desktop devices. Thanks to @RumiaKitinari for reporting this. (#2009) Restored Tab and Shift+Tab focus movement in the Create new task modal's natural language input instead of letting the markdown editor indent the title. Thanks to @prepare4robots for reporting this. (#2007) Fixed status autocomplete in the task creation modal leaving status value fragments in the task title when the editor auto-paired the status trigger. Thanks to @prepare4robots for reporting this. (#2004) Fixed the Pomodoro start command forgetting the selected task after it was completed, so reopening the task lets it be picked up again. Thanks to @MPourjam for reporting this. (#1996) Made Kanban card drag-and-drop show a clear drop slot marker while cards are being repositioned, so the landing position remains visible during sorting. Thanks to @phillipadsmith for reporting this. Fixed runtime API dependency removal so removing the last dependency from a task also clears the mapped blockedBy property from the note."},{"route":"/obsidian/releases/4.11.1/","title":"TaskNotes 4.11.1","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.11.1.md","namespace":"obsidian","relativePath":"releases/4.11.1.md","raw":"# TaskNotes 4.11.1\n\n## Added\n\n- (#2024) Added materialized occurrence notes to the Relationships widget, so recurring parent task notes can show their occurrence notes in an **Occurrences** tab. See [Relationships Widget](https://tasknotes.dev/features/inline-tasks/#relationships-widget). Thanks to @3zra47 for requesting this.\n- (#2022) Added a **Skip instance** / **Unskip instance** action to the recurring task edit modal's completion calendar, so skipped dates can be adjusted from the same date menu as completions. See [Recurring Tasks](https://tasknotes.dev/features/recurring-tasks/#completion-tracking). Thanks to @AmonAmarthFTW for requesting this.\n- (#2048) Added current due and scheduled dates to the edit modal's task information. Thanks to @1activegeek for requesting this.\n- (#2058, #2059) Added natural-language parsing and the full date picker to date-type custom fields. Thanks to @chmac for requesting this.\n- (#2060) Added date-type custom fields to the task right-click menu under **Custom dates**. Thanks to @chmac for requesting this.\n- (#2067) Added an **Edit task** action to the task card context menu, including inline task cards. Thanks to @DarkCellar for requesting this.\n- (#2068) Added `reminders` input support to the MCP `tasknotes_create_task` and `tasknotes_update_task` tools. Thanks to @Spirit597 for requesting this.\n- (#2069) Added an **Add project** action to the Quick Actions palette. Thanks to @chmac for requesting this.\n\n## Fixed\n\n- (#2007) Fixed a remaining task creation autocomplete case where a status value containing another status label could leave status fragments in the task title. Thanks to @prepare4robots for the follow-up report.\n- (#2031) Fixed quick task creation failing when natural language input created a recurring task with a scheduled time. Thanks to @rdefaccio for reporting this.\n- (#2034) Fixed Advanced Calendar timed events switching to a high-contrast mobile fill when Obsidian is narrowed or split on desktop. Thanks to @RumiaKitinari for reporting this.\n- (#2039) Fixed broken images on the Workflows and Calendar Setup documentation pages. Thanks to @chmac for reporting this.\n- (#2045) Fixed custom modal fields assigned to Basic Information not appearing in task creation or edit modals. Thanks to @chmac for reporting this.\n- (#2063) Fixed project autocomplete storing ambiguous project links without the selected note's folder path. Thanks to @chmac for reporting this.\n- (#2072) Fixed inline task links to headings so they show both the task title and heading instead of only the heading. Thanks to @spasche for reporting this.\n- (#2075) Fixed multiday Calendar events being clipped to one day when a Base is embedded in Reading view. Thanks to @ddevaal for reporting this.\n- (#2079) Fixed the reminder modal's **Absolute** tab so it switches from relative fields to absolute date and time fields. Thanks to @JunwonYoon for reporting this and identifying the CSS specificity issue.\n\n## Changed\n\n- Improved local review checks so unsafe direct `Object.prototype` method access is caught before submission.\n","aliases":["/releases/4.11.1/","/releases/4.11.1/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"changed","text":"Changed"}],"html":"

Added#

\n
    \n
  • (#2024) Added materialized occurrence notes to the Relationships widget, so recurring parent task notes can show their occurrence notes in an Occurrences tab. See Relationships Widget. Thanks to @3zra47 for requesting this.
  • \n
  • (#2022) Added a Skip instance / Unskip instance action to the recurring task edit modal's completion calendar, so skipped dates can be adjusted from the same date menu as completions. See Recurring Tasks. Thanks to @AmonAmarthFTW for requesting this.
  • \n
  • (#2048) Added current due and scheduled dates to the edit modal's task information. Thanks to @1activegeek for requesting this.
  • \n
  • (#2058, #2059) Added natural-language parsing and the full date picker to date-type custom fields. Thanks to @chmac for requesting this.
  • \n
  • (#2060) Added date-type custom fields to the task right-click menu under Custom dates. Thanks to @chmac for requesting this.
  • \n
  • (#2067) Added an Edit task action to the task card context menu, including inline task cards. Thanks to @DarkCellar for requesting this.
  • \n
  • (#2068) Added reminders input support to the MCP tasknotes_create_task and tasknotes_update_task tools. Thanks to @Spirit597 for requesting this.
  • \n
  • (#2069) Added an Add project action to the Quick Actions palette. Thanks to @chmac for requesting this.
  • \n
\n

Fixed#

\n
    \n
  • (#2007) Fixed a remaining task creation autocomplete case where a status value containing another status label could leave status fragments in the task title. Thanks to @prepare4robots for the follow-up report.
  • \n
  • (#2031) Fixed quick task creation failing when natural language input created a recurring task with a scheduled time. Thanks to @rdefaccio for reporting this.
  • \n
  • (#2034) Fixed Advanced Calendar timed events switching to a high-contrast mobile fill when Obsidian is narrowed or split on desktop. Thanks to @RumiaKitinari for reporting this.
  • \n
  • (#2039) Fixed broken images on the Workflows and Calendar Setup documentation pages. Thanks to @chmac for reporting this.
  • \n
  • (#2045) Fixed custom modal fields assigned to Basic Information not appearing in task creation or edit modals. Thanks to @chmac for reporting this.
  • \n
  • (#2063) Fixed project autocomplete storing ambiguous project links without the selected note's folder path. Thanks to @chmac for reporting this.
  • \n
  • (#2072) Fixed inline task links to headings so they show both the task title and heading instead of only the heading. Thanks to @spasche for reporting this.
  • \n
  • (#2075) Fixed multiday Calendar events being clipped to one day when a Base is embedded in Reading view. Thanks to @ddevaal for reporting this.
  • \n
  • (#2079) Fixed the reminder modal's Absolute tab so it switches from relative fields to absolute date and time fields. Thanks to @JunwonYoon for reporting this and identifying the CSS specificity issue.
  • \n
\n

Changed#

\n
    \n
  • Improved local review checks so unsafe direct Object.prototype method access is caught before submission.
  • \n
\n","text":"Added# (#2024) Added materialized occurrence notes to the Relationships widget, so recurring parent task notes can show their occurrence notes in an Occurrences tab. See Relationships Widget. Thanks to @3zra47 for requesting this. (#2022) Added a Skip instance / Unskip instance action to the recurring task edit modal's completion calendar, so skipped dates can be adjusted from the same date menu as completions. See Recurring Tasks. Thanks to @AmonAmarthFTW for requesting this. (#2048) Added current due and scheduled dates to the edit modal's task information. Thanks to @1activegeek for requesting this. (#2058, #2059) Added natural-language parsing and the full date picker to date-type custom fields. Thanks to @chmac for requesting this. (#2060) Added date-type custom fields to the task right-click menu under Custom dates. Thanks to @chmac for requesting this. (#2067) Added an Edit task action to the task card context menu, including inline task cards. Thanks to @DarkCellar for requesting this. (#2068) Added reminders input support to the MCP tasknotes_create_task and tasknotes_update_task tools. Thanks to @Spirit597 for requesting this. (#2069) Added an Add project action to the Quick Actions palette. Thanks to @chmac for requesting this. Fixed# (#2007) Fixed a remaining task creation autocomplete case where a status value containing another status label could leave status fragments in the task title. Thanks to @prepare4robots for the follow-up report. (#2031) Fixed quick task creation failing when natural language input created a recurring task with a scheduled time. Thanks to @rdefaccio for reporting this. (#2034) Fixed Advanced Calendar timed events switching to a high-contrast mobile fill when Obsidian is narrowed or split on desktop. Thanks to @RumiaKitinari for reporting this. (#2039) Fixed broken images on the Workflows and Calendar Setup documentation pages. Thanks to @chmac for reporting this. (#2045) Fixed custom modal fields assigned to Basic Information not appearing in task creation or edit modals. Thanks to @chmac for reporting this. (#2063) Fixed project autocomplete storing ambiguous project links without the selected note's folder path. Thanks to @chmac for reporting this. (#2072) Fixed inline task links to headings so they show both the task title and heading instead of only the heading. Thanks to @spasche for reporting this. (#2075) Fixed multiday Calendar events being clipped to one day when a Base is embedded in Reading view. Thanks to @ddevaal for reporting this. (#2079) Fixed the reminder modal's Absolute tab so it switches from relative fields to absolute date and time fields. Thanks to @JunwonYoon for reporting this and identifying the CSS specificity issue. Changed# Improved local review checks so unsafe direct Object.prototype method access is caught before submission."},{"route":"/obsidian/releases/4.12.0/","title":"TaskNotes 4.12.0","description":"[!info] TaskNotes v5 beta","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.12.0.md","namespace":"obsidian","relativePath":"releases/4.12.0.md","raw":"# TaskNotes 4.12.0\n\n> [!info] TaskNotes v5 beta\n>\n> [TaskNotes v5](https://github.com/callumalpass/tasknotes/releases/tag/5.0.0-beta.0) is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release.\n>\n> The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the [TaskNotes app](https://app.tasknotes.dev/), which is also available in beta, so the same tasks can be managed through either interface.\n>\n> TaskNotes collections are built on [mdbase](https://mdbase.dev/), a Markdown-native collection format. [mdbase Connect](https://mdbase.dev/connect/) provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand.\n>\n> TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and [report any problems you encounter](https://github.com/callumalpass/tasknotes/issues).\n\n## Security\n\n- Calendar OAuth credentials and account tokens are now stored in Obsidian Secret Storage instead of TaskNotes' `data.json`, with automatic migration for existing connections. See [Calendar Integration](https://tasknotes.dev/features/calendar-integration/).\n - Thanks to @mcuste for the contribution\n- Updated bundled HTTP, address parsing, and schema validation dependencies to\n versions containing their current security fixes.\n\n## Added\n\n- Added portable task attachment references. Attachments now round-trip as an\n ordered `attachments` link list in task frontmatter and are exposed through\n the TaskNotes model and runtime API. These are collection-file references\n only; attachment bytes and binary metadata remain owned by the host.\n- (#2142) MCP `tasknotes_create_task` and `tasknotes_update_task` now accept\n `customProperties` for configured TaskNotes user fields. Thanks to\n @phillipadsmith for suggesting this.\n- (#2126, #2134) Added optional filename templates for materialized recurring\n occurrence notes, with explicit date, ISO week, month, year, and month-name\n variables plus per-parent overrides. Existing naming remains unchanged until a\n template is configured. See [Recurring Tasks](https://tasknotes.dev/features/recurring-tasks/#occurrence-filenames).\n Thanks to @raphaelfaouakhiri for reporting and implementing this.\n- (#2105) Added `{{projectFolder}}` and `{{projectFolders}}` folder template\n variables for storing tasks alongside linked project notes. See\n [Template Variables](https://tasknotes.dev/features/template-variables/).\n Thanks to @carypruitt for this contribution.\n\n## Changed\n\n- Generated TaskNotes type contracts now include configured natural-language\n capture triggers, allowing compatible clients to offer the same field\n suggestions.\n- Rebuilt the TaskNotes documentation with\n reorganized navigation, full-text search, mobile and accessibility\n improvements, and references generated from the current commands, settings,\n compatibility metadata, HTTP routes, and default Bases. Added practical\n guides for adopting TaskNotes in an existing vault, mobile use, custom Bases,\n and backup and recovery. See the\n [TaskNotes documentation](https://tasknotes.dev/).\n- (#2088) Convert current note to task now uses your default scheduled date when\n the note does not already have `scheduled` frontmatter, while the **None**\n default still leaves converted notes unscheduled. See\n [Task Properties](https://tasknotes.dev/settings/task-properties/#scheduled-date).\n Thanks to @e-zz for suggesting this.\n\n## Fixed\n\n- Plugin settings now recover when Obsidian briefly returns no data while\n reloading an externally changed settings file, preventing a post-reload error\n without overwriting the existing settings.\n- (#2194) Pomodoro task selection suggestions now keep rich task cards at the\n menu width, preventing task titles from wrapping one letter per line. Thanks\n to @Evilgenee for reporting this.\n- (#2196) Drag-to-reorder now works for Task List Bases embedded in Live Preview\n notes, matching the behavior of directly opened Bases and Reading mode embeds.\n Thanks to @jimbo108108 for reporting this.\n- (#2198) Agenda Bases can now show overdue scheduled or due tasks on today's\n row with `showOverdueOnToday`, and regenerated default Agenda files enable\n that behavior by default. Thanks to @vicrdguez for reporting this.\n- (#2182) Checklist progress on task cards now excludes cancelled markdown\n checklist items such as `[-]` from the completed/total count. Thanks to\n @ctrl-q for reporting this.\n- (#2180) Inline task cards in Live Preview now keep their click and context menu\n handlers active on Obsidian 1.13, so clicking a rendered task link opens the\n edit modal instead of revealing the raw wikilink. Thanks to @npondel for the\n detailed diagnosis and @minchinweb for confirming the issue.\n- (#2171) Stopped recurring\n notification and status-bar scans from reading unindexed notes directly from\n disk while preserving the fallback for direct task lookups. Thanks to\n @tgrosinger for identifying and diagnosing the excessive vault reads.\n- (#2174) **Open or create occurrence note** from Quick Actions now uses the\n recurring task's scheduled occurrence date, preventing duplicate occurrence\n notes keyed to the day the action was run. Thanks to @chmac for reporting\n this.\n- (#2169) Regenerated default Base views now include tasks whose identifying\n property is stored as a list containing the configured task value. Thanks to\n @GlebYavorski for reporting this.\n- (#2166) Fixed Task List views configured to start collapsed so the first\n chevron click expands only the selected group instead of expanding every\n other group. Thanks to @renatomen for reporting and fixing this.\n- (#2165) **Convert current note to task** now reads configured field mappings,\n including list-valued title fields such as `aliases`, and preserves an\n existing aliases list when the title is unchanged. Thanks to @jkuball for\n reporting this.\n- (#2164) Flat Kanban boards now clear stale swimlane layout state when they\n rerender, preventing columns from occasionally stacking into one vertical\n strip after switching tabs. Thanks to @brienna for reporting this.\n- (#2160, #2161) Generated Kanban Bases now use the correct TaskNotes status\n property and configuration block. Rich Bases status values render as their\n configured labels, while pinned columns and saved column order are honored.\n Thanks to @kevin-4c for the detailed reports and diagnosis.\n- (#2111, #2159) Recurring task instances now remain visible through the final\n day of Calendar and Agenda ranges in positive-offset time zones, regardless\n of the configured first day of the week. Thanks to @Arachnidai and @odxn0803\n for reporting this.\n- (#2155) Regenerated default Calendar Bases now inherit the app-level time slot\n duration instead of hardcoding 30 minutes. Existing per-Base time settings\n remain intentional overrides. Thanks to @SZZ504232 for reporting this.\n- (#2154) Timed ICS events without a `TZID` now preserve their floating wall\n time in the user's local timezone instead of being interpreted as UTC. Thanks\n to @cloesophia for the reproducible calendar sample.\n- (#2152) Fixed paginated Google Calendar refreshes for calendars with many\n events so secondary calendars do not disappear after Google returns a second\n page. Thanks to @wobafett for reporting and diagnosing this.\n- (#2141) Fixed Task List groups for tasks without scheduled or due dates showing\n a raw Bases icon object instead of **None**. Thanks to @ks-studio-net for\n reporting this.\n- (#2140) The edit task modal now shows saved task-identification tags when\n hiding identification tags is disabled. Thanks to @3zra47 for reporting this.\n- (#2148) Empty list-like frontmatter values no longer become literal `\"null\"`\n entries when tasks are edited. Thanks to @minchinweb for reporting this.\n- (#2120, #2135) Long all-day event titles in Calendar week and day views now\n truncate instead of stretching the all-day row. Thanks to @same774 and\n @ks-studio-net for reporting this.\n- (#2124) Fixed a Kanban crash when opening or closing the edit modal immediately\n after moving a task between list-valued swimlanes such as contexts. Thanks to\n @Decia-C for reporting this.\n- (#2114) Completing a rescheduled occurrence for a scheduled-anchored recurring\n task now advances the parent from the moved occurrence date instead of an\n earlier original occurrence date. Thanks to @chrabia for reporting this.\n- (#2113) Failed Google Calendar manual refreshes no longer make the next\n immediate refresh show a misleading success notice. Thanks to @JohWQ for\n reporting this.\n- (#2109) TaskNotes no longer injects instant-conversion controls into embedded\n or detached Markdown editors, preventing checkbox notes opened from unrelated\n Bases from freezing Obsidian on mobile. Thanks to @jmartinmcfly for the clear\n reproduction and recording.\n- (#2107, #2108) Creating tasks with **Store title in filename** enabled now\n handles duplicate or case-variant titles without failing or replacing the task\n title with a suffixed filename. Thanks to @AdmiralClackington for reporting and\n diagnosing this.\n- (#2106) Regenerated default Calendar Base files now use your configured first\n day of the week instead of forcing Sunday. Thanks to @atos2212-blip, @cweekly,\n @idontcode34, and @hikatamika for reporting this.\n- (#2100) Tags added while creating a task now keep the same frontmatter order as\n tags added later from the task context menu. Thanks to @mgrecar for reporting\n this.\n- (#2092) New non-recurring tasks created directly in a completed status now get\n a completed date, so completed-date views can find them immediately. Thanks\n to @Crell for reporting this.\n- (#2096) Fixed TaskNotes Kanban swimlanes falling back to **None** when the\n swimlane used a Bases formula that was not already cached by Bases. Thanks to\n @ddevaal for reporting this.\n- (#2093) TaskNotes now retries custom Bases view registration when the Bases\n core plugin is enabled after TaskNotes, preventing default views from showing\n **Unknown view type** until TaskNotes is reloaded. Thanks to @yaye-work for\n reporting this.\n- (#2084) The Relationships widget no longer prevents editor text selection from\n autoscrolling when dragging below the bottom edge of a task note. Thanks to\n @lostwildland for reporting this.\n- (#2081, #2103) Kept task card and relationships widgets visible in reading mode\n when Obsidian scroll or preview updates remove their DOM, and refreshed visible\n widgets promptly after metadata changes. Thanks to @mukhozhuk for reporting and\n debugging this and @martin-forge for fixing it.\n- (#2064, #2066) Recurring tasks now advance correctly after their next\n scheduled date is manually adjusted, preserving due-date offsets and times\n without jumping back to an earlier occurrence. Thanks to @chmac for reporting\n and fixing this.\n- (#2018) Fixed **Hide empty columns** in Kanban views with swimlanes so columns\n with no visible tasks are hidden while pinned columns remain. Thanks to\n @scottTomaszewski for reporting and fixing this.\n- Fixed recurring all-day ICS subscription events keeping the original end date\n on later instances, which could cause calendar list views to show events under\n the wrong day. Thanks to @abbiefalls90.\n- (#2033) Fixed the project folder badge on task cards so, when expandable\n subtasks are enabled, it expands or collapses inline subtasks instead of\n showing an unavailable-action notice. Thanks to @abbiefalls90 for the fix and\n @scottkodai for the follow-up feedback.\n- (#2040, #2041) Stopped newly created tasks from filling the Google Calendar\n retry queue when calendar export is disabled. Thanks to @chmac for reporting\n and fixing this.\n- (#2046, #2051) The date and time picker now focuses the natural-language input\n when it is enabled, making keyboard-driven quick actions ready for immediate\n typing. Thanks to @DevOps-Toast for reporting this and @ther12k for fixing it.\n- (#2125, #2129) Materialized recurring occurrence notes now record the date\n they were actually completed, while the parent recurring task continues to\n track the occurrence date. Thanks to @raphaelfaouakhiri for reporting and\n fixing this.\n- (#2173, #2175) Completion-anchored recurring tasks with materialized\n occurrence notes now schedule the next occurrence from the day the occurrence\n was actually completed. Thanks to @chmac for reporting and fixing this.\n- (#1982) Preserved the Task List's own scroll position during Bases refreshes so\n long mobile lists do not jump back to the top after task updates. Thanks to\n @3zra47 for the follow-up report.\n- (#1863) Microsoft Calendar event updates now accept opaque Exchange calendar\n IDs instead of failing local validation before contacting Microsoft Graph.\n Thanks to @fmacondray for reporting this and providing the follow-up stack\n trace.\n","aliases":["/releases/4.12.0/","/releases/4.12.0/"],"toc":[{"level":2,"id":"security","text":"Security"},{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"
\n

[!info] TaskNotes v5 beta

\n

TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release.

\n

The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface.

\n

TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand.

\n

TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter.

\n
\n

Security#

\n
    \n
  • Calendar OAuth credentials and account tokens are now stored in Obsidian Secret Storage instead of TaskNotes' data.json, with automatic migration for existing connections. See Calendar Integration.
      \n
    • Thanks to @mcuste for the contribution
    • \n
    \n
  • \n
  • Updated bundled HTTP, address parsing, and schema validation dependencies to\nversions containing their current security fixes.
  • \n
\n

Added#

\n
    \n
  • Added portable task attachment references. Attachments now round-trip as an\nordered attachments link list in task frontmatter and are exposed through\nthe TaskNotes model and runtime API. These are collection-file references\nonly; attachment bytes and binary metadata remain owned by the host.
  • \n
  • (#2142) MCP tasknotes_create_task and tasknotes_update_task now accept\ncustomProperties for configured TaskNotes user fields. Thanks to\n@phillipadsmith for suggesting this.
  • \n
  • (#2126, #2134) Added optional filename templates for materialized recurring\noccurrence notes, with explicit date, ISO week, month, year, and month-name\nvariables plus per-parent overrides. Existing naming remains unchanged until a\ntemplate is configured. See Recurring Tasks.\nThanks to @raphaelfaouakhiri for reporting and implementing this.
  • \n
  • (#2105) Added {{projectFolder}} and {{projectFolders}} folder template\nvariables for storing tasks alongside linked project notes. See\nTemplate Variables.\nThanks to @carypruitt for this contribution.
  • \n
\n

Changed#

\n
    \n
  • Generated TaskNotes type contracts now include configured natural-language\ncapture triggers, allowing compatible clients to offer the same field\nsuggestions.
  • \n
  • Rebuilt the TaskNotes documentation with\nreorganized navigation, full-text search, mobile and accessibility\nimprovements, and references generated from the current commands, settings,\ncompatibility metadata, HTTP routes, and default Bases. Added practical\nguides for adopting TaskNotes in an existing vault, mobile use, custom Bases,\nand backup and recovery. See the\nTaskNotes documentation.
  • \n
  • (#2088) Convert current note to task now uses your default scheduled date when\nthe note does not already have scheduled frontmatter, while the None\ndefault still leaves converted notes unscheduled. See\nTask Properties.\nThanks to @e-zz for suggesting this.
  • \n
\n

Fixed#

\n
    \n
  • Plugin settings now recover when Obsidian briefly returns no data while\nreloading an externally changed settings file, preventing a post-reload error\nwithout overwriting the existing settings.
  • \n
  • (#2194) Pomodoro task selection suggestions now keep rich task cards at the\nmenu width, preventing task titles from wrapping one letter per line. Thanks\nto @Evilgenee for reporting this.
  • \n
  • (#2196) Drag-to-reorder now works for Task List Bases embedded in Live Preview\nnotes, matching the behavior of directly opened Bases and Reading mode embeds.\nThanks to @jimbo108108 for reporting this.
  • \n
  • (#2198) Agenda Bases can now show overdue scheduled or due tasks on today's\nrow with showOverdueOnToday, and regenerated default Agenda files enable\nthat behavior by default. Thanks to @vicrdguez for reporting this.
  • \n
  • (#2182) Checklist progress on task cards now excludes cancelled markdown\nchecklist items such as [-] from the completed/total count. Thanks to\n@ctrl-q for reporting this.
  • \n
  • (#2180) Inline task cards in Live Preview now keep their click and context menu\nhandlers active on Obsidian 1.13, so clicking a rendered task link opens the\nedit modal instead of revealing the raw wikilink. Thanks to @npondel for the\ndetailed diagnosis and @minchinweb for confirming the issue.
  • \n
  • (#2171) Stopped recurring\nnotification and status-bar scans from reading unindexed notes directly from\ndisk while preserving the fallback for direct task lookups. Thanks to\n@tgrosinger for identifying and diagnosing the excessive vault reads.
  • \n
  • (#2174) Open or create occurrence note from Quick Actions now uses the\nrecurring task's scheduled occurrence date, preventing duplicate occurrence\nnotes keyed to the day the action was run. Thanks to @chmac for reporting\nthis.
  • \n
  • (#2169) Regenerated default Base views now include tasks whose identifying\nproperty is stored as a list containing the configured task value. Thanks to\n@GlebYavorski for reporting this.
  • \n
  • (#2166) Fixed Task List views configured to start collapsed so the first\nchevron click expands only the selected group instead of expanding every\nother group. Thanks to @renatomen for reporting and fixing this.
  • \n
  • (#2165) Convert current note to task now reads configured field mappings,\nincluding list-valued title fields such as aliases, and preserves an\nexisting aliases list when the title is unchanged. Thanks to @jkuball for\nreporting this.
  • \n
  • (#2164) Flat Kanban boards now clear stale swimlane layout state when they\nrerender, preventing columns from occasionally stacking into one vertical\nstrip after switching tabs. Thanks to @brienna for reporting this.
  • \n
  • (#2160, #2161) Generated Kanban Bases now use the correct TaskNotes status\nproperty and configuration block. Rich Bases status values render as their\nconfigured labels, while pinned columns and saved column order are honored.\nThanks to @kevin-4c for the detailed reports and diagnosis.
  • \n
  • (#2111, #2159) Recurring task instances now remain visible through the final\nday of Calendar and Agenda ranges in positive-offset time zones, regardless\nof the configured first day of the week. Thanks to @Arachnidai and @odxn0803\nfor reporting this.
  • \n
  • (#2155) Regenerated default Calendar Bases now inherit the app-level time slot\nduration instead of hardcoding 30 minutes. Existing per-Base time settings\nremain intentional overrides. Thanks to @SZZ504232 for reporting this.
  • \n
  • (#2154) Timed ICS events without a TZID now preserve their floating wall\ntime in the user's local timezone instead of being interpreted as UTC. Thanks\nto @cloesophia for the reproducible calendar sample.
  • \n
  • (#2152) Fixed paginated Google Calendar refreshes for calendars with many\nevents so secondary calendars do not disappear after Google returns a second\npage. Thanks to @wobafett for reporting and diagnosing this.
  • \n
  • (#2141) Fixed Task List groups for tasks without scheduled or due dates showing\na raw Bases icon object instead of None. Thanks to @ks-studio-net for\nreporting this.
  • \n
  • (#2140) The edit task modal now shows saved task-identification tags when\nhiding identification tags is disabled. Thanks to @3zra47 for reporting this.
  • \n
  • (#2148) Empty list-like frontmatter values no longer become literal "null"\nentries when tasks are edited. Thanks to @minchinweb for reporting this.
  • \n
  • (#2120, #2135) Long all-day event titles in Calendar week and day views now\ntruncate instead of stretching the all-day row. Thanks to @same774 and\n@ks-studio-net for reporting this.
  • \n
  • (#2124) Fixed a Kanban crash when opening or closing the edit modal immediately\nafter moving a task between list-valued swimlanes such as contexts. Thanks to\n@Decia-C for reporting this.
  • \n
  • (#2114) Completing a rescheduled occurrence for a scheduled-anchored recurring\ntask now advances the parent from the moved occurrence date instead of an\nearlier original occurrence date. Thanks to @chrabia for reporting this.
  • \n
  • (#2113) Failed Google Calendar manual refreshes no longer make the next\nimmediate refresh show a misleading success notice. Thanks to @JohWQ for\nreporting this.
  • \n
  • (#2109) TaskNotes no longer injects instant-conversion controls into embedded\nor detached Markdown editors, preventing checkbox notes opened from unrelated\nBases from freezing Obsidian on mobile. Thanks to @jmartinmcfly for the clear\nreproduction and recording.
  • \n
  • (#2107, #2108) Creating tasks with Store title in filename enabled now\nhandles duplicate or case-variant titles without failing or replacing the task\ntitle with a suffixed filename. Thanks to @AdmiralClackington for reporting and\ndiagnosing this.
  • \n
  • (#2106) Regenerated default Calendar Base files now use your configured first\nday of the week instead of forcing Sunday. Thanks to @atos2212-blip, @cweekly,\n@idontcode34, and @hikatamika for reporting this.
  • \n
  • (#2100) Tags added while creating a task now keep the same frontmatter order as\ntags added later from the task context menu. Thanks to @mgrecar for reporting\nthis.
  • \n
  • (#2092) New non-recurring tasks created directly in a completed status now get\na completed date, so completed-date views can find them immediately. Thanks\nto @Crell for reporting this.
  • \n
  • (#2096) Fixed TaskNotes Kanban swimlanes falling back to None when the\nswimlane used a Bases formula that was not already cached by Bases. Thanks to\n@ddevaal for reporting this.
  • \n
  • (#2093) TaskNotes now retries custom Bases view registration when the Bases\ncore plugin is enabled after TaskNotes, preventing default views from showing\nUnknown view type until TaskNotes is reloaded. Thanks to @yaye-work for\nreporting this.
  • \n
  • (#2084) The Relationships widget no longer prevents editor text selection from\nautoscrolling when dragging below the bottom edge of a task note. Thanks to\n@lostwildland for reporting this.
  • \n
  • (#2081, #2103) Kept task card and relationships widgets visible in reading mode\nwhen Obsidian scroll or preview updates remove their DOM, and refreshed visible\nwidgets promptly after metadata changes. Thanks to @mukhozhuk for reporting and\ndebugging this and @martin-forge for fixing it.
  • \n
  • (#2064, #2066) Recurring tasks now advance correctly after their next\nscheduled date is manually adjusted, preserving due-date offsets and times\nwithout jumping back to an earlier occurrence. Thanks to @chmac for reporting\nand fixing this.
  • \n
  • (#2018) Fixed Hide empty columns in Kanban views with swimlanes so columns\nwith no visible tasks are hidden while pinned columns remain. Thanks to\n@scottTomaszewski for reporting and fixing this.
  • \n
  • Fixed recurring all-day ICS subscription events keeping the original end date\non later instances, which could cause calendar list views to show events under\nthe wrong day. Thanks to @abbiefalls90.
  • \n
  • (#2033) Fixed the project folder badge on task cards so, when expandable\nsubtasks are enabled, it expands or collapses inline subtasks instead of\nshowing an unavailable-action notice. Thanks to @abbiefalls90 for the fix and\n@scottkodai for the follow-up feedback.
  • \n
  • (#2040, #2041) Stopped newly created tasks from filling the Google Calendar\nretry queue when calendar export is disabled. Thanks to @chmac for reporting\nand fixing this.
  • \n
  • (#2046, #2051) The date and time picker now focuses the natural-language input\nwhen it is enabled, making keyboard-driven quick actions ready for immediate\ntyping. Thanks to @DevOps-Toast for reporting this and @ther12k for fixing it.
  • \n
  • (#2125, #2129) Materialized recurring occurrence notes now record the date\nthey were actually completed, while the parent recurring task continues to\ntrack the occurrence date. Thanks to @raphaelfaouakhiri for reporting and\nfixing this.
  • \n
  • (#2173, #2175) Completion-anchored recurring tasks with materialized\noccurrence notes now schedule the next occurrence from the day the occurrence\nwas actually completed. Thanks to @chmac for reporting and fixing this.
  • \n
  • (#1982) Preserved the Task List's own scroll position during Bases refreshes so\nlong mobile lists do not jump back to the top after task updates. Thanks to\n@3zra47 for the follow-up report.
  • \n
  • (#1863) Microsoft Calendar event updates now accept opaque Exchange calendar\nIDs instead of failing local validation before contacting Microsoft Graph.\nThanks to @fmacondray for reporting this and providing the follow-up stack\ntrace.
  • \n
\n","text":"[!info] TaskNotes v5 beta TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release. The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface. TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand. TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter. Security# Calendar OAuth credentials and account tokens are now stored in Obsidian Secret Storage instead of TaskNotes' data.json, with automatic migration for existing connections. See Calendar Integration. Thanks to @mcuste for the contribution Updated bundled HTTP, address parsing, and schema validation dependencies to versions containing their current security fixes. Added# Added portable task attachment references. Attachments now round-trip as an ordered attachments link list in task frontmatter and are exposed through the TaskNotes model and runtime API. These are collection-file references only; attachment bytes and binary metadata remain owned by the host. (#2142) MCP tasknotes_create_task and tasknotes_update_task now accept customProperties for configured TaskNotes user fields. Thanks to @phillipadsmith for suggesting this. (#2126, #2134) Added optional filename templates for materialized recurring occurrence notes, with explicit date, ISO week, month, year, and month-name variables plus per-parent overrides. Existing naming remains unchanged until a template is configured. See Recurring Tasks. Thanks to @raphaelfaouakhiri for reporting and implementing this. (#2105) Added {{projectFolder}} and {{projectFolders}} folder template variables for storing tasks alongside linked project notes. See Template Variables. Thanks to @carypruitt for this contribution. Changed# Generated TaskNotes type contracts now include configured natural-language capture triggers, allowing compatible clients to offer the same field suggestions. Rebuilt the TaskNotes documentation with reorganized navigation, full-text search, mobile and accessibility improvements, and references generated from the current commands, settings, compatibility metadata, HTTP routes, and default Bases. Added practical guides for adopting TaskNotes in an existing vault, mobile use, custom Bases, and backup and recovery. See the TaskNotes documentation. (#2088) Convert current note to task now uses your default scheduled date when the note does not already have scheduled frontmatter, while the None default still leaves converted notes unscheduled. See Task Properties. Thanks to @e-zz for suggesting this. Fixed# Plugin settings now recover when Obsidian briefly returns no data while reloading an externally changed settings file, preventing a post-reload error without overwriting the existing settings. (#2194) Pomodoro task selection suggestions now keep rich task cards at the menu width, preventing task titles from wrapping one letter per line. Thanks to @Evilgenee for reporting this. (#2196) Drag-to-reorder now works for Task List Bases embedded in Live Preview notes, matching the behavior of directly opened Bases and Reading mode embeds. Thanks to @jimbo108108 for reporting this. (#2198) Agenda Bases can now show overdue scheduled or due tasks on today's row with showOverdueOnToday, and regenerated default Agenda files enable that behavior by default. Thanks to @vicrdguez for reporting this. (#2182) Checklist progress on task cards now excludes cancelled markdown checklist items such as [-] from the completed/total count. Thanks to @ctrl-q for reporting this. (#2180) Inline task cards in Live Preview now keep their click and context menu handlers active on Obsidian 1.13, so clicking a rendered task link opens the edit modal instead of revealing the raw wikilink. Thanks to @npondel for the detailed diagnosis and @minchinweb for confirming the issue. (#2171) Stopped recurring notification and status-bar scans from reading unindexed notes directly from disk while preserving the fallback for direct task lookups. Thanks to @tgrosinger for identifying and diagnosing the excessive vault reads. (#2174) Open or create occurrence note from Quick Actions now uses the recurring task's scheduled occurrence date, preventing duplicate occurrence notes keyed to the day the action was run. Thanks to @chmac for reporting this. (#2169) Regenerated default Base views now include tasks whose identifying property is stored as a list containing the configured task value. Thanks to @GlebYavorski for reporting this. (#2166) Fixed Task List views configured to start collapsed so the first chevron click expands only the selected group instead of expanding every other group. Thanks to @renatomen for reporting and fixing this. (#2165) Convert current note to task now reads configured field mappings, including list-valued title fields such as aliases, and preserves an existing aliases list when the title is unchanged. Thanks to @jkuball for reporting this. (#2164) Flat Kanban boards now clear stale swimlane layout state when they rerender, preventing columns from occasionally stacking into one vertical strip after switching tabs. Thanks to @brienna for reporting this. (#2160, #2161) Generated Kanban Bases now use the correct TaskNotes status property and configuration block. Rich Bases status values render as their configured labels, while pinned columns and saved column order are honored. Thanks to @kevin-4c for the detailed reports and diagnosis. (#2111, #2159) Recurring task instances now remain visible through the final day of Calendar and Agenda ranges in positive-offset time zones, regardless of the configured first day of the week. Thanks to @Arachnidai and @odxn0803 for reporting this. (#2155) Regenerated default Calendar Bases now inherit the app-level time slot duration instead of hardcoding 30 minutes. Existing per-Base time settings remain intentional overrides. Thanks to @SZZ504232 for reporting this. (#2154) Timed ICS events without a TZID now preserve their floating wall time in the user's local timezone instead of being interpreted as UTC. Thanks to @cloesophia for the reproducible calendar sample. (#2152) Fixed paginated Google Calendar refreshes for calendars with many events so secondary calendars do not disappear after Google returns a second page. Thanks to @wobafett for reporting and diagnosing this. (#2141) Fixed Task List groups for tasks without scheduled or due dates showing a raw Bases icon object instead of None. Thanks to @ks-studio-net for reporting this. (#2140) The edit task modal now shows saved task-identification tags when hiding identification tags is disabled. Thanks to @3zra47 for reporting this. (#2148) Empty list-like frontmatter values no longer become literal \"null\" entries when tasks are edited. Thanks to @minchinweb for reporting this. (#2120, #2135) Long all-day event titles in Calendar week and day views now truncate instead of stretching the all-day row. Thanks to @same774 and @ks-studio-net for reporting this. (#2124) Fixed a Kanban crash when opening or closing the edit modal immediately after moving a task between list-valued swimlanes such as contexts. Thanks to @Decia-C for reporting this. (#2114) Completing a rescheduled occurrence for a scheduled-anchored recurring task now advances the parent from the moved occurrence date instead of an earlier original occurrence date. Thanks to @chrabia for reporting this. (#2113) Failed Google Calendar manual refreshes no longer make the next immediate refresh show a misleading success notice. Thanks to @JohWQ for reporting this. (#2109) TaskNotes no longer injects instant-conversion controls into embedded or detached Markdown editors, preventing checkbox notes opened from unrelated Bases from freezing Obsidian on mobile. Thanks to @jmartinmcfly for the clear reproduction and recording. (#2107, #2108) Creating tasks with Store title in filename enabled now handles duplicate or case-variant titles without failing or replacing the task title with a suffixed filename. Thanks to @AdmiralClackington for reporting and diagnosing this. (#2106) Regenerated default Calendar Base files now use your configured first day of the week instead of forcing Sunday. Thanks to @atos2212-blip, @cweekly, @idontcode34, and @hikatamika for reporting this. (#2100) Tags added while creating a task now keep the same frontmatter order as tags added later from the task context menu. Thanks to @mgrecar for reporting this. (#2092) New non-recurring tasks created directly in a completed status now get a completed date, so completed-date views can find them immediately. Thanks to @Crell for reporting this. (#2096) Fixed TaskNotes Kanban swimlanes falling back to None when the swimlane used a Bases formula that was not already cached by Bases. Thanks to @ddevaal for reporting this. (#2093) TaskNotes now retries custom Bases view registration when the Bases core plugin is enabled after TaskNotes, preventing default views from showing Unknown view type until TaskNotes is reloaded. Thanks to @yaye-work for reporting this. (#2084) The Relationships widget no longer prevents editor text selection from autoscrolling when dragging below the bottom edge of a task note. Thanks to @lostwildland for reporting this. (#2081, #2103) Kept task card and relationships widgets visible in reading mode when Obsidian scroll or preview updates remove their DOM, and refreshed visible widgets promptly after metadata changes. Thanks to @mukhozhuk for reporting and debugging this and @martin-forge for fixing it. (#2064, #2066) Recurring tasks now advance correctly after their next scheduled date is manually adjusted, preserving due-date offsets and times without jumping back to an earlier occurrence. Thanks to @chmac for reporting and fixing this. (#2018) Fixed Hide empty columns in Kanban views with swimlanes so columns with no visible tasks are hidden while pinned columns remain. Thanks to @scottTomaszewski for reporting and fixing this. Fixed recurring all-day ICS subscription events keeping the original end date on later instances, which could cause calendar list views to show events under the wrong day. Thanks to @abbiefalls90. (#2033) Fixed the project folder badge on task cards so, when expandable subtasks are enabled, it expands or collapses inline subtasks instead of showing an unavailable-action notice. Thanks to @abbiefalls90 for the fix and @scottkodai for the follow-up feedback. (#2040, #2041) Stopped newly created tasks from filling the Google Calendar retry queue when calendar export is disabled. Thanks to @chmac for reporting and fixing this. (#2046, #2051) The date and time picker now focuses the natural-language input when it is enabled, making keyboard-driven quick actions ready for immediate typing. Thanks to @DevOps-Toast for reporting this and @ther12k for fixing it. (#2125, #2129) Materialized recurring occurrence notes now record the date they were actually completed, while the parent recurring task continues to track the occurrence date. Thanks to @raphaelfaouakhiri for reporting and fixing this. (#2173, #2175) Completion-anchored recurring tasks with materialized occurrence notes now schedule the next occurrence from the day the occurrence was actually completed. Thanks to @chmac for reporting and fixing this. (#1982) Preserved the Task List's own scroll position during Bases refreshes so long mobile lists do not jump back to the top after task updates. Thanks to @3zra47 for the follow-up report. (#1863) Microsoft Calendar event updates now accept opaque Exchange calendar IDs instead of failing local validation before contacting Microsoft Graph. Thanks to @fmacondray for reporting this and providing the follow-up stack trace."},{"route":"/obsidian/releases/4.12.1/","title":"TaskNotes 4.12.1","description":"[!info] TaskNotes v5 beta","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.12.1.md","namespace":"obsidian","relativePath":"releases/4.12.1.md","raw":"# TaskNotes 4.12.1\n\n> [!info] TaskNotes v5 beta\n>\n> [TaskNotes v5](https://github.com/callumalpass/tasknotes/releases/tag/5.0.0-beta.0) is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release.\n>\n> The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the [TaskNotes app](https://app.tasknotes.dev/), which is also available in beta, so the same tasks can be managed through either interface.\n>\n> TaskNotes collections are built on [mdbase](https://mdbase.dev/), a Markdown-native collection format. [mdbase Connect](https://mdbase.dev/connect/) provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand.\n>\n> TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and [report any problems you encounter](https://github.com/callumalpass/tasknotes/issues).\n\n## Changed\n\n- (#2204) Public documentation is now published from the dedicated `tasknotes.dev` repository. Plugin release notes and internal documentation remain in this repository.\n- Updated compatibility with Obsidian's current plugin review and settings search.\n\n## Fixed\n\n- Fixed TaskNotes interface elements sometimes appearing in the wrong window when using Obsidian pop-out windows.\n- Improved confirmation dialogs, icons, and modal styling to use Obsidian's current interface APIs.\n","aliases":["/releases/4.12.1/","/releases/4.12.1/"],"toc":[{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"
\n

[!info] TaskNotes v5 beta

\n

TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release.

\n

The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface.

\n

TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand.

\n

TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter.

\n
\n

Changed#

\n
    \n
  • (#2204) Public documentation is now published from the dedicated tasknotes.dev repository. Plugin release notes and internal documentation remain in this repository.
  • \n
  • Updated compatibility with Obsidian's current plugin review and settings search.
  • \n
\n

Fixed#

\n
    \n
  • Fixed TaskNotes interface elements sometimes appearing in the wrong window when using Obsidian pop-out windows.
  • \n
  • Improved confirmation dialogs, icons, and modal styling to use Obsidian's current interface APIs.
  • \n
\n","text":"[!info] TaskNotes v5 beta TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release. The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface. TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand. TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter. Changed# (#2204) Public documentation is now published from the dedicated tasknotes.dev repository. Plugin release notes and internal documentation remain in this repository. Updated compatibility with Obsidian's current plugin review and settings search. Fixed# Fixed TaskNotes interface elements sometimes appearing in the wrong window when using Obsidian pop-out windows. Improved confirmation dialogs, icons, and modal styling to use Obsidian's current interface APIs."},{"route":"/obsidian/releases/4.12.2/","title":"TaskNotes 4.12.2","description":"[!info] TaskNotes v5 beta","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.12.2.md","namespace":"obsidian","relativePath":"releases/4.12.2.md","raw":"# TaskNotes 4.12.2\n\n> [!info] TaskNotes v5 beta\n>\n> [TaskNotes v5](https://github.com/callumalpass/tasknotes/releases/tag/5.0.0-beta.0) is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release.\n>\n> The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the [TaskNotes app](https://app.tasknotes.dev/), which is also available in beta, so the same tasks can be managed through either interface.\n>\n> TaskNotes collections are built on [mdbase](https://mdbase.dev/), a Markdown-native collection format. [mdbase Connect](https://mdbase.dev/connect/) provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand.\n>\n> TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and [report any problems you encounter](https://github.com/callumalpass/tasknotes/issues).\n\n## Fixed\n\n- (#2212) Fixed TaskNotes settings sections appearing pushed across the Obsidian settings pane on desktop. Thanks to @RafaQNunes for reporting this.\n","aliases":["/releases/4.12.2/","/releases/4.12.2/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"}],"html":"
\n

[!info] TaskNotes v5 beta

\n

TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release.

\n

The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface.

\n

TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand.

\n

TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter.

\n
\n

Fixed#

\n
    \n
  • (#2212) Fixed TaskNotes settings sections appearing pushed across the Obsidian settings pane on desktop. Thanks to @RafaQNunes for reporting this.
  • \n
\n","text":"[!info] TaskNotes v5 beta TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release. The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface. TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand. TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter. Fixed# (#2212) Fixed TaskNotes settings sections appearing pushed across the Obsidian settings pane on desktop. Thanks to @RafaQNunes for reporting this."},{"route":"/obsidian/releases/4.12.3/","title":"TaskNotes 4.12.3","description":"[!info] TaskNotes v5 beta","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.12.3.md","namespace":"obsidian","relativePath":"releases/4.12.3.md","raw":"# TaskNotes 4.12.3\n\n> [!info] TaskNotes v5 beta\n>\n> [TaskNotes v5](https://github.com/callumalpass/tasknotes/releases/tag/5.0.0-beta.0) is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release.\n>\n> The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the [TaskNotes app](https://app.tasknotes.dev/), which is also available in beta, so the same tasks can be managed through either interface.\n>\n> TaskNotes collections are built on [mdbase](https://mdbase.dev/), a Markdown-native collection format. [mdbase Connect](https://mdbase.dev/connect/) provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand.\n>\n> TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and [report any problems you encounter](https://github.com/callumalpass/tasknotes/issues).\n\n## Fixed\n\n- (#2212) Fixed TaskNotes settings sections appearing offscreen or blank on\n Obsidian 1.13 desktop. Thanks to @RafaQNunes for reporting this, and to\n @m4to-3pe and @matthewrishii for confirming it remained in 4.12.2.\n- (#2213) Runtime plugin-data updates now avoid writing when Obsidian cannot\n safely read an existing TaskNotes `data.json`, preventing calendar sync,\n Pomodoro, ICS, or auto-archive state writes from replacing saved settings.\n Thanks to @3zra47 for the follow-up details and file-history evidence.\n- (#2216) Fixed updated default Kanban Bases grouping every task into the\n `None` column when grouping by status. The generated Kanban templates now use\n the real status property, and existing Kanban files using `task.status` keep\n grouping from TaskNotes task data. Thanks to @Esvorst for reporting this.\n- (#2120, #2135) Long all-day event titles in Calendar week and day views now\n truncate in the all-day row instead of stretching it vertically. Thanks to\n @same774 and @ks-studio-net for reporting this, and to @Admorei for confirming\n it remained in 4.12.2.\n","aliases":["/releases/4.12.3/","/releases/4.12.3/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"}],"html":"
\n

[!info] TaskNotes v5 beta

\n

TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release.

\n

The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface.

\n

TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand.

\n

TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter.

\n
\n

Fixed#

\n
    \n
  • (#2212) Fixed TaskNotes settings sections appearing offscreen or blank on\nObsidian 1.13 desktop. Thanks to @RafaQNunes for reporting this, and to\n@m4to-3pe and @matthewrishii for confirming it remained in 4.12.2.
  • \n
  • (#2213) Runtime plugin-data updates now avoid writing when Obsidian cannot\nsafely read an existing TaskNotes data.json, preventing calendar sync,\nPomodoro, ICS, or auto-archive state writes from replacing saved settings.\nThanks to @3zra47 for the follow-up details and file-history evidence.
  • \n
  • (#2216) Fixed updated default Kanban Bases grouping every task into the\nNone column when grouping by status. The generated Kanban templates now use\nthe real status property, and existing Kanban files using task.status keep\ngrouping from TaskNotes task data. Thanks to @Esvorst for reporting this.
  • \n
  • (#2120, #2135) Long all-day event titles in Calendar week and day views now\ntruncate in the all-day row instead of stretching it vertically. Thanks to\n@same774 and @ks-studio-net for reporting this, and to @Admorei for confirming\nit remained in 4.12.2.
  • \n
\n","text":"[!info] TaskNotes v5 beta TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release. The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface. TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand. TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter. Fixed# (#2212) Fixed TaskNotes settings sections appearing offscreen or blank on Obsidian 1.13 desktop. Thanks to @RafaQNunes for reporting this, and to @m4to-3pe and @matthewrishii for confirming it remained in 4.12.2. (#2213) Runtime plugin-data updates now avoid writing when Obsidian cannot safely read an existing TaskNotes data.json, preventing calendar sync, Pomodoro, ICS, or auto-archive state writes from replacing saved settings. Thanks to @3zra47 for the follow-up details and file-history evidence. (#2216) Fixed updated default Kanban Bases grouping every task into the None column when grouping by status. The generated Kanban templates now use the real status property, and existing Kanban files using task.status keep grouping from TaskNotes task data. Thanks to @Esvorst for reporting this. (#2120, #2135) Long all-day event titles in Calendar week and day views now truncate in the all-day row instead of stretching it vertically. Thanks to @same774 and @ks-studio-net for reporting this, and to @Admorei for confirming it remained in 4.12.2."},{"route":"/obsidian/releases/4.2.0/","title":"TaskNotes 4.2.0","description":"Added Korean (한국어) language support","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.2.0.md","namespace":"obsidian","relativePath":"releases/4.2.0.md","raw":"# TaskNotes 4.2.0\n\n## Added\n\n- Added Korean (한국어) language support\n - Full translation of all 1911 localization keys\n - Korean language option now available in Settings → General → Language\n\n- Adopted Obsidian 1.11.0 API features with backwards compatibility\n - Settings tab now displays TaskNotes icon in the sidebar (Obsidian 1.11.0+)\n - Settings sections now use native `SettingGroup` for improved visual grouping (Obsidian 1.11.0+)\n - Falls back gracefully to traditional section headers on older Obsidian versions\n\n- (#59) Added `shortYear` template variable for custom filename and folder templates\n - Use `{shortYear}` in filename templates (e.g., \"25\" for 2025)\n - Use `{{shortYear}}` in folder templates\n - Thanks to @Pixeltica for the feature request\n\n- (#1393) Option to prevent auto-creation of default Base view files on startup\n - New \"Auto-create default files\" toggle in Settings → Integrations → Bases Integration\n - When disabled, deleted sample Base files will not be recreated on plugin load\n - The manual \"Create Default Files\" button remains available for on-demand recreation\n - Thanks to @wealthychef1 for the feature request\n\n- (#1408) Shift+click on status icon to cycle backwards through statuses\n - Normal click cycles forward through status order\n - Shift+click cycles in reverse order\n - Thanks to @JerryLu086 for the feature request\n\n- (#1410) Task creation modal now starts in vim insert mode when vim keybindings are enabled\n - Previously required pressing 'i' before typing when Obsidian vim mode was active\n - The modal now automatically enters insert mode on focus, allowing immediate typing\n - Thanks to @Leo310 for the feature request\n\n- Added button tooltips to calendar view toolbar\n - Hovering over navigation and view buttons now shows descriptive hints\n - Buttons include: Today, Previous, Next, Month, Week, Day, Year, List\n\n- Added tooltips to task modal action icons\n - Icon buttons for status, date, project, priority, recurrence, and reminder now show tooltips on hover\n - Improves discoverability for new users\n\n- (#503) Settings now sync automatically across devices via Obsidian Sync\n - Changes to custom statuses, priorities, and other settings apply immediately without restart\n - Thanks to @jhedlund for the feature request and @l-mb for the implementation\n\n- (#1403) Kanban view option to consolidate status icons in column headers\n - New \"Show status icon in column header only\" toggle in Kanban view settings (disabled by default)\n - When enabled and grouped by status, shows the icon in the column header and hides it on cards\n - Reduces visual redundancy when the column already indicates the status\n - Thanks to @l-mb for the feature request and implementation\n\n- (#1401) Calendar view option to span tasks between scheduled and due dates\n - New \"Span tasks between scheduled and due dates\" toggle in Calendar view Layout settings\n - When enabled, tasks with both scheduled and due dates display as multi-day bars\n - Provides Gantt chart-style visualization for project planning\n - Thanks to @0atman for the feature request\n\n- (#1334) `{{currentNotePath}}` now works for \"Create new inline task\" command\n - The inline task folder setting with `{{currentNotePath}}` previously only worked for checkbox conversion\n - Now also applies when using the \"Create new inline task\" command from the command palette\n - Thanks to @kmaustral for the feature request\n\n- (#1264) Option to open Pomodoro timer in mobile sidebar instead of note panel\n - New \"Mobile sidebar\" setting in Settings → Features → Pomodoro Timer\n - Choose between: Note panel (default tab behavior), Left sidebar, or Right sidebar\n - Allows quick swipe access to the timer without switching notes on mobile devices\n - Thanks to @Evthestrike for the feature request\n\n- (#1220) Option to use ICS event end time as task due date\n - New \"Use ICS event end time as task due date\" toggle in Settings → Integrations → Calendar Subscriptions\n - When enabled, tasks created from calendar events will have their due date set to the event's end time\n - For all-day events, uses the event date (not the ICS container end date which is the next day per ICS spec)\n - For timed events, includes the exact end time\n - Defaults to disabled to preserve existing behavior\n - Thanks to @MiserMagus for the feature request\n\n- (#1108) Option to use task duration instead of due date for ICS calendar export\n - New \"Use task duration for event length\" toggle in Settings → Integrations → Automatic ICS Export\n - When enabled, exported calendar events use scheduled date + time estimate as DTSTART/DTEND\n - This aligns with GTD workflows where scheduled + duration represents work planning, while due date represents deadlines\n - When disabled (default), preserves existing behavior using due date as DTEND\n - Thanks to @bepolymathe for the feature request\n\n## Fixed\n\n- (#1421) Fixed natural language parser only capturing one date when both scheduled and due dates are specified\n - Input like \"Task scheduled for tomorrow due next week\" now correctly sets both scheduled and due dates\n - Previously the parser would return early after finding the first date trigger, ignoring any subsequent triggers\n - Thanks to @wealthychef1 for reporting\n\n- (#1384) Fixed title being sanitized even when \"Store Task Title in Filename\" is disabled\n - Characters like `?`, `<`, `>`, `:`, etc. are now preserved in task titles when they won't be used in filenames\n - When `storeTitleInFilename` is false, only minimal sanitization (whitespace normalization, control character removal) is applied\n - Thanks to @allison-casey for reporting\n\n- (#1028), (#1140), (#1152), (#1354), (#1362) Fixed duplicate task entries appearing in Agenda view\n - Tasks were shown twice: once as TaskNotes events and again as property-based events with a file icon\n - Changed default Agenda template to disable property-based events (`showPropertyBasedEvents: false`)\n - Users can re-enable property-based events in view settings if needed for non-task date properties\n - Thanks to @YIRU69, @jhedlund, @dblinnikov, @Snakiest, @WeiYiAcc, @JacksonMcDonaldDev, @jimbo108108, and @krelltunez for reporting\n\n- (#1386) Fixed `timeEstimateCategory` formula showing \"Long (>2h)\" instead of \"No estimate\" for new tasks\n - The condition didn't properly handle null values when `timeEstimate` property is unset\n - Also fixed the same issue in `trackingStatus` formula\n - Thanks to @nicou for reporting and @osxisl for the PR\n\n- (#1397) Fixed Bases views (Kanban, Calendar, Task List) resetting to Calendar view after a few minutes\n - Also fixed CalendarView corrupting other view files when saving state on unload\n - Thanks to @music-soul1-1 for reporting\n\n- (#1398) Fixed overdue strikethrough showing on completed tasks\n - Completed tasks with past due dates no longer display overdue styling \n - Respects the \"Hide completed from overdue\" setting which defaults to true\n\n- (#1363) Fixed calendar view showing nothing when a task has an invalid date format\n - Tasks with malformed dates (e.g., \"262025-12-16\" instead of \"2025-12-16\") no longer crash the entire calendar\n - Invalid tasks are now skipped with a console warning, allowing other events to display normally\n - Thanks to @Erelen for reporting\n\n- Fixed today column in week/day calendar views using FullCalendar's default yellow instead of theme accent\n - Today's column now uses a tint of the theme accent color for consistent styling\n\n- (#1399) Fixed drag-and-drop not working in Kanban view on mobile\n - Cards and columns can now be dragged using long-press gesture on touch devices\n - Includes haptic feedback and auto-scroll when dragging near edges\n - Thanks to @l-mb for reporting and the fix\n\n- (#1381) Fixed Pomodoro \"Change Task\" menu not showing newly created tasks\n - Tasks created while the Pomodoro view was open would not appear in the task selector\n - Improved metadata cache synchronization to properly wait for new files to be indexed\n - Thanks to @Ghosthael for reporting\n\n- (#1344) Fixed \"Unsaved Changes\" popup appearing randomly when closing task edit modal\n - The popup would appear even when no changes were made to the task\n - Caused by inconsistent trailing whitespace normalization when comparing details content\n - Thanks to @hasanyilmaz for reporting\n\n- (#1402) Fixed Kanban swimlane view showing tasks in wrong column when grouped by formula\n - After editing task metadata, cards would jump to \"None\" column until Obsidian reload\n - Column assignment now uses Bases' computed grouping instead of cached formula outputs\n - Thanks to @bailob for the fix\n\n- (#1352) Fixed date context menu not preserving time when using increment options\n - Using +1 day, -1 day, +1 week, or -1 week on a task with a time (e.g., `2025-12-10T16:00`) now preserves the time\n - Previously the time would be stripped, changing `2025-12-10T16:00` to `2025-12-11` instead of `2025-12-11T16:00`\n - Thanks to @cathywu for the feature request\n\n- Fixed v3 saved views exporting incorrectly to Bases format\n - Title filters now correctly use `file.name` instead of `note.title`\n - Archived filters now generate valid boolean expressions instead of malformed comparisons\n - \"Is Blocked\" filters now generate correct expressions with proper operator precedence\n\n- (#1036) Due dates can now be dragged in the calendar view\n - Previously only scheduled dates were draggable; due dates were locked in place\n - Dragging a due event now updates the task's due date property\n - Thanks to @same774 for reporting\n\n- Improved calendar view responsiveness for user interactions\n - Task creation, editing, timeblock changes, and view option toggles now update immediately\n - Previously these actions waited 5 seconds due to the debounce intended for external file changes\n - The 5-second debounce is now bypassed for direct user actions while still preventing flicker during typing\n\n- Improved visual affordance for Pomodoro timer duration adjustment buttons\n - The +/- buttons below the timer now have visible backgrounds and borders\n - Hover states show accent color border for clearer interactivity feedback\n - Previously buttons were nearly invisible with transparent backgrounds\n\n- (#1409), (#1214), (#979) Improved Calendar, Agenda, Kanban, and Stats views in pop-out windows\n - Drag-and-drop in Kanban view now works correctly when the view is in a new window\n - Context menus (status, priority, task) now work correctly in pop-out windows\n - Stats view drill-down modal now appears in the correct window\n - Search boxes, task cards, and grouped task lists render correctly\n - Root cause: Code was using global `document` and standard `instanceof` checks which fail across windows\n - Solution: Use `ownerDocument` for DOM operations and Obsidian's cross-window `instanceOf()` method\n - **Known limitation**: Calendar event dragging does not work in pop-out windows due to FullCalendar library using global `document` for mouse event listeners. Use context menus or edit modals as a workaround.\n - Updated FullCalendar to v6.1.20\n - Thanks to @Snakiest, @same774, and @3zra47 for reporting\n\n- (#1337) Fixed \"Convert current note to task\" hotkey not applying default values from settings\n - When user configured default status/priority as \"None\", the modal would show \"Open\" and \"Normal\" instead\n - Root cause: Task edit modal was refreshing data from file and overwriting user-configured defaults\n - Now preserves constructor-provided task data when converting non-task files\n - Thanks to @guihasparyk for reporting\n\n- (#1304) Fixed \"Cannot find function map on type Link\" error in Blocking view\n - Error occurred when embedding the Relationships base and opening the Blocking view\n - Root cause: When `blockedBy` contained a single dependency, Bases returned it as a Link object without a `.map()` method\n - Fixed by wrapping `blockedBy` with `list()` before calling `.map()`, consistent with the Blocked By view\n - Thanks to @prayidae for reporting\n\n- (#1295) Fixed missing navigation link to Default Base Templates page on tasknotes.dev\n - The page existed but was not accessible from the site navigation\n - Thanks to @Arachnidai for reporting\n\n- (#1223) Fixed \"Go to today's note\" command opening wrong date in positive UTC offset timezones\n - In timezones like Japan (UTC+9), early morning use of this command opened yesterday's note\n - Root cause: Incorrectly extracting UTC date components instead of local timezone date\n - Thanks to @BrucePlumb for reporting\n","aliases":["/releases/4.2.0/","/releases/4.2.0/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • Added Korean (한국어) language support

    \n
      \n
    • Full translation of all 1911 localization keys
    • \n
    • Korean language option now available in Settings → General → Language
    • \n
    \n
  • \n
  • Adopted Obsidian 1.11.0 API features with backwards compatibility

    \n
      \n
    • Settings tab now displays TaskNotes icon in the sidebar (Obsidian 1.11.0+)
    • \n
    • Settings sections now use native SettingGroup for improved visual grouping (Obsidian 1.11.0+)
    • \n
    • Falls back gracefully to traditional section headers on older Obsidian versions
    • \n
    \n
  • \n
  • (#59) Added shortYear template variable for custom filename and folder templates

    \n
      \n
    • Use {shortYear} in filename templates (e.g., "25" for 2025)
    • \n
    • Use {{shortYear}} in folder templates
    • \n
    • Thanks to @Pixeltica for the feature request
    • \n
    \n
  • \n
  • (#1393) Option to prevent auto-creation of default Base view files on startup

    \n
      \n
    • New "Auto-create default files" toggle in Settings → Integrations → Bases Integration
    • \n
    • When disabled, deleted sample Base files will not be recreated on plugin load
    • \n
    • The manual "Create Default Files" button remains available for on-demand recreation
    • \n
    • Thanks to @wealthychef1 for the feature request
    • \n
    \n
  • \n
  • (#1408) Shift+click on status icon to cycle backwards through statuses

    \n
      \n
    • Normal click cycles forward through status order
    • \n
    • Shift+click cycles in reverse order
    • \n
    • Thanks to @JerryLu086 for the feature request
    • \n
    \n
  • \n
  • (#1410) Task creation modal now starts in vim insert mode when vim keybindings are enabled

    \n
      \n
    • Previously required pressing 'i' before typing when Obsidian vim mode was active
    • \n
    • The modal now automatically enters insert mode on focus, allowing immediate typing
    • \n
    • Thanks to @Leo310 for the feature request
    • \n
    \n
  • \n
  • Added button tooltips to calendar view toolbar

    \n
      \n
    • Hovering over navigation and view buttons now shows descriptive hints
    • \n
    • Buttons include: Today, Previous, Next, Month, Week, Day, Year, List
    • \n
    \n
  • \n
  • Added tooltips to task modal action icons

    \n
      \n
    • Icon buttons for status, date, project, priority, recurrence, and reminder now show tooltips on hover
    • \n
    • Improves discoverability for new users
    • \n
    \n
  • \n
  • (#503) Settings now sync automatically across devices via Obsidian Sync

    \n
      \n
    • Changes to custom statuses, priorities, and other settings apply immediately without restart
    • \n
    • Thanks to @jhedlund for the feature request and @l-mb for the implementation
    • \n
    \n
  • \n
  • (#1403) Kanban view option to consolidate status icons in column headers

    \n
      \n
    • New "Show status icon in column header only" toggle in Kanban view settings (disabled by default)
    • \n
    • When enabled and grouped by status, shows the icon in the column header and hides it on cards
    • \n
    • Reduces visual redundancy when the column already indicates the status
    • \n
    • Thanks to @l-mb for the feature request and implementation
    • \n
    \n
  • \n
  • (#1401) Calendar view option to span tasks between scheduled and due dates

    \n
      \n
    • New "Span tasks between scheduled and due dates" toggle in Calendar view Layout settings
    • \n
    • When enabled, tasks with both scheduled and due dates display as multi-day bars
    • \n
    • Provides Gantt chart-style visualization for project planning
    • \n
    • Thanks to @0atman for the feature request
    • \n
    \n
  • \n
  • (#1334) {{currentNotePath}} now works for "Create new inline task" command

    \n
      \n
    • The inline task folder setting with {{currentNotePath}} previously only worked for checkbox conversion
    • \n
    • Now also applies when using the "Create new inline task" command from the command palette
    • \n
    • Thanks to @kmaustral for the feature request
    • \n
    \n
  • \n
  • (#1264) Option to open Pomodoro timer in mobile sidebar instead of note panel

    \n
      \n
    • New "Mobile sidebar" setting in Settings → Features → Pomodoro Timer
    • \n
    • Choose between: Note panel (default tab behavior), Left sidebar, or Right sidebar
    • \n
    • Allows quick swipe access to the timer without switching notes on mobile devices
    • \n
    • Thanks to @Evthestrike for the feature request
    • \n
    \n
  • \n
  • (#1220) Option to use ICS event end time as task due date

    \n
      \n
    • New "Use ICS event end time as task due date" toggle in Settings → Integrations → Calendar Subscriptions
    • \n
    • When enabled, tasks created from calendar events will have their due date set to the event's end time
    • \n
    • For all-day events, uses the event date (not the ICS container end date which is the next day per ICS spec)
    • \n
    • For timed events, includes the exact end time
    • \n
    • Defaults to disabled to preserve existing behavior
    • \n
    • Thanks to @MiserMagus for the feature request
    • \n
    \n
  • \n
  • (#1108) Option to use task duration instead of due date for ICS calendar export

    \n
      \n
    • New "Use task duration for event length" toggle in Settings → Integrations → Automatic ICS Export
    • \n
    • When enabled, exported calendar events use scheduled date + time estimate as DTSTART/DTEND
    • \n
    • This aligns with GTD workflows where scheduled + duration represents work planning, while due date represents deadlines
    • \n
    • When disabled (default), preserves existing behavior using due date as DTEND
    • \n
    • Thanks to @bepolymathe for the feature request
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1421) Fixed natural language parser only capturing one date when both scheduled and due dates are specified

    \n
      \n
    • Input like "Task scheduled for tomorrow due next week" now correctly sets both scheduled and due dates
    • \n
    • Previously the parser would return early after finding the first date trigger, ignoring any subsequent triggers
    • \n
    • Thanks to @wealthychef1 for reporting
    • \n
    \n
  • \n
  • (#1384) Fixed title being sanitized even when "Store Task Title in Filename" is disabled

    \n
      \n
    • Characters like ?, <, >, :, etc. are now preserved in task titles when they won't be used in filenames
    • \n
    • When storeTitleInFilename is false, only minimal sanitization (whitespace normalization, control character removal) is applied
    • \n
    • Thanks to @allison-casey for reporting
    • \n
    \n
  • \n
  • (#1028), (#1140), (#1152), (#1354), (#1362) Fixed duplicate task entries appearing in Agenda view

    \n
      \n
    • Tasks were shown twice: once as TaskNotes events and again as property-based events with a file icon
    • \n
    • Changed default Agenda template to disable property-based events (showPropertyBasedEvents: false)
    • \n
    • Users can re-enable property-based events in view settings if needed for non-task date properties
    • \n
    • Thanks to @YIRU69, @jhedlund, @dblinnikov, @Snakiest, @WeiYiAcc, @JacksonMcDonaldDev, @jimbo108108, and @krelltunez for reporting
    • \n
    \n
  • \n
  • (#1386) Fixed timeEstimateCategory formula showing "Long (>2h)" instead of "No estimate" for new tasks

    \n
      \n
    • The condition didn't properly handle null values when timeEstimate property is unset
    • \n
    • Also fixed the same issue in trackingStatus formula
    • \n
    • Thanks to @nicou for reporting and @osxisl for the PR
    • \n
    \n
  • \n
  • (#1397) Fixed Bases views (Kanban, Calendar, Task List) resetting to Calendar view after a few minutes

    \n
      \n
    • Also fixed CalendarView corrupting other view files when saving state on unload
    • \n
    • Thanks to @music-soul1-1 for reporting
    • \n
    \n
  • \n
  • (#1398) Fixed overdue strikethrough showing on completed tasks

    \n
      \n
    • Completed tasks with past due dates no longer display overdue styling
    • \n
    • Respects the "Hide completed from overdue" setting which defaults to true
    • \n
    \n
  • \n
  • (#1363) Fixed calendar view showing nothing when a task has an invalid date format

    \n
      \n
    • Tasks with malformed dates (e.g., "262025-12-16" instead of "2025-12-16") no longer crash the entire calendar
    • \n
    • Invalid tasks are now skipped with a console warning, allowing other events to display normally
    • \n
    • Thanks to @Erelen for reporting
    • \n
    \n
  • \n
  • Fixed today column in week/day calendar views using FullCalendar's default yellow instead of theme accent

    \n
      \n
    • Today's column now uses a tint of the theme accent color for consistent styling
    • \n
    \n
  • \n
  • (#1399) Fixed drag-and-drop not working in Kanban view on mobile

    \n
      \n
    • Cards and columns can now be dragged using long-press gesture on touch devices
    • \n
    • Includes haptic feedback and auto-scroll when dragging near edges
    • \n
    • Thanks to @l-mb for reporting and the fix
    • \n
    \n
  • \n
  • (#1381) Fixed Pomodoro "Change Task" menu not showing newly created tasks

    \n
      \n
    • Tasks created while the Pomodoro view was open would not appear in the task selector
    • \n
    • Improved metadata cache synchronization to properly wait for new files to be indexed
    • \n
    • Thanks to @Ghosthael for reporting
    • \n
    \n
  • \n
  • (#1344) Fixed "Unsaved Changes" popup appearing randomly when closing task edit modal

    \n
      \n
    • The popup would appear even when no changes were made to the task
    • \n
    • Caused by inconsistent trailing whitespace normalization when comparing details content
    • \n
    • Thanks to @hasanyilmaz for reporting
    • \n
    \n
  • \n
  • (#1402) Fixed Kanban swimlane view showing tasks in wrong column when grouped by formula

    \n
      \n
    • After editing task metadata, cards would jump to "None" column until Obsidian reload
    • \n
    • Column assignment now uses Bases' computed grouping instead of cached formula outputs
    • \n
    • Thanks to @bailob for the fix
    • \n
    \n
  • \n
  • (#1352) Fixed date context menu not preserving time when using increment options

    \n
      \n
    • Using +1 day, -1 day, +1 week, or -1 week on a task with a time (e.g., 2025-12-10T16:00) now preserves the time
    • \n
    • Previously the time would be stripped, changing 2025-12-10T16:00 to 2025-12-11 instead of 2025-12-11T16:00
    • \n
    • Thanks to @cathywu for the feature request
    • \n
    \n
  • \n
  • Fixed v3 saved views exporting incorrectly to Bases format

    \n
      \n
    • Title filters now correctly use file.name instead of note.title
    • \n
    • Archived filters now generate valid boolean expressions instead of malformed comparisons
    • \n
    • "Is Blocked" filters now generate correct expressions with proper operator precedence
    • \n
    \n
  • \n
  • (#1036) Due dates can now be dragged in the calendar view

    \n
      \n
    • Previously only scheduled dates were draggable; due dates were locked in place
    • \n
    • Dragging a due event now updates the task's due date property
    • \n
    • Thanks to @same774 for reporting
    • \n
    \n
  • \n
  • Improved calendar view responsiveness for user interactions

    \n
      \n
    • Task creation, editing, timeblock changes, and view option toggles now update immediately
    • \n
    • Previously these actions waited 5 seconds due to the debounce intended for external file changes
    • \n
    • The 5-second debounce is now bypassed for direct user actions while still preventing flicker during typing
    • \n
    \n
  • \n
  • Improved visual affordance for Pomodoro timer duration adjustment buttons

    \n
      \n
    • The +/- buttons below the timer now have visible backgrounds and borders
    • \n
    • Hover states show accent color border for clearer interactivity feedback
    • \n
    • Previously buttons were nearly invisible with transparent backgrounds
    • \n
    \n
  • \n
  • (#1409), (#1214), (#979) Improved Calendar, Agenda, Kanban, and Stats views in pop-out windows

    \n
      \n
    • Drag-and-drop in Kanban view now works correctly when the view is in a new window
    • \n
    • Context menus (status, priority, task) now work correctly in pop-out windows
    • \n
    • Stats view drill-down modal now appears in the correct window
    • \n
    • Search boxes, task cards, and grouped task lists render correctly
    • \n
    • Root cause: Code was using global document and standard instanceof checks which fail across windows
    • \n
    • Solution: Use ownerDocument for DOM operations and Obsidian's cross-window instanceOf() method
    • \n
    • Known limitation: Calendar event dragging does not work in pop-out windows due to FullCalendar library using global document for mouse event listeners. Use context menus or edit modals as a workaround.
    • \n
    • Updated FullCalendar to v6.1.20
    • \n
    • Thanks to @Snakiest, @same774, and @3zra47 for reporting
    • \n
    \n
  • \n
  • (#1337) Fixed "Convert current note to task" hotkey not applying default values from settings

    \n
      \n
    • When user configured default status/priority as "None", the modal would show "Open" and "Normal" instead
    • \n
    • Root cause: Task edit modal was refreshing data from file and overwriting user-configured defaults
    • \n
    • Now preserves constructor-provided task data when converting non-task files
    • \n
    • Thanks to @guihasparyk for reporting
    • \n
    \n
  • \n
  • (#1304) Fixed "Cannot find function map on type Link" error in Blocking view

    \n
      \n
    • Error occurred when embedding the Relationships base and opening the Blocking view
    • \n
    • Root cause: When blockedBy contained a single dependency, Bases returned it as a Link object without a .map() method
    • \n
    • Fixed by wrapping blockedBy with list() before calling .map(), consistent with the Blocked By view
    • \n
    • Thanks to @prayidae for reporting
    • \n
    \n
  • \n
  • (#1295) Fixed missing navigation link to Default Base Templates page on tasknotes.dev

    \n
      \n
    • The page existed but was not accessible from the site navigation
    • \n
    • Thanks to @Arachnidai for reporting
    • \n
    \n
  • \n
  • (#1223) Fixed "Go to today's note" command opening wrong date in positive UTC offset timezones

    \n
      \n
    • In timezones like Japan (UTC+9), early morning use of this command opened yesterday's note
    • \n
    • Root cause: Incorrectly extracting UTC date components instead of local timezone date
    • \n
    • Thanks to @BrucePlumb for reporting
    • \n
    \n
  • \n
\n","text":"Added# Added Korean (한국어) language support Full translation of all 1911 localization keys Korean language option now available in Settings → General → Language Adopted Obsidian 1.11.0 API features with backwards compatibility Settings tab now displays TaskNotes icon in the sidebar (Obsidian 1.11.0+) Settings sections now use native SettingGroup for improved visual grouping (Obsidian 1.11.0+) Falls back gracefully to traditional section headers on older Obsidian versions (#59) Added shortYear template variable for custom filename and folder templates Use {shortYear} in filename templates (e.g., \"25\" for 2025) Use {{shortYear}} in folder templates Thanks to @Pixeltica for the feature request (#1393) Option to prevent auto-creation of default Base view files on startup New \"Auto-create default files\" toggle in Settings → Integrations → Bases Integration When disabled, deleted sample Base files will not be recreated on plugin load The manual \"Create Default Files\" button remains available for on-demand recreation Thanks to @wealthychef1 for the feature request (#1408) Shift+click on status icon to cycle backwards through statuses Normal click cycles forward through status order Shift+click cycles in reverse order Thanks to @JerryLu086 for the feature request (#1410) Task creation modal now starts in vim insert mode when vim keybindings are enabled Previously required pressing 'i' before typing when Obsidian vim mode was active The modal now automatically enters insert mode on focus, allowing immediate typing Thanks to @Leo310 for the feature request Added button tooltips to calendar view toolbar Hovering over navigation and view buttons now shows descriptive hints Buttons include: Today, Previous, Next, Month, Week, Day, Year, List Added tooltips to task modal action icons Icon buttons for status, date, project, priority, recurrence, and reminder now show tooltips on hover Improves discoverability for new users (#503) Settings now sync automatically across devices via Obsidian Sync Changes to custom statuses, priorities, and other settings apply immediately without restart Thanks to @jhedlund for the feature request and @l-mb for the implementation (#1403) Kanban view option to consolidate status icons in column headers New \"Show status icon in column header only\" toggle in Kanban view settings (disabled by default) When enabled and grouped by status, shows the icon in the column header and hides it on cards Reduces visual redundancy when the column already indicates the status Thanks to @l-mb for the feature request and implementation (#1401) Calendar view option to span tasks between scheduled and due dates New \"Span tasks between scheduled and due dates\" toggle in Calendar view Layout settings When enabled, tasks with both scheduled and due dates display as multi-day bars Provides Gantt chart-style visualization for project planning Thanks to @0atman for the feature request (#1334) {{currentNotePath}} now works for \"Create new inline task\" command The inline task folder setting with {{currentNotePath}} previously only worked for checkbox conversion Now also applies when using the \"Create new inline task\" command from the command palette Thanks to @kmaustral for the feature request (#1264) Option to open Pomodoro timer in mobile sidebar instead of note panel New \"Mobile sidebar\" setting in Settings → Features → Pomodoro Timer Choose between: Note panel (default tab behavior), Left sidebar, or Right sidebar Allows quick swipe access to the timer without switching notes on mobile devices Thanks to @Evthestrike for the feature request (#1220) Option to use ICS event end time as task due date New \"Use ICS event end time as task due date\" toggle in Settings → Integrations → Calendar Subscriptions When enabled, tasks created from calendar events will have their due date set to the event's end time For all-day events, uses the event date (not the ICS container end date which is the next day per ICS spec) For timed events, includes the exact end time Defaults to disabled to preserve existing behavior Thanks to @MiserMagus for the feature request (#1108) Option to use task duration instead of due date for ICS calendar export New \"Use task duration for event length\" toggle in Settings → Integrations → Automatic ICS Export When enabled, exported calendar events use scheduled date + time estimate as DTSTART/DTEND This aligns with GTD workflows where scheduled + duration represents work planning, while due date represents deadlines When disabled (default), preserves existing behavior using due date as DTEND Thanks to @bepolymathe for the feature request Fixed# (#1421) Fixed natural language parser only capturing one date when both scheduled and due dates are specified Input like \"Task scheduled for tomorrow due next week\" now correctly sets both scheduled and due dates Previously the parser would return early after finding the first date trigger, ignoring any subsequent triggers Thanks to @wealthychef1 for reporting (#1384) Fixed title being sanitized even when \"Store Task Title in Filename\" is disabled Characters like ?, <, >, :, etc. are now preserved in task titles when they won't be used in filenames When storeTitleInFilename is false, only minimal sanitization (whitespace normalization, control character removal) is applied Thanks to @allison-casey for reporting (#1028), (#1140), (#1152), (#1354), (#1362) Fixed duplicate task entries appearing in Agenda view Tasks were shown twice: once as TaskNotes events and again as property-based events with a file icon Changed default Agenda template to disable property-based events (showPropertyBasedEvents: false) Users can re-enable property-based events in view settings if needed for non-task date properties Thanks to @YIRU69, @jhedlund, @dblinnikov, @Snakiest, @WeiYiAcc, @JacksonMcDonaldDev, @jimbo108108, and @krelltunez for reporting (#1386) Fixed timeEstimateCategory formula showing \"Long (>2h)\" instead of \"No estimate\" for new tasks The condition didn't properly handle null values when timeEstimate property is unset Also fixed the same issue in trackingStatus formula Thanks to @nicou for reporting and @osxisl for the PR (#1397) Fixed Bases views (Kanban, Calendar, Task List) resetting to Calendar view after a few minutes Also fixed CalendarView corrupting other view files when saving state on unload Thanks to @music-soul1-1 for reporting (#1398) Fixed overdue strikethrough showing on completed tasks Completed tasks with past due dates no longer display overdue styling Respects the \"Hide completed from overdue\" setting which defaults to true (#1363) Fixed calendar view showing nothing when a task has an invalid date format Tasks with malformed dates (e.g., \"262025-12-16\" instead of \"2025-12-16\") no longer crash the entire calendar Invalid tasks are now skipped with a console warning, allowing other events to display normally Thanks to @Erelen for reporting Fixed today column in week/day calendar views using FullCalendar's default yellow instead of theme accent Today's column now uses a tint of the theme accent color for consistent styling (#1399) Fixed drag-and-drop not working in Kanban view on mobile Cards and columns can now be dragged using long-press gesture on touch devices Includes haptic feedback and auto-scroll when dragging near edges Thanks to @l-mb for reporting and the fix (#1381) Fixed Pomodoro \"Change Task\" menu not showing newly created tasks Tasks created while the Pomodoro view was open would not appear in the task selector Improved metadata cache synchronization to properly wait for new files to be indexed Thanks to @Ghosthael for reporting (#1344) Fixed \"Unsaved Changes\" popup appearing randomly when closing task edit modal The popup would appear even when no changes were made to the task Caused by inconsistent trailing whitespace normalization when comparing details content Thanks to @hasanyilmaz for reporting (#1402) Fixed Kanban swimlane view showing tasks in wrong column when grouped by formula After editing task metadata, cards would jump to \"None\" column until Obsidian reload Column assignment now uses Bases' computed grouping instead of cached formula outputs Thanks to @bailob for the fix (#1352) Fixed date context menu not preserving time when using increment options Using +1 day, -1 day, +1 week, or -1 week on a task with a time (e.g., 2025-12-10T16:00) now preserves the time Previously the time would be stripped, changing 2025-12-10T16:00 to 2025-12-11 instead of 2025-12-11T16:00 Thanks to @cathywu for the feature request Fixed v3 saved views exporting incorrectly to Bases format Title filters now correctly use file.name instead of note.title Archived filters now generate valid boolean expressions instead of malformed comparisons \"Is Blocked\" filters now generate correct expressions with proper operator precedence (#1036) Due dates can now be dragged in the calendar view Previously only scheduled dates were draggable; due dates were locked in place Dragging a due event now updates the task's due date property Thanks to @same774 for reporting Improved calendar view responsiveness for user interactions Task creation, editing, timeblock changes, and view option toggles now update immediately Previously these actions waited 5 seconds due to the debounce intended for external file changes The 5-second debounce is now bypassed for direct user actions while still preventing flicker during typing Improved visual affordance for Pomodoro timer duration adjustment buttons The +/- buttons below the timer now have visible backgrounds and borders Hover states show accent color border for clearer interactivity feedback Previously buttons were nearly invisible with transparent backgrounds (#1409), (#1214), (#979) Improved Calendar, Agenda, Kanban, and Stats views in pop-out windows Drag-and-drop in Kanban view now works correctly when the view is in a new window Context menus (status, priority, task) now work correctly in pop-out windows Stats view drill-down modal now appears in the correct window Search boxes, task cards, and grouped task lists render correctly Root cause: Code was using global document and standard instanceof checks which fail across windows Solution: Use ownerDocument for DOM operations and Obsidian's cross-window instanceOf() method Known limitation: Calendar event dragging does not work in pop-out windows due to FullCalendar library using global document for mouse event listeners. Use context menus or edit modals as a workaround. Updated FullCalendar to v6.1.20 Thanks to @Snakiest, @same774, and @3zra47 for reporting (#1337) Fixed \"Convert current note to task\" hotkey not applying default values from settings When user configured default status/priority as \"None\", the modal would show \"Open\" and \"Normal\" instead Root cause: Task edit modal was refreshing data from file and overwriting user-configured defaults Now preserves constructor-provided task data when converting non-task files Thanks to @guihasparyk for reporting (#1304) Fixed \"Cannot find function map on type Link\" error in Blocking view Error occurred when embedding the Relationships base and opening the Blocking view Root cause: When blockedBy contained a single dependency, Bases returned it as a Link object without a .map() method Fixed by wrapping blockedBy with list() before calling .map(), consistent with the Blocked By view Thanks to @prayidae for reporting (#1295) Fixed missing navigation link to Default Base Templates page on tasknotes.dev The page existed but was not accessible from the site navigation Thanks to @Arachnidai for reporting (#1223) Fixed \"Go to today's note\" command opening wrong date in positive UTC offset timezones In timezones like Japan (UTC+9), early morning use of this command opened yesterday's note Root cause: Incorrectly extracting UTC date components instead of local timezone date Thanks to @BrucePlumb for reporting"},{"route":"/obsidian/releases/4.2.1/","title":"TaskNotes 4.2.1","description":"(#1424) Fixed \"Create New Task\" command creating tasks in active folder instead of default folder","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.2.1.md","namespace":"obsidian","relativePath":"releases/4.2.1.md","raw":"# TaskNotes 4.2.1\n\n## Added\n\n- New Calendars API endpoint for access to calendar data\n - Access calendar provider information and connection status\n - Query events from Google Calendar, Microsoft Calendar, and ICS subscriptions\n - Filter events by date range\n - [`tasknotes-cli`](https://github.com/callumalpass/tasknotes-cli) has been updated to make use of this endpoint\n\n## Fixed\n\n- (#1424) Fixed \"Create New Task\" command creating tasks in active folder instead of default folder\n - \"Create New Task\" now correctly uses the configured default task folder\n - \"Create New Inline Task\" continues to use the inline task folder setting\n - Thanks to @Gogo-XD for reporting and @TonyAtlas for confirming\n\n- (#1421), (#1042) Fixed natural language parser only setting one date when both scheduled and due dates are specified\n - Entering something like \"task due Jan 9 at Jan 9\" now correctly sets both the due date and scheduled date\n - Thanks to @wealthychef1 and @dblinnikov for reporting\n\n- (#1410) Fixed vim insert mode not activating in task creation modal\n - The modal now correctly enters insert mode when vim keybindings are enabled\n - Thanks to @Leo310 for the feature request\n\n- (#1422) Fixed tags with dashes not being parsed correctly\n - Tags like `#my-tag` were being truncated to `#my`\n - Thanks to @JerryLu086 for reporting\n\n- (#1419) Fixed custom statuses and priorities not saving in settings\n - Values entered in text fields were sometimes lost when closing the settings modal\n - Thanks to @s33a for reporting\n","aliases":["/releases/4.2.1/","/releases/4.2.1/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • New Calendars API endpoint for access to calendar data
      \n
    • Access calendar provider information and connection status
    • \n
    • Query events from Google Calendar, Microsoft Calendar, and ICS subscriptions
    • \n
    • Filter events by date range
    • \n
    • tasknotes-cli has been updated to make use of this endpoint
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1424) Fixed "Create New Task" command creating tasks in active folder instead of default folder

    \n
      \n
    • "Create New Task" now correctly uses the configured default task folder
    • \n
    • "Create New Inline Task" continues to use the inline task folder setting
    • \n
    • Thanks to @Gogo-XD for reporting and @TonyAtlas for confirming
    • \n
    \n
  • \n
  • (#1421), (#1042) Fixed natural language parser only setting one date when both scheduled and due dates are specified

    \n
      \n
    • Entering something like "task due Jan 9 at Jan 9" now correctly sets both the due date and scheduled date
    • \n
    • Thanks to @wealthychef1 and @dblinnikov for reporting
    • \n
    \n
  • \n
  • (#1410) Fixed vim insert mode not activating in task creation modal

    \n
      \n
    • The modal now correctly enters insert mode when vim keybindings are enabled
    • \n
    • Thanks to @Leo310 for the feature request
    • \n
    \n
  • \n
  • (#1422) Fixed tags with dashes not being parsed correctly

    \n
      \n
    • Tags like #my-tag were being truncated to #my
    • \n
    • Thanks to @JerryLu086 for reporting
    • \n
    \n
  • \n
  • (#1419) Fixed custom statuses and priorities not saving in settings

    \n
      \n
    • Values entered in text fields were sometimes lost when closing the settings modal
    • \n
    • Thanks to @s33a for reporting
    • \n
    \n
  • \n
\n","text":"Added# New Calendars API endpoint for access to calendar data Access calendar provider information and connection status Query events from Google Calendar, Microsoft Calendar, and ICS subscriptions Filter events by date range tasknotes-cli has been updated to make use of this endpoint Fixed# (#1424) Fixed \"Create New Task\" command creating tasks in active folder instead of default folder \"Create New Task\" now correctly uses the configured default task folder \"Create New Inline Task\" continues to use the inline task folder setting Thanks to @Gogo-XD for reporting and @TonyAtlas for confirming (#1421), (#1042) Fixed natural language parser only setting one date when both scheduled and due dates are specified Entering something like \"task due Jan 9 at Jan 9\" now correctly sets both the due date and scheduled date Thanks to @wealthychef1 and @dblinnikov for reporting (#1410) Fixed vim insert mode not activating in task creation modal The modal now correctly enters insert mode when vim keybindings are enabled Thanks to @Leo310 for the feature request (#1422) Fixed tags with dashes not being parsed correctly Tags like #my-tag were being truncated to #my Thanks to @JerryLu086 for reporting (#1419) Fixed custom statuses and priorities not saving in settings Values entered in text fields were sometimes lost when closing the settings modal Thanks to @s33a for reporting"},{"route":"/obsidian/releases/4.3.0/","title":"TaskNotes 4.3.0","description":"(#1361) Option to disable inline task overlay for aliased wikilinks","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.3.0.md","namespace":"obsidian","relativePath":"releases/4.3.0.md","raw":"# TaskNotes 4.3.0\n\n## Changed\n\n- (#1437) Unified template variable syntax and available variables across filename and body templates\n - Both systems now use double-brace `{{variable}}` syntax consistently\n - Single-brace `{variable}` syntax remains supported for backwards compatibility but is deprecated\n - Settings UI shows a warning when deprecated single-brace syntax is detected\n - Filename templates gain body template variables: `{{contexts}}`, `{{tags}}`, `{{hashtags}}`, `{{timeEstimate}}`, `{{details}}`, `{{parentNote}}`\n - Body templates gain filename template variables: `{{zettel}}`, `{{nano}}`, and all extended date/time variables\n - Thanks to @23maverick23 for reporting\n\n## Added\n\n- (#1361) Option to disable inline task overlay for aliased wikilinks\n - New setting in Features → Inline Tasks: \"Disable overlay for aliased links\"\n - When enabled, links with aliases like `[[Task|Check Status]]` render as plain links\n - Links without aliases continue to show the interactive task widget\n - Useful when embedding tasks in prose where the widget would be disruptive\n - Thanks to @diegomarzaa for the contribution and @jldiaz for proposing this feature in #1117\n\n- (#1199, #1205) Google Calendar export for tasks\n - Sync tasks to Google Calendar based on scheduled or due dates\n - Automatic sync on task create, update, complete, and delete\n - Configurable event title templates with placeholders (`{{title}}`, `{{status}}`, `{{priority}}`, etc.)\n - Event descriptions include task metadata and optional Obsidian deep link\n - Support for all-day or timed events with customizable duration\n - Event color customization using Google Calendar's color palette\n - Default reminder setting for popup notifications\n - Bulk sync and unlink actions in settings\n - Task-event linking stored in frontmatter (`googleCalendarEventId`)\n - Recurring tasks sync as Google Calendar recurring events\n - Completed or skipped recurring instances are automatically excluded\n - Thanks to @someromans and @Leonard-44 for requesting this feature, and @dmantisk, @farangkao, @rayvermey, and @rdpr for their input\n\n## Fixed\n\n- (#1413) Fixed angle-bracket links and project title display\n - Angle-bracket links like `[Spec]()` now resolve correctly\n - Project links display frontmatter `title` instead of raw filename/path when available\n - Dependency values normalize consistently across wikilinks, markdown links, and angle-bracket variants\n - Many thanks to @normenmueller for the contribution\n\n- (#1414) Kanban column headers now display configured priority labels instead of raw values\n - Many thanks to @normenmueller for the contribution\n\n- (#1416) Fixed property-based task identification mutating tags unexpectedly\n - Tags are only written when explicitly changed by the user\n - Task tag is only added in tag-based identification mode\n - Fixes #1391\n - Thanks to @loukandr for reporting and @normenmueller for the fix\n\n- (#1187) Fixed \"Unknown view types\" error when opening Bases views after upgrading from pre-V4\n - Users who had disabled Bases support in earlier versions could not open Bases views after upgrading\n - Settings migration now automatically re-enables Bases support since the toggle was removed in V4\n - Thanks to @MiracleXYZ for reporting\n\n- (#1144) Fixed relationships.base showing empty views for Projects, Blocked By, and Blocking tabs\n - The top-level task filter was excluding non-task files from the Projects view\n - Projects can be any file type (not just tasks), so the filter is now applied per-view\n - Subtasks, Blocked By, and Blocking views retain the task filter; Projects view does not\n - Users with existing relationships.base files should delete and regenerate them to get the fix\n - Thanks to @needo37 for reporting, and @n1njaznutz, @nestor50, and @IvyDliu for investigating and confirming the solution\n\n- Fixed calendar view type not persisting or applying when changed\n - View type changes via header buttons (week/day/month) are now saved to the .base file\n - View type changes via Bases settings panel now apply immediately without reload\n\n- (#1441) Fixed task dragging broken with \"Span tasks between scheduled and due dates\" enabled\n - Span events can now be dragged to move tasks in time\n - Dragging shifts both scheduled and due dates proportionally, preserving the span duration\n - Previously, dragging span events would cause a visual/data mismatch where the calendar showed the wrong position\n - Thanks to @Peeeet for reporting\n","aliases":["/releases/4.3.0/","/releases/4.3.0/"],"toc":[{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Changed#

\n
    \n
  • (#1437) Unified template variable syntax and available variables across filename and body templates
      \n
    • Both systems now use double-brace {{variable}} syntax consistently
    • \n
    • Single-brace {variable} syntax remains supported for backwards compatibility but is deprecated
    • \n
    • Settings UI shows a warning when deprecated single-brace syntax is detected
    • \n
    • Filename templates gain body template variables: {{contexts}}, {{tags}}, {{hashtags}}, {{timeEstimate}}, {{details}}, {{parentNote}}
    • \n
    • Body templates gain filename template variables: {{zettel}}, {{nano}}, and all extended date/time variables
    • \n
    • Thanks to @23maverick23 for reporting
    • \n
    \n
  • \n
\n

Added#

\n
    \n
  • (#1361) Option to disable inline task overlay for aliased wikilinks

    \n
      \n
    • New setting in Features → Inline Tasks: "Disable overlay for aliased links"
    • \n
    • When enabled, links with aliases like [[Task|Check Status]] render as plain links
    • \n
    • Links without aliases continue to show the interactive task widget
    • \n
    • Useful when embedding tasks in prose where the widget would be disruptive
    • \n
    • Thanks to @diegomarzaa for the contribution and @jldiaz for proposing this feature in #1117
    • \n
    \n
  • \n
  • (#1199, #1205) Google Calendar export for tasks

    \n
      \n
    • Sync tasks to Google Calendar based on scheduled or due dates
    • \n
    • Automatic sync on task create, update, complete, and delete
    • \n
    • Configurable event title templates with placeholders ({{title}}, {{status}}, {{priority}}, etc.)
    • \n
    • Event descriptions include task metadata and optional Obsidian deep link
    • \n
    • Support for all-day or timed events with customizable duration
    • \n
    • Event color customization using Google Calendar's color palette
    • \n
    • Default reminder setting for popup notifications
    • \n
    • Bulk sync and unlink actions in settings
    • \n
    • Task-event linking stored in frontmatter (googleCalendarEventId)
    • \n
    • Recurring tasks sync as Google Calendar recurring events
    • \n
    • Completed or skipped recurring instances are automatically excluded
    • \n
    • Thanks to @someromans and @Leonard-44 for requesting this feature, and @dmantisk, @farangkao, @rayvermey, and @rdpr for their input
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1413) Fixed angle-bracket links and project title display

    \n
      \n
    • Angle-bracket links like [Spec](<Projects/Client X/Spec.md>) now resolve correctly
    • \n
    • Project links display frontmatter title instead of raw filename/path when available
    • \n
    • Dependency values normalize consistently across wikilinks, markdown links, and angle-bracket variants
    • \n
    • Many thanks to @normenmueller for the contribution
    • \n
    \n
  • \n
  • (#1414) Kanban column headers now display configured priority labels instead of raw values

    \n
      \n
    • Many thanks to @normenmueller for the contribution
    • \n
    \n
  • \n
  • (#1416) Fixed property-based task identification mutating tags unexpectedly

    \n
      \n
    • Tags are only written when explicitly changed by the user
    • \n
    • Task tag is only added in tag-based identification mode
    • \n
    • Fixes #1391
    • \n
    • Thanks to @loukandr for reporting and @normenmueller for the fix
    • \n
    \n
  • \n
  • (#1187) Fixed "Unknown view types" error when opening Bases views after upgrading from pre-V4

    \n
      \n
    • Users who had disabled Bases support in earlier versions could not open Bases views after upgrading
    • \n
    • Settings migration now automatically re-enables Bases support since the toggle was removed in V4
    • \n
    • Thanks to @MiracleXYZ for reporting
    • \n
    \n
  • \n
  • (#1144) Fixed relationships.base showing empty views for Projects, Blocked By, and Blocking tabs

    \n
      \n
    • The top-level task filter was excluding non-task files from the Projects view
    • \n
    • Projects can be any file type (not just tasks), so the filter is now applied per-view
    • \n
    • Subtasks, Blocked By, and Blocking views retain the task filter; Projects view does not
    • \n
    • Users with existing relationships.base files should delete and regenerate them to get the fix
    • \n
    • Thanks to @needo37 for reporting, and @n1njaznutz, @nestor50, and @IvyDliu for investigating and confirming the solution
    • \n
    \n
  • \n
  • Fixed calendar view type not persisting or applying when changed

    \n
      \n
    • View type changes via header buttons (week/day/month) are now saved to the .base file
    • \n
    • View type changes via Bases settings panel now apply immediately without reload
    • \n
    \n
  • \n
  • (#1441) Fixed task dragging broken with "Span tasks between scheduled and due dates" enabled

    \n
      \n
    • Span events can now be dragged to move tasks in time
    • \n
    • Dragging shifts both scheduled and due dates proportionally, preserving the span duration
    • \n
    • Previously, dragging span events would cause a visual/data mismatch where the calendar showed the wrong position
    • \n
    • Thanks to @Peeeet for reporting
    • \n
    \n
  • \n
\n","text":"Changed# (#1437) Unified template variable syntax and available variables across filename and body templates Both systems now use double-brace {{variable}} syntax consistently Single-brace {variable} syntax remains supported for backwards compatibility but is deprecated Settings UI shows a warning when deprecated single-brace syntax is detected Filename templates gain body template variables: {{contexts}}, {{tags}}, {{hashtags}}, {{timeEstimate}}, {{details}}, {{parentNote}} Body templates gain filename template variables: {{zettel}}, {{nano}}, and all extended date/time variables Thanks to @23maverick23 for reporting Added# (#1361) Option to disable inline task overlay for aliased wikilinks New setting in Features → Inline Tasks: \"Disable overlay for aliased links\" When enabled, links with aliases like [[Task|Check Status]] render as plain links Links without aliases continue to show the interactive task widget Useful when embedding tasks in prose where the widget would be disruptive Thanks to @diegomarzaa for the contribution and @jldiaz for proposing this feature in #1117 (#1199, #1205) Google Calendar export for tasks Sync tasks to Google Calendar based on scheduled or due dates Automatic sync on task create, update, complete, and delete Configurable event title templates with placeholders ({{title}}, {{status}}, {{priority}}, etc.) Event descriptions include task metadata and optional Obsidian deep link Support for all-day or timed events with customizable duration Event color customization using Google Calendar's color palette Default reminder setting for popup notifications Bulk sync and unlink actions in settings Task-event linking stored in frontmatter (googleCalendarEventId) Recurring tasks sync as Google Calendar recurring events Completed or skipped recurring instances are automatically excluded Thanks to @someromans and @Leonard-44 for requesting this feature, and @dmantisk, @farangkao, @rayvermey, and @rdpr for their input Fixed# (#1413) Fixed angle-bracket links and project title display Angle-bracket links like [Spec]() now resolve correctly Project links display frontmatter title instead of raw filename/path when available Dependency values normalize consistently across wikilinks, markdown links, and angle-bracket variants Many thanks to @normenmueller for the contribution (#1414) Kanban column headers now display configured priority labels instead of raw values Many thanks to @normenmueller for the contribution (#1416) Fixed property-based task identification mutating tags unexpectedly Tags are only written when explicitly changed by the user Task tag is only added in tag-based identification mode Fixes #1391 Thanks to @loukandr for reporting and @normenmueller for the fix (#1187) Fixed \"Unknown view types\" error when opening Bases views after upgrading from pre-V4 Users who had disabled Bases support in earlier versions could not open Bases views after upgrading Settings migration now automatically re-enables Bases support since the toggle was removed in V4 Thanks to @MiracleXYZ for reporting (#1144) Fixed relationships.base showing empty views for Projects, Blocked By, and Blocking tabs The top-level task filter was excluding non-task files from the Projects view Projects can be any file type (not just tasks), so the filter is now applied per-view Subtasks, Blocked By, and Blocking views retain the task filter; Projects view does not Users with existing relationships.base files should delete and regenerate them to get the fix Thanks to @needo37 for reporting, and @n1njaznutz, @nestor50, and @IvyDliu for investigating and confirming the solution Fixed calendar view type not persisting or applying when changed View type changes via header buttons (week/day/month) are now saved to the .base file View type changes via Bases settings panel now apply immediately without reload (#1441) Fixed task dragging broken with \"Span tasks between scheduled and due dates\" enabled Span events can now be dragged to move tasks in time Dragging shifts both scheduled and due dates proportionally, preserving the span duration Previously, dragging span events would cause a visual/data mismatch where the calendar showed the wrong position Thanks to @Peeeet for reporting"},{"route":"/obsidian/releases/4.3.1/","title":"TaskNotes 4.3.1","description":"(#1546) Added sticky kanban column headers that remain visible while scrolling","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.3.1.md","namespace":"obsidian","relativePath":"releases/4.3.1.md","raw":"# TaskNotes 4.3.1\n\n## Added\n\n- (#1546) Added sticky kanban column headers that remain visible while scrolling\n - Thanks to @normenmueller for the contribution\n\n- (#1458) Added CSS color classes to context tags for custom styling\n - Each context tag now receives a unique CSS class based on its name (e.g., `context-tag--color-0` through `context-tag--color-19`)\n - Enables styling individual contexts via CSS snippets\n - Thanks to @phortx for the contribution\n\n- Added [mdbase-spec](https://mdbase.dev) type definition generation\n - New setting in Integrations tab to generate mdbase-spec v0.2.0 type definition files (`mdbase.yaml` and `_types/task.md`) at the vault root\n - Type definitions are derived from TaskNotes settings (statuses, priorities, field mappings, user fields) and regenerated automatically when settings change\n - Enables interoperability with other tools that support the mdbase-spec format\n\n## Fixed\n\n- (#1472) Fixed task dependencies not being stored as wikilinks in frontmatter\n - Dependencies now retain their `[[wikilink]]` format when saved, preventing them from breaking on file rename\n - Thanks to @renekalff for reporting\n\n- (#1443) Fixed default status/priority not updating when the referenced custom value is deleted\n - Deleting a custom status or priority that was set as the default now resets the default to the first available value\n - Thanks to @l-mb for the contribution\n\n- (#1448) Fixed project removals not persisting from the task edit modal\n - Removing all projects from a task now correctly clears the projects field\n - Different link formats (e.g., markdown links vs wikilinks) no longer cause false change detection\n - Thanks to @normenmueller for the contribution\n\n- (#1514), (#1517) Fixed task reminders not syncing to Google Calendar\n - Task-specific reminders (both relative and absolute) now sync to Google Calendar\n - Previously only the global default reminder setting was used, ignoring per-task reminders\n - Thanks to @christenbc for the contribution\n\n- (#1525), (#1531) Fixed subtask status dot not refreshing visually when clicked\n - Status dot, checkbox, and card styling now update instantly when cycling status\n - Thanks to @christenbc for the contribution\n\n- (#1537) Fixed Google Calendar errors during bulk sync\n - Added rate limiting to space out API calls, preventing errors when syncing many tasks at once\n - Thanks to @Lorite for the contribution\n\n- (#1515), (#1540) Fixed time loss when setting recurrence and recurrence not clearing from Google Calendar\n - Setting recurrence on a task with a scheduled time now preserves the time, preventing Google Calendar events from appearing as all-day\n - Clearing recurrence from a task now also removes it from the synced Google Calendar event\n - Thanks to @christenbc for the contribution\n\n- (#1428), (#1559) Fixed hierarchical tags with slashes (e.g., `#project/sub-project`) being truncated in link text\n - Tags containing slashes, hyphens, and Unicode characters now render correctly\n - Thanks to @normenmueller for the contribution and @ysafonov for reporting\n\n- (#1565) Fixed Google Calendar target calendar dropdown appearing empty after app restart\n - The dropdown now re-populates once calendars are fetched during startup\n - Thanks to @N-HEDGER for reporting\n\n- (#1567) Fixed inline task card widgets disappearing momentarily\n - When the task cache is temporarily cleared (e.g., during Smart Connections processing), the previously-rendered widget is now preserved instead of reverting to a plain wiki link\n - Thanks to @scztt for reporting\n\n- (#1568) Fixed deleted tasks not being removed from Google Calendar\n - When a task file is deleted outside of TaskNotes (e.g., via Obsidian's file manager), the synced Google Calendar event is now cleaned up automatically\n - Thanks to @kmaustral for reporting\n\n- Fixed Integrations tab spacing and layout issues\n - Improved positioning of buttons and status indicators across Google Calendar, ICS, and Webhooks sections\n","aliases":["/releases/4.3.1/","/releases/4.3.1/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • (#1546) Added sticky kanban column headers that remain visible while scrolling

    \n
      \n
    • Thanks to @normenmueller for the contribution
    • \n
    \n
  • \n
  • (#1458) Added CSS color classes to context tags for custom styling

    \n
      \n
    • Each context tag now receives a unique CSS class based on its name (e.g., context-tag--color-0 through context-tag--color-19)
    • \n
    • Enables styling individual contexts via CSS snippets
    • \n
    • Thanks to @phortx for the contribution
    • \n
    \n
  • \n
  • Added mdbase-spec type definition generation

    \n
      \n
    • New setting in Integrations tab to generate mdbase-spec v0.2.0 type definition files (mdbase.yaml and _types/task.md) at the vault root
    • \n
    • Type definitions are derived from TaskNotes settings (statuses, priorities, field mappings, user fields) and regenerated automatically when settings change
    • \n
    • Enables interoperability with other tools that support the mdbase-spec format
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1472) Fixed task dependencies not being stored as wikilinks in frontmatter

    \n
      \n
    • Dependencies now retain their [[wikilink]] format when saved, preventing them from breaking on file rename
    • \n
    • Thanks to @renekalff for reporting
    • \n
    \n
  • \n
  • (#1443) Fixed default status/priority not updating when the referenced custom value is deleted

    \n
      \n
    • Deleting a custom status or priority that was set as the default now resets the default to the first available value
    • \n
    • Thanks to @l-mb for the contribution
    • \n
    \n
  • \n
  • (#1448) Fixed project removals not persisting from the task edit modal

    \n
      \n
    • Removing all projects from a task now correctly clears the projects field
    • \n
    • Different link formats (e.g., markdown links vs wikilinks) no longer cause false change detection
    • \n
    • Thanks to @normenmueller for the contribution
    • \n
    \n
  • \n
  • (#1514), (#1517) Fixed task reminders not syncing to Google Calendar

    \n
      \n
    • Task-specific reminders (both relative and absolute) now sync to Google Calendar
    • \n
    • Previously only the global default reminder setting was used, ignoring per-task reminders
    • \n
    • Thanks to @christenbc for the contribution
    • \n
    \n
  • \n
  • (#1525), (#1531) Fixed subtask status dot not refreshing visually when clicked

    \n
      \n
    • Status dot, checkbox, and card styling now update instantly when cycling status
    • \n
    • Thanks to @christenbc for the contribution
    • \n
    \n
  • \n
  • (#1537) Fixed Google Calendar errors during bulk sync

    \n
      \n
    • Added rate limiting to space out API calls, preventing errors when syncing many tasks at once
    • \n
    • Thanks to @Lorite for the contribution
    • \n
    \n
  • \n
  • (#1515), (#1540) Fixed time loss when setting recurrence and recurrence not clearing from Google Calendar

    \n
      \n
    • Setting recurrence on a task with a scheduled time now preserves the time, preventing Google Calendar events from appearing as all-day
    • \n
    • Clearing recurrence from a task now also removes it from the synced Google Calendar event
    • \n
    • Thanks to @christenbc for the contribution
    • \n
    \n
  • \n
  • (#1428), (#1559) Fixed hierarchical tags with slashes (e.g., #project/sub-project) being truncated in link text

    \n
      \n
    • Tags containing slashes, hyphens, and Unicode characters now render correctly
    • \n
    • Thanks to @normenmueller for the contribution and @ysafonov for reporting
    • \n
    \n
  • \n
  • (#1565) Fixed Google Calendar target calendar dropdown appearing empty after app restart

    \n
      \n
    • The dropdown now re-populates once calendars are fetched during startup
    • \n
    • Thanks to @N-HEDGER for reporting
    • \n
    \n
  • \n
  • (#1567) Fixed inline task card widgets disappearing momentarily

    \n
      \n
    • When the task cache is temporarily cleared (e.g., during Smart Connections processing), the previously-rendered widget is now preserved instead of reverting to a plain wiki link
    • \n
    • Thanks to @scztt for reporting
    • \n
    \n
  • \n
  • (#1568) Fixed deleted tasks not being removed from Google Calendar

    \n
      \n
    • When a task file is deleted outside of TaskNotes (e.g., via Obsidian's file manager), the synced Google Calendar event is now cleaned up automatically
    • \n
    • Thanks to @kmaustral for reporting
    • \n
    \n
  • \n
  • Fixed Integrations tab spacing and layout issues

    \n
      \n
    • Improved positioning of buttons and status indicators across Google Calendar, ICS, and Webhooks sections
    • \n
    \n
  • \n
\n","text":"Added# (#1546) Added sticky kanban column headers that remain visible while scrolling Thanks to @normenmueller for the contribution (#1458) Added CSS color classes to context tags for custom styling Each context tag now receives a unique CSS class based on its name (e.g., context-tag--color-0 through context-tag--color-19) Enables styling individual contexts via CSS snippets Thanks to @phortx for the contribution Added mdbase-spec type definition generation New setting in Integrations tab to generate mdbase-spec v0.2.0 type definition files (mdbase.yaml and _types/task.md) at the vault root Type definitions are derived from TaskNotes settings (statuses, priorities, field mappings, user fields) and regenerated automatically when settings change Enables interoperability with other tools that support the mdbase-spec format Fixed# (#1472) Fixed task dependencies not being stored as wikilinks in frontmatter Dependencies now retain their [[wikilink]] format when saved, preventing them from breaking on file rename Thanks to @renekalff for reporting (#1443) Fixed default status/priority not updating when the referenced custom value is deleted Deleting a custom status or priority that was set as the default now resets the default to the first available value Thanks to @l-mb for the contribution (#1448) Fixed project removals not persisting from the task edit modal Removing all projects from a task now correctly clears the projects field Different link formats (e.g., markdown links vs wikilinks) no longer cause false change detection Thanks to @normenmueller for the contribution (#1514), (#1517) Fixed task reminders not syncing to Google Calendar Task-specific reminders (both relative and absolute) now sync to Google Calendar Previously only the global default reminder setting was used, ignoring per-task reminders Thanks to @christenbc for the contribution (#1525), (#1531) Fixed subtask status dot not refreshing visually when clicked Status dot, checkbox, and card styling now update instantly when cycling status Thanks to @christenbc for the contribution (#1537) Fixed Google Calendar errors during bulk sync Added rate limiting to space out API calls, preventing errors when syncing many tasks at once Thanks to @Lorite for the contribution (#1515), (#1540) Fixed time loss when setting recurrence and recurrence not clearing from Google Calendar Setting recurrence on a task with a scheduled time now preserves the time, preventing Google Calendar events from appearing as all-day Clearing recurrence from a task now also removes it from the synced Google Calendar event Thanks to @christenbc for the contribution (#1428), (#1559) Fixed hierarchical tags with slashes (e.g., #project/sub-project) being truncated in link text Tags containing slashes, hyphens, and Unicode characters now render correctly Thanks to @normenmueller for the contribution and @ysafonov for reporting (#1565) Fixed Google Calendar target calendar dropdown appearing empty after app restart The dropdown now re-populates once calendars are fetched during startup Thanks to @N-HEDGER for reporting (#1567) Fixed inline task card widgets disappearing momentarily When the task cache is temporarily cleared (e.g., during Smart Connections processing), the previously-rendered widget is now preserved instead of reverting to a plain wiki link Thanks to @scztt for reporting (#1568) Fixed deleted tasks not being removed from Google Calendar When a task file is deleted outside of TaskNotes (e.g., via Obsidian's file manager), the synced Google Calendar event is now cleaned up automatically Thanks to @kmaustral for reporting Fixed Integrations tab spacing and layout issues Improved positioning of buttons and status indicators across Google Calendar, ICS, and Webhooks sections"},{"route":"/obsidian/releases/4.3.2/","title":"TaskNotes 4.3.2","description":"(#1520) Tag and Context fields in Edit Task modal now show all available suggestions immediately on focus","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.3.2.md","namespace":"obsidian","relativePath":"releases/4.3.2.md","raw":"# TaskNotes 4.3.2\n\n## Added\n\n- (#1520) Tag and Context fields in Edit Task modal now show all available suggestions immediately on focus\n - Previously required typing at least one character before suggestions appeared\n - Already-selected values are excluded from the suggestion list\n - Thanks to @Glint-Eye for the suggestion\n\n- (#1506) Added setting to configure the default color for new timeblocks\n - New color picker in Settings > Features > Timeblocking\n - Previously hardcoded to indigo; now user-configurable\n - Thanks to @phillipadsmith for the suggestion\n\n## Fixed\n\n- Fixed [mdbase-spec](https://mdbase.dev) type definition generation not triggering when settings change\n\n- (#1456) Fixed inline tasks jumping visually when marked as completed\n - Thanks to @3zra47 for reporting\n\n- (#1364) Fixed auto-stop time tracking not triggering when completing recurring task instances\n - Thanks to @slipstyle for reporting\n\n- (#1465) Fixed all-day events synced to Google Calendar receiving wrong notification time\n - All-day events now use Google Calendar's configured all-day notification defaults instead of a minutes-based reminder\n - Thanks to @Jomo94 for reporting\n\n- (#1470) Fixed cursor showing as default instead of pointer on interactive elements\n - Thanks to @TheFrostedDev for reporting\n\n- (#1491) Fixed boolean property values being quoted as strings in Bases filter generation\n - When using a boolean property (e.g. `tasknote: true`) for task identification, the filter now correctly handles the value\n - Thanks to @denisgorod for reporting\n\n- (#1494) Fixed Kanban swimlane resetting to \"None\" on initial load and after navigation\n - Thanks to @tnguyen2018 for reporting\n\n- (#1555) Fixed \"Folder already exists\" error when creating tasks or converting inline tasks\n - Thanks to @jkune5 for reporting\n\n- (#1532) Fixed expanded task modal buttons being cut off when content exceeds viewport height\n - Thanks to @willfanguy for reporting\n\n- (#1542) Fixed declined and cancelled events from ICS calendar subscriptions appearing in calendar view\n - Thanks to @karenchoe428 for reporting\n\n- (#1556) Fixed completion-based recurring tasks not rescheduling when the recurrence interval is large\n - Thanks to @kazerniel for reporting\n\n- (#1492) Fixed hardcoded \"open\" status leaking into filenames, recurring task displays, and parsing fallbacks\n - Users with custom default statuses (e.g. \"inbox\") no longer see \"open\" where their configured default should appear\n - Recurring tasks now show their actual configured status instead of always displaying \"open\" when not completed\n - Thanks to @macdrifter for reporting\n\n- (#1501) Fixed Google/Microsoft Calendar event colors not showing in agenda/list view\n - Per-event and calendar-level colors now display correctly in the list view, matching grid view behavior\n - Added today indicator highlighting to list view day headers\n - Thanks to @Robubble for the suggestion\n","aliases":["/releases/4.3.2/","/releases/4.3.2/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • (#1520) Tag and Context fields in Edit Task modal now show all available suggestions immediately on focus

    \n
      \n
    • Previously required typing at least one character before suggestions appeared
    • \n
    • Already-selected values are excluded from the suggestion list
    • \n
    • Thanks to @Glint-Eye for the suggestion
    • \n
    \n
  • \n
  • (#1506) Added setting to configure the default color for new timeblocks

    \n
      \n
    • New color picker in Settings > Features > Timeblocking
    • \n
    • Previously hardcoded to indigo; now user-configurable
    • \n
    • Thanks to @phillipadsmith for the suggestion
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • Fixed mdbase-spec type definition generation not triggering when settings change

    \n
  • \n
  • (#1456) Fixed inline tasks jumping visually when marked as completed

    \n
      \n
    • Thanks to @3zra47 for reporting
    • \n
    \n
  • \n
  • (#1364) Fixed auto-stop time tracking not triggering when completing recurring task instances

    \n
      \n
    • Thanks to @slipstyle for reporting
    • \n
    \n
  • \n
  • (#1465) Fixed all-day events synced to Google Calendar receiving wrong notification time

    \n
      \n
    • All-day events now use Google Calendar's configured all-day notification defaults instead of a minutes-based reminder
    • \n
    • Thanks to @Jomo94 for reporting
    • \n
    \n
  • \n
  • (#1470) Fixed cursor showing as default instead of pointer on interactive elements

    \n
      \n
    • Thanks to @TheFrostedDev for reporting
    • \n
    \n
  • \n
  • (#1491) Fixed boolean property values being quoted as strings in Bases filter generation

    \n
      \n
    • When using a boolean property (e.g. tasknote: true) for task identification, the filter now correctly handles the value
    • \n
    • Thanks to @denisgorod for reporting
    • \n
    \n
  • \n
  • (#1494) Fixed Kanban swimlane resetting to "None" on initial load and after navigation

    \n
      \n
    • Thanks to @tnguyen2018 for reporting
    • \n
    \n
  • \n
  • (#1555) Fixed "Folder already exists" error when creating tasks or converting inline tasks

    \n
      \n
    • Thanks to @jkune5 for reporting
    • \n
    \n
  • \n
  • (#1532) Fixed expanded task modal buttons being cut off when content exceeds viewport height

    \n
      \n
    • Thanks to @willfanguy for reporting
    • \n
    \n
  • \n
  • (#1542) Fixed declined and cancelled events from ICS calendar subscriptions appearing in calendar view

    \n
      \n
    • Thanks to @karenchoe428 for reporting
    • \n
    \n
  • \n
  • (#1556) Fixed completion-based recurring tasks not rescheduling when the recurrence interval is large

    \n
      \n
    • Thanks to @kazerniel for reporting
    • \n
    \n
  • \n
  • (#1492) Fixed hardcoded "open" status leaking into filenames, recurring task displays, and parsing fallbacks

    \n
      \n
    • Users with custom default statuses (e.g. "inbox") no longer see "open" where their configured default should appear
    • \n
    • Recurring tasks now show their actual configured status instead of always displaying "open" when not completed
    • \n
    • Thanks to @macdrifter for reporting
    • \n
    \n
  • \n
  • (#1501) Fixed Google/Microsoft Calendar event colors not showing in agenda/list view

    \n
      \n
    • Per-event and calendar-level colors now display correctly in the list view, matching grid view behavior
    • \n
    • Added today indicator highlighting to list view day headers
    • \n
    • Thanks to @Robubble for the suggestion
    • \n
    \n
  • \n
\n","text":"Added# (#1520) Tag and Context fields in Edit Task modal now show all available suggestions immediately on focus Previously required typing at least one character before suggestions appeared Already-selected values are excluded from the suggestion list Thanks to @Glint-Eye for the suggestion (#1506) Added setting to configure the default color for new timeblocks New color picker in Settings > Features > Timeblocking Previously hardcoded to indigo; now user-configurable Thanks to @phillipadsmith for the suggestion Fixed# Fixed mdbase-spec type definition generation not triggering when settings change (#1456) Fixed inline tasks jumping visually when marked as completed Thanks to @3zra47 for reporting (#1364) Fixed auto-stop time tracking not triggering when completing recurring task instances Thanks to @slipstyle for reporting (#1465) Fixed all-day events synced to Google Calendar receiving wrong notification time All-day events now use Google Calendar's configured all-day notification defaults instead of a minutes-based reminder Thanks to @Jomo94 for reporting (#1470) Fixed cursor showing as default instead of pointer on interactive elements Thanks to @TheFrostedDev for reporting (#1491) Fixed boolean property values being quoted as strings in Bases filter generation When using a boolean property (e.g. tasknote: true) for task identification, the filter now correctly handles the value Thanks to @denisgorod for reporting (#1494) Fixed Kanban swimlane resetting to \"None\" on initial load and after navigation Thanks to @tnguyen2018 for reporting (#1555) Fixed \"Folder already exists\" error when creating tasks or converting inline tasks Thanks to @jkune5 for reporting (#1532) Fixed expanded task modal buttons being cut off when content exceeds viewport height Thanks to @willfanguy for reporting (#1542) Fixed declined and cancelled events from ICS calendar subscriptions appearing in calendar view Thanks to @karenchoe428 for reporting (#1556) Fixed completion-based recurring tasks not rescheduling when the recurrence interval is large Thanks to @kazerniel for reporting (#1492) Fixed hardcoded \"open\" status leaking into filenames, recurring task displays, and parsing fallbacks Users with custom default statuses (e.g. \"inbox\") no longer see \"open\" where their configured default should appear Recurring tasks now show their actual configured status instead of always displaying \"open\" when not completed Thanks to @macdrifter for reporting (#1501) Fixed Google/Microsoft Calendar event colors not showing in agenda/list view Per-event and calendar-level colors now display correctly in the list view, matching grid view behavior Added today indicator highlighting to list view day headers Thanks to @Robubble for the suggestion"},{"route":"/obsidian/releases/4.3.3/","title":"TaskNotes 4.3.3","description":"Published mdbase-tasknotes (mtn), a standalone CLI for managing tasks in markdown files via mdbase","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.3.3.md","namespace":"obsidian","relativePath":"releases/4.3.3.md","raw":"# TaskNotes 4.3.3\n\n## Changed\n\n- Published [`mdbase-tasknotes`](https://github.com/callumalpass/mdbase-tasknotes) (`mtn`), a standalone CLI for managing tasks in markdown files via mdbase\n - Works on the same vault and `_types/task.md` schema that TaskNotes generates, without requiring the plugin or HTTP API\n - Preferable over [tasknotes-cli](https://github.com/callumalpass/tasknotes-cli) as a lighter-weight alternative and when Obsidian is not running, on remote machines, or in scripts and CI environments\n - Supports natural language task creation, time tracking, project aggregation, statistics, and an interactive REPL\n\n- Extracted shared natural language parsing logic into the standalone npm package [`tasknotes-nlp-core`](https://github.com/callumalpass/tasknotes-nlp-core)\n - The NLP parser and related language configuration are now shared through this package\n - This keeps behavior consistent between the plugin and CLI tools\n\n## Added\n\n- (#1549) Added setting to reset markdown checkboxes when recurring tasks are completed\n - When enabled, all checked checkboxes (`- [x]`) in the task body are reset to unchecked when a recurring task instance is completed and rescheduled\n - Useful for recurring tasks with subtask checklists that need to be repeated each instance\n - Configurable via Settings > Features > Recurring Tasks > \"Reset checkboxes on recurrence\"\n - Thanks to @phortx for the feature request\n\n- (#1548) Added ability to create calendar events on connected external calendars directly from the calendar view\n - When clicking or dragging to select a time slot, a new \"Create calendar event\" option appears in the context menu\n - Opens a modal to enter event title, description, location, and select which calendar to create on\n - Supports both Google Calendar and Microsoft Calendar providers\n - Thanks to @Robubble for the feature request\n\n- (#1597) Added MCP server for AI agent integration\n - Exposes TaskNotes tools at `/mcp` endpoint, gated behind `enableMCP` setting\n - Supports tasks (CRUD, query, toggle status/archive, parse from text), time tracking, pomodoro, calendar events, and task statistics\n - Thanks to @dstotijn for the contribution\n\n## Fixed\n\n- Fixed generated [mdbase](https://mdbase.dev) type definitions for task dependencies using the wrong field type\n - In `_types/task.md`, `blockedBy[].uid` now uses `type: link` (was `type: string`)\n - Better matches how dependency links are serialized in task frontmatter (`[[...]]`)\n\n- Fixed generated mdbase reminder type definitions to better match TaskNotes reminder data\n - In `_types/task.md`, `reminders[].type` now uses enum values `absolute|relative`\n - `reminders[].relatedTo` now uses enum values `due|scheduled`\n - `reminders[].absoluteTime` now uses `type: datetime` (was `type: string`)\n\n- (#1597) Fixed webhook payloads for time tracking start-with-description containing stale data\n - Thanks to @dstotijn for the fix\n\n- (#1581) Fixed Pomodoro starting break instead of work session after app restart\n - After completing a work session and restarting, pressing Start would incorrectly start a break\n - Now properly resets `nextSessionType` when clearing stale sessions or stopping the timer\n - Thanks to @Sirnii for the detailed bug report and root cause analysis\n\n- (#1577) Fixed Edit Note/Task modal hiding action buttons when content exceeds viewport height\n - Added vertical scroll to modal content area while keeping buttons pinned at bottom\n - Thanks to @hossam-elshabory for reporting and @ivannin for helping in discussion\n\n- (#1600) Fixed kanban view grouping not working when more than 20 views exist\n - The `getGroupByPropertyId()` method had a hardcoded loop limit of 20 iterations\n - Views at index 20 or higher would not be found, causing groupBy to return null\n - Thanks to @IHaveNoShame for reporting\n\n- (#1595) Fixed task modal floating buttons blocking content on mobile\n - Added mobile-specific (`body.is-mobile`) CSS to ensure proper flex layout\n - Button container now stays pinned at bottom without overlapping scrollable content\n - Thanks to @Jomo94 for reporting\n\n- (#1590) Fixed HTTP API not allowing `blockedBy` dependencies when creating tasks\n - Added `blockedBy` field support to `TaskService.createTask()`\n - Updated API documentation with `blockedBy`, `recurrence`, and `reminders` fields\n - Thanks to @hGriff0n for reporting\n\n- (#1582) Fixed recurring tasks not appearing at end of visible calendar range for non-UTC timezones\n - Daily/weekly recurring tasks with times after ~1pm would disappear on the last day of the visible range for users in positive UTC offsets (e.g., UTC+11)\n - Fixed date boundary comparisons in both `generateRecurringInstances()` and `generateRecurringTaskInstances()` to compare dates only, not timestamps\n - Thanks to @benefitbug for reporting\n\n- (#1580) Fixed Google Calendar sync failing after OAuth token expires with unhelpful error message\n - When refresh tokens expire or are revoked (e.g., Google Cloud project in Testing mode, user revoked access), the error message was confusing: \"Failed to refresh google token: Request failed, status 400\"\n - Now detects irrecoverable token errors (`invalid_grant`, `invalid_client`) and automatically disconnects the OAuth connection\n - Shows actionable error message: \"Google Calendar connection expired. Please reconnect in Settings > Integrations.\"\n - Prevents repeated failed refresh attempts and error message spam\n - Thanks to @osxisl for reporting and @Naesue for helping in discussion\n\n- (#1584) Fixed DOMTokenList error when task status values contain spaces\n - Clicking the status ring on a task card threw an error when status contained spaces (e.g., \"In Progress\")\n - Status and priority values are now sanitized before being used as CSS class names\n - Thanks to @omber for reporting\n","aliases":["/releases/4.3.3/","/releases/4.3.3/"],"toc":[{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Changed#

\n
    \n
  • Published mdbase-tasknotes (mtn), a standalone CLI for managing tasks in markdown files via mdbase

    \n
      \n
    • Works on the same vault and _types/task.md schema that TaskNotes generates, without requiring the plugin or HTTP API
    • \n
    • Preferable over tasknotes-cli as a lighter-weight alternative and when Obsidian is not running, on remote machines, or in scripts and CI environments
    • \n
    • Supports natural language task creation, time tracking, project aggregation, statistics, and an interactive REPL
    • \n
    \n
  • \n
  • Extracted shared natural language parsing logic into the standalone npm package tasknotes-nlp-core

    \n
      \n
    • The NLP parser and related language configuration are now shared through this package
    • \n
    • This keeps behavior consistent between the plugin and CLI tools
    • \n
    \n
  • \n
\n

Added#

\n
    \n
  • (#1549) Added setting to reset markdown checkboxes when recurring tasks are completed

    \n
      \n
    • When enabled, all checked checkboxes (- [x]) in the task body are reset to unchecked when a recurring task instance is completed and rescheduled
    • \n
    • Useful for recurring tasks with subtask checklists that need to be repeated each instance
    • \n
    • Configurable via Settings > Features > Recurring Tasks > "Reset checkboxes on recurrence"
    • \n
    • Thanks to @phortx for the feature request
    • \n
    \n
  • \n
  • (#1548) Added ability to create calendar events on connected external calendars directly from the calendar view

    \n
      \n
    • When clicking or dragging to select a time slot, a new "Create calendar event" option appears in the context menu
    • \n
    • Opens a modal to enter event title, description, location, and select which calendar to create on
    • \n
    • Supports both Google Calendar and Microsoft Calendar providers
    • \n
    • Thanks to @Robubble for the feature request
    • \n
    \n
  • \n
  • (#1597) Added MCP server for AI agent integration

    \n
      \n
    • Exposes TaskNotes tools at /mcp endpoint, gated behind enableMCP setting
    • \n
    • Supports tasks (CRUD, query, toggle status/archive, parse from text), time tracking, pomodoro, calendar events, and task statistics
    • \n
    • Thanks to @dstotijn for the contribution
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • Fixed generated mdbase type definitions for task dependencies using the wrong field type

    \n
      \n
    • In _types/task.md, blockedBy[].uid now uses type: link (was type: string)
    • \n
    • Better matches how dependency links are serialized in task frontmatter ([[...]])
    • \n
    \n
  • \n
  • Fixed generated mdbase reminder type definitions to better match TaskNotes reminder data

    \n
      \n
    • In _types/task.md, reminders[].type now uses enum values absolute|relative
    • \n
    • reminders[].relatedTo now uses enum values due|scheduled
    • \n
    • reminders[].absoluteTime now uses type: datetime (was type: string)
    • \n
    \n
  • \n
  • (#1597) Fixed webhook payloads for time tracking start-with-description containing stale data

    \n
      \n
    • Thanks to @dstotijn for the fix
    • \n
    \n
  • \n
  • (#1581) Fixed Pomodoro starting break instead of work session after app restart

    \n
      \n
    • After completing a work session and restarting, pressing Start would incorrectly start a break
    • \n
    • Now properly resets nextSessionType when clearing stale sessions or stopping the timer
    • \n
    • Thanks to @Sirnii for the detailed bug report and root cause analysis
    • \n
    \n
  • \n
  • (#1577) Fixed Edit Note/Task modal hiding action buttons when content exceeds viewport height

    \n
      \n
    • Added vertical scroll to modal content area while keeping buttons pinned at bottom
    • \n
    • Thanks to @hossam-elshabory for reporting and @ivannin for helping in discussion
    • \n
    \n
  • \n
  • (#1600) Fixed kanban view grouping not working when more than 20 views exist

    \n
      \n
    • The getGroupByPropertyId() method had a hardcoded loop limit of 20 iterations
    • \n
    • Views at index 20 or higher would not be found, causing groupBy to return null
    • \n
    • Thanks to @IHaveNoShame for reporting
    • \n
    \n
  • \n
  • (#1595) Fixed task modal floating buttons blocking content on mobile

    \n
      \n
    • Added mobile-specific (body.is-mobile) CSS to ensure proper flex layout
    • \n
    • Button container now stays pinned at bottom without overlapping scrollable content
    • \n
    • Thanks to @Jomo94 for reporting
    • \n
    \n
  • \n
  • (#1590) Fixed HTTP API not allowing blockedBy dependencies when creating tasks

    \n
      \n
    • Added blockedBy field support to TaskService.createTask()
    • \n
    • Updated API documentation with blockedBy, recurrence, and reminders fields
    • \n
    • Thanks to @hGriff0n for reporting
    • \n
    \n
  • \n
  • (#1582) Fixed recurring tasks not appearing at end of visible calendar range for non-UTC timezones

    \n
      \n
    • Daily/weekly recurring tasks with times after ~1pm would disappear on the last day of the visible range for users in positive UTC offsets (e.g., UTC+11)
    • \n
    • Fixed date boundary comparisons in both generateRecurringInstances() and generateRecurringTaskInstances() to compare dates only, not timestamps
    • \n
    • Thanks to @benefitbug for reporting
    • \n
    \n
  • \n
  • (#1580) Fixed Google Calendar sync failing after OAuth token expires with unhelpful error message

    \n
      \n
    • When refresh tokens expire or are revoked (e.g., Google Cloud project in Testing mode, user revoked access), the error message was confusing: "Failed to refresh google token: Request failed, status 400"
    • \n
    • Now detects irrecoverable token errors (invalid_grant, invalid_client) and automatically disconnects the OAuth connection
    • \n
    • Shows actionable error message: "Google Calendar connection expired. Please reconnect in Settings > Integrations."
    • \n
    • Prevents repeated failed refresh attempts and error message spam
    • \n
    • Thanks to @osxisl for reporting and @Naesue for helping in discussion
    • \n
    \n
  • \n
  • (#1584) Fixed DOMTokenList error when task status values contain spaces

    \n
      \n
    • Clicking the status ring on a task card threw an error when status contained spaces (e.g., "In Progress")
    • \n
    • Status and priority values are now sanitized before being used as CSS class names
    • \n
    • Thanks to @omber for reporting
    • \n
    \n
  • \n
\n","text":"Changed# Published mdbase-tasknotes (mtn), a standalone CLI for managing tasks in markdown files via mdbase Works on the same vault and _types/task.md schema that TaskNotes generates, without requiring the plugin or HTTP API Preferable over tasknotes-cli as a lighter-weight alternative and when Obsidian is not running, on remote machines, or in scripts and CI environments Supports natural language task creation, time tracking, project aggregation, statistics, and an interactive REPL Extracted shared natural language parsing logic into the standalone npm package tasknotes-nlp-core The NLP parser and related language configuration are now shared through this package This keeps behavior consistent between the plugin and CLI tools Added# (#1549) Added setting to reset markdown checkboxes when recurring tasks are completed When enabled, all checked checkboxes (- [x]) in the task body are reset to unchecked when a recurring task instance is completed and rescheduled Useful for recurring tasks with subtask checklists that need to be repeated each instance Configurable via Settings > Features > Recurring Tasks > \"Reset checkboxes on recurrence\" Thanks to @phortx for the feature request (#1548) Added ability to create calendar events on connected external calendars directly from the calendar view When clicking or dragging to select a time slot, a new \"Create calendar event\" option appears in the context menu Opens a modal to enter event title, description, location, and select which calendar to create on Supports both Google Calendar and Microsoft Calendar providers Thanks to @Robubble for the feature request (#1597) Added MCP server for AI agent integration Exposes TaskNotes tools at /mcp endpoint, gated behind enableMCP setting Supports tasks (CRUD, query, toggle status/archive, parse from text), time tracking, pomodoro, calendar events, and task statistics Thanks to @dstotijn for the contribution Fixed# Fixed generated mdbase type definitions for task dependencies using the wrong field type In _types/task.md, blockedBy[].uid now uses type: link (was type: string) Better matches how dependency links are serialized in task frontmatter ([[...]]) Fixed generated mdbase reminder type definitions to better match TaskNotes reminder data In _types/task.md, reminders[].type now uses enum values absolute|relative reminders[].relatedTo now uses enum values due|scheduled reminders[].absoluteTime now uses type: datetime (was type: string) (#1597) Fixed webhook payloads for time tracking start-with-description containing stale data Thanks to @dstotijn for the fix (#1581) Fixed Pomodoro starting break instead of work session after app restart After completing a work session and restarting, pressing Start would incorrectly start a break Now properly resets nextSessionType when clearing stale sessions or stopping the timer Thanks to @Sirnii for the detailed bug report and root cause analysis (#1577) Fixed Edit Note/Task modal hiding action buttons when content exceeds viewport height Added vertical scroll to modal content area while keeping buttons pinned at bottom Thanks to @hossam-elshabory for reporting and @ivannin for helping in discussion (#1600) Fixed kanban view grouping not working when more than 20 views exist The getGroupByPropertyId() method had a hardcoded loop limit of 20 iterations Views at index 20 or higher would not be found, causing groupBy to return null Thanks to @IHaveNoShame for reporting (#1595) Fixed task modal floating buttons blocking content on mobile Added mobile-specific (body.is-mobile) CSS to ensure proper flex layout Button container now stays pinned at bottom without overlapping scrollable content Thanks to @Jomo94 for reporting (#1590) Fixed HTTP API not allowing blockedBy dependencies when creating tasks Added blockedBy field support to TaskService.createTask() Updated API documentation with blockedBy, recurrence, and reminders fields Thanks to @hGriff0n for reporting (#1582) Fixed recurring tasks not appearing at end of visible calendar range for non-UTC timezones Daily/weekly recurring tasks with times after ~1pm would disappear on the last day of the visible range for users in positive UTC offsets (e.g., UTC+11) Fixed date boundary comparisons in both generateRecurringInstances() and generateRecurringTaskInstances() to compare dates only, not timestamps Thanks to @benefitbug for reporting (#1580) Fixed Google Calendar sync failing after OAuth token expires with unhelpful error message When refresh tokens expire or are revoked (e.g., Google Cloud project in Testing mode, user revoked access), the error message was confusing: \"Failed to refresh google token: Request failed, status 400\" Now detects irrecoverable token errors (invalid_grant, invalid_client) and automatically disconnects the OAuth connection Shows actionable error message: \"Google Calendar connection expired. Please reconnect in Settings > Integrations.\" Prevents repeated failed refresh attempts and error message spam Thanks to @osxisl for reporting and @Naesue for helping in discussion (#1584) Fixed DOMTokenList error when task status values contain spaces Clicking the status ring on a task card threw an error when status contained spaces (e.g., \"In Progress\") Status and priority values are now sanitized before being used as CSS class names Thanks to @omber for reporting"},{"route":"/obsidian/releases/4.4.0/","title":"TaskNotes 4.4.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.4.0.md","namespace":"obsidian","relativePath":"releases/4.4.0.md","raw":"# TaskNotes 4.4.0\n\n## Added\n\n- [Mdbase](https://mdbase.dev) type generation now includes `tn_role` annotations so external tools can identify each field's role even when frontmatter names are customized\n- (#1618) Mdbase type matching now follows your task identification settings (tag or frontmatter property), with fallback to tag matching when needed\n - Thanks to @jimbo108108 for reporting\n- Mdbase type status fields now include `tn_completed_values` so external tools can reliably identify which status values count as completed\n- (#1576) Added an optional `Checklist Progress` task-card property that renders a compact progress bar and `completed/total` count from top-level markdown checkboxes\n - Uses metadata cache list items and excludes nested checklist entries so progress reflects top-level task steps\n - In Bases views, map `tasks` (`file.tasks`) to `Checklist Progress`\n - Existing `.base` files need `file.tasks` added to the view `order` YAML manually\n - Newly generated `.base` templates now include `file.tasks` in view `order` by default\n - Thanks to @phortx for opening #1576 and for the earlier implementation PR, and @piyushaswani55 for feedback in the issue discussion\n\n## Changed\n\n- Mdbase type generation no longer overwrites `mdbase.yaml` if the file already exists, preserving user customisations\n- Webhooks now fire consistently regardless of whether updates come from the UI, HTTP API, or MCP\n- Webhook runtime state now syncs automatically when plugin settings change\n- Shared HTTP response/body parsing utilities are now consolidated in a dedicated `httpUtils` module\n- Release notes now include a reminder on every release page that default generated `.base` template changes never overwrite existing user `.base` files, and that users can regenerate templates from Settings to pick up updates\n\n## Fixed\n\n- (#1608) Fixed task title frontmatter being removed when `storeTitleInFilename` is enabled\n - `title` is now retained in frontmatter while filename derivation from title remains unchanged\n - Thanks to @victoraraujo105 for the PR\n- (#1602) Fixed time tracking statistics showing incorrect or zero values for Today/Week/Month due to UTC-anchored date range boundaries in Stats View\n - Updated range calculations to use local calendar-day boundaries consistently\n- (#1602) Fixed inconsistent `timeEntries` timestamp formats across create/edit/drag/resize flows\n - Time entry timestamps are now written in canonical UTC ISO format (`toISOString()` with `Z`) across all write paths\n- (#1602) Fixed denormalized `timeEntries.duration` drift after edits\n - Time tracking calculations now derive duration from `startTime`/`endTime`\n - Time entry save paths now strip legacy `duration` values instead of persisting them\n - Thanks to @dy66 for opening #1602\n","aliases":["/releases/4.4.0/","/releases/4.4.0/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • Mdbase type generation now includes tn_role annotations so external tools can identify each field's role even when frontmatter names are customized
  • \n
  • (#1618) Mdbase type matching now follows your task identification settings (tag or frontmatter property), with fallback to tag matching when needed
      \n
    • Thanks to @jimbo108108 for reporting
    • \n
    \n
  • \n
  • Mdbase type status fields now include tn_completed_values so external tools can reliably identify which status values count as completed
  • \n
  • (#1576) Added an optional Checklist Progress task-card property that renders a compact progress bar and completed/total count from top-level markdown checkboxes
      \n
    • Uses metadata cache list items and excludes nested checklist entries so progress reflects top-level task steps
    • \n
    • In Bases views, map tasks (file.tasks) to Checklist Progress
    • \n
    • Existing .base files need file.tasks added to the view order YAML manually
    • \n
    • Newly generated .base templates now include file.tasks in view order by default
    • \n
    • Thanks to @phortx for opening #1576 and for the earlier implementation PR, and @piyushaswani55 for feedback in the issue discussion
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Mdbase type generation no longer overwrites mdbase.yaml if the file already exists, preserving user customisations
  • \n
  • Webhooks now fire consistently regardless of whether updates come from the UI, HTTP API, or MCP
  • \n
  • Webhook runtime state now syncs automatically when plugin settings change
  • \n
  • Shared HTTP response/body parsing utilities are now consolidated in a dedicated httpUtils module
  • \n
  • Release notes now include a reminder on every release page that default generated .base template changes never overwrite existing user .base files, and that users can regenerate templates from Settings to pick up updates
  • \n
\n

Fixed#

\n
    \n
  • (#1608) Fixed task title frontmatter being removed when storeTitleInFilename is enabled
      \n
    • title is now retained in frontmatter while filename derivation from title remains unchanged
    • \n
    • Thanks to @victoraraujo105 for the PR
    • \n
    \n
  • \n
  • (#1602) Fixed time tracking statistics showing incorrect or zero values for Today/Week/Month due to UTC-anchored date range boundaries in Stats View
      \n
    • Updated range calculations to use local calendar-day boundaries consistently
    • \n
    \n
  • \n
  • (#1602) Fixed inconsistent timeEntries timestamp formats across create/edit/drag/resize flows
      \n
    • Time entry timestamps are now written in canonical UTC ISO format (toISOString() with Z) across all write paths
    • \n
    \n
  • \n
  • (#1602) Fixed denormalized timeEntries.duration drift after edits
      \n
    • Time tracking calculations now derive duration from startTime/endTime
    • \n
    • Time entry save paths now strip legacy duration values instead of persisting them
    • \n
    • Thanks to @dy66 for opening #1602
    • \n
    \n
  • \n
\n","text":"Added# Mdbase type generation now includes tn_role annotations so external tools can identify each field's role even when frontmatter names are customized (#1618) Mdbase type matching now follows your task identification settings (tag or frontmatter property), with fallback to tag matching when needed Thanks to @jimbo108108 for reporting Mdbase type status fields now include tn_completed_values so external tools can reliably identify which status values count as completed (#1576) Added an optional Checklist Progress task-card property that renders a compact progress bar and completed/total count from top-level markdown checkboxes Uses metadata cache list items and excludes nested checklist entries so progress reflects top-level task steps In Bases views, map tasks (file.tasks) to Checklist Progress Existing .base files need file.tasks added to the view order YAML manually Newly generated .base templates now include file.tasks in view order by default Thanks to @phortx for opening #1576 and for the earlier implementation PR, and @piyushaswani55 for feedback in the issue discussion Changed# Mdbase type generation no longer overwrites mdbase.yaml if the file already exists, preserving user customisations Webhooks now fire consistently regardless of whether updates come from the UI, HTTP API, or MCP Webhook runtime state now syncs automatically when plugin settings change Shared HTTP response/body parsing utilities are now consolidated in a dedicated httpUtils module Release notes now include a reminder on every release page that default generated .base template changes never overwrite existing user .base files, and that users can regenerate templates from Settings to pick up updates Fixed# (#1608) Fixed task title frontmatter being removed when storeTitleInFilename is enabled title is now retained in frontmatter while filename derivation from title remains unchanged Thanks to @victoraraujo105 for the PR (#1602) Fixed time tracking statistics showing incorrect or zero values for Today/Week/Month due to UTC-anchored date range boundaries in Stats View Updated range calculations to use local calendar-day boundaries consistently (#1602) Fixed inconsistent timeEntries timestamp formats across create/edit/drag/resize flows Time entry timestamps are now written in canonical UTC ISO format (toISOString() with Z) across all write paths (#1602) Fixed denormalized timeEntries.duration drift after edits Time tracking calculations now derive duration from startTime/endTime Time entry save paths now strip legacy duration values instead of persisting them Thanks to @dy66 for opening #1602"},{"route":"/obsidian/releases/4.5.0/","title":"TaskNotes 4.5.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.5.0.md","namespace":"obsidian","relativePath":"releases/4.5.0.md","raw":"# TaskNotes 4.5.0\n\n## Fixed\n\n- (#1652) Fixed API, MCP, and NLP task creation so it respects your configured filename format when title storage in filenames is disabled\n - Thanks to @36mimu36 for reporting, and @rafavital and @warm-july for follow-up discussion and reports\n- (#1601, #1709) Fixed reading-mode relationship widgets sometimes rendering multiple times during startup\n - Applied the same protection to task cards so overlapping refreshes are coalesced there too\n - Thanks to @wealthychef1 and @CarlJohnson99 for reporting, and @benmartinek for confirming the behavior\n- (#1713) Fixed ICS export so date-only scheduled tasks are written as all-day events instead of midnight events\n - Thanks to @bepolymathe for the request and interoperability details\n- (#267, #948, #1682, #1717, #1725) Fixed expanded subtasks and dependency cards in Bases Task List and Kanban views so related items can inherit the current view's filters instead of always showing every linked task\n - Added a per-view \"Expanded relationships\" option so you can switch between inherited filters and showing all related tasks\n - Thanks to @mdbraber, @GardarikanetS, @Glint-Eye, @prepare4robots, and @robmcphers0n for the original reports and feature requests, and @marblebyte for follow-up discussion\n- Improved custom view and search-pane activation when reopening deferred tabs\n- (#1720) Fixed Bases Task List cards showing icon tokens such as `clock` instead of readable date-like values, and fixed property labels to use Bases display names instead of raw property IDs\n - Thanks to @Sirnii for reporting\n- (#1633) Fixed interactive task-card labels and ribbon labels so Bases-backed cards use translations and configured display names instead of hardcoded English or raw property IDs\n - Thanks to @Sarryaz for reporting\n- (#1651) Fixed date `is` query filtering so date-only searches also match timed `scheduled` and `due` values during prefiltering\n - Thanks to @36mimu36 for reporting\n- (#1644) Fixed generated default task views so recurring tasks without a `complete_instances` property still appear as incomplete where appropriate\n - Thanks to @bkennedy-improving for reporting, and @SandroK for follow-up discussion on related default-view behavior\n- (#1513, #1686) Fixed a calendar issue where creating or editing events and timeblocks could reset the visible date back to today\n - In-place calendar recreation now preserves the visible date unless you explicitly navigate elsewhere\n - Thanks to @owenoxen for opening #1513, and @Lorite for opening #1686 and contributing the fix\n- Fixed documentation deployment CI failures caused by `docs-builder/src/js/main.js` being excluded by a broad `.gitignore` rule\n- Reduced background calendar-sync overhead when persisting sync tokens\n- Prevented duplicate auto-stop time-tracking listeners from accumulating after settings reloads\n- Fixed a settings-lifecycle issue that could accumulate calendar update callbacks while the Integrations tab is repeatedly opened\n- (#1630) Fixed TaskNote inline task cards ignoring centered \"Readable line length\" layout in the Minimal theme\n - Thanks to @martin-forge for reporting\n- Fixed a broken docs cross-reference from Property Types Reference to Task Properties settings\n- Fixed docs site links so internal Markdown links resolve to app routes instead of broken `.md` paths\n- Fixed docs release-note links by building Markdown pages even when they are not listed directly in the sidebar\n\n## Added\n\n- (#1704) Added an option to widen the current day column in multi-day calendar time-grid views\n - You can control the width multiplier and choose whether it applies to week view, custom multi-day view, or both\n - Thanks to @dictionarymouse for the feature request\n- Added TaskNotes Obsidian CLI commands for task creation, time tracking, and Pomodoro control\n - Includes shared NLP-to-task conversion across the CLI, modal, and API capture flows, plus new user documentation for the built-in CLI commands\n- (#1716) Added roomier subtask and dependency cards inside the task modal while keeping the task options menu available\n - Thanks to @hokfujow for the feature request\n- (#1619, #386, #621) Added drag-to-reorder for Kanban and Task List views\n - Supports grouped Task List moves, manual ordering via the `tasknotes_manual_order` property, and improved drag/drop behavior for swimlanes, filtered views, and interactive task controls\n - To use it, sort the view by the Manual Order field (`tasknotes_manual_order` by default), or regenerate the built-in `.base` templates from **Settings → TaskNotes → General → Create Default Files**\n - Thanks to @ac8318740 for the original contribution in PR #1619, @iholston and @dsebastien for opening #386 and #621, and @mdbraber, @elvarb, @LucidToday, @craziedde, @kmaustral, @SKIERZZ, @sookochoff, and @kanzaki1201 for follow-up discussion and testing across the linked issues and PR\n- Added a standalone [TaskNotes Specification](https://github.com/callumalpass/tasknotes-spec) repo and docs section covering the data model, field mapping, recurrence behavior, validation rules, and conformance tests\n- Added [tasknotes-tui](https://github.com/callumalpass/tasknotes-tui), a terminal UI for working with TaskNotes vaults\n - Includes keyboard-driven views, date navigation, time tracking, recurring task support, and a command palette\n\n## Changed\n\n- Refactored several internal modules to reduce coupling and make maintenance safer\n- Updated generated `_types/task.md` output so `dateCreated` and `dateModified` include generated timestamp values, and `recurrence_anchor` defaults to `scheduled`\n- Cleaned up API, webhook, NLP, privacy, settings, and view documentation for clarity and accuracy\n- Expanded Task List and Kanban documentation for drag-to-reorder, including manual-order sorting, grouped and swimlane scope, and filtered-view limitations\n","aliases":["/releases/4.5.0/","/releases/4.5.0/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"}],"html":"

Fixed#

\n
    \n
  • (#1652) Fixed API, MCP, and NLP task creation so it respects your configured filename format when title storage in filenames is disabled
      \n
    • Thanks to @36mimu36 for reporting, and @rafavital and @warm-july for follow-up discussion and reports
    • \n
    \n
  • \n
  • (#1601, #1709) Fixed reading-mode relationship widgets sometimes rendering multiple times during startup
      \n
    • Applied the same protection to task cards so overlapping refreshes are coalesced there too
    • \n
    • Thanks to @wealthychef1 and @CarlJohnson99 for reporting, and @benmartinek for confirming the behavior
    • \n
    \n
  • \n
  • (#1713) Fixed ICS export so date-only scheduled tasks are written as all-day events instead of midnight events
      \n
    • Thanks to @bepolymathe for the request and interoperability details
    • \n
    \n
  • \n
  • (#267, #948, #1682, #1717, #1725) Fixed expanded subtasks and dependency cards in Bases Task List and Kanban views so related items can inherit the current view's filters instead of always showing every linked task
      \n
    • Added a per-view "Expanded relationships" option so you can switch between inherited filters and showing all related tasks
    • \n
    • Thanks to @mdbraber, @GardarikanetS, @Glint-Eye, @prepare4robots, and @robmcphers0n for the original reports and feature requests, and @marblebyte for follow-up discussion
    • \n
    \n
  • \n
  • Improved custom view and search-pane activation when reopening deferred tabs
  • \n
  • (#1720) Fixed Bases Task List cards showing icon tokens such as clock instead of readable date-like values, and fixed property labels to use Bases display names instead of raw property IDs
      \n
    • Thanks to @Sirnii for reporting
    • \n
    \n
  • \n
  • (#1633) Fixed interactive task-card labels and ribbon labels so Bases-backed cards use translations and configured display names instead of hardcoded English or raw property IDs
      \n
    • Thanks to @Sarryaz for reporting
    • \n
    \n
  • \n
  • (#1651) Fixed date is query filtering so date-only searches also match timed scheduled and due values during prefiltering
      \n
    • Thanks to @36mimu36 for reporting
    • \n
    \n
  • \n
  • (#1644) Fixed generated default task views so recurring tasks without a complete_instances property still appear as incomplete where appropriate
      \n
    • Thanks to @bkennedy-improving for reporting, and @SandroK for follow-up discussion on related default-view behavior
    • \n
    \n
  • \n
  • (#1513, #1686) Fixed a calendar issue where creating or editing events and timeblocks could reset the visible date back to today
      \n
    • In-place calendar recreation now preserves the visible date unless you explicitly navigate elsewhere
    • \n
    • Thanks to @owenoxen for opening #1513, and @Lorite for opening #1686 and contributing the fix
    • \n
    \n
  • \n
  • Fixed documentation deployment CI failures caused by docs-builder/src/js/main.js being excluded by a broad .gitignore rule
  • \n
  • Reduced background calendar-sync overhead when persisting sync tokens
  • \n
  • Prevented duplicate auto-stop time-tracking listeners from accumulating after settings reloads
  • \n
  • Fixed a settings-lifecycle issue that could accumulate calendar update callbacks while the Integrations tab is repeatedly opened
  • \n
  • (#1630) Fixed TaskNote inline task cards ignoring centered "Readable line length" layout in the Minimal theme
      \n
    • Thanks to @martin-forge for reporting
    • \n
    \n
  • \n
  • Fixed a broken docs cross-reference from Property Types Reference to Task Properties settings
  • \n
  • Fixed docs site links so internal Markdown links resolve to app routes instead of broken .md paths
  • \n
  • Fixed docs release-note links by building Markdown pages even when they are not listed directly in the sidebar
  • \n
\n

Added#

\n
    \n
  • (#1704) Added an option to widen the current day column in multi-day calendar time-grid views
      \n
    • You can control the width multiplier and choose whether it applies to week view, custom multi-day view, or both
    • \n
    • Thanks to @dictionarymouse for the feature request
    • \n
    \n
  • \n
  • Added TaskNotes Obsidian CLI commands for task creation, time tracking, and Pomodoro control
      \n
    • Includes shared NLP-to-task conversion across the CLI, modal, and API capture flows, plus new user documentation for the built-in CLI commands
    • \n
    \n
  • \n
  • (#1716) Added roomier subtask and dependency cards inside the task modal while keeping the task options menu available
      \n
    • Thanks to @hokfujow for the feature request
    • \n
    \n
  • \n
  • (#1619, #386, #621) Added drag-to-reorder for Kanban and Task List views
      \n
    • Supports grouped Task List moves, manual ordering via the tasknotes_manual_order property, and improved drag/drop behavior for swimlanes, filtered views, and interactive task controls
    • \n
    • To use it, sort the view by the Manual Order field (tasknotes_manual_order by default), or regenerate the built-in .base templates from Settings → TaskNotes → General → Create Default Files
    • \n
    • Thanks to @ac8318740 for the original contribution in PR #1619, @iholston and @dsebastien for opening #386 and #621, and @mdbraber, @elvarb, @LucidToday, @craziedde, @kmaustral, @SKIERZZ, @sookochoff, and @kanzaki1201 for follow-up discussion and testing across the linked issues and PR
    • \n
    \n
  • \n
  • Added a standalone TaskNotes Specification repo and docs section covering the data model, field mapping, recurrence behavior, validation rules, and conformance tests
  • \n
  • Added tasknotes-tui, a terminal UI for working with TaskNotes vaults
      \n
    • Includes keyboard-driven views, date navigation, time tracking, recurring task support, and a command palette
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Refactored several internal modules to reduce coupling and make maintenance safer
  • \n
  • Updated generated _types/task.md output so dateCreated and dateModified include generated timestamp values, and recurrence_anchor defaults to scheduled
  • \n
  • Cleaned up API, webhook, NLP, privacy, settings, and view documentation for clarity and accuracy
  • \n
  • Expanded Task List and Kanban documentation for drag-to-reorder, including manual-order sorting, grouped and swimlane scope, and filtered-view limitations
  • \n
\n","text":"Fixed# (#1652) Fixed API, MCP, and NLP task creation so it respects your configured filename format when title storage in filenames is disabled Thanks to @36mimu36 for reporting, and @rafavital and @warm-july for follow-up discussion and reports (#1601, #1709) Fixed reading-mode relationship widgets sometimes rendering multiple times during startup Applied the same protection to task cards so overlapping refreshes are coalesced there too Thanks to @wealthychef1 and @CarlJohnson99 for reporting, and @benmartinek for confirming the behavior (#1713) Fixed ICS export so date-only scheduled tasks are written as all-day events instead of midnight events Thanks to @bepolymathe for the request and interoperability details (#267, #948, #1682, #1717, #1725) Fixed expanded subtasks and dependency cards in Bases Task List and Kanban views so related items can inherit the current view's filters instead of always showing every linked task Added a per-view \"Expanded relationships\" option so you can switch between inherited filters and showing all related tasks Thanks to @mdbraber, @GardarikanetS, @Glint-Eye, @prepare4robots, and @robmcphers0n for the original reports and feature requests, and @marblebyte for follow-up discussion Improved custom view and search-pane activation when reopening deferred tabs (#1720) Fixed Bases Task List cards showing icon tokens such as clock instead of readable date-like values, and fixed property labels to use Bases display names instead of raw property IDs Thanks to @Sirnii for reporting (#1633) Fixed interactive task-card labels and ribbon labels so Bases-backed cards use translations and configured display names instead of hardcoded English or raw property IDs Thanks to @Sarryaz for reporting (#1651) Fixed date is query filtering so date-only searches also match timed scheduled and due values during prefiltering Thanks to @36mimu36 for reporting (#1644) Fixed generated default task views so recurring tasks without a complete_instances property still appear as incomplete where appropriate Thanks to @bkennedy-improving for reporting, and @SandroK for follow-up discussion on related default-view behavior (#1513, #1686) Fixed a calendar issue where creating or editing events and timeblocks could reset the visible date back to today In-place calendar recreation now preserves the visible date unless you explicitly navigate elsewhere Thanks to @owenoxen for opening #1513, and @Lorite for opening #1686 and contributing the fix Fixed documentation deployment CI failures caused by docs-builder/src/js/main.js being excluded by a broad .gitignore rule Reduced background calendar-sync overhead when persisting sync tokens Prevented duplicate auto-stop time-tracking listeners from accumulating after settings reloads Fixed a settings-lifecycle issue that could accumulate calendar update callbacks while the Integrations tab is repeatedly opened (#1630) Fixed TaskNote inline task cards ignoring centered \"Readable line length\" layout in the Minimal theme Thanks to @martin-forge for reporting Fixed a broken docs cross-reference from Property Types Reference to Task Properties settings Fixed docs site links so internal Markdown links resolve to app routes instead of broken .md paths Fixed docs release-note links by building Markdown pages even when they are not listed directly in the sidebar Added# (#1704) Added an option to widen the current day column in multi-day calendar time-grid views You can control the width multiplier and choose whether it applies to week view, custom multi-day view, or both Thanks to @dictionarymouse for the feature request Added TaskNotes Obsidian CLI commands for task creation, time tracking, and Pomodoro control Includes shared NLP-to-task conversion across the CLI, modal, and API capture flows, plus new user documentation for the built-in CLI commands (#1716) Added roomier subtask and dependency cards inside the task modal while keeping the task options menu available Thanks to @hokfujow for the feature request (#1619, #386, #621) Added drag-to-reorder for Kanban and Task List views Supports grouped Task List moves, manual ordering via the tasknotes_manual_order property, and improved drag/drop behavior for swimlanes, filtered views, and interactive task controls To use it, sort the view by the Manual Order field (tasknotes_manual_order by default), or regenerate the built-in .base templates from Settings → TaskNotes → General → Create Default Files Thanks to @ac8318740 for the original contribution in PR #1619, @iholston and @dsebastien for opening #386 and #621, and @mdbraber, @elvarb, @LucidToday, @craziedde, @kmaustral, @SKIERZZ, @sookochoff, and @kanzaki1201 for follow-up discussion and testing across the linked issues and PR Added a standalone TaskNotes Specification repo and docs section covering the data model, field mapping, recurrence behavior, validation rules, and conformance tests Added tasknotes-tui, a terminal UI for working with TaskNotes vaults Includes keyboard-driven views, date navigation, time tracking, recurring task support, and a command palette Changed# Refactored several internal modules to reduce coupling and make maintenance safer Updated generated _types/task.md output so dateCreated and dateModified include generated timestamp values, and recurrence_anchor defaults to scheduled Cleaned up API, webhook, NLP, privacy, settings, and view documentation for clarity and accuracy Expanded Task List and Kanban documentation for drag-to-reorder, including manual-order sorting, grouped and swimlane scope, and filtered-view limitations"},{"route":"/obsidian/releases/4.5.1/","title":"TaskNotes 4.5.1","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.5.1.md","namespace":"obsidian","relativePath":"releases/4.5.1.md","raw":"# TaskNotes 4.5.1\n\n## Fixed\n\n- (#1672) Fixed custom date ranges in the MCP time summary tool so `from` and `to` dates work as expected\n - Thanks to @pib for the fix\n- (#1742) Fixed calendar week and day views so the time scale stays aligned on the left instead of drifting inward\n - Thanks to @ysafonov for the report and screenshot\n","aliases":["/releases/4.5.1/","/releases/4.5.1/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Fixed#

\n
    \n
  • (#1672) Fixed custom date ranges in the MCP time summary tool so from and to dates work as expected
      \n
    • Thanks to @pib for the fix
    • \n
    \n
  • \n
  • (#1742) Fixed calendar week and day views so the time scale stays aligned on the left instead of drifting inward
      \n
    • Thanks to @ysafonov for the report and screenshot
    • \n
    \n
  • \n
\n","text":"Fixed# (#1672) Fixed custom date ranges in the MCP time summary tool so from and to dates work as expected Thanks to @pib for the fix (#1742) Fixed calendar week and day views so the time scale stays aligned on the left instead of drifting inward Thanks to @ysafonov for the report and screenshot"},{"route":"/obsidian/releases/4.5.2/","title":"TaskNotes 4.5.2","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.5.2.md","namespace":"obsidian","relativePath":"releases/4.5.2.md","raw":"# TaskNotes 4.5.2\n\n## Added\n\n- (#1342, #1793) Added native tag autocomplete to time entry descriptions by using the embedded markdown editor in the time entry editor modal.\n - Thanks to @fastrick for the request and @renatomen for the PR.\n- (#1756, #1798) Added HTTP API support for configured custom user fields so task responses include them and create/update requests can round-trip their values.\n - Thanks to @Treygec for the request and PR.\n- (#1777) Added a Modal Fields setting to choose whether Tab/Shift+Tab move focus out of the task details editor or use the markdown editor's indentation behavior.\n - Thanks to @P-Sc for the PR.\n\n## Changed\n\n- Updated the Obsidian API dependency to 1.12.3 and switched the Bases integration to the official API type declarations.\n- Bases task cards and property-event cards now render metadata values through Obsidian's native Bases value renderer so links, dates, lists, icons, and formula values display more faithfully.\n\n## Fixed\n\n- (#1778) Fixed MCP initialize requests using newer protocol versions such as `2025-11-25` failing instead of negotiating down to TaskNotes' supported MCP version.\n - Thanks to @SakulaPor for reporting.\n- (#1781) Fixed duplicate metadata properties on Bases task cards when bare and `note.`-prefixed property IDs map to the same TaskNotes field.\n - Thanks to @loukandr for reporting and tracing the issue.\n- (#1787) Removed the \"(click to change)\" helper text from recurrence tooltips on task cards.\n - Thanks to @kazerniel for reporting.\n- (#1828) Fixed subtask creation from a task card dropping the parent task project when natural-language input also adds projects.\n - Thanks to @prepare4robots for reporting.\n- (#1786) Fixed TaskNotes task cards and relationships/subtasks widgets appearing inside embedded task-note heading or block sections.\n - Skips note-level widget injection in detached or embedded Markdown editor contexts used by plugins such as Block Link Plus.\n - Thanks to @3zra47 for reporting.\n- (#1815) Fixed the Priority property settings so the NLP trigger character field is visible and editable even when priority NLP parsing is disabled.\n - Thanks to @spiv for reporting.\n- (#1035) Fixed the task modal title field causing the modal to jump to the bottom when focused on iPhone.\n - Thanks to @3zra47 for reporting and following up.\n- (#1045) Fixed inline linked recurring tasks keeping the previous day's completed state after the calendar day changes.\n - Thanks to @3zra47 for reporting and following up.\n- (#1788) Fixed Task List subgroup headers and cards rendering without clear indentation.\n - Thanks to @renatomen for the PR.\n- (#1810) Updated Japanese Kanban terminology to use the more natural katakana spelling.\n - Thanks to @sigma7863 for the PR.\n- (#1633) Fixed Bases task cards using fallback labels instead of Bases display names for mapped task fields and file properties.\n - Thanks to @Sarryaz for reporting the Bases task card i18n and field-mapping issue.\n- (#884) Fixed untranslated strings and English placeholder examples across non-English interface translations.\n - Thanks to @berzernberg for reporting Russian translation gaps.\n- (#1765, #1769) Fixed auto-archived tasks leaving stale Google Calendar events when cleanup runs before calendar sync is ready or after the task moves into the archive folder.\n - Thanks to @martin-forge for reporting and the PR.\n- (#1764) Fixed Google Calendar sync using stale task metadata after rapid task updates, and fixed late recurring completions/skips recording the completion day instead of the scheduled occurrence date.\n - Thanks to @martin-forge for the PR and to @jpmoo for reporting the recurring completion issues.\n- (#1782) Fixed CI test runs resolving the NLP parser package from a local sibling checkout instead of the published dependency.\n - Thanks to @martin-forge for reporting.\n- Published [`mdbase-tasknotes`](https://github.com/callumalpass/mdbase-tasknotes) 0.1.3 with compatibility fixes for TaskNotes-generated mdbase schemas.\n - Includes clearer create-path diagnostics, natural-language `mtn list --due` filters, timer log datetime filters, home-directory path expansion, project wikilink preservation, and correct `mtn --version` reporting.\n - Thanks to @tparsons9, @anomatomato, @npondel, @plashal, and @waspeer for the reports and PR.\n- (#1667) Fixed NLP scheduled-date parsing so standalone `scheduled` and `start` triggers can set scheduled dates alongside due dates.\n - Thanks to @hokfujow for reporting and @UniqueClone for the NLP core PR.\n- Fixed NLP parser title cleanup for explicit date triggers and Japanese/Chinese priority phrases.\n- (#1658) Fixed Pomodoro stats date bucketing for sessions near local midnight.\n - Pomodoro session stats now compare the recorded session calendar date against UTC-anchored target days without shifting through UTC or the reader's current timezone.\n - Pomodoro daily-note storage now writes sessions to the daily note matching the recorded session date.\n - Thanks to @ewgdg for reporting, @AntonIlinykh and @dkchacha for follow-up discussion, and @ITblacksheep for PR #1758.\n- (#1813) Fixed Pomodoro timer UI stalls caused by refreshing session statistics on every timer tick.\n - Pomodoro stats now refresh on initial render and session completion instead of once per second.\n - Pomodoro daily-note stats now read the relevant date/range instead of routing through all history.\n - Native Pomodoro notifications now respect the notification setting and granted permission before showing.\n - Thanks to @Szu-Szu for reporting and @its-thex for confirming.\n- (#1744) Fixed Bases Task List views so changing the per-view `Expanded relationships` option takes effect on re-render.\n - Restores the expected `show-all` behavior for setups that hide subtasks at the top level with `note.projects.isEmpty()`.\n - Thanks to @minol-dev for reporting, @Glint-Eye for follow-up discussion, and @stanley-910 for PR #1792 exploring the related standalone-subtask workflow.\n- Fixed tag clicks in task cards opening the task edit modal in addition to the tag search panel, and kept rendered tag metadata on a single row inside task cards.\n","aliases":["/releases/4.5.2/","/releases/4.5.2/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • (#1342, #1793) Added native tag autocomplete to time entry descriptions by using the embedded markdown editor in the time entry editor modal.
      \n
    • Thanks to @fastrick for the request and @renatomen for the PR.
    • \n
    \n
  • \n
  • (#1756, #1798) Added HTTP API support for configured custom user fields so task responses include them and create/update requests can round-trip their values.
      \n
    • Thanks to @Treygec for the request and PR.
    • \n
    \n
  • \n
  • (#1777) Added a Modal Fields setting to choose whether Tab/Shift+Tab move focus out of the task details editor or use the markdown editor's indentation behavior.
      \n
    • Thanks to @P-Sc for the PR.
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Updated the Obsidian API dependency to 1.12.3 and switched the Bases integration to the official API type declarations.
  • \n
  • Bases task cards and property-event cards now render metadata values through Obsidian's native Bases value renderer so links, dates, lists, icons, and formula values display more faithfully.
  • \n
\n

Fixed#

\n
    \n
  • (#1778) Fixed MCP initialize requests using newer protocol versions such as 2025-11-25 failing instead of negotiating down to TaskNotes' supported MCP version.
      \n
    • Thanks to @SakulaPor for reporting.
    • \n
    \n
  • \n
  • (#1781) Fixed duplicate metadata properties on Bases task cards when bare and note.-prefixed property IDs map to the same TaskNotes field.
      \n
    • Thanks to @loukandr for reporting and tracing the issue.
    • \n
    \n
  • \n
  • (#1787) Removed the "(click to change)" helper text from recurrence tooltips on task cards.
      \n
    • Thanks to @kazerniel for reporting.
    • \n
    \n
  • \n
  • (#1828) Fixed subtask creation from a task card dropping the parent task project when natural-language input also adds projects.
      \n
    • Thanks to @prepare4robots for reporting.
    • \n
    \n
  • \n
  • (#1786) Fixed TaskNotes task cards and relationships/subtasks widgets appearing inside embedded task-note heading or block sections.
      \n
    • Skips note-level widget injection in detached or embedded Markdown editor contexts used by plugins such as Block Link Plus.
    • \n
    • Thanks to @3zra47 for reporting.
    • \n
    \n
  • \n
  • (#1815) Fixed the Priority property settings so the NLP trigger character field is visible and editable even when priority NLP parsing is disabled.
      \n
    • Thanks to @spiv for reporting.
    • \n
    \n
  • \n
  • (#1035) Fixed the task modal title field causing the modal to jump to the bottom when focused on iPhone.
      \n
    • Thanks to @3zra47 for reporting and following up.
    • \n
    \n
  • \n
  • (#1045) Fixed inline linked recurring tasks keeping the previous day's completed state after the calendar day changes.
      \n
    • Thanks to @3zra47 for reporting and following up.
    • \n
    \n
  • \n
  • (#1788) Fixed Task List subgroup headers and cards rendering without clear indentation.
      \n
    • Thanks to @renatomen for the PR.
    • \n
    \n
  • \n
  • (#1810) Updated Japanese Kanban terminology to use the more natural katakana spelling.
      \n
    • Thanks to @sigma7863 for the PR.
    • \n
    \n
  • \n
  • (#1633) Fixed Bases task cards using fallback labels instead of Bases display names for mapped task fields and file properties.
      \n
    • Thanks to @Sarryaz for reporting the Bases task card i18n and field-mapping issue.
    • \n
    \n
  • \n
  • (#884) Fixed untranslated strings and English placeholder examples across non-English interface translations.
      \n
    • Thanks to @berzernberg for reporting Russian translation gaps.
    • \n
    \n
  • \n
  • (#1765, #1769) Fixed auto-archived tasks leaving stale Google Calendar events when cleanup runs before calendar sync is ready or after the task moves into the archive folder.
      \n
    • Thanks to @martin-forge for reporting and the PR.
    • \n
    \n
  • \n
  • (#1764) Fixed Google Calendar sync using stale task metadata after rapid task updates, and fixed late recurring completions/skips recording the completion day instead of the scheduled occurrence date.
      \n
    • Thanks to @martin-forge for the PR and to @jpmoo for reporting the recurring completion issues.
    • \n
    \n
  • \n
  • (#1782) Fixed CI test runs resolving the NLP parser package from a local sibling checkout instead of the published dependency.
      \n
    • Thanks to @martin-forge for reporting.
    • \n
    \n
  • \n
  • Published mdbase-tasknotes 0.1.3 with compatibility fixes for TaskNotes-generated mdbase schemas.
      \n
    • Includes clearer create-path diagnostics, natural-language mtn list --due filters, timer log datetime filters, home-directory path expansion, project wikilink preservation, and correct mtn --version reporting.
    • \n
    • Thanks to @tparsons9, @anomatomato, @npondel, @plashal, and @waspeer for the reports and PR.
    • \n
    \n
  • \n
  • (#1667) Fixed NLP scheduled-date parsing so standalone scheduled and start triggers can set scheduled dates alongside due dates.
      \n
    • Thanks to @hokfujow for reporting and @UniqueClone for the NLP core PR.
    • \n
    \n
  • \n
  • Fixed NLP parser title cleanup for explicit date triggers and Japanese/Chinese priority phrases.
  • \n
  • (#1658) Fixed Pomodoro stats date bucketing for sessions near local midnight.
      \n
    • Pomodoro session stats now compare the recorded session calendar date against UTC-anchored target days without shifting through UTC or the reader's current timezone.
    • \n
    • Pomodoro daily-note storage now writes sessions to the daily note matching the recorded session date.
    • \n
    • Thanks to @ewgdg for reporting, @AntonIlinykh and @dkchacha for follow-up discussion, and @ITblacksheep for PR #1758.
    • \n
    \n
  • \n
  • (#1813) Fixed Pomodoro timer UI stalls caused by refreshing session statistics on every timer tick.
      \n
    • Pomodoro stats now refresh on initial render and session completion instead of once per second.
    • \n
    • Pomodoro daily-note stats now read the relevant date/range instead of routing through all history.
    • \n
    • Native Pomodoro notifications now respect the notification setting and granted permission before showing.
    • \n
    • Thanks to @Szu-Szu for reporting and @its-thex for confirming.
    • \n
    \n
  • \n
  • (#1744) Fixed Bases Task List views so changing the per-view Expanded relationships option takes effect on re-render.
      \n
    • Restores the expected show-all behavior for setups that hide subtasks at the top level with note.projects.isEmpty().
    • \n
    • Thanks to @minol-dev for reporting, @Glint-Eye for follow-up discussion, and @stanley-910 for PR #1792 exploring the related standalone-subtask workflow.
    • \n
    \n
  • \n
  • Fixed tag clicks in task cards opening the task edit modal in addition to the tag search panel, and kept rendered tag metadata on a single row inside task cards.
  • \n
\n","text":"Added# (#1342, #1793) Added native tag autocomplete to time entry descriptions by using the embedded markdown editor in the time entry editor modal. Thanks to @fastrick for the request and @renatomen for the PR. (#1756, #1798) Added HTTP API support for configured custom user fields so task responses include them and create/update requests can round-trip their values. Thanks to @Treygec for the request and PR. (#1777) Added a Modal Fields setting to choose whether Tab/Shift+Tab move focus out of the task details editor or use the markdown editor's indentation behavior. Thanks to @P-Sc for the PR. Changed# Updated the Obsidian API dependency to 1.12.3 and switched the Bases integration to the official API type declarations. Bases task cards and property-event cards now render metadata values through Obsidian's native Bases value renderer so links, dates, lists, icons, and formula values display more faithfully. Fixed# (#1778) Fixed MCP initialize requests using newer protocol versions such as 2025-11-25 failing instead of negotiating down to TaskNotes' supported MCP version. Thanks to @SakulaPor for reporting. (#1781) Fixed duplicate metadata properties on Bases task cards when bare and note.-prefixed property IDs map to the same TaskNotes field. Thanks to @loukandr for reporting and tracing the issue. (#1787) Removed the \"(click to change)\" helper text from recurrence tooltips on task cards. Thanks to @kazerniel for reporting. (#1828) Fixed subtask creation from a task card dropping the parent task project when natural-language input also adds projects. Thanks to @prepare4robots for reporting. (#1786) Fixed TaskNotes task cards and relationships/subtasks widgets appearing inside embedded task-note heading or block sections. Skips note-level widget injection in detached or embedded Markdown editor contexts used by plugins such as Block Link Plus. Thanks to @3zra47 for reporting. (#1815) Fixed the Priority property settings so the NLP trigger character field is visible and editable even when priority NLP parsing is disabled. Thanks to @spiv for reporting. (#1035) Fixed the task modal title field causing the modal to jump to the bottom when focused on iPhone. Thanks to @3zra47 for reporting and following up. (#1045) Fixed inline linked recurring tasks keeping the previous day's completed state after the calendar day changes. Thanks to @3zra47 for reporting and following up. (#1788) Fixed Task List subgroup headers and cards rendering without clear indentation. Thanks to @renatomen for the PR. (#1810) Updated Japanese Kanban terminology to use the more natural katakana spelling. Thanks to @sigma7863 for the PR. (#1633) Fixed Bases task cards using fallback labels instead of Bases display names for mapped task fields and file properties. Thanks to @Sarryaz for reporting the Bases task card i18n and field-mapping issue. (#884) Fixed untranslated strings and English placeholder examples across non-English interface translations. Thanks to @berzernberg for reporting Russian translation gaps. (#1765, #1769) Fixed auto-archived tasks leaving stale Google Calendar events when cleanup runs before calendar sync is ready or after the task moves into the archive folder. Thanks to @martin-forge for reporting and the PR. (#1764) Fixed Google Calendar sync using stale task metadata after rapid task updates, and fixed late recurring completions/skips recording the completion day instead of the scheduled occurrence date. Thanks to @martin-forge for the PR and to @jpmoo for reporting the recurring completion issues. (#1782) Fixed CI test runs resolving the NLP parser package from a local sibling checkout instead of the published dependency. Thanks to @martin-forge for reporting. Published mdbase-tasknotes 0.1.3 with compatibility fixes for TaskNotes-generated mdbase schemas. Includes clearer create-path diagnostics, natural-language mtn list --due filters, timer log datetime filters, home-directory path expansion, project wikilink preservation, and correct mtn --version reporting. Thanks to @tparsons9, @anomatomato, @npondel, @plashal, and @waspeer for the reports and PR. (#1667) Fixed NLP scheduled-date parsing so standalone scheduled and start triggers can set scheduled dates alongside due dates. Thanks to @hokfujow for reporting and @UniqueClone for the NLP core PR. Fixed NLP parser title cleanup for explicit date triggers and Japanese/Chinese priority phrases. (#1658) Fixed Pomodoro stats date bucketing for sessions near local midnight. Pomodoro session stats now compare the recorded session calendar date against UTC-anchored target days without shifting through UTC or the reader's current timezone. Pomodoro daily-note storage now writes sessions to the daily note matching the recorded session date. Thanks to @ewgdg for reporting, @AntonIlinykh and @dkchacha for follow-up discussion, and @ITblacksheep for PR #1758. (#1813) Fixed Pomodoro timer UI stalls caused by refreshing session statistics on every timer tick. Pomodoro stats now refresh on initial render and session completion instead of once per second. Pomodoro daily-note stats now read the relevant date/range instead of routing through all history. Native Pomodoro notifications now respect the notification setting and granted permission before showing. Thanks to @Szu-Szu for reporting and @its-thex for confirming. (#1744) Fixed Bases Task List views so changing the per-view Expanded relationships option takes effect on re-render. Restores the expected show-all behavior for setups that hide subtasks at the top level with note.projects.isEmpty(). Thanks to @minol-dev for reporting, @Glint-Eye for follow-up discussion, and @stanley-910 for PR #1792 exploring the related standalone-subtask workflow. Fixed tag clicks in task cards opening the task edit modal in addition to the tag search panel, and kept rendered tag metadata on a single row inside task cards."},{"route":"/obsidian/releases/4.5.3/","title":"TaskNotes 4.5.3","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.5.3.md","namespace":"obsidian","relativePath":"releases/4.5.3.md","raw":"# TaskNotes 4.5.3\n\n## Fixed\n\n- (#1834, #1847) Fixed empty Bases formula and custom properties showing `null` or `undefined` on TaskNotes task cards.\n - A big thanks to @Glint-Eye and @3zra47 for reporting.\n- (#1836) Fixed TaskNotes Bases views not refreshing task cards after status, archive, and auto-archive updates.\n - A big thanks to @kmaustral for reporting.\n","aliases":["/releases/4.5.3/","/releases/4.5.3/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Fixed#

\n
    \n
  • (#1834, #1847) Fixed empty Bases formula and custom properties showing null or undefined on TaskNotes task cards.
      \n
    • A big thanks to @Glint-Eye and @3zra47 for reporting.
    • \n
    \n
  • \n
  • (#1836) Fixed TaskNotes Bases views not refreshing task cards after status, archive, and auto-archive updates.
      \n
    • A big thanks to @kmaustral for reporting.
    • \n
    \n
  • \n
\n","text":"Fixed# (#1834, #1847) Fixed empty Bases formula and custom properties showing null or undefined on TaskNotes task cards. A big thanks to @Glint-Eye and @3zra47 for reporting. (#1836) Fixed TaskNotes Bases views not refreshing task cards after status, archive, and auto-archive updates. A big thanks to @kmaustral for reporting."},{"route":"/obsidian/releases/4.6.0/","title":"TaskNotes 4.6.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.6.0.md","namespace":"obsidian","relativePath":"releases/4.6.0.md","raw":"# TaskNotes 4.6.0\n\n## Changed\n\n- TaskNotes now requires Obsidian 1.12.2 or later, matching the Obsidian APIs used by the plugin.\n- Improved internal code quality by resolving lint warnings, moving static inline styles into CSS utilities, and extending sentence-case lint coverage to English localization strings, with no intended behavior changes.\n\n## Fixed\n\n- Fixed TaskNotes failing to load when Obsidian opened without an active Markdown file.\n","aliases":["/releases/4.6.0/","/releases/4.6.0/"],"toc":[{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Changed#

\n
    \n
  • TaskNotes now requires Obsidian 1.12.2 or later, matching the Obsidian APIs used by the plugin.
  • \n
  • Improved internal code quality by resolving lint warnings, moving static inline styles into CSS utilities, and extending sentence-case lint coverage to English localization strings, with no intended behavior changes.
  • \n
\n

Fixed#

\n
    \n
  • Fixed TaskNotes failing to load when Obsidian opened without an active Markdown file.
  • \n
\n","text":"Changed# TaskNotes now requires Obsidian 1.12.2 or later, matching the Obsidian APIs used by the plugin. Improved internal code quality by resolving lint warnings, moving static inline styles into CSS utilities, and extending sentence-case lint coverage to English localization strings, with no intended behavior changes. Fixed# Fixed TaskNotes failing to load when Obsidian opened without an active Markdown file."},{"route":"/obsidian/releases/4.7.0/","title":"TaskNotes 4.7.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.7.0.md","namespace":"obsidian","relativePath":"releases/4.7.0.md","raw":"# TaskNotes 4.7.0\n\n## Changed\n\n- Enabled lint checks that mirror Obsidian community plugin review findings, including dynamic code execution, Promise handling, deprecated APIs, unsafe stringification, directive comments, Node built-in imports, and explicit `any` usage.\n- Clarified privacy documentation for optional integrations that make periodic background network refreshes.\n- Cleaned up internal Obsidian and Bases compatibility adapters used by search and grouped views.\n- (#1839, #1881) Updated default Base urgency scoring so timed tasks earlier in the day sort above later tasks with the same priority and date\n - Thanks to @loukandr for the contribution\n\n## Fixed\n\n- Fixed project autocomplete searches so non-empty `+` queries only return files matching the query in the basename, title, aliases, or explicitly searchable metadata rows.\n- (#1713) Fixed all-tasks ICS export when a task uses a space-separated scheduled datetime such as `2025-08-12 18:00`\n - Thanks to @bepolymathe for requesting this and @m4to-3pe for following up\n- Fixed Pomodoro stats reopening immediately after a plugin reload before the Pomodoro service has finished initializing.\n- (#1872) Fixed unarchiving moved tasks so the destination task folder processes template variables such as `{{project}}` before moving the file\n - Thanks to @OXI-717 for reporting\n- (#1870) Fixed custom user field NLP triggers with file autosuggest so selecting a wikilink suggestion stores the link in the user field instead of leaving it in the task title\n - Thanks to @Sineapple for reporting\n- (#1878) Fixed completed tasks still appearing as active blockers for dependent tasks\n - Thanks to @macbikegeek for reporting\n- (#1880) Fixed the status bar time-tracking label for task titles that contain a dash\n - Thanks to @ubidev for reporting\n- (#1854) Fixed modal task completion so completed tasks receive a completed date consistently\n - Thanks to @misolex for reporting\n- (#1124, #1838, #1881) Fixed default Base views and formulas excluding tasks scheduled or due today at a non-midnight time from day-level comparisons\n - Thanks to @kmaustral for reporting and @loukandr for the fix\n\n## Removed\n\n- Removed JavaScript webhook transform support and examples. JSON webhook transform templates remain supported.\n","aliases":["/releases/4.7.0/","/releases/4.7.0/"],"toc":[{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"removed","text":"Removed"}],"html":"

Changed#

\n
    \n
  • Enabled lint checks that mirror Obsidian community plugin review findings, including dynamic code execution, Promise handling, deprecated APIs, unsafe stringification, directive comments, Node built-in imports, and explicit any usage.
  • \n
  • Clarified privacy documentation for optional integrations that make periodic background network refreshes.
  • \n
  • Cleaned up internal Obsidian and Bases compatibility adapters used by search and grouped views.
  • \n
  • (#1839, #1881) Updated default Base urgency scoring so timed tasks earlier in the day sort above later tasks with the same priority and date
      \n
    • Thanks to @loukandr for the contribution
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • Fixed project autocomplete searches so non-empty + queries only return files matching the query in the basename, title, aliases, or explicitly searchable metadata rows.
  • \n
  • (#1713) Fixed all-tasks ICS export when a task uses a space-separated scheduled datetime such as 2025-08-12 18:00
      \n
    • Thanks to @bepolymathe for requesting this and @m4to-3pe for following up
    • \n
    \n
  • \n
  • Fixed Pomodoro stats reopening immediately after a plugin reload before the Pomodoro service has finished initializing.
  • \n
  • (#1872) Fixed unarchiving moved tasks so the destination task folder processes template variables such as {{project}} before moving the file
      \n
    • Thanks to @OXI-717 for reporting
    • \n
    \n
  • \n
  • (#1870) Fixed custom user field NLP triggers with file autosuggest so selecting a wikilink suggestion stores the link in the user field instead of leaving it in the task title
      \n
    • Thanks to @Sineapple for reporting
    • \n
    \n
  • \n
  • (#1878) Fixed completed tasks still appearing as active blockers for dependent tasks
      \n
    • Thanks to @macbikegeek for reporting
    • \n
    \n
  • \n
  • (#1880) Fixed the status bar time-tracking label for task titles that contain a dash
      \n
    • Thanks to @ubidev for reporting
    • \n
    \n
  • \n
  • (#1854) Fixed modal task completion so completed tasks receive a completed date consistently
      \n
    • Thanks to @misolex for reporting
    • \n
    \n
  • \n
  • (#1124, #1838, #1881) Fixed default Base views and formulas excluding tasks scheduled or due today at a non-midnight time from day-level comparisons
      \n
    • Thanks to @kmaustral for reporting and @loukandr for the fix
    • \n
    \n
  • \n
\n

Removed#

\n
    \n
  • Removed JavaScript webhook transform support and examples. JSON webhook transform templates remain supported.
  • \n
\n","text":"Changed# Enabled lint checks that mirror Obsidian community plugin review findings, including dynamic code execution, Promise handling, deprecated APIs, unsafe stringification, directive comments, Node built-in imports, and explicit any usage. Clarified privacy documentation for optional integrations that make periodic background network refreshes. Cleaned up internal Obsidian and Bases compatibility adapters used by search and grouped views. (#1839, #1881) Updated default Base urgency scoring so timed tasks earlier in the day sort above later tasks with the same priority and date Thanks to @loukandr for the contribution Fixed# Fixed project autocomplete searches so non-empty + queries only return files matching the query in the basename, title, aliases, or explicitly searchable metadata rows. (#1713) Fixed all-tasks ICS export when a task uses a space-separated scheduled datetime such as 2025-08-12 18:00 Thanks to @bepolymathe for requesting this and @m4to-3pe for following up Fixed Pomodoro stats reopening immediately after a plugin reload before the Pomodoro service has finished initializing. (#1872) Fixed unarchiving moved tasks so the destination task folder processes template variables such as {{project}} before moving the file Thanks to @OXI-717 for reporting (#1870) Fixed custom user field NLP triggers with file autosuggest so selecting a wikilink suggestion stores the link in the user field instead of leaving it in the task title Thanks to @Sineapple for reporting (#1878) Fixed completed tasks still appearing as active blockers for dependent tasks Thanks to @macbikegeek for reporting (#1880) Fixed the status bar time-tracking label for task titles that contain a dash Thanks to @ubidev for reporting (#1854) Fixed modal task completion so completed tasks receive a completed date consistently Thanks to @misolex for reporting (#1124, #1838, #1881) Fixed default Base views and formulas excluding tasks scheduled or due today at a non-midnight time from day-level comparisons Thanks to @kmaustral for reporting and @loukandr for the fix Removed# Removed JavaScript webhook transform support and examples. JSON webhook transform templates remain supported."},{"route":"/obsidian/releases/4.7.1/","title":"TaskNotes 4.7.1","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.7.1.md","namespace":"obsidian","relativePath":"releases/4.7.1.md","raw":"# TaskNotes 4.7.1\n\n## Changed\n\n- Release assets are now built with GitHub artifact attestations so users and reviewers can verify the provenance of `main.js`, `manifest.json`, and `styles.css`.\n","aliases":["/releases/4.7.1/","/releases/4.7.1/"],"toc":[{"level":2,"id":"changed","text":"Changed"}],"html":"

Changed#

\n
    \n
  • Release assets are now built with GitHub artifact attestations so users and reviewers can verify the provenance of main.js, manifest.json, and styles.css.
  • \n
\n","text":"Changed# Release assets are now built with GitHub artifact attestations so users and reviewers can verify the provenance of main.js, manifest.json, and styles.css."},{"route":"/obsidian/releases/4.7.2/","title":"TaskNotes 4.7.2","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.7.2.md","namespace":"obsidian","relativePath":"releases/4.7.2.md","raw":"# TaskNotes 4.7.2\n\n## Changed\n\n- Improved local lint checks so package and CSS issues reported by Obsidian's online review can be caught before submission.\n- Cleaned up stylesheet compatibility issues reported by Obsidian's online review without changing the intended TaskNotes appearance.\n- Improved spacing and alignment in task, timeblock, and webhook modals after the stylesheet cleanup.\n- Reworked optional calendar and ICS subscription refresh scheduling to avoid interval-based network polling while preserving the same refresh intervals.\n- Cleaned up additional source patterns reported by Obsidian's online review, including unsafe default object stringification and redundant external type unions.\n- Prevented a console error when plugin listeners are cleaned up after reloads.\n- Added a local lint check to prevent interval-based polling in files that also perform network requests.\n","aliases":["/releases/4.7.2/","/releases/4.7.2/"],"toc":[{"level":2,"id":"changed","text":"Changed"}],"html":"

Changed#

\n
    \n
  • Improved local lint checks so package and CSS issues reported by Obsidian's online review can be caught before submission.
  • \n
  • Cleaned up stylesheet compatibility issues reported by Obsidian's online review without changing the intended TaskNotes appearance.
  • \n
  • Improved spacing and alignment in task, timeblock, and webhook modals after the stylesheet cleanup.
  • \n
  • Reworked optional calendar and ICS subscription refresh scheduling to avoid interval-based network polling while preserving the same refresh intervals.
  • \n
  • Cleaned up additional source patterns reported by Obsidian's online review, including unsafe default object stringification and redundant external type unions.
  • \n
  • Prevented a console error when plugin listeners are cleaned up after reloads.
  • \n
  • Added a local lint check to prevent interval-based polling in files that also perform network requests.
  • \n
\n","text":"Changed# Improved local lint checks so package and CSS issues reported by Obsidian's online review can be caught before submission. Cleaned up stylesheet compatibility issues reported by Obsidian's online review without changing the intended TaskNotes appearance. Improved spacing and alignment in task, timeblock, and webhook modals after the stylesheet cleanup. Reworked optional calendar and ICS subscription refresh scheduling to avoid interval-based network polling while preserving the same refresh intervals. Cleaned up additional source patterns reported by Obsidian's online review, including unsafe default object stringification and redundant external type unions. Prevented a console error when plugin listeners are cleaned up after reloads. Added a local lint check to prevent interval-based polling in files that also perform network requests."},{"route":"/obsidian/releases/4.8.0/","title":"TaskNotes 4.8.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.8.0.md","namespace":"obsidian","relativePath":"releases/4.8.0.md","raw":"# TaskNotes 4.8.0\n\n## Added\n\n- (#353) Added a `Has Subtasks` filter for task queries, so views and API clients can show only project-style tasks or direct tasks. Thanks to @mdbraber for suggesting this.\n- (#380) Added a test-reminder button in notification settings, so reminder setup can be checked without creating a real task reminder. Thanks to @mdbraber for suggesting this.\n- (#711, #168) Added an optional task-creation setting to open the new task note after saving, either in the current tab or a new tab. Thanks to @phortx and @23426356587 for suggesting this, and to @edward-peters and @obsilover for the follow-up.\n- (#1041, #1800) Added copy-drag support for timeblocks: hold Ctrl, Cmd, or Alt/Option while dragging an existing timeblock to duplicate it at the new date and time. Thanks to @0-BSCode and @cweekly for suggesting this.\n- (#1052) Added a public JavaScript API for in-vault scripts at `app.plugins.plugins.tasknotes.api.parseNaturalLanguage(text)`, so Templater, QuickAdd, and MetaBind workflows can use TaskNotes' natural-language parser without running the HTTP API. Thanks to @edakimling for suggesting this.\n- (#1235) Added a task-card toggle for blocked tasks, so you can expand a blocked task to see the tasks it is waiting on. Thanks to @craziedde for suggesting this.\n- (#1254) Added `../` and `./` normalization for folder templates after variables are expanded, so instant task conversion can target sibling folders such as `{{currentNotePath}}/../Tasks`. Thanks to @rdick for suggesting this.\n- (#1267) Added Daily Notes-style date tokens such as `YYYY`, `MM`, `DD`, `MMMM`, and `dddd` to TaskNotes folder templates. Thanks to @paulsen-it for suggesting this.\n- (#1380) Added tag actions to task context menus, including add/remove actions for individual tasks and batch-selected tasks. Thanks to @Chuhtra for suggesting this.\n- (#1377) Added right-click Mini Calendar actions for opening daily notes from day cells and weekly notes from week numbers. Thanks to @hasanyilmaz for suggesting this.\n- (#1151) Added a Mini Calendar max color note count option, so one-note days can use the strongest heatmap color when that better fits the view. Thanks to @arreme for suggesting this.\n- (#1376) Added backslash escapes for NLP trigger tokens, so text like `\\@context`, `\\*done`, or `\\tomorrow` can stay in the task title. Thanks to @JerryLu086 for suggesting this.\n- (#1366) Added CSS variables for compacting nested task-card indentation, with smaller defaults on mobile and documented snippets for tighter task-link lists. Thanks to @rk-kontur for suggesting this.\n- (#1502, #603) Added calendar indicators for external events that have linked notes or tasks, and showed loaded event titles in task-card calendar metadata instead of only the linked event count. Thanks to @Robubble and @mdbraber for suggesting this, and to @ubidev for the follow-up.\n- (#1522) Added a per-status option to skip rarely used statuses when cycling task-card status indicators. Thanks to @Glint-Eye for suggesting this.\n- (#144) Added an \"Open note in new tab\" action to the task context menu. Thanks to @cathywu for suggesting this and @macbikegeek for the follow-up feedback.\n- (#167) Added an optional next-status override for each status, so forward cycling can jump to a configured status instead of always following the status order. Thanks to @DanBrazelton for suggesting this, and to @michelebugio, @Moyf, @anareaty, and @vorrermid for the follow-up feedback.\n- (#1520) Made tag and context fields show available suggestions as soon as the field is focused. Thanks to @Glint-Eye for suggesting this, and to @craziedde for the follow-up.\n- (#1541) Added `{{currentNotePath}}` and `{{currentNoteTitle}}` support to the default tasks folder, so normal task creation can place new tasks beside the active note without creating an inline link. Thanks to @ChristianAnyanwu for suggesting this, and to @abbasou and @ttlaylor for the follow-up feedback.\n- (#648, #1605) Added clickable links in task-card contexts for note links, markdown links, and web URLs while keeping plain contexts as tag-search buttons. Thanks to @trdischat and @Glint-Eye for suggesting this, and to @renatomen for the follow-up feedback.\n- (#1482) Added clickable custom-field links on task cards for wikilinks, markdown links, autolinks, and bare web URLs. Thanks to @ptbosch-figueiredorj for suggesting this, and to @Soleone for the follow-up use case.\n- (#1471) Added Kanban column and swimlane-cell add buttons that open the TaskNotes creation modal with the grouped values already filled in. Thanks to @byheaven for suggesting this and @Davincible for the project-board use case.\n- (#933) Added non-Markdown vault files such as canvases to project suggestions, using extension-qualified link targets so those files can be selected as task projects. Thanks to @Alvin21Bon for suggesting this.\n- (#1475, #725) Added quote/backtick escapes for NLP input, so literal course codes or date words can stay in task titles without being parsed as estimates or dates. Thanks to @RumiaKitinari and @gavingwebb for suggesting this.\n- (#1462) Added natural-language date entry to the task date picker, so existing due and scheduled dates can be changed with phrases such as \"tomorrow at 3pm\" when NLP is enabled. Thanks to @Ruboks-Cube for suggesting this.\n- (#1526) Added a native date field to the task date picker, so scheduled and due dates can be changed with the device date picker while keeping optional times visible. Thanks to @jmartinmcfly for suggesting this and @23426356587 for the follow-up feedback.\n- (#1603) Added Calendar view toggles for hiding completed or skipped recurring task instances while keeping future outstanding instances visible. Thanks to @wandererovertheseaofpiss for suggesting this.\n- (#287, #273, #274) Added linked hover highlighting for Calendar and Agenda events that come from the same task note, so scheduled, due, and recurring entries are easier to connect. Thanks to @girisumit for suggesting this.\n- (#280) Added project-specific CSS hooks to task cards and Calendar events, so project-based visual styling can be handled with user snippets. Thanks to @girisumit for suggesting this.\n- (#1625) Added `Shift` + `Cmd`/`Ctrl` + `Enter` in the Create Task modal to save the current task and reopen the modal for the next one. Thanks to @tcb678 for suggesting this.\n- (#1353) Focused the Create Task modal's natural-language input when the modal opens, with a longer mobile delay so the keyboard can open after layout. Thanks to @GiovanH for suggesting this.\n- (#1664) Added project-based custom filename template variables, including the first project, all projects, and a short `projectId`. Thanks to @bendavis987 for the contribution.\n- (#923) Added `{{projectFilePath}}` and `{{projectFilePaths}}` folder template variables, so task folders can mirror project note locations in the vault. Thanks to @PacoTaco2 for suggesting this.\n- (#1697) Added cached Google Calendar, Microsoft Calendar, and ICS events to Mini Calendar days, with compact colored dots and event details from the existing calendar connection. Thanks to @RPGArchivist for suggesting this.\n- (#1754) Added optional icons for priority values, so task cards can show a configured priority icon instead of only a colored dot. Thanks to @BrucePlumb for suggesting this and @prepare4robots for the follow-up feedback.\n- (#1761) Added TaskNotes edit and task-action submenu entries to Obsidian's native file context menu for recognized task notes. Thanks to @delzero for suggesting this.\n- (#1771) Added mobile drag handles to manually sorted Task List Bases views, so dragging can start from the handle without disabling normal text interaction on the rest of the card. Thanks to @PatrickGolz for suggesting this.\n- (#1776) Allowed calendar timeline end times after midnight, such as `26:00` for a 2 AM next-day end. Thanks to @chrabia for suggesting this.\n- (#1784, #1833) Added a per-view `pinnedColumns` option for TaskNotes Kanban views, so selected empty columns can stay visible as drop targets while other empty columns remain hidden. Thanks to @loukandr for suggesting and prototyping this.\n- (#1794) Added context updates to the task card context menu, so contexts can be added, toggled, or cleared without opening the task edit modal. Thanks to @m13ntrpn for suggesting this.\n- (#315, #1356, #1748, #1809) Added a subtle task-card indicator and CSS hooks for tasks with note body details, including existing task bodies read through Obsidian's metadata cache. Thanks to @volodxyz, @Karut, @yeHHH1g, and @aliceinwaterdeep for suggesting this, and to @minchinweb for the follow-up.\n- (#1808) Added advanced Kanban swimlane ordering through `swimLaneOrder`, so swimlane rows can stay in a stable configured order. Thanks to @rookledookle for suggesting this, and to @benmartinek and @chrabia for the follow-up feedback.\n- (#1805) Added an ICS export option to omit completed tasks from generated calendar files. Thanks to @bepolymathe for suggesting this.\n- (#659) Added Obsidian links to ICS export descriptions, so exported calendar events can open their source task notes. Thanks to @bepolymathe for suggesting this.\n- (#589) Added an Appearance toggle to turn off strikethrough styling on completed task card titles. Thanks to @BrucePlumb for suggesting this.\n- (#561) Added a \"Last day\" option to the custom recurrence month-day picker for month-end repeating tasks. Thanks to @TonyAtlas for suggesting this and @BrucePlumb for the follow-up.\n- (#217) Added weekday selection to daily custom recurrence rules, so interval rules such as every three days can skip weekends from the recurrence modal. Thanks to @kmaustral for suggesting this.\n- (#1818) Added an auto-height mode for TaskNotes Calendar Bases views so embedded agenda/list sections can size to their content instead of forcing an inner scroller. Thanks to @martin-forge for suggesting this.\n- (#1201) Added a Calendar Bases toggle to hide the hourly breakdown in week, custom-days, and day views while keeping the all-day planning row visible. Thanks to @PacoTaco2 for suggesting this.\n- (#1176) Added advanced Kanban WIP limits through `wipLimits`, so column headers can show `(current/limit)` counts and highlight exceeded limits. Thanks to @williamcheuk03 for suggesting this.\n- (#914) Added a generated `Due in` countdown to the default Agenda Base and allowed Calendar Bases list agendas to span up to 365 days. Thanks to @williamcheuk03 for suggesting this.\n- (#900) Added an instant-conversion setting to keep the original Markdown checkbox marker when converting a checkbox into a TaskNote link. Thanks to @dsebastien for suggesting this.\n- (#898) Added a mobile-only calendar integration opt-out, so synced desktop calendar settings no longer have to trigger external calendar loading on Obsidian Mobile. Thanks to @cathywu for suggesting this.\n- (#887) Added built-in scheduled and due date presets to the Quick actions palette for current tasks. Thanks to @willgraham345 for suggesting this and @anrie for the related preset feedback.\n- (#819) Added a command to open Quick actions for the inline task link under the cursor. Thanks to @rlolingo for suggesting this.\n- (#798, #1732, #1835) Added hotkeyable commands to edit the current task, add a project to the current task, and add an existing task as a subtask of the current note. Thanks to @xorander00 and @prepare4robots for requesting this, and to @musta-code and @ubidev for the follow-up suggestions.\n- (#791) Added a UUID v4 task filename format and `{{uuid}}` custom filename template variable. Thanks to @bangbangbanggit for suggesting this.\n- (#932) Added hotkeyable commands to cycle the current task's status and priority. Thanks to @rxunique for suggesting this and @luckb0x for the follow-up feedback.\n- (#1655) Added live elapsed time to the optional active time tracking status bar item. Thanks to @connradolisboa for suggesting this.\n- (#1622) Allowed multiple comma-separated default reminder offsets for timed Google Calendar task exports. Thanks to @solidabstract for suggesting this.\n- (#706, #820, #1040) Added direct Pomodoro duration editing, hour-aware timer formatting, clearer one-minute controls, and an optional active Pomodoro status bar countdown. Thanks to @SublunarSage, @lj1446615403-cloud, @0-BSCode, and @thestrike72 for the suggestions and feedback.\n- (#873) Added an optional built-in sound for task reminder notifications, with volume and preview controls in Settings. Thanks to @berzernberg for suggesting this.\n- Added a generated Pomodoro statistics Base with daily and monthly summary views for Pomodoro history stored in daily notes.\n\n## Changed\n\n- Expanded the bug report template to ask for Obsidian \"Show debug info\" output, affected task frontmatter, relevant Bases file contents, reproduction steps, and related logs or screenshots.\n- Release notes now show the default `.base` file regeneration reminder only on the current version section, keeping older bundled sections focused on their own changes.\n- Updated the release notes GitHub prompt to invite feedback while still asking satisfied users to star the project.\n- (#239) Ordered Kanban status and priority columns by the configured status order and priority weights when no manual column order is saved. Thanks to @ScumbagScalawag for asking about this, and to @nightroman, @lavir, and @elvarb for the follow-up discussion.\n- (#269) Marked Kanban status columns that come from values outside the configured TaskNotes statuses, so manually edited or external status values are visible as non-standard instead of blending into the board. Thanks to @cstelmach for suggesting this and @digitaldoctors for the follow-up.\n- Refined Kanban empty columns, swimlane rows, and column drag handles, and added a per-view compact card layout option for denser boards.\n- Kept Kanban swimlane rows from shrinking to share the viewport so the Max Swimlane Height setting is respected.\n- Added guidance in Pomodoro statistics and Base file settings explaining that Pomodoro Base views require daily notes storage.\n- (#323) Reordered task modal action buttons to match the right-click task menu order. Thanks to @23426356587 for suggesting this.\n- (#1189) Made the Create/Edit Task modal priority picker follow the priority order configured in Settings. Thanks to @n1njaznutz for suggesting this.\n- Made task-card priority dots and configured priority icons slightly larger for better visibility.\n- (#1244) Clarified the Task Properties documentation for custom property keys and status values in Bases filters and sorting. Thanks to @Arachnidai for suggesting this.\n- (#1234) Kept right-aligned subtask chevrons visible on task cards instead of only showing them on hover. Thanks to @n1njaznutz for suggesting this.\n- (#1237) Made today's date more visible in the Mini Calendar view when another day is selected. Thanks to @riekusr for suggesting this.\n- (#1348) Let long task titles wrap inside the Create/Edit Task modal title field while keeping saved titles single-line, and widened the contexts and tags fields in the modal details area. Thanks to @hasanyilmaz for suggesting this.\n- (#1392) Made TaskNotes date fields accept compact `YYYYMMDD` typing and pasted dates. Thanks to @kazerniel for suggesting this.\n- (#1431) Showed the year on task-card due and scheduled dates when the date is outside the current year. Thanks to @kazerniel for suggesting this.\n- (#1429) Opened TaskNotes view commands in a new tab when they load configured Base files, so they do not replace the active note. Thanks to @Ruboks-Cube for suggesting this.\n- (#1426) Added copy actions for TaskNotes Bases views, including current-view filenames, links, and titles from the result count menu, plus selected-task copy actions in the batch menu, while keeping the native Bases copy and CSV export actions available. Thanks to @kmaustral for suggesting this.\n- Improved keyboard access, mobile layout, and theme color consistency across task cards, TaskNotes Kanban, Bases Kanban, calendar controls, stats, settings, and filter popovers.\n- (#1526) Made the Create/Edit Task modal due and scheduled date buttons open a calendar-first picker where clicking a date saves immediately, with time entry still available in the picker. Thanks to @jmartinmcfly for suggesting this and @23426356587 for the follow-up feedback.\n- (#1642) Made completion-based custom recurrence use flexible weekly, monthly, and yearly intervals without forcing a fixed weekday, month day, or month. Thanks to @Volker-brdb for suggesting this.\n- (#1724) Moved recurring task complete/skip instance actions into the date area of the task context menu. Thanks to @prepare4robots for suggesting this.\n- (#1762) Used the configured Google Calendar task export target as the default calendar when creating manual external calendar events. Thanks to @chrabia for suggesting this.\n- (#1774) Made expandable project chevrons visible and easier to tap on mobile. Thanks to @sh0nuff for suggesting this.\n- (#190) Made task-card and inline task-link action controls easier to tap on mobile, including always-visible task options on touch layouts. Thanks to @Poly-0000 for suggesting this.\n- (#518, #1710, #1785) Added an opt-in setting for Create subtask to inherit the parent task's projects, contexts, priority, and non-identifying tags while always keeping the parent-task project link. Thanks to @bepolymathe, @Jalpara, and @poulpoulsen for reporting this, and to @tomsymonds, @AndyEveritt, @wedgen, @lindsaylearns, and @hokfujow for the follow-up feedback.\n- (#1790) Extended the identifying-tag hiding setting to task modal tag suggestions, and kept hidden identifying tag children in place when editing other tags. Thanks to @loukandr for suggesting this.\n- (#1804) Made the inline-created task folder setting visible even when instant conversion is disabled, and clarified that leaving it empty uses the default tasks folder. Thanks to @CaFeZn for suggesting this.\n- (#1822) Matched the Task Edit Modal subtask list order to the existing relationship sort, so active and higher-priority subtasks appear ahead of completed ones. Thanks to @Glint-Eye for suggesting this.\n- (#1233, #1339) Added an Appearance setting to expand project subtasks by default in task cards, while still letting individual cards be collapsed. Thanks to @n1njaznutz and @hasanyilmaz for suggesting this and @kazerniel and @benmartinek for the follow-up.\n- (#763) Made the Relationships widget appear on project notes that match Project Autosuggest tag or property filters, even before any tasks link to the project. Thanks to @ChadHattabaugh for suggesting this.\n- (#732) Remembered the Task & Project Statistics filters between openings, including the selected date range, custom dates, and minimum time filter. Thanks to @RumiaKitinari for suggesting this.\n- (#1335) Added optional default times for new task scheduled and due dates, so default-dated tasks can appear as timed calendar events instead of all-day events. Thanks to @echo-saurav for suggesting this.\n- (#1327) Made TaskNotes Bases search match any word in a multi-word search instead of requiring the whole phrase. Thanks to @craziedde for suggesting this.\n- (#1318) Made aliased inline task links use the alias text inside the task widget, so `[[Task title|short label]]` can display as `short label`. Thanks to @3zra47 for suggesting this and @kazerniel for the follow-up.\n- (#1325) Added `./` and `../` support to Include folders filters for project and file autosuggest, resolved from the active note's folder. Thanks to @EpolPers for suggesting this.\n- (#1313) Added generated `llms.txt` and `llms-full.txt` files to the documentation site, so the primary docs can be shared with LLM tools more easily. Thanks to @JacksonMcDonaldDev for suggesting this.\n- (#1308) Added a Calendar view option to stop date links from creating missing daily notes, while still opening existing daily notes. Thanks to @Arachnidai for suggesting this.\n- (#1300) Allowed priority, status, calendar subscription, and timeblock color settings to use Obsidian theme color names such as `red`, `blue`, and `cyan`. Thanks to @thestrike72 for suggesting this.\n- (#1299) Added a command that creates or opens a task and immediately starts time tracking for it. Thanks to @slipstyle for suggesting this.\n- (#1284) Added an exact-match option for hiding task identification tags, so `#task` can be hidden while nested tags such as `#task/project` remain visible. Thanks to @3zra47 for suggesting this.\n- (#1009) Added a confirmed Delete button to the Edit Task modal, so unwanted task notes can be removed without first opening the note file. Thanks to @jalooc for suggesting this.\n- Improved the internal structure of Calendar, Kanban, Bases, task cards, and task modals to make future changes easier to test and maintain.\n\n## Fixed\n\n- (#697, #1374) Recognized manually authored task notes that use a single scalar tag such as `tags: task`, so they appear in TaskNotes views and menus like notes using YAML list tags. Thanks to @aubreyz and @phortx for reporting this, and to @jleewastaken for the follow-up.\n- Removed the upward hover shift from calendar events while keeping the hover shadow feedback.\n- Made same-column manual-order drops in TaskNotes Kanban settle immediately when the local order patch is safe, including virtual columns through a stable reorder path that avoids layout jumps.\n- Made single-card cross-column drops in TaskNotes Kanban settle through a local state patch when the move is safe, reducing the wait for the full Bases refresh.\n- Fixed Calendar timeblocks created from a selected time range so they appear as soon as Obsidian indexes the daily note update, instead of waiting for a later refresh.\n- Replaced the external calendar event emoji marker with the calendar icon and kept it in the same top-right event corner.\n- Restored Task List group toggles and recurring calendar month controls to compact icon buttons instead of inherited boxed theme buttons.\n- Refined the settings tab navigation styling so tabs read as quieter inline navigation instead of default buttons.\n- (#263) Made the instant inline task conversion button respond to touch/pointer activation, so mobile multi-line selections can be converted into TaskNotes. Thanks to @cathywu for reporting this.\n- (#216) Preserved `@context` markers when converting Tasks-plugin-style checkbox tasks into TaskNotes, while keeping those contexts out of the created task title. Thanks to @ksdavidc for suggesting this, and to @hangryscribe3, @nayatiuh, and @natleahh for the follow-up feedback.\n- (#508) Showed project note names instead of full project paths in grouped Kanban and Task List headings, while keeping the headings linked to the project note. Thanks to @elvarb for reporting this and @dmodify for confirming it in Task List.\n- (#408) Used the task title as the native system notification title for task reminders instead of always showing `TaskNotes Reminder`. Thanks to @DudeThatsErin for reporting this and @phillipadsmith for the follow-up.\n- (#385) Let Mini Calendar month controls shrink and wrap cleanly in narrow sidebars. Thanks to @iholston for reporting this.\n- Fixed Calendar List view task cards so they use the available row width without duplicate list cells, row-hover backgrounds, or linked-hover styling.\n- (#552) Made instant task convert buttons appear for checkbox tasks inside callouts, and kept converted links inside the callout list. Thanks to @Oblique82 for reporting this and @ksdavidc for the follow-up.\n- (#559) Treated notes linked to one loaded recurring calendar event instance as related to the other instances in that series. Thanks to @cathywu for reporting this and @mdbraber for the implementation notes.\n- (#685) Made Calendar list views respect the All-day slot option by hiding all-day events from the list when that option is turned off. Thanks to @RumiaKitinari for reporting this.\n- (#643) Stopped custom filename templates such as `task-{year}{month}{day}{hour}{minute}` from incorrectly showing the \"filename shortened\" notice when creating tasks. Thanks to @minchinweb for reporting this.\n- (#722) Made Skip Break reset a queued Pomodoro break back to the next focus timer without starting a session. Thanks to @Goossiii for reporting this and @YIRU69 for the follow-up.\n- (#782) Made recurrence weekday choices follow the configured first day of week, and made the quick \"Weekdays only\" recurrence use locale weekend data instead of assuming Monday through Friday everywhere. Thanks to @BKSalman for reporting this.\n- (#872) Made note-level task cards appear immediately, and stay visible while editing, when a task note is embedded as a Canvas file node. Thanks to @bangbangbanggit for reporting this and @benmartinek for the follow-up.\n- (#856) Fixed filters for number custom fields so numeric task values match equivalent filter values entered as text. Thanks to @thoughtcipher for reporting this.\n- (#1039) Restored clearer TaskNotes Bases grouping for nested project paths, and made the Calendar refresh control an icon button again. Thanks to @dblinnikov for reporting this.\n- (#1034) Let embedded TaskNotes Calendar views size to their content by default, so month, week, and day embeds no longer reserve full-pane proportions inside notes. Thanks to @same774 for reporting this.\n- (#1023) Kept task modal custom fields scrollable above the iPhone keyboard while creating or editing tasks. Thanks to @3zra47 for reporting this.\n- (#1019) Kept active Pomodoro and time-tracking task references working after the tracked task file is renamed. Thanks to @AndreMonthy for reporting this.\n- (#1037) Let embedded TaskNotes Calendar year views size to their content and kept the year title from wrapping vertically. Thanks to @same774 for reporting this.\n- (#1047) Wrapped long file paths in the Edit Task modal metadata section, so narrow mobile screens no longer get a sideways scrollbar from the File row. Thanks to @3zra47 for reporting this.\n- (#1051) Preserved extra values on a property-based task identification field when saving a task, so list properties such as `class: [task, habit]` no longer get collapsed to only the identifying value. Thanks to @WhoIsSeanGalt for reporting this.\n- (#1060) Reused and revealed an already-open Calendar/Base view when running view commands, so a view kept in the sidebar no longer reopens in a new main tab. Thanks to @kmaustral for reporting this.\n- (#1075) Hid the native WebKit date-input label that could appear as `Label` when editing scheduled dates on macOS. Thanks to @3zra47 for reporting this.\n- (#1076) Allowed timeblocks to end at midnight using `00:00`, and accepted `24:00` as an explicit end-of-day value in timeblock validation. Thanks to @skoove for reporting this and @gregor202 for the follow-up.\n- (#1086) Fixed the Calendar `+ more` control in dark mode so expanded all-day task groups stay readable. Thanks to @same774 for reporting this.\n- (#1100) Applied Advanced Calendar View search and title filters to the tasks used for calendar rendering, so filtering controls affect which tasks appear on the calendar. Thanks to @quiet-coder-io for reporting this.\n- (#1147) Added a delete action for recent Pomodoro statistics sessions, so erroneous Pomodoro history can be removed without editing plugin storage or daily-note frontmatter manually. Thanks to @RumiaKitinari for reporting this and @BrucePlumb for the follow-up.\n- (#1150) Kept recurring tasks' due dates visible in Calendar Bases views, and showed their scheduled date when recurrence instances are hidden. Thanks to @thomatino for reporting this and @BrucePlumb for the follow-up.\n- (#1159) Softened Calendar time-entry styling so recorded time blocks no longer visually outweigh task events. Thanks to @hatespinach for reporting this.\n- (#1191) Aligned the task-card and relationships widgets inside notes with Obsidian's editor margins, including readable-line-width layouts. Thanks to @minchinweb for reporting this.\n- (#1183) Kept the Calendar create menu open after drag-selecting a time range, so the selected duration can be used when creating a task. Thanks to @randomness42 for reporting this.\n- (#1179) Stopped Calendar Bases views from repainting after unrelated note updates when the visible calendar data has not changed. Thanks to @same774 for reporting this.\n- (#1156) Kept property-based task identification through the `tags` property from rewriting task tags as a plain text value, and generated default Bases now use tag membership for that setting. Thanks to @seepage87 for the detailed migration report and @chrsdk for the follow-up.\n- (#1232) Fixed generated Task List Base date filters so recurring tasks scheduled for today appear in the Today view, and today's completed recurring instances stay hidden. Thanks to @mvichosfm for reporting this and @ArthurGideon and @VarunNikam22 for the follow-up.\n- (#1231) Fixed the generated Task List Base Overdue view so tasks with scheduled dates in the past appear alongside tasks with due dates in the past. Thanks to @Lorite for reporting this and @dictionarymouse for the follow-up.\n- (#1228) Matched the task details editor's Markdown heading colors to the active Obsidian theme, including themes that customize heading colors. Thanks to @BrucePlumb for requesting this.\n- (#1227) Refreshed the relationships widget when project references are indexed or updated so project notes can show related tasks automatically again. Thanks to @luckb0x for reporting this.\n- (#1219) Fixed Kanban drags that start on an expanded subtask card so they move that subtask instead of dragging the parent card. Thanks to @craziedde for reporting this.\n- (#990) Treated one-item status lists written by Obsidian Properties as the same status value in TaskNotes Kanban, so they no longer create duplicate columns. Thanks to @mlevison for reporting this.\n- (#983) Let Agenda Calendar views wrap their header controls and task titles inside narrow sidebars, so Today and refresh controls and task icons remain visible without sideways scrolling. Thanks to @3zra47 for reporting this.\n- (#982) Made TaskNotes task-card typography scale from Obsidian's text font size setting, so Bases and Agenda task text follows larger mobile font settings. Thanks to @3zra47 for suggesting this and @chrsdk and @scottaltham-payroc for the follow-up.\n- (#966) Made reminder delete buttons larger and always visible on mobile, so reminders can be removed from the Manage All Reminders modal on iPad. Thanks to @PSG2017 for reporting this.\n- (#964) Made Pomodoro and time-tracking task selection use the current recurring instance status, so a recurring task can still be selected after an earlier instance was completed. Thanks to @lomarcanys for reporting this.\n- (#944) Preserved number and boolean custom field values when moving tasks between grouped Kanban or Task List columns, and when creating a task from a grouped Kanban column. Thanks to @thoughtcipher for reporting this.\n- (#935) Fixed Task List priority sorting so descending order puts higher-weighted priorities first, and due dates are used before scheduled dates when priority values tie. Thanks to @Glint-Eye for reporting this and @kacoroski for the follow-up.\n- (#922) Made the `Blocked` task-card pill expand the blocker tasks, and rendered `blockedBy` dependencies as clickable links when that property is shown on cards. Thanks to @prayidae for reporting this and following up.\n- (#919) Fixed exported ICS task events so they use valid calendar event statuses and can be imported by stricter calendar apps. Thanks to @benoitjadinon for reporting this.\n- (#1213) Fixed embedded Task List Bases in Obsidian pop-out windows so typing below the embed no longer leaves a large blank gap. Thanks to @same774 for reporting this.\n- (#1243) Removed quoted multi-word custom field NLP expressions from created task titles after saving the custom field value. Thanks to @Arachnidai for reporting this.\n- (#1252) Hardened the calendar-first task date picker for iPad taps so date buttons use direct touch manipulation. Thanks to @alxandrharris for reporting this.\n- (#1261) Removed the extra Task List Base scrollbar when an embedded task list note is placed in a sidebar, while keeping normal embedded task lists scrollable in the main note area. Thanks to @cathywu for reporting this.\n- (#1347) Lowered TaskNotes task-card tag CSS specificity so hierarchical tag colors from Obsidian themes and tag-color plugins can apply correctly. Thanks to @3Fish for reporting this.\n- (#1374) Recognized status and priority labels entered through Obsidian Properties or Bases as their configured TaskNotes values. Thanks to @phortx for reporting this.\n- (#1373) Parsed numeric natural-language dates with the configured calendar locale, so `en-GB` treats `11/06/2026` as 11 June instead of November 6, and `YYYY/MM/DD` works consistently. Thanks to @AleMunin for reporting this and @imsuck for the follow-up.\n- (#1370) Prevented recurring task series from being queued for auto-archive when their parent status uses auto-archive, so ongoing recurring tasks are not moved away after completing an occurrence. Thanks to @Jomo94 for reporting this and @martin-forge for the follow-up discussion.\n- (#1367) Made recurring task completion counts use the total expected instances for finite `COUNT` or `UNTIL` recurrences, and stopped showing a made-up percentage for unbounded recurrences. Thanks to @saurinni for reporting this.\n- (#1365) Preserved email and other URI links from converted inline task titles by moving the original links into the new task body, and rendered `message:`/`mailto:` markdown links as external links in TaskNotes surfaces. Thanks to @phillipadsmith for reporting this and @hasanyilmaz for the follow-up.\n- (#1350) Refreshed inline task widgets in Reading mode after task property edits, so changed dates and other visible properties no longer stay stale until the note is reopened. Thanks to @tmsbn for reporting this.\n- (#1329) Pulled the relationships widget up to the end of the note content without removing its normal spacing, and kept that placement updated while editing and on load so it no longer covers the editor. Thanks to @Volker-brdb for reporting this.\n- (#1326) Treated empty task frontmatter values as missing, so empty titles fall back to the filename and blank date, priority, and recurrence fields are ignored. Thanks to @craziedde for suggesting this.\n- (#1316) Stopped stale Workspace state from overriding the configured Calendar view mode, so switching Workspaces no longer forces an old Day/Week/List choice over the view default. Thanks to @kmaustral for reporting this and following up.\n- (#1302) Read task frontmatter directly from the task file when Obsidian has not indexed its metadata yet, so visible tasks can still be opened, updated, and selected instead of reporting \"Task not found\". Thanks to @WorldTeacher for reporting this and @Steven-AA for confirming it.\n- Kept just-written task data available while Obsidian's metadata cache catches up, so immediate reads after task edits no longer briefly return stale values.\n- (#1297) Made the Create or open task footer tappable, so mobile users can create the typed task without needing the Shift+Enter shortcut. Thanks to @slipstyle for reporting this.\n- (#1288) Allowed formula properties to appear in Calendar property-based event start and end date selectors. Thanks to @hasanyilmaz for reporting this.\n- Made TaskNotes Kanban drags show a lightweight held-card preview, so the dragged card remains easy to track while the source column opens the drop slot.\n- (#1423) Refreshed TaskNotes Bases views when subtasks are deleted, so expanded project cards drop removed subtasks and stop showing project controls when the last subtask is gone. Thanks to @normenmueller for reporting this.\n- (#1419) Kept custom user field name, key, and default-value edits in Task Properties settings when closing settings without first blurring the field. Thanks to @s33a for reporting this and @kacoroski for the follow-up.\n- Reduced redundant settings writes by coalescing overlapping saves, so settings changes made in quick succession finish with the latest values without repeating every intermediate save cycle.\n- (#1331, #1411) Made Agenda Calendar Bases respect the Base sort order within each day instead of falling back to alphabetical title order. Thanks to @bane73 and @ky1ejs for reporting this.\n- (#1383) Made task modal markdown editors expose the active editor API expected by plugins such as Templater. Thanks to @tomsymonds for reporting this.\n- Fixed the first-run Create/Edit Task modal so the default fields appear immediately after installing TaskNotes, without needing to open Modal Fields settings or restart Obsidian.\n- (#1895) Restored the natural-language preview in the Create Task modal. Thanks to @ssonhub for reporting this.\n- (#1898) Cleared stale Calendar time-axis column widths when switching views, so Day, Week, and 3-day views keep the time labels anchored on the left. Thanks to @ddevaal for reporting this.\n- (#1439) Fixed generated Bases dependency filters so `blockedBy` entries stored as links, strings, or dependency objects are handled consistently in Not Blocked and Relationships views. Thanks to @prayidae for reporting this and following up.\n- (#1435) Prevented malformed task dependency, status, or priority values from breaking the task context menu. Thanks to @23maverick23 for reporting this.\n- (#1434) Kept older filename-titled tasks readable after turning off \"Store title in filename\" by falling back to the filename when a task has no usable title property. Thanks to @hujuDev for reporting this.\n- (#1433) Made the Due date and Scheduled date weekday picker follow the configured first day of week. Thanks to @sandchipper for reporting this.\n- (#1430) Showed custom user-field property keys in Modal Fields settings instead of internal field IDs. Thanks to @JerryLu086 for reporting this.\n- (#1427) Fixed project autosuggest Required Tags filters so frontmatter tags parsed by Obsidian are handled the same way as direct tag-property filters. Thanks to @ProHaller for reporting this.\n- (#1495) Added an Update default files action for generated Bases views, so task-tag or task-identification setting changes can refresh existing `.base` filters without deleting files manually. Thanks to @Liya430 for reporting this.\n- (#1512) Prevented the split Create/Edit Task modal details pane from collapsing to a one-character-wide column under the Minimal theme. Thanks to @willfanguy for reporting this and sharing detailed CSS notes.\n- (#1524) Fixed task-card font sizes shrinking when a Bases view is opened in an Obsidian pop-out window. Thanks to @Glint-Eye for reporting this.\n- (#1535) Fixed the generated Relationships Base Subtasks filter so single project links do not trigger a Bases `contains` error. Thanks to @DanaKyle for reporting this.\n- (#1102) Refreshed task cards when a task status is edited directly in Obsidian frontmatter, so the card no longer stays on the old status until it is clicked. Thanks to @Wayment9504 for reporting this.\n- (#1105) Added an explicit Close action to the mobile task options menu, so iPhone users do not need to tap near the top system bar to dismiss it. Thanks to @J-R-Troutman for reporting this.\n- (#1550) Prevented mobile Calendar event drags from opening the task context menu before the drag can begin. Thanks to @stil-sudo for suggesting this.\n- (#1563) Removed duplicate entries from Calendar event related notes when the same linked file is also a TaskNote. Thanks to @VarunNikam22 for reporting this.\n- (#1566) Rendered grouped multi-project values as individual links when a Bases group title contains multiple project links. Thanks to @ptsouchlos for suggesting this.\n- (#1569) Allowed local ICS calendar paths inside the vault to be pasted as absolute filesystem paths, and showed a clearer error when the file is outside the vault. Thanks to @Photon89 for reporting this and following up.\n- (#1584) Sanitized task-card status and priority class names, so custom values with spaces no longer create invalid CSS classes. Thanks to @omber for reporting this.\n- (#1587) Stored dependencies added from the task context menu as wikilinks, matching the Edit Task modal. Thanks to @mgrecar for reporting this.\n- (#1590) Clarified HTTP API task creation docs and OpenAPI schema for writable `blockedBy` dependencies, and marked `blocking` as a read-only derived relationship. Thanks to @hGriff0n for reporting this.\n- (#1591) Added a startup guard that avoids saving default settings over an existing settings file if Obsidian temporarily returns no plugin data during an update. Thanks to @GGlider for reporting this.\n- (#1593) Made the New button in TaskNotes Bases views open the TaskNotes create task modal again, so new tasks respect the configured default tasks folder. Thanks to @katlandreth for reporting this.\n- (#1594) Made task cards inside recurring task notes complete the task's current scheduled occurrence instead of today's date when no calendar or view date is supplied. Thanks to @ngraham20 for reporting this.\n- (#1601) Prevented overlapping Live Preview relationship-widget injections from leaving duplicate subtask/relationship sections in a note. Thanks to @wealthychef1 for reporting this and @benmartinek for confirming it.\n- (#1610) Made expanded subtasks in TaskNotes Bases views follow the current view's sorted task order instead of a fixed fallback order. Thanks to @MrZzard for reporting this and @slipstyle for confirming it.\n- (#1609) Restored scrolling in wide split-layout task edit modals when the form content is taller than the modal. Thanks to @3zra47 for reporting this.\n- (#1614) Wrote unchecked boolean custom user-field defaults to new task frontmatter, including tasks created through instant conversion. Thanks to @kobalteule for reporting this.\n- (#1611) Made generated default Bases urgency scores fall back safely when the next-date distance is missing. Thanks to @benoitjadinon for reporting this and suggesting the formula fix.\n- (#1623) Honored \"Store title in filename\" across task creation and edits, so the mapped title property is omitted from frontmatter and stale title fields are removed on save. Thanks to @VenturaNotes for reporting this, and to @Ender367, @slipstyle, and @loukandr for confirming and tracing affected paths.\n- (#1621) Made Kanban swimlane labels stop freezing on mobile and kept their label column compact, leaving more room for task cards while horizontally scrolling. Thanks to @karenchoe428 for reporting this.\n- (#1615) Detected Obsidian custom multi-text properties exposed through `widget: \"multitext\"` as list properties, so Kanban can split those values into multiple columns. Thanks to @konton71 for reporting this.\n- (#1626) Expanded recurring ICS subscription events through the one-year subscription window for high-frequency recurring calendars. Thanks to @pib for reporting this.\n- (#1628) Refreshed Calendar Bases views promptly when switching between filtered Agenda views, so the previous view's task set does not stay visible until the delayed refresh. Thanks to @Lanalangz for reporting this.\n- (#1629) Saved `blockedBy` dependencies selected in the Create Task modal. Thanks to @obsilover for reporting this.\n- (#1634) Aligned custom status icons in inline tasks with the default inline status circle. Thanks to @ttlaylor for reporting this and @basbarten for confirming it.\n- (#1636) Restored the active styling for the Calendar list-view toolbar button. Thanks to @vroablec for reporting this.\n- (#1493, #1638) Kept task time tracking consistent when switching or clearing tasks during an active Pomodoro. Thanks to @ROS-SDN and @katonapng for reporting this, and to @anomatomato for confirming it.\n- (#1639) Respected the aliased-link overlay exclusion in Reading mode even when the alias text matches the task title. Thanks to @MiracleXYZ for reporting this.\n- Fixed actively tracked task cards so the blue time-tracking outline stays visible along the card edges.\n- (#1657) Preserved Bases view defaults when creating tasks from the TaskNotes Kanban/List view New button, so project-scoped views can pass their project assignment into the create task modal. Thanks to @casualQuads122 for reporting this.\n- (#728, #1831) Preserved frontmatter defaults supplied by Obsidian's Bases New action when opening the TaskNotes create task modal from custom Bases views, so filtered views can prefill matching tags, projects, contexts, and custom fields. Thanks to @DillPickle80 and @echo-saurav for suggesting this, and to @prayidae and @renatomen for the detailed follow-up.\n- (#726) Added an instant-conversion option to use the closest heading above the converted line as a project, so checkbox tasks under project headings can inherit that project automatically. Thanks to @ghelton for suggesting this.\n- (#1662) Preserved frontmatter from ICS event note templates when quoted event variables or Templater expressions are used. Thanks to @victorhg for reporting this.\n- (#1663) Fixed Japanese and other Unicode tags on task cards so Kanban tag pills keep the same rounded styling as ASCII tags. Thanks to @kutty-1119 for reporting this.\n- (#1649) Restored daily-note navigation from the Calendar Day view date header. Thanks to @BaccanoMob for reporting this.\n- (#1648, #1665) Fixed the API endpoint list in Integrations settings so it uses the configured bearer token when API authentication is enabled, instead of reporting the running local server as inaccessible. Thanks to @npondel and @warm-july for reporting this.\n- (#1668) Fixed the Create Task magic wand so NLP-triggered custom field values are copied into the custom property inputs before saving. Thanks to @hokfujow for reporting this.\n- (#1669) Stopped the startup settings migration check from rewriting `data.json` just because saved calendar defaults are `false`, `0`, empty, or `null`, reducing unnecessary sync churn. Thanks to @thehyperadvisor for reporting this.\n- (#1674) Improved the timeblock creation error when Daily Notes cannot read its configured folder, so the modal notice points to the Daily Notes core plugin settings instead of only logging the folder lookup failure. Thanks to @Ender367 for reporting this.\n- (#1680) Fixed TaskNotes Calendar Bases options stored under `options`, so Agenda views respect `showPropertyBasedEvents: false` and no longer show duplicate property-based rows for the same task. Thanks to @xiaoyaozhu1991 for reporting this and @KondrotM for confirming it.\n- (#1681) Reduced the cost of inline checkbox convert buttons by only scanning the visible editor range instead of the full document. Thanks to @en-ot for reporting this and @hokfujow for the follow-up.\n- (#1689) Fixed task reminders added or rescheduled through direct frontmatter edits so the notification queue refreshes immediately and relative reminders recalculate from the latest task dates. Thanks to @garzonjav for reporting this.\n- (#1693) Fixed generated default Bases formulas so empty due and scheduled dates are checked with `.isEmpty()` instead of date-field truthiness. Thanks to @benoitjadinon for reporting this.\n- (#1702) Removed the forced bottom gap under TaskNotes custom Bases views, so calendar and other TaskNotes views can fill the available pane height. Thanks to @AudreyLooby for reporting this.\n- (#1719) Fixed task cards in reading mode so Obsidian 1.12.x header changes no longer place the card above the title and properties or drop it after returning to a tab. Thanks to @tholbrook9 for reporting this and tracing the DOM change.\n- (#1722) Saved the source note immediately after converting an inline checkbox task to a TaskNote, so Kanban views do not keep showing the stale inline task alongside the new task file. Thanks to @literallydope for reporting this and sharing screenshots.\n- (#1750) Fixed generated default Bases filters for property-based task identification when the identifying property name contains spaces. Thanks to @Igorgro for reporting this.\n- (#1745) Clarified the inline task documentation so `Create new inline task` is distinguished from current-line conversion. Thanks to @yvos for reporting the mismatch.\n- (#1485) Stopped Google Calendar manual refresh from showing a success notice after token refresh or calendar-list failures. Thanks to @ebanDev for reporting this.\n- (#1474) Made priority-based Kanban swimlanes follow the configured priority order instead of alphabetical task data order. Thanks to @kanzaki1201 for reporting this and @SoTHISIsFitness for the follow-up investigation.\n- (#1470) Restored pointer cursors on TaskNotes interactive elements under Obsidian themes that set `--cursor` to the default cursor. Thanks to @TheFrostedDev for reporting this.\n- (#1463) Documented the supported `FilterQuery` payload for `POST /api/tasks/query`, including context filtering examples and generated API schema details. Thanks to @tcb678 for reporting this and @soloidx for sharing a working query example.\n- (#1464) Made `context` on `GET /api/tasks` follow the same filtering guidance as `project`, so the API now points clients to `POST /api/tasks/query` instead of ignoring the parameter. Thanks to @tcb678 for suggesting this.\n- (#1457) Rendered scheduled-to-due calendar spans with scheduled times as daily timed events instead of moving them to the all-day section. Thanks to @atos2212-blip for reporting this and @rayvermey for confirming it.\n- (#1450) Returned configured user fields in HTTP API task responses under `customProperties`, while keeping the configured frontmatter keys available on each task. Thanks to @Admorei for reporting this and @nschenone for the follow-up.\n- (#1449) Let embedded Agenda views use auto-height sizing by default, so one-day list embeds no longer reserve a large empty calendar block. Thanks to @GlebYavorski for reporting this.\n- (#1446) Kept custom Kanban columns from `columnOrder` available when they are empty, so `hideEmptyColumns: false` can show drop targets for custom grouped values. Thanks to @akhtsang for reporting this.\n- (#1459) Avoided double \"Failed to create task\" prefixes in task creation error notices. Thanks to @Sineapple for reporting this, and to @slipstyle and @Stockemer for the follow-up investigation.\n- (#1469) Fixed Convert current note to task so saving the untouched edit modal writes the task frontmatter instead of reporting no changes. Thanks to @slipstyle for reporting this, and to @jhoogeboom and @ngraham20 for confirming it.\n- (#1466) Prefilled the current note as the project when creating a task from an embedded Subtasks/Relationships Base filtered with `this.file.asLink()`. Thanks to @jhoogeboom for reporting this, and to @cybersader, @fsmontenegro, and @benmartinek for the follow-up discussion.\n- (#1476) Showed linked parent-task project titles instead of timestamp filenames in project stats and grouped task views when the linked task has a frontmatter title. Thanks to @RumiaKitinari for reporting this.\n- (#1487) Let Calendar task event titles wrap instead of clipping long names, and removed the redundant due-date prefix from due task events. Thanks to @Alexander-Bergmann for reporting this.\n- (#1488, #1739) Enabled Kanban touch dragging on touch-capable desktop and convertible devices, not only mobile Obsidian. Thanks to @tmoyland001 and @mgsima for reporting the drag failures, and @SoTHISIsFitness for investigating related task-property cases.\n- (#1738) Fixed Outlook calendar subscriptions whose event timezones reference the base Windows timezone name while the feed defines a suffixed timezone name. Thanks to @Mirrimo for reporting this, @rafavital for confirming it, and @rogerfsh for tracing the ICS timezone mismatch.\n- (#1734) Fixed dependency picker search when task priority values are stored as non-string frontmatter values. Thanks to @MatthewClarkeDev for reporting this and identifying the stack trace.\n- (#1733) Preserved wikilinks in task titles and rendered them as clickable links on task cards. Thanks to @bitscorch for suggesting this.\n- (#1728) Applied the \"Use parent note as project\" default when creating a new task from the command palette or ribbon. Thanks to @greatEmily for reporting this.\n- (#1759) Advanced stale due dates when recurring tasks move to their next scheduled occurrence, so work-window tasks do not remain overdue after completion. Thanks to @MattPryze for reporting this.\n- (#1766) Fixed Calendar Bases date navigation from custom note properties, so embedded calendar views can open on the date stored in the selected property instead of falling back to today. Thanks to @chrabia for reporting this.\n- (#1767) Aligned the start and end time rows in the timeblock creation modal. Thanks to @loiveli for reporting this.\n- (#1783) Replaced the default browser drag ghost for Kanban cards so dragging a card no longer makes the next card look semi-transparent. Thanks to @loukandr for reporting this and tracing the drag image behavior.\n- (#1796) Restored expanded subtasks immediately after renaming a parent task file and updating links. Thanks to @bung69 for reporting this.\n- (#1797) Improved manual ordering so long Kanban columns remain scrollable while dragging, mobile Kanban drops can place a card relative to another card, Kanban/Task List drops resolve the final drop position more reliably, generated manual-order ranks match Bases sorting, and manual-order properties such as `sort_order` render on task cards when enabled. Thanks to @SKIERZZ for reporting this and sharing videos.\n- (#1812) Separated Microsoft OAuth token status from calendar sync status, and surfaced Microsoft calendar fetch errors in the integrations settings card instead of leaving them console-only. Thanks to @henninger80 for the detailed report.\n- (#1814) Restored NLP project autosuggest in the Create or Open Task command, so `+` project suggestions use the same filtered project lookup as the Create Task modal. Thanks to @adammahad for reporting this.\n- (#1820) Kept API-created tasks readable immediately after creation even if Obsidian has not finished indexing the new file metadata yet. Thanks to @vadminas for reporting and tracing the cache desync.\n- (#1823) Prevented zero-duration timed external calendar events from rendering under more than one day in list-style calendar views. Thanks to @martin-forge for reporting and tracing the Google Calendar case.\n- (#1841) Prevented Kanban boards from duplicating columns when wikilinked status values are grouped through Bases. Thanks to @lendamico for reporting and sharing the screen recording.\n- (#1846) Saved NLP-triggered boolean custom fields as real booleans instead of quoted strings, so they match checkbox-created values and Bases filters. Thanks to @DevOps-Toast for reporting and sharing screenshots.\n- (#1849) Prevented repeated clicks on task-card scheduled and due date labels from stacking duplicate date menus when Obsidian native menus are disabled. Thanks to @3zra47 for reporting.\n- (#1850) Added mobile bottom spacing to TaskNotes list views so the final task can scroll above Obsidian's floating mobile controls. Thanks to @AlejandroRigau for reporting and sharing the iPhone screenshot.\n- (#1852) Improved mobile timed calendar event rendering with shorter time labels, tighter spacing, and event-colored task/calendar blocks. Thanks to @redrumthebum for reporting and sharing screenshots.\n- (#1757, #1853, #1775) Respected an existing `mdbase.yaml` `types_folder` when regenerating mdbase task type definitions, so the generated `task.md` can live outside the vault-root `_types` folder. Thanks to @aldrichtr for the original request and implementation exploration, and @hangryscribe3 for the follow-up request.\n- (#1858) Included task body details in single-task HTTP API and MCP reads. Thanks to @vanillaflava for reporting and outlining the expected behavior.\n- (#1859) Clarified the Google Calendar setup guide for OAuth testing-mode `access_denied` errors. Thanks to @PE-Boy for reporting and @tiagoarroz for the workaround.\n- (#1860) Preserved accented characters in tags when converting checkbox tasks to TaskNotes. Thanks to @e-zz for reporting.\n- (#1869) Preserved Calendar Month View scroll position after task updates. Thanks to @sisyowo for reporting and linking the earlier Kanban fix.\n- (#1873) Prevented Calendar Bases from rendering in Obsidian pop-out windows because restoring FullCalendar there can freeze Obsidian. Thanks to @misolex for reporting.\n- (#1497, #1870) Fixed NLP file suggestions for custom fields so selected wikilinks are captured as custom field values, including list-type fields. Thanks to @Naesue and @Sineapple for reporting this, and to @bradleyed and @Xananax for the follow-up details.\n- (#1888) Allowed project autosuggest required property filters to match any comma-separated value, such as `project, area`. Thanks to @BrianHicks for suggesting.\n- (#1886) Added a command to postpone active overdue scheduled tasks to today. Thanks to @chrabia for the suggestion.\n- (#1889) Fixed Kanban swimlanes for list-valued properties so tags and contexts use individual list items instead of comma-joined values. Thanks to @pkropotin for reporting.\n- (#1890) Fixed scheduled-date Kanban columns dropping tasks when date-only and timed tasks on the same day are sorted by a scheduled-time formula. Thanks to @chrabia for reporting and investigating.\n- (#773) Added ICS export filters for archived tasks, completed tasks, due dates, and scheduled dates. Thanks to @ras0q for suggesting this and @slipstyle for the scheduled-date follow-up.\n- (#765) Reduced side-pane gutters around embedded TaskNotes Bases views, so embedded task lists use about the same horizontal space as directly opened Bases views. Thanks to @TonyAtlas for suggesting this.\n- (#1892) Fixed nested Markdown list indentation in the Task Edit Modal details editor. Thanks to @Glint-Eye for reporting.\n- (#1891) Fixed TaskNotes modal markdown editors collapsing to one-character-wide lines when Pretty Properties is installed. Thanks to @bkennedy-improving for reporting.\n- (#1499) Respected excluded folders when opening tasks directly from view results and when building dependency/project indexes, so template-folder tasks no longer appear through TaskNotes views. Thanks to @Liya430 for reporting.\n- (#136, #1500) Made the Pomodoro countdown derive remaining time from the session clock instead of from counted interval ticks, so delayed, backgrounded, or screen-off ticks catch up cleanly without over-recording a completed session. Thanks to @Poly-0000 for reporting and documenting the original background timer issue, @Totobal5 for the earlier worker-based fix, and @CoffeaUrbana for the Android screen-off report.\n- Restored padding in task modal Markdown editors.\n- Made the markdown editor areas in task modals easier to click and focus.\n- Strengthened local CSS linting to catch unscoped selectors, unknown CSS, and fixed-position overlays before review.\n- Reduced false-positive plugin review warnings by making background auto-export and auto-archive schedulers non-overlapping and tightening type/string conversion paths.\n- (#1882) Made Google Calendar task descriptions use mobile-friendly plain text for Obsidian links and display labels for wiki-style project/context links. Thanks to @martin-forge for the contribution.\n- (#1883) Improved Google Calendar task sync recovery so failed deletions, offline sync requests, reconnects, and quick create/update races are retried more reliably. Thanks to @martin-forge for the contribution.\n","aliases":["/releases/4.8.0/","/releases/4.8.0/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • (#353) Added a Has Subtasks filter for task queries, so views and API clients can show only project-style tasks or direct tasks. Thanks to @mdbraber for suggesting this.
  • \n
  • (#380) Added a test-reminder button in notification settings, so reminder setup can be checked without creating a real task reminder. Thanks to @mdbraber for suggesting this.
  • \n
  • (#711, #168) Added an optional task-creation setting to open the new task note after saving, either in the current tab or a new tab. Thanks to @phortx and @23426356587 for suggesting this, and to @edward-peters and @obsilover for the follow-up.
  • \n
  • (#1041, #1800) Added copy-drag support for timeblocks: hold Ctrl, Cmd, or Alt/Option while dragging an existing timeblock to duplicate it at the new date and time. Thanks to @0-BSCode and @cweekly for suggesting this.
  • \n
  • (#1052) Added a public JavaScript API for in-vault scripts at app.plugins.plugins.tasknotes.api.parseNaturalLanguage(text), so Templater, QuickAdd, and MetaBind workflows can use TaskNotes' natural-language parser without running the HTTP API. Thanks to @edakimling for suggesting this.
  • \n
  • (#1235) Added a task-card toggle for blocked tasks, so you can expand a blocked task to see the tasks it is waiting on. Thanks to @craziedde for suggesting this.
  • \n
  • (#1254) Added ../ and ./ normalization for folder templates after variables are expanded, so instant task conversion can target sibling folders such as {{currentNotePath}}/../Tasks. Thanks to @rdick for suggesting this.
  • \n
  • (#1267) Added Daily Notes-style date tokens such as YYYY, MM, DD, MMMM, and dddd to TaskNotes folder templates. Thanks to @paulsen-it for suggesting this.
  • \n
  • (#1380) Added tag actions to task context menus, including add/remove actions for individual tasks and batch-selected tasks. Thanks to @Chuhtra for suggesting this.
  • \n
  • (#1377) Added right-click Mini Calendar actions for opening daily notes from day cells and weekly notes from week numbers. Thanks to @hasanyilmaz for suggesting this.
  • \n
  • (#1151) Added a Mini Calendar max color note count option, so one-note days can use the strongest heatmap color when that better fits the view. Thanks to @arreme for suggesting this.
  • \n
  • (#1376) Added backslash escapes for NLP trigger tokens, so text like \\@context, \\*done, or \\tomorrow can stay in the task title. Thanks to @JerryLu086 for suggesting this.
  • \n
  • (#1366) Added CSS variables for compacting nested task-card indentation, with smaller defaults on mobile and documented snippets for tighter task-link lists. Thanks to @rk-kontur for suggesting this.
  • \n
  • (#1502, #603) Added calendar indicators for external events that have linked notes or tasks, and showed loaded event titles in task-card calendar metadata instead of only the linked event count. Thanks to @Robubble and @mdbraber for suggesting this, and to @ubidev for the follow-up.
  • \n
  • (#1522) Added a per-status option to skip rarely used statuses when cycling task-card status indicators. Thanks to @Glint-Eye for suggesting this.
  • \n
  • (#144) Added an "Open note in new tab" action to the task context menu. Thanks to @cathywu for suggesting this and @macbikegeek for the follow-up feedback.
  • \n
  • (#167) Added an optional next-status override for each status, so forward cycling can jump to a configured status instead of always following the status order. Thanks to @DanBrazelton for suggesting this, and to @michelebugio, @Moyf, @anareaty, and @vorrermid for the follow-up feedback.
  • \n
  • (#1520) Made tag and context fields show available suggestions as soon as the field is focused. Thanks to @Glint-Eye for suggesting this, and to @craziedde for the follow-up.
  • \n
  • (#1541) Added {{currentNotePath}} and {{currentNoteTitle}} support to the default tasks folder, so normal task creation can place new tasks beside the active note without creating an inline link. Thanks to @ChristianAnyanwu for suggesting this, and to @abbasou and @ttlaylor for the follow-up feedback.
  • \n
  • (#648, #1605) Added clickable links in task-card contexts for note links, markdown links, and web URLs while keeping plain contexts as tag-search buttons. Thanks to @trdischat and @Glint-Eye for suggesting this, and to @renatomen for the follow-up feedback.
  • \n
  • (#1482) Added clickable custom-field links on task cards for wikilinks, markdown links, autolinks, and bare web URLs. Thanks to @ptbosch-figueiredorj for suggesting this, and to @Soleone for the follow-up use case.
  • \n
  • (#1471) Added Kanban column and swimlane-cell add buttons that open the TaskNotes creation modal with the grouped values already filled in. Thanks to @byheaven for suggesting this and @Davincible for the project-board use case.
  • \n
  • (#933) Added non-Markdown vault files such as canvases to project suggestions, using extension-qualified link targets so those files can be selected as task projects. Thanks to @Alvin21Bon for suggesting this.
  • \n
  • (#1475, #725) Added quote/backtick escapes for NLP input, so literal course codes or date words can stay in task titles without being parsed as estimates or dates. Thanks to @RumiaKitinari and @gavingwebb for suggesting this.
  • \n
  • (#1462) Added natural-language date entry to the task date picker, so existing due and scheduled dates can be changed with phrases such as "tomorrow at 3pm" when NLP is enabled. Thanks to @Ruboks-Cube for suggesting this.
  • \n
  • (#1526) Added a native date field to the task date picker, so scheduled and due dates can be changed with the device date picker while keeping optional times visible. Thanks to @jmartinmcfly for suggesting this and @23426356587 for the follow-up feedback.
  • \n
  • (#1603) Added Calendar view toggles for hiding completed or skipped recurring task instances while keeping future outstanding instances visible. Thanks to @wandererovertheseaofpiss for suggesting this.
  • \n
  • (#287, #273, #274) Added linked hover highlighting for Calendar and Agenda events that come from the same task note, so scheduled, due, and recurring entries are easier to connect. Thanks to @girisumit for suggesting this.
  • \n
  • (#280) Added project-specific CSS hooks to task cards and Calendar events, so project-based visual styling can be handled with user snippets. Thanks to @girisumit for suggesting this.
  • \n
  • (#1625) Added Shift + Cmd/Ctrl + Enter in the Create Task modal to save the current task and reopen the modal for the next one. Thanks to @tcb678 for suggesting this.
  • \n
  • (#1353) Focused the Create Task modal's natural-language input when the modal opens, with a longer mobile delay so the keyboard can open after layout. Thanks to @GiovanH for suggesting this.
  • \n
  • (#1664) Added project-based custom filename template variables, including the first project, all projects, and a short projectId. Thanks to @bendavis987 for the contribution.
  • \n
  • (#923) Added {{projectFilePath}} and {{projectFilePaths}} folder template variables, so task folders can mirror project note locations in the vault. Thanks to @PacoTaco2 for suggesting this.
  • \n
  • (#1697) Added cached Google Calendar, Microsoft Calendar, and ICS events to Mini Calendar days, with compact colored dots and event details from the existing calendar connection. Thanks to @RPGArchivist for suggesting this.
  • \n
  • (#1754) Added optional icons for priority values, so task cards can show a configured priority icon instead of only a colored dot. Thanks to @BrucePlumb for suggesting this and @prepare4robots for the follow-up feedback.
  • \n
  • (#1761) Added TaskNotes edit and task-action submenu entries to Obsidian's native file context menu for recognized task notes. Thanks to @delzero for suggesting this.
  • \n
  • (#1771) Added mobile drag handles to manually sorted Task List Bases views, so dragging can start from the handle without disabling normal text interaction on the rest of the card. Thanks to @PatrickGolz for suggesting this.
  • \n
  • (#1776) Allowed calendar timeline end times after midnight, such as 26:00 for a 2 AM next-day end. Thanks to @chrabia for suggesting this.
  • \n
  • (#1784, #1833) Added a per-view pinnedColumns option for TaskNotes Kanban views, so selected empty columns can stay visible as drop targets while other empty columns remain hidden. Thanks to @loukandr for suggesting and prototyping this.
  • \n
  • (#1794) Added context updates to the task card context menu, so contexts can be added, toggled, or cleared without opening the task edit modal. Thanks to @m13ntrpn for suggesting this.
  • \n
  • (#315, #1356, #1748, #1809) Added a subtle task-card indicator and CSS hooks for tasks with note body details, including existing task bodies read through Obsidian's metadata cache. Thanks to @volodxyz, @Karut, @yeHHH1g, and @aliceinwaterdeep for suggesting this, and to @minchinweb for the follow-up.
  • \n
  • (#1808) Added advanced Kanban swimlane ordering through swimLaneOrder, so swimlane rows can stay in a stable configured order. Thanks to @rookledookle for suggesting this, and to @benmartinek and @chrabia for the follow-up feedback.
  • \n
  • (#1805) Added an ICS export option to omit completed tasks from generated calendar files. Thanks to @bepolymathe for suggesting this.
  • \n
  • (#659) Added Obsidian links to ICS export descriptions, so exported calendar events can open their source task notes. Thanks to @bepolymathe for suggesting this.
  • \n
  • (#589) Added an Appearance toggle to turn off strikethrough styling on completed task card titles. Thanks to @BrucePlumb for suggesting this.
  • \n
  • (#561) Added a "Last day" option to the custom recurrence month-day picker for month-end repeating tasks. Thanks to @TonyAtlas for suggesting this and @BrucePlumb for the follow-up.
  • \n
  • (#217) Added weekday selection to daily custom recurrence rules, so interval rules such as every three days can skip weekends from the recurrence modal. Thanks to @kmaustral for suggesting this.
  • \n
  • (#1818) Added an auto-height mode for TaskNotes Calendar Bases views so embedded agenda/list sections can size to their content instead of forcing an inner scroller. Thanks to @martin-forge for suggesting this.
  • \n
  • (#1201) Added a Calendar Bases toggle to hide the hourly breakdown in week, custom-days, and day views while keeping the all-day planning row visible. Thanks to @PacoTaco2 for suggesting this.
  • \n
  • (#1176) Added advanced Kanban WIP limits through wipLimits, so column headers can show (current/limit) counts and highlight exceeded limits. Thanks to @williamcheuk03 for suggesting this.
  • \n
  • (#914) Added a generated Due in countdown to the default Agenda Base and allowed Calendar Bases list agendas to span up to 365 days. Thanks to @williamcheuk03 for suggesting this.
  • \n
  • (#900) Added an instant-conversion setting to keep the original Markdown checkbox marker when converting a checkbox into a TaskNote link. Thanks to @dsebastien for suggesting this.
  • \n
  • (#898) Added a mobile-only calendar integration opt-out, so synced desktop calendar settings no longer have to trigger external calendar loading on Obsidian Mobile. Thanks to @cathywu for suggesting this.
  • \n
  • (#887) Added built-in scheduled and due date presets to the Quick actions palette for current tasks. Thanks to @willgraham345 for suggesting this and @anrie for the related preset feedback.
  • \n
  • (#819) Added a command to open Quick actions for the inline task link under the cursor. Thanks to @rlolingo for suggesting this.
  • \n
  • (#798, #1732, #1835) Added hotkeyable commands to edit the current task, add a project to the current task, and add an existing task as a subtask of the current note. Thanks to @xorander00 and @prepare4robots for requesting this, and to @musta-code and @ubidev for the follow-up suggestions.
  • \n
  • (#791) Added a UUID v4 task filename format and {{uuid}} custom filename template variable. Thanks to @bangbangbanggit for suggesting this.
  • \n
  • (#932) Added hotkeyable commands to cycle the current task's status and priority. Thanks to @rxunique for suggesting this and @luckb0x for the follow-up feedback.
  • \n
  • (#1655) Added live elapsed time to the optional active time tracking status bar item. Thanks to @connradolisboa for suggesting this.
  • \n
  • (#1622) Allowed multiple comma-separated default reminder offsets for timed Google Calendar task exports. Thanks to @solidabstract for suggesting this.
  • \n
  • (#706, #820, #1040) Added direct Pomodoro duration editing, hour-aware timer formatting, clearer one-minute controls, and an optional active Pomodoro status bar countdown. Thanks to @SublunarSage, @lj1446615403-cloud, @0-BSCode, and @thestrike72 for the suggestions and feedback.
  • \n
  • (#873) Added an optional built-in sound for task reminder notifications, with volume and preview controls in Settings. Thanks to @berzernberg for suggesting this.
  • \n
  • Added a generated Pomodoro statistics Base with daily and monthly summary views for Pomodoro history stored in daily notes.
  • \n
\n

Changed#

\n
    \n
  • Expanded the bug report template to ask for Obsidian "Show debug info" output, affected task frontmatter, relevant Bases file contents, reproduction steps, and related logs or screenshots.
  • \n
  • Release notes now show the default .base file regeneration reminder only on the current version section, keeping older bundled sections focused on their own changes.
  • \n
  • Updated the release notes GitHub prompt to invite feedback while still asking satisfied users to star the project.
  • \n
  • (#239) Ordered Kanban status and priority columns by the configured status order and priority weights when no manual column order is saved. Thanks to @ScumbagScalawag for asking about this, and to @nightroman, @lavir, and @elvarb for the follow-up discussion.
  • \n
  • (#269) Marked Kanban status columns that come from values outside the configured TaskNotes statuses, so manually edited or external status values are visible as non-standard instead of blending into the board. Thanks to @cstelmach for suggesting this and @digitaldoctors for the follow-up.
  • \n
  • Refined Kanban empty columns, swimlane rows, and column drag handles, and added a per-view compact card layout option for denser boards.
  • \n
  • Kept Kanban swimlane rows from shrinking to share the viewport so the Max Swimlane Height setting is respected.
  • \n
  • Added guidance in Pomodoro statistics and Base file settings explaining that Pomodoro Base views require daily notes storage.
  • \n
  • (#323) Reordered task modal action buttons to match the right-click task menu order. Thanks to @23426356587 for suggesting this.
  • \n
  • (#1189) Made the Create/Edit Task modal priority picker follow the priority order configured in Settings. Thanks to @n1njaznutz for suggesting this.
  • \n
  • Made task-card priority dots and configured priority icons slightly larger for better visibility.
  • \n
  • (#1244) Clarified the Task Properties documentation for custom property keys and status values in Bases filters and sorting. Thanks to @Arachnidai for suggesting this.
  • \n
  • (#1234) Kept right-aligned subtask chevrons visible on task cards instead of only showing them on hover. Thanks to @n1njaznutz for suggesting this.
  • \n
  • (#1237) Made today's date more visible in the Mini Calendar view when another day is selected. Thanks to @riekusr for suggesting this.
  • \n
  • (#1348) Let long task titles wrap inside the Create/Edit Task modal title field while keeping saved titles single-line, and widened the contexts and tags fields in the modal details area. Thanks to @hasanyilmaz for suggesting this.
  • \n
  • (#1392) Made TaskNotes date fields accept compact YYYYMMDD typing and pasted dates. Thanks to @kazerniel for suggesting this.
  • \n
  • (#1431) Showed the year on task-card due and scheduled dates when the date is outside the current year. Thanks to @kazerniel for suggesting this.
  • \n
  • (#1429) Opened TaskNotes view commands in a new tab when they load configured Base files, so they do not replace the active note. Thanks to @Ruboks-Cube for suggesting this.
  • \n
  • (#1426) Added copy actions for TaskNotes Bases views, including current-view filenames, links, and titles from the result count menu, plus selected-task copy actions in the batch menu, while keeping the native Bases copy and CSV export actions available. Thanks to @kmaustral for suggesting this.
  • \n
  • Improved keyboard access, mobile layout, and theme color consistency across task cards, TaskNotes Kanban, Bases Kanban, calendar controls, stats, settings, and filter popovers.
  • \n
  • (#1526) Made the Create/Edit Task modal due and scheduled date buttons open a calendar-first picker where clicking a date saves immediately, with time entry still available in the picker. Thanks to @jmartinmcfly for suggesting this and @23426356587 for the follow-up feedback.
  • \n
  • (#1642) Made completion-based custom recurrence use flexible weekly, monthly, and yearly intervals without forcing a fixed weekday, month day, or month. Thanks to @Volker-brdb for suggesting this.
  • \n
  • (#1724) Moved recurring task complete/skip instance actions into the date area of the task context menu. Thanks to @prepare4robots for suggesting this.
  • \n
  • (#1762) Used the configured Google Calendar task export target as the default calendar when creating manual external calendar events. Thanks to @chrabia for suggesting this.
  • \n
  • (#1774) Made expandable project chevrons visible and easier to tap on mobile. Thanks to @sh0nuff for suggesting this.
  • \n
  • (#190) Made task-card and inline task-link action controls easier to tap on mobile, including always-visible task options on touch layouts. Thanks to @Poly-0000 for suggesting this.
  • \n
  • (#518, #1710, #1785) Added an opt-in setting for Create subtask to inherit the parent task's projects, contexts, priority, and non-identifying tags while always keeping the parent-task project link. Thanks to @bepolymathe, @Jalpara, and @poulpoulsen for reporting this, and to @tomsymonds, @AndyEveritt, @wedgen, @lindsaylearns, and @hokfujow for the follow-up feedback.
  • \n
  • (#1790) Extended the identifying-tag hiding setting to task modal tag suggestions, and kept hidden identifying tag children in place when editing other tags. Thanks to @loukandr for suggesting this.
  • \n
  • (#1804) Made the inline-created task folder setting visible even when instant conversion is disabled, and clarified that leaving it empty uses the default tasks folder. Thanks to @CaFeZn for suggesting this.
  • \n
  • (#1822) Matched the Task Edit Modal subtask list order to the existing relationship sort, so active and higher-priority subtasks appear ahead of completed ones. Thanks to @Glint-Eye for suggesting this.
  • \n
  • (#1233, #1339) Added an Appearance setting to expand project subtasks by default in task cards, while still letting individual cards be collapsed. Thanks to @n1njaznutz and @hasanyilmaz for suggesting this and @kazerniel and @benmartinek for the follow-up.
  • \n
  • (#763) Made the Relationships widget appear on project notes that match Project Autosuggest tag or property filters, even before any tasks link to the project. Thanks to @ChadHattabaugh for suggesting this.
  • \n
  • (#732) Remembered the Task & Project Statistics filters between openings, including the selected date range, custom dates, and minimum time filter. Thanks to @RumiaKitinari for suggesting this.
  • \n
  • (#1335) Added optional default times for new task scheduled and due dates, so default-dated tasks can appear as timed calendar events instead of all-day events. Thanks to @echo-saurav for suggesting this.
  • \n
  • (#1327) Made TaskNotes Bases search match any word in a multi-word search instead of requiring the whole phrase. Thanks to @craziedde for suggesting this.
  • \n
  • (#1318) Made aliased inline task links use the alias text inside the task widget, so [[Task title|short label]] can display as short label. Thanks to @3zra47 for suggesting this and @kazerniel for the follow-up.
  • \n
  • (#1325) Added ./ and ../ support to Include folders filters for project and file autosuggest, resolved from the active note's folder. Thanks to @EpolPers for suggesting this.
  • \n
  • (#1313) Added generated llms.txt and llms-full.txt files to the documentation site, so the primary docs can be shared with LLM tools more easily. Thanks to @JacksonMcDonaldDev for suggesting this.
  • \n
  • (#1308) Added a Calendar view option to stop date links from creating missing daily notes, while still opening existing daily notes. Thanks to @Arachnidai for suggesting this.
  • \n
  • (#1300) Allowed priority, status, calendar subscription, and timeblock color settings to use Obsidian theme color names such as red, blue, and cyan. Thanks to @thestrike72 for suggesting this.
  • \n
  • (#1299) Added a command that creates or opens a task and immediately starts time tracking for it. Thanks to @slipstyle for suggesting this.
  • \n
  • (#1284) Added an exact-match option for hiding task identification tags, so #task can be hidden while nested tags such as #task/project remain visible. Thanks to @3zra47 for suggesting this.
  • \n
  • (#1009) Added a confirmed Delete button to the Edit Task modal, so unwanted task notes can be removed without first opening the note file. Thanks to @jalooc for suggesting this.
  • \n
  • Improved the internal structure of Calendar, Kanban, Bases, task cards, and task modals to make future changes easier to test and maintain.
  • \n
\n

Fixed#

\n
    \n
  • (#697, #1374) Recognized manually authored task notes that use a single scalar tag such as tags: task, so they appear in TaskNotes views and menus like notes using YAML list tags. Thanks to @aubreyz and @phortx for reporting this, and to @jleewastaken for the follow-up.
  • \n
  • Removed the upward hover shift from calendar events while keeping the hover shadow feedback.
  • \n
  • Made same-column manual-order drops in TaskNotes Kanban settle immediately when the local order patch is safe, including virtual columns through a stable reorder path that avoids layout jumps.
  • \n
  • Made single-card cross-column drops in TaskNotes Kanban settle through a local state patch when the move is safe, reducing the wait for the full Bases refresh.
  • \n
  • Fixed Calendar timeblocks created from a selected time range so they appear as soon as Obsidian indexes the daily note update, instead of waiting for a later refresh.
  • \n
  • Replaced the external calendar event emoji marker with the calendar icon and kept it in the same top-right event corner.
  • \n
  • Restored Task List group toggles and recurring calendar month controls to compact icon buttons instead of inherited boxed theme buttons.
  • \n
  • Refined the settings tab navigation styling so tabs read as quieter inline navigation instead of default buttons.
  • \n
  • (#263) Made the instant inline task conversion button respond to touch/pointer activation, so mobile multi-line selections can be converted into TaskNotes. Thanks to @cathywu for reporting this.
  • \n
  • (#216) Preserved @context markers when converting Tasks-plugin-style checkbox tasks into TaskNotes, while keeping those contexts out of the created task title. Thanks to @ksdavidc for suggesting this, and to @hangryscribe3, @nayatiuh, and @natleahh for the follow-up feedback.
  • \n
  • (#508) Showed project note names instead of full project paths in grouped Kanban and Task List headings, while keeping the headings linked to the project note. Thanks to @elvarb for reporting this and @dmodify for confirming it in Task List.
  • \n
  • (#408) Used the task title as the native system notification title for task reminders instead of always showing TaskNotes Reminder. Thanks to @DudeThatsErin for reporting this and @phillipadsmith for the follow-up.
  • \n
  • (#385) Let Mini Calendar month controls shrink and wrap cleanly in narrow sidebars. Thanks to @iholston for reporting this.
  • \n
  • Fixed Calendar List view task cards so they use the available row width without duplicate list cells, row-hover backgrounds, or linked-hover styling.
  • \n
  • (#552) Made instant task convert buttons appear for checkbox tasks inside callouts, and kept converted links inside the callout list. Thanks to @Oblique82 for reporting this and @ksdavidc for the follow-up.
  • \n
  • (#559) Treated notes linked to one loaded recurring calendar event instance as related to the other instances in that series. Thanks to @cathywu for reporting this and @mdbraber for the implementation notes.
  • \n
  • (#685) Made Calendar list views respect the All-day slot option by hiding all-day events from the list when that option is turned off. Thanks to @RumiaKitinari for reporting this.
  • \n
  • (#643) Stopped custom filename templates such as task-{year}{month}{day}{hour}{minute} from incorrectly showing the "filename shortened" notice when creating tasks. Thanks to @minchinweb for reporting this.
  • \n
  • (#722) Made Skip Break reset a queued Pomodoro break back to the next focus timer without starting a session. Thanks to @Goossiii for reporting this and @YIRU69 for the follow-up.
  • \n
  • (#782) Made recurrence weekday choices follow the configured first day of week, and made the quick "Weekdays only" recurrence use locale weekend data instead of assuming Monday through Friday everywhere. Thanks to @BKSalman for reporting this.
  • \n
  • (#872) Made note-level task cards appear immediately, and stay visible while editing, when a task note is embedded as a Canvas file node. Thanks to @bangbangbanggit for reporting this and @benmartinek for the follow-up.
  • \n
  • (#856) Fixed filters for number custom fields so numeric task values match equivalent filter values entered as text. Thanks to @thoughtcipher for reporting this.
  • \n
  • (#1039) Restored clearer TaskNotes Bases grouping for nested project paths, and made the Calendar refresh control an icon button again. Thanks to @dblinnikov for reporting this.
  • \n
  • (#1034) Let embedded TaskNotes Calendar views size to their content by default, so month, week, and day embeds no longer reserve full-pane proportions inside notes. Thanks to @same774 for reporting this.
  • \n
  • (#1023) Kept task modal custom fields scrollable above the iPhone keyboard while creating or editing tasks. Thanks to @3zra47 for reporting this.
  • \n
  • (#1019) Kept active Pomodoro and time-tracking task references working after the tracked task file is renamed. Thanks to @AndreMonthy for reporting this.
  • \n
  • (#1037) Let embedded TaskNotes Calendar year views size to their content and kept the year title from wrapping vertically. Thanks to @same774 for reporting this.
  • \n
  • (#1047) Wrapped long file paths in the Edit Task modal metadata section, so narrow mobile screens no longer get a sideways scrollbar from the File row. Thanks to @3zra47 for reporting this.
  • \n
  • (#1051) Preserved extra values on a property-based task identification field when saving a task, so list properties such as class: [task, habit] no longer get collapsed to only the identifying value. Thanks to @WhoIsSeanGalt for reporting this.
  • \n
  • (#1060) Reused and revealed an already-open Calendar/Base view when running view commands, so a view kept in the sidebar no longer reopens in a new main tab. Thanks to @kmaustral for reporting this.
  • \n
  • (#1075) Hid the native WebKit date-input label that could appear as Label when editing scheduled dates on macOS. Thanks to @3zra47 for reporting this.
  • \n
  • (#1076) Allowed timeblocks to end at midnight using 00:00, and accepted 24:00 as an explicit end-of-day value in timeblock validation. Thanks to @skoove for reporting this and @gregor202 for the follow-up.
  • \n
  • (#1086) Fixed the Calendar + more control in dark mode so expanded all-day task groups stay readable. Thanks to @same774 for reporting this.
  • \n
  • (#1100) Applied Advanced Calendar View search and title filters to the tasks used for calendar rendering, so filtering controls affect which tasks appear on the calendar. Thanks to @quiet-coder-io for reporting this.
  • \n
  • (#1147) Added a delete action for recent Pomodoro statistics sessions, so erroneous Pomodoro history can be removed without editing plugin storage or daily-note frontmatter manually. Thanks to @RumiaKitinari for reporting this and @BrucePlumb for the follow-up.
  • \n
  • (#1150) Kept recurring tasks' due dates visible in Calendar Bases views, and showed their scheduled date when recurrence instances are hidden. Thanks to @thomatino for reporting this and @BrucePlumb for the follow-up.
  • \n
  • (#1159) Softened Calendar time-entry styling so recorded time blocks no longer visually outweigh task events. Thanks to @hatespinach for reporting this.
  • \n
  • (#1191) Aligned the task-card and relationships widgets inside notes with Obsidian's editor margins, including readable-line-width layouts. Thanks to @minchinweb for reporting this.
  • \n
  • (#1183) Kept the Calendar create menu open after drag-selecting a time range, so the selected duration can be used when creating a task. Thanks to @randomness42 for reporting this.
  • \n
  • (#1179) Stopped Calendar Bases views from repainting after unrelated note updates when the visible calendar data has not changed. Thanks to @same774 for reporting this.
  • \n
  • (#1156) Kept property-based task identification through the tags property from rewriting task tags as a plain text value, and generated default Bases now use tag membership for that setting. Thanks to @seepage87 for the detailed migration report and @chrsdk for the follow-up.
  • \n
  • (#1232) Fixed generated Task List Base date filters so recurring tasks scheduled for today appear in the Today view, and today's completed recurring instances stay hidden. Thanks to @mvichosfm for reporting this and @ArthurGideon and @VarunNikam22 for the follow-up.
  • \n
  • (#1231) Fixed the generated Task List Base Overdue view so tasks with scheduled dates in the past appear alongside tasks with due dates in the past. Thanks to @Lorite for reporting this and @dictionarymouse for the follow-up.
  • \n
  • (#1228) Matched the task details editor's Markdown heading colors to the active Obsidian theme, including themes that customize heading colors. Thanks to @BrucePlumb for requesting this.
  • \n
  • (#1227) Refreshed the relationships widget when project references are indexed or updated so project notes can show related tasks automatically again. Thanks to @luckb0x for reporting this.
  • \n
  • (#1219) Fixed Kanban drags that start on an expanded subtask card so they move that subtask instead of dragging the parent card. Thanks to @craziedde for reporting this.
  • \n
  • (#990) Treated one-item status lists written by Obsidian Properties as the same status value in TaskNotes Kanban, so they no longer create duplicate columns. Thanks to @mlevison for reporting this.
  • \n
  • (#983) Let Agenda Calendar views wrap their header controls and task titles inside narrow sidebars, so Today and refresh controls and task icons remain visible without sideways scrolling. Thanks to @3zra47 for reporting this.
  • \n
  • (#982) Made TaskNotes task-card typography scale from Obsidian's text font size setting, so Bases and Agenda task text follows larger mobile font settings. Thanks to @3zra47 for suggesting this and @chrsdk and @scottaltham-payroc for the follow-up.
  • \n
  • (#966) Made reminder delete buttons larger and always visible on mobile, so reminders can be removed from the Manage All Reminders modal on iPad. Thanks to @PSG2017 for reporting this.
  • \n
  • (#964) Made Pomodoro and time-tracking task selection use the current recurring instance status, so a recurring task can still be selected after an earlier instance was completed. Thanks to @lomarcanys for reporting this.
  • \n
  • (#944) Preserved number and boolean custom field values when moving tasks between grouped Kanban or Task List columns, and when creating a task from a grouped Kanban column. Thanks to @thoughtcipher for reporting this.
  • \n
  • (#935) Fixed Task List priority sorting so descending order puts higher-weighted priorities first, and due dates are used before scheduled dates when priority values tie. Thanks to @Glint-Eye for reporting this and @kacoroski for the follow-up.
  • \n
  • (#922) Made the Blocked task-card pill expand the blocker tasks, and rendered blockedBy dependencies as clickable links when that property is shown on cards. Thanks to @prayidae for reporting this and following up.
  • \n
  • (#919) Fixed exported ICS task events so they use valid calendar event statuses and can be imported by stricter calendar apps. Thanks to @benoitjadinon for reporting this.
  • \n
  • (#1213) Fixed embedded Task List Bases in Obsidian pop-out windows so typing below the embed no longer leaves a large blank gap. Thanks to @same774 for reporting this.
  • \n
  • (#1243) Removed quoted multi-word custom field NLP expressions from created task titles after saving the custom field value. Thanks to @Arachnidai for reporting this.
  • \n
  • (#1252) Hardened the calendar-first task date picker for iPad taps so date buttons use direct touch manipulation. Thanks to @alxandrharris for reporting this.
  • \n
  • (#1261) Removed the extra Task List Base scrollbar when an embedded task list note is placed in a sidebar, while keeping normal embedded task lists scrollable in the main note area. Thanks to @cathywu for reporting this.
  • \n
  • (#1347) Lowered TaskNotes task-card tag CSS specificity so hierarchical tag colors from Obsidian themes and tag-color plugins can apply correctly. Thanks to @3Fish for reporting this.
  • \n
  • (#1374) Recognized status and priority labels entered through Obsidian Properties or Bases as their configured TaskNotes values. Thanks to @phortx for reporting this.
  • \n
  • (#1373) Parsed numeric natural-language dates with the configured calendar locale, so en-GB treats 11/06/2026 as 11 June instead of November 6, and YYYY/MM/DD works consistently. Thanks to @AleMunin for reporting this and @imsuck for the follow-up.
  • \n
  • (#1370) Prevented recurring task series from being queued for auto-archive when their parent status uses auto-archive, so ongoing recurring tasks are not moved away after completing an occurrence. Thanks to @Jomo94 for reporting this and @martin-forge for the follow-up discussion.
  • \n
  • (#1367) Made recurring task completion counts use the total expected instances for finite COUNT or UNTIL recurrences, and stopped showing a made-up percentage for unbounded recurrences. Thanks to @saurinni for reporting this.
  • \n
  • (#1365) Preserved email and other URI links from converted inline task titles by moving the original links into the new task body, and rendered message:/mailto: markdown links as external links in TaskNotes surfaces. Thanks to @phillipadsmith for reporting this and @hasanyilmaz for the follow-up.
  • \n
  • (#1350) Refreshed inline task widgets in Reading mode after task property edits, so changed dates and other visible properties no longer stay stale until the note is reopened. Thanks to @tmsbn for reporting this.
  • \n
  • (#1329) Pulled the relationships widget up to the end of the note content without removing its normal spacing, and kept that placement updated while editing and on load so it no longer covers the editor. Thanks to @Volker-brdb for reporting this.
  • \n
  • (#1326) Treated empty task frontmatter values as missing, so empty titles fall back to the filename and blank date, priority, and recurrence fields are ignored. Thanks to @craziedde for suggesting this.
  • \n
  • (#1316) Stopped stale Workspace state from overriding the configured Calendar view mode, so switching Workspaces no longer forces an old Day/Week/List choice over the view default. Thanks to @kmaustral for reporting this and following up.
  • \n
  • (#1302) Read task frontmatter directly from the task file when Obsidian has not indexed its metadata yet, so visible tasks can still be opened, updated, and selected instead of reporting "Task not found". Thanks to @WorldTeacher for reporting this and @Steven-AA for confirming it.
  • \n
  • Kept just-written task data available while Obsidian's metadata cache catches up, so immediate reads after task edits no longer briefly return stale values.
  • \n
  • (#1297) Made the Create or open task footer tappable, so mobile users can create the typed task without needing the Shift+Enter shortcut. Thanks to @slipstyle for reporting this.
  • \n
  • (#1288) Allowed formula properties to appear in Calendar property-based event start and end date selectors. Thanks to @hasanyilmaz for reporting this.
  • \n
  • Made TaskNotes Kanban drags show a lightweight held-card preview, so the dragged card remains easy to track while the source column opens the drop slot.
  • \n
  • (#1423) Refreshed TaskNotes Bases views when subtasks are deleted, so expanded project cards drop removed subtasks and stop showing project controls when the last subtask is gone. Thanks to @normenmueller for reporting this.
  • \n
  • (#1419) Kept custom user field name, key, and default-value edits in Task Properties settings when closing settings without first blurring the field. Thanks to @s33a for reporting this and @kacoroski for the follow-up.
  • \n
  • Reduced redundant settings writes by coalescing overlapping saves, so settings changes made in quick succession finish with the latest values without repeating every intermediate save cycle.
  • \n
  • (#1331, #1411) Made Agenda Calendar Bases respect the Base sort order within each day instead of falling back to alphabetical title order. Thanks to @bane73 and @ky1ejs for reporting this.
  • \n
  • (#1383) Made task modal markdown editors expose the active editor API expected by plugins such as Templater. Thanks to @tomsymonds for reporting this.
  • \n
  • Fixed the first-run Create/Edit Task modal so the default fields appear immediately after installing TaskNotes, without needing to open Modal Fields settings or restart Obsidian.
  • \n
  • (#1895) Restored the natural-language preview in the Create Task modal. Thanks to @ssonhub for reporting this.
  • \n
  • (#1898) Cleared stale Calendar time-axis column widths when switching views, so Day, Week, and 3-day views keep the time labels anchored on the left. Thanks to @ddevaal for reporting this.
  • \n
  • (#1439) Fixed generated Bases dependency filters so blockedBy entries stored as links, strings, or dependency objects are handled consistently in Not Blocked and Relationships views. Thanks to @prayidae for reporting this and following up.
  • \n
  • (#1435) Prevented malformed task dependency, status, or priority values from breaking the task context menu. Thanks to @23maverick23 for reporting this.
  • \n
  • (#1434) Kept older filename-titled tasks readable after turning off "Store title in filename" by falling back to the filename when a task has no usable title property. Thanks to @hujuDev for reporting this.
  • \n
  • (#1433) Made the Due date and Scheduled date weekday picker follow the configured first day of week. Thanks to @sandchipper for reporting this.
  • \n
  • (#1430) Showed custom user-field property keys in Modal Fields settings instead of internal field IDs. Thanks to @JerryLu086 for reporting this.
  • \n
  • (#1427) Fixed project autosuggest Required Tags filters so frontmatter tags parsed by Obsidian are handled the same way as direct tag-property filters. Thanks to @ProHaller for reporting this.
  • \n
  • (#1495) Added an Update default files action for generated Bases views, so task-tag or task-identification setting changes can refresh existing .base filters without deleting files manually. Thanks to @Liya430 for reporting this.
  • \n
  • (#1512) Prevented the split Create/Edit Task modal details pane from collapsing to a one-character-wide column under the Minimal theme. Thanks to @willfanguy for reporting this and sharing detailed CSS notes.
  • \n
  • (#1524) Fixed task-card font sizes shrinking when a Bases view is opened in an Obsidian pop-out window. Thanks to @Glint-Eye for reporting this.
  • \n
  • (#1535) Fixed the generated Relationships Base Subtasks filter so single project links do not trigger a Bases contains error. Thanks to @DanaKyle for reporting this.
  • \n
  • (#1102) Refreshed task cards when a task status is edited directly in Obsidian frontmatter, so the card no longer stays on the old status until it is clicked. Thanks to @Wayment9504 for reporting this.
  • \n
  • (#1105) Added an explicit Close action to the mobile task options menu, so iPhone users do not need to tap near the top system bar to dismiss it. Thanks to @J-R-Troutman for reporting this.
  • \n
  • (#1550) Prevented mobile Calendar event drags from opening the task context menu before the drag can begin. Thanks to @stil-sudo for suggesting this.
  • \n
  • (#1563) Removed duplicate entries from Calendar event related notes when the same linked file is also a TaskNote. Thanks to @VarunNikam22 for reporting this.
  • \n
  • (#1566) Rendered grouped multi-project values as individual links when a Bases group title contains multiple project links. Thanks to @ptsouchlos for suggesting this.
  • \n
  • (#1569) Allowed local ICS calendar paths inside the vault to be pasted as absolute filesystem paths, and showed a clearer error when the file is outside the vault. Thanks to @Photon89 for reporting this and following up.
  • \n
  • (#1584) Sanitized task-card status and priority class names, so custom values with spaces no longer create invalid CSS classes. Thanks to @omber for reporting this.
  • \n
  • (#1587) Stored dependencies added from the task context menu as wikilinks, matching the Edit Task modal. Thanks to @mgrecar for reporting this.
  • \n
  • (#1590) Clarified HTTP API task creation docs and OpenAPI schema for writable blockedBy dependencies, and marked blocking as a read-only derived relationship. Thanks to @hGriff0n for reporting this.
  • \n
  • (#1591) Added a startup guard that avoids saving default settings over an existing settings file if Obsidian temporarily returns no plugin data during an update. Thanks to @GGlider for reporting this.
  • \n
  • (#1593) Made the New button in TaskNotes Bases views open the TaskNotes create task modal again, so new tasks respect the configured default tasks folder. Thanks to @katlandreth for reporting this.
  • \n
  • (#1594) Made task cards inside recurring task notes complete the task's current scheduled occurrence instead of today's date when no calendar or view date is supplied. Thanks to @ngraham20 for reporting this.
  • \n
  • (#1601) Prevented overlapping Live Preview relationship-widget injections from leaving duplicate subtask/relationship sections in a note. Thanks to @wealthychef1 for reporting this and @benmartinek for confirming it.
  • \n
  • (#1610) Made expanded subtasks in TaskNotes Bases views follow the current view's sorted task order instead of a fixed fallback order. Thanks to @MrZzard for reporting this and @slipstyle for confirming it.
  • \n
  • (#1609) Restored scrolling in wide split-layout task edit modals when the form content is taller than the modal. Thanks to @3zra47 for reporting this.
  • \n
  • (#1614) Wrote unchecked boolean custom user-field defaults to new task frontmatter, including tasks created through instant conversion. Thanks to @kobalteule for reporting this.
  • \n
  • (#1611) Made generated default Bases urgency scores fall back safely when the next-date distance is missing. Thanks to @benoitjadinon for reporting this and suggesting the formula fix.
  • \n
  • (#1623) Honored "Store title in filename" across task creation and edits, so the mapped title property is omitted from frontmatter and stale title fields are removed on save. Thanks to @VenturaNotes for reporting this, and to @Ender367, @slipstyle, and @loukandr for confirming and tracing affected paths.
  • \n
  • (#1621) Made Kanban swimlane labels stop freezing on mobile and kept their label column compact, leaving more room for task cards while horizontally scrolling. Thanks to @karenchoe428 for reporting this.
  • \n
  • (#1615) Detected Obsidian custom multi-text properties exposed through widget: "multitext" as list properties, so Kanban can split those values into multiple columns. Thanks to @konton71 for reporting this.
  • \n
  • (#1626) Expanded recurring ICS subscription events through the one-year subscription window for high-frequency recurring calendars. Thanks to @pib for reporting this.
  • \n
  • (#1628) Refreshed Calendar Bases views promptly when switching between filtered Agenda views, so the previous view's task set does not stay visible until the delayed refresh. Thanks to @Lanalangz for reporting this.
  • \n
  • (#1629) Saved blockedBy dependencies selected in the Create Task modal. Thanks to @obsilover for reporting this.
  • \n
  • (#1634) Aligned custom status icons in inline tasks with the default inline status circle. Thanks to @ttlaylor for reporting this and @basbarten for confirming it.
  • \n
  • (#1636) Restored the active styling for the Calendar list-view toolbar button. Thanks to @vroablec for reporting this.
  • \n
  • (#1493, #1638) Kept task time tracking consistent when switching or clearing tasks during an active Pomodoro. Thanks to @ROS-SDN and @katonapng for reporting this, and to @anomatomato for confirming it.
  • \n
  • (#1639) Respected the aliased-link overlay exclusion in Reading mode even when the alias text matches the task title. Thanks to @MiracleXYZ for reporting this.
  • \n
  • Fixed actively tracked task cards so the blue time-tracking outline stays visible along the card edges.
  • \n
  • (#1657) Preserved Bases view defaults when creating tasks from the TaskNotes Kanban/List view New button, so project-scoped views can pass their project assignment into the create task modal. Thanks to @casualQuads122 for reporting this.
  • \n
  • (#728, #1831) Preserved frontmatter defaults supplied by Obsidian's Bases New action when opening the TaskNotes create task modal from custom Bases views, so filtered views can prefill matching tags, projects, contexts, and custom fields. Thanks to @DillPickle80 and @echo-saurav for suggesting this, and to @prayidae and @renatomen for the detailed follow-up.
  • \n
  • (#726) Added an instant-conversion option to use the closest heading above the converted line as a project, so checkbox tasks under project headings can inherit that project automatically. Thanks to @ghelton for suggesting this.
  • \n
  • (#1662) Preserved frontmatter from ICS event note templates when quoted event variables or Templater expressions are used. Thanks to @victorhg for reporting this.
  • \n
  • (#1663) Fixed Japanese and other Unicode tags on task cards so Kanban tag pills keep the same rounded styling as ASCII tags. Thanks to @kutty-1119 for reporting this.
  • \n
  • (#1649) Restored daily-note navigation from the Calendar Day view date header. Thanks to @BaccanoMob for reporting this.
  • \n
  • (#1648, #1665) Fixed the API endpoint list in Integrations settings so it uses the configured bearer token when API authentication is enabled, instead of reporting the running local server as inaccessible. Thanks to @npondel and @warm-july for reporting this.
  • \n
  • (#1668) Fixed the Create Task magic wand so NLP-triggered custom field values are copied into the custom property inputs before saving. Thanks to @hokfujow for reporting this.
  • \n
  • (#1669) Stopped the startup settings migration check from rewriting data.json just because saved calendar defaults are false, 0, empty, or null, reducing unnecessary sync churn. Thanks to @thehyperadvisor for reporting this.
  • \n
  • (#1674) Improved the timeblock creation error when Daily Notes cannot read its configured folder, so the modal notice points to the Daily Notes core plugin settings instead of only logging the folder lookup failure. Thanks to @Ender367 for reporting this.
  • \n
  • (#1680) Fixed TaskNotes Calendar Bases options stored under options, so Agenda views respect showPropertyBasedEvents: false and no longer show duplicate property-based rows for the same task. Thanks to @xiaoyaozhu1991 for reporting this and @KondrotM for confirming it.
  • \n
  • (#1681) Reduced the cost of inline checkbox convert buttons by only scanning the visible editor range instead of the full document. Thanks to @en-ot for reporting this and @hokfujow for the follow-up.
  • \n
  • (#1689) Fixed task reminders added or rescheduled through direct frontmatter edits so the notification queue refreshes immediately and relative reminders recalculate from the latest task dates. Thanks to @garzonjav for reporting this.
  • \n
  • (#1693) Fixed generated default Bases formulas so empty due and scheduled dates are checked with .isEmpty() instead of date-field truthiness. Thanks to @benoitjadinon for reporting this.
  • \n
  • (#1702) Removed the forced bottom gap under TaskNotes custom Bases views, so calendar and other TaskNotes views can fill the available pane height. Thanks to @AudreyLooby for reporting this.
  • \n
  • (#1719) Fixed task cards in reading mode so Obsidian 1.12.x header changes no longer place the card above the title and properties or drop it after returning to a tab. Thanks to @tholbrook9 for reporting this and tracing the DOM change.
  • \n
  • (#1722) Saved the source note immediately after converting an inline checkbox task to a TaskNote, so Kanban views do not keep showing the stale inline task alongside the new task file. Thanks to @literallydope for reporting this and sharing screenshots.
  • \n
  • (#1750) Fixed generated default Bases filters for property-based task identification when the identifying property name contains spaces. Thanks to @Igorgro for reporting this.
  • \n
  • (#1745) Clarified the inline task documentation so Create new inline task is distinguished from current-line conversion. Thanks to @yvos for reporting the mismatch.
  • \n
  • (#1485) Stopped Google Calendar manual refresh from showing a success notice after token refresh or calendar-list failures. Thanks to @ebanDev for reporting this.
  • \n
  • (#1474) Made priority-based Kanban swimlanes follow the configured priority order instead of alphabetical task data order. Thanks to @kanzaki1201 for reporting this and @SoTHISIsFitness for the follow-up investigation.
  • \n
  • (#1470) Restored pointer cursors on TaskNotes interactive elements under Obsidian themes that set --cursor to the default cursor. Thanks to @TheFrostedDev for reporting this.
  • \n
  • (#1463) Documented the supported FilterQuery payload for POST /api/tasks/query, including context filtering examples and generated API schema details. Thanks to @tcb678 for reporting this and @soloidx for sharing a working query example.
  • \n
  • (#1464) Made context on GET /api/tasks follow the same filtering guidance as project, so the API now points clients to POST /api/tasks/query instead of ignoring the parameter. Thanks to @tcb678 for suggesting this.
  • \n
  • (#1457) Rendered scheduled-to-due calendar spans with scheduled times as daily timed events instead of moving them to the all-day section. Thanks to @atos2212-blip for reporting this and @rayvermey for confirming it.
  • \n
  • (#1450) Returned configured user fields in HTTP API task responses under customProperties, while keeping the configured frontmatter keys available on each task. Thanks to @Admorei for reporting this and @nschenone for the follow-up.
  • \n
  • (#1449) Let embedded Agenda views use auto-height sizing by default, so one-day list embeds no longer reserve a large empty calendar block. Thanks to @GlebYavorski for reporting this.
  • \n
  • (#1446) Kept custom Kanban columns from columnOrder available when they are empty, so hideEmptyColumns: false can show drop targets for custom grouped values. Thanks to @akhtsang for reporting this.
  • \n
  • (#1459) Avoided double "Failed to create task" prefixes in task creation error notices. Thanks to @Sineapple for reporting this, and to @slipstyle and @Stockemer for the follow-up investigation.
  • \n
  • (#1469) Fixed Convert current note to task so saving the untouched edit modal writes the task frontmatter instead of reporting no changes. Thanks to @slipstyle for reporting this, and to @jhoogeboom and @ngraham20 for confirming it.
  • \n
  • (#1466) Prefilled the current note as the project when creating a task from an embedded Subtasks/Relationships Base filtered with this.file.asLink(). Thanks to @jhoogeboom for reporting this, and to @cybersader, @fsmontenegro, and @benmartinek for the follow-up discussion.
  • \n
  • (#1476) Showed linked parent-task project titles instead of timestamp filenames in project stats and grouped task views when the linked task has a frontmatter title. Thanks to @RumiaKitinari for reporting this.
  • \n
  • (#1487) Let Calendar task event titles wrap instead of clipping long names, and removed the redundant due-date prefix from due task events. Thanks to @Alexander-Bergmann for reporting this.
  • \n
  • (#1488, #1739) Enabled Kanban touch dragging on touch-capable desktop and convertible devices, not only mobile Obsidian. Thanks to @tmoyland001 and @mgsima for reporting the drag failures, and @SoTHISIsFitness for investigating related task-property cases.
  • \n
  • (#1738) Fixed Outlook calendar subscriptions whose event timezones reference the base Windows timezone name while the feed defines a suffixed timezone name. Thanks to @Mirrimo for reporting this, @rafavital for confirming it, and @rogerfsh for tracing the ICS timezone mismatch.
  • \n
  • (#1734) Fixed dependency picker search when task priority values are stored as non-string frontmatter values. Thanks to @MatthewClarkeDev for reporting this and identifying the stack trace.
  • \n
  • (#1733) Preserved wikilinks in task titles and rendered them as clickable links on task cards. Thanks to @bitscorch for suggesting this.
  • \n
  • (#1728) Applied the "Use parent note as project" default when creating a new task from the command palette or ribbon. Thanks to @greatEmily for reporting this.
  • \n
  • (#1759) Advanced stale due dates when recurring tasks move to their next scheduled occurrence, so work-window tasks do not remain overdue after completion. Thanks to @MattPryze for reporting this.
  • \n
  • (#1766) Fixed Calendar Bases date navigation from custom note properties, so embedded calendar views can open on the date stored in the selected property instead of falling back to today. Thanks to @chrabia for reporting this.
  • \n
  • (#1767) Aligned the start and end time rows in the timeblock creation modal. Thanks to @loiveli for reporting this.
  • \n
  • (#1783) Replaced the default browser drag ghost for Kanban cards so dragging a card no longer makes the next card look semi-transparent. Thanks to @loukandr for reporting this and tracing the drag image behavior.
  • \n
  • (#1796) Restored expanded subtasks immediately after renaming a parent task file and updating links. Thanks to @bung69 for reporting this.
  • \n
  • (#1797) Improved manual ordering so long Kanban columns remain scrollable while dragging, mobile Kanban drops can place a card relative to another card, Kanban/Task List drops resolve the final drop position more reliably, generated manual-order ranks match Bases sorting, and manual-order properties such as sort_order render on task cards when enabled. Thanks to @SKIERZZ for reporting this and sharing videos.
  • \n
  • (#1812) Separated Microsoft OAuth token status from calendar sync status, and surfaced Microsoft calendar fetch errors in the integrations settings card instead of leaving them console-only. Thanks to @henninger80 for the detailed report.
  • \n
  • (#1814) Restored NLP project autosuggest in the Create or Open Task command, so + project suggestions use the same filtered project lookup as the Create Task modal. Thanks to @adammahad for reporting this.
  • \n
  • (#1820) Kept API-created tasks readable immediately after creation even if Obsidian has not finished indexing the new file metadata yet. Thanks to @vadminas for reporting and tracing the cache desync.
  • \n
  • (#1823) Prevented zero-duration timed external calendar events from rendering under more than one day in list-style calendar views. Thanks to @martin-forge for reporting and tracing the Google Calendar case.
  • \n
  • (#1841) Prevented Kanban boards from duplicating columns when wikilinked status values are grouped through Bases. Thanks to @lendamico for reporting and sharing the screen recording.
  • \n
  • (#1846) Saved NLP-triggered boolean custom fields as real booleans instead of quoted strings, so they match checkbox-created values and Bases filters. Thanks to @DevOps-Toast for reporting and sharing screenshots.
  • \n
  • (#1849) Prevented repeated clicks on task-card scheduled and due date labels from stacking duplicate date menus when Obsidian native menus are disabled. Thanks to @3zra47 for reporting.
  • \n
  • (#1850) Added mobile bottom spacing to TaskNotes list views so the final task can scroll above Obsidian's floating mobile controls. Thanks to @AlejandroRigau for reporting and sharing the iPhone screenshot.
  • \n
  • (#1852) Improved mobile timed calendar event rendering with shorter time labels, tighter spacing, and event-colored task/calendar blocks. Thanks to @redrumthebum for reporting and sharing screenshots.
  • \n
  • (#1757, #1853, #1775) Respected an existing mdbase.yaml types_folder when regenerating mdbase task type definitions, so the generated task.md can live outside the vault-root _types folder. Thanks to @aldrichtr for the original request and implementation exploration, and @hangryscribe3 for the follow-up request.
  • \n
  • (#1858) Included task body details in single-task HTTP API and MCP reads. Thanks to @vanillaflava for reporting and outlining the expected behavior.
  • \n
  • (#1859) Clarified the Google Calendar setup guide for OAuth testing-mode access_denied errors. Thanks to @PE-Boy for reporting and @tiagoarroz for the workaround.
  • \n
  • (#1860) Preserved accented characters in tags when converting checkbox tasks to TaskNotes. Thanks to @e-zz for reporting.
  • \n
  • (#1869) Preserved Calendar Month View scroll position after task updates. Thanks to @sisyowo for reporting and linking the earlier Kanban fix.
  • \n
  • (#1873) Prevented Calendar Bases from rendering in Obsidian pop-out windows because restoring FullCalendar there can freeze Obsidian. Thanks to @misolex for reporting.
  • \n
  • (#1497, #1870) Fixed NLP file suggestions for custom fields so selected wikilinks are captured as custom field values, including list-type fields. Thanks to @Naesue and @Sineapple for reporting this, and to @bradleyed and @Xananax for the follow-up details.
  • \n
  • (#1888) Allowed project autosuggest required property filters to match any comma-separated value, such as project, area. Thanks to @BrianHicks for suggesting.
  • \n
  • (#1886) Added a command to postpone active overdue scheduled tasks to today. Thanks to @chrabia for the suggestion.
  • \n
  • (#1889) Fixed Kanban swimlanes for list-valued properties so tags and contexts use individual list items instead of comma-joined values. Thanks to @pkropotin for reporting.
  • \n
  • (#1890) Fixed scheduled-date Kanban columns dropping tasks when date-only and timed tasks on the same day are sorted by a scheduled-time formula. Thanks to @chrabia for reporting and investigating.
  • \n
  • (#773) Added ICS export filters for archived tasks, completed tasks, due dates, and scheduled dates. Thanks to @ras0q for suggesting this and @slipstyle for the scheduled-date follow-up.
  • \n
  • (#765) Reduced side-pane gutters around embedded TaskNotes Bases views, so embedded task lists use about the same horizontal space as directly opened Bases views. Thanks to @TonyAtlas for suggesting this.
  • \n
  • (#1892) Fixed nested Markdown list indentation in the Task Edit Modal details editor. Thanks to @Glint-Eye for reporting.
  • \n
  • (#1891) Fixed TaskNotes modal markdown editors collapsing to one-character-wide lines when Pretty Properties is installed. Thanks to @bkennedy-improving for reporting.
  • \n
  • (#1499) Respected excluded folders when opening tasks directly from view results and when building dependency/project indexes, so template-folder tasks no longer appear through TaskNotes views. Thanks to @Liya430 for reporting.
  • \n
  • (#136, #1500) Made the Pomodoro countdown derive remaining time from the session clock instead of from counted interval ticks, so delayed, backgrounded, or screen-off ticks catch up cleanly without over-recording a completed session. Thanks to @Poly-0000 for reporting and documenting the original background timer issue, @Totobal5 for the earlier worker-based fix, and @CoffeaUrbana for the Android screen-off report.
  • \n
  • Restored padding in task modal Markdown editors.
  • \n
  • Made the markdown editor areas in task modals easier to click and focus.
  • \n
  • Strengthened local CSS linting to catch unscoped selectors, unknown CSS, and fixed-position overlays before review.
  • \n
  • Reduced false-positive plugin review warnings by making background auto-export and auto-archive schedulers non-overlapping and tightening type/string conversion paths.
  • \n
  • (#1882) Made Google Calendar task descriptions use mobile-friendly plain text for Obsidian links and display labels for wiki-style project/context links. Thanks to @martin-forge for the contribution.
  • \n
  • (#1883) Improved Google Calendar task sync recovery so failed deletions, offline sync requests, reconnects, and quick create/update races are retried more reliably. Thanks to @martin-forge for the contribution.
  • \n
\n","text":"Added# (#353) Added a Has Subtasks filter for task queries, so views and API clients can show only project-style tasks or direct tasks. Thanks to @mdbraber for suggesting this. (#380) Added a test-reminder button in notification settings, so reminder setup can be checked without creating a real task reminder. Thanks to @mdbraber for suggesting this. (#711, #168) Added an optional task-creation setting to open the new task note after saving, either in the current tab or a new tab. Thanks to @phortx and @23426356587 for suggesting this, and to @edward-peters and @obsilover for the follow-up. (#1041, #1800) Added copy-drag support for timeblocks: hold Ctrl, Cmd, or Alt/Option while dragging an existing timeblock to duplicate it at the new date and time. Thanks to @0-BSCode and @cweekly for suggesting this. (#1052) Added a public JavaScript API for in-vault scripts at app.plugins.plugins.tasknotes.api.parseNaturalLanguage(text), so Templater, QuickAdd, and MetaBind workflows can use TaskNotes' natural-language parser without running the HTTP API. Thanks to @edakimling for suggesting this. (#1235) Added a task-card toggle for blocked tasks, so you can expand a blocked task to see the tasks it is waiting on. Thanks to @craziedde for suggesting this. (#1254) Added ../ and ./ normalization for folder templates after variables are expanded, so instant task conversion can target sibling folders such as {{currentNotePath}}/../Tasks. Thanks to @rdick for suggesting this. (#1267) Added Daily Notes-style date tokens such as YYYY, MM, DD, MMMM, and dddd to TaskNotes folder templates. Thanks to @paulsen-it for suggesting this. (#1380) Added tag actions to task context menus, including add/remove actions for individual tasks and batch-selected tasks. Thanks to @Chuhtra for suggesting this. (#1377) Added right-click Mini Calendar actions for opening daily notes from day cells and weekly notes from week numbers. Thanks to @hasanyilmaz for suggesting this. (#1151) Added a Mini Calendar max color note count option, so one-note days can use the strongest heatmap color when that better fits the view. Thanks to @arreme for suggesting this. (#1376) Added backslash escapes for NLP trigger tokens, so text like \\@context, \\*done, or \\tomorrow can stay in the task title. Thanks to @JerryLu086 for suggesting this. (#1366) Added CSS variables for compacting nested task-card indentation, with smaller defaults on mobile and documented snippets for tighter task-link lists. Thanks to @rk-kontur for suggesting this. (#1502, #603) Added calendar indicators for external events that have linked notes or tasks, and showed loaded event titles in task-card calendar metadata instead of only the linked event count. Thanks to @Robubble and @mdbraber for suggesting this, and to @ubidev for the follow-up. (#1522) Added a per-status option to skip rarely used statuses when cycling task-card status indicators. Thanks to @Glint-Eye for suggesting this. (#144) Added an \"Open note in new tab\" action to the task context menu. Thanks to @cathywu for suggesting this and @macbikegeek for the follow-up feedback. (#167) Added an optional next-status override for each status, so forward cycling can jump to a configured status instead of always following the status order. Thanks to @DanBrazelton for suggesting this, and to @michelebugio, @Moyf, @anareaty, and @vorrermid for the follow-up feedback. (#1520) Made tag and context fields show available suggestions as soon as the field is focused. Thanks to @Glint-Eye for suggesting this, and to @craziedde for the follow-up. (#1541) Added {{currentNotePath}} and {{currentNoteTitle}} support to the default tasks folder, so normal task creation can place new tasks beside the active note without creating an inline link. Thanks to @ChristianAnyanwu for suggesting this, and to @abbasou and @ttlaylor for the follow-up feedback. (#648, #1605) Added clickable links in task-card contexts for note links, markdown links, and web URLs while keeping plain contexts as tag-search buttons. Thanks to @trdischat and @Glint-Eye for suggesting this, and to @renatomen for the follow-up feedback. (#1482) Added clickable custom-field links on task cards for wikilinks, markdown links, autolinks, and bare web URLs. Thanks to @ptbosch-figueiredorj for suggesting this, and to @Soleone for the follow-up use case. (#1471) Added Kanban column and swimlane-cell add buttons that open the TaskNotes creation modal with the grouped values already filled in. Thanks to @byheaven for suggesting this and @Davincible for the project-board use case. (#933) Added non-Markdown vault files such as canvases to project suggestions, using extension-qualified link targets so those files can be selected as task projects. Thanks to @Alvin21Bon for suggesting this. (#1475, #725) Added quote/backtick escapes for NLP input, so literal course codes or date words can stay in task titles without being parsed as estimates or dates. Thanks to @RumiaKitinari and @gavingwebb for suggesting this. (#1462) Added natural-language date entry to the task date picker, so existing due and scheduled dates can be changed with phrases such as \"tomorrow at 3pm\" when NLP is enabled. Thanks to @Ruboks-Cube for suggesting this. (#1526) Added a native date field to the task date picker, so scheduled and due dates can be changed with the device date picker while keeping optional times visible. Thanks to @jmartinmcfly for suggesting this and @23426356587 for the follow-up feedback. (#1603) Added Calendar view toggles for hiding completed or skipped recurring task instances while keeping future outstanding instances visible. Thanks to @wandererovertheseaofpiss for suggesting this. (#287, #273, #274) Added linked hover highlighting for Calendar and Agenda events that come from the same task note, so scheduled, due, and recurring entries are easier to connect. Thanks to @girisumit for suggesting this. (#280) Added project-specific CSS hooks to task cards and Calendar events, so project-based visual styling can be handled with user snippets. Thanks to @girisumit for suggesting this. (#1625) Added Shift + Cmd/Ctrl + Enter in the Create Task modal to save the current task and reopen the modal for the next one. Thanks to @tcb678 for suggesting this. (#1353) Focused the Create Task modal's natural-language input when the modal opens, with a longer mobile delay so the keyboard can open after layout. Thanks to @GiovanH for suggesting this. (#1664) Added project-based custom filename template variables, including the first project, all projects, and a short projectId. Thanks to @bendavis987 for the contribution. (#923) Added {{projectFilePath}} and {{projectFilePaths}} folder template variables, so task folders can mirror project note locations in the vault. Thanks to @PacoTaco2 for suggesting this. (#1697) Added cached Google Calendar, Microsoft Calendar, and ICS events to Mini Calendar days, with compact colored dots and event details from the existing calendar connection. Thanks to @RPGArchivist for suggesting this. (#1754) Added optional icons for priority values, so task cards can show a configured priority icon instead of only a colored dot. Thanks to @BrucePlumb for suggesting this and @prepare4robots for the follow-up feedback. (#1761) Added TaskNotes edit and task-action submenu entries to Obsidian's native file context menu for recognized task notes. Thanks to @delzero for suggesting this. (#1771) Added mobile drag handles to manually sorted Task List Bases views, so dragging can start from the handle without disabling normal text interaction on the rest of the card. Thanks to @PatrickGolz for suggesting this. (#1776) Allowed calendar timeline end times after midnight, such as 26:00 for a 2 AM next-day end. Thanks to @chrabia for suggesting this. (#1784, #1833) Added a per-view pinnedColumns option for TaskNotes Kanban views, so selected empty columns can stay visible as drop targets while other empty columns remain hidden. Thanks to @loukandr for suggesting and prototyping this. (#1794) Added context updates to the task card context menu, so contexts can be added, toggled, or cleared without opening the task edit modal. Thanks to @m13ntrpn for suggesting this. (#315, #1356, #1748, #1809) Added a subtle task-card indicator and CSS hooks for tasks with note body details, including existing task bodies read through Obsidian's metadata cache. Thanks to @volodxyz, @Karut, @yeHHH1g, and @aliceinwaterdeep for suggesting this, and to @minchinweb for the follow-up. (#1808) Added advanced Kanban swimlane ordering through swimLaneOrder, so swimlane rows can stay in a stable configured order. Thanks to @rookledookle for suggesting this, and to @benmartinek and @chrabia for the follow-up feedback. (#1805) Added an ICS export option to omit completed tasks from generated calendar files. Thanks to @bepolymathe for suggesting this. (#659) Added Obsidian links to ICS export descriptions, so exported calendar events can open their source task notes. Thanks to @bepolymathe for suggesting this. (#589) Added an Appearance toggle to turn off strikethrough styling on completed task card titles. Thanks to @BrucePlumb for suggesting this. (#561) Added a \"Last day\" option to the custom recurrence month-day picker for month-end repeating tasks. Thanks to @TonyAtlas for suggesting this and @BrucePlumb for the follow-up. (#217) Added weekday selection to daily custom recurrence rules, so interval rules such as every three days can skip weekends from the recurrence modal. Thanks to @kmaustral for suggesting this. (#1818) Added an auto-height mode for TaskNotes Calendar Bases views so embedded agenda/list sections can size to their content instead of forcing an inner scroller. Thanks to @martin-forge for suggesting this. (#1201) Added a Calendar Bases toggle to hide the hourly breakdown in week, custom-days, and day views while keeping the all-day planning row visible. Thanks to @PacoTaco2 for suggesting this. (#1176) Added advanced Kanban WIP limits through wipLimits, so column headers can show (current/limit) counts and highlight exceeded limits. Thanks to @williamcheuk03 for suggesting this. (#914) Added a generated Due in countdown to the default Agenda Base and allowed Calendar Bases list agendas to span up to 365 days. Thanks to @williamcheuk03 for suggesting this. (#900) Added an instant-conversion setting to keep the original Markdown checkbox marker when converting a checkbox into a TaskNote link. Thanks to @dsebastien for suggesting this. (#898) Added a mobile-only calendar integration opt-out, so synced desktop calendar settings no longer have to trigger external calendar loading on Obsidian Mobile. Thanks to @cathywu for suggesting this. (#887) Added built-in scheduled and due date presets to the Quick actions palette for current tasks. Thanks to @willgraham345 for suggesting this and @anrie for the related preset feedback. (#819) Added a command to open Quick actions for the inline task link under the cursor. Thanks to @rlolingo for suggesting this. (#798, #1732, #1835) Added hotkeyable commands to edit the current task, add a project to the current task, and add an existing task as a subtask of the current note. Thanks to @xorander00 and @prepare4robots for requesting this, and to @musta-code and @ubidev for the follow-up suggestions. (#791) Added a UUID v4 task filename format and {{uuid}} custom filename template variable. Thanks to @bangbangbanggit for suggesting this. (#932) Added hotkeyable commands to cycle the current task's status and priority. Thanks to @rxunique for suggesting this and @luckb0x for the follow-up feedback. (#1655) Added live elapsed time to the optional active time tracking status bar item. Thanks to @connradolisboa for suggesting this. (#1622) Allowed multiple comma-separated default reminder offsets for timed Google Calendar task exports. Thanks to @solidabstract for suggesting this. (#706, #820, #1040) Added direct Pomodoro duration editing, hour-aware timer formatting, clearer one-minute controls, and an optional active Pomodoro status bar countdown. Thanks to @SublunarSage, @lj1446615403-cloud, @0-BSCode, and @thestrike72 for the suggestions and feedback. (#873) Added an optional built-in sound for task reminder notifications, with volume and preview controls in Settings. Thanks to @berzernberg for suggesting this. Added a generated Pomodoro statistics Base with daily and monthly summary views for Pomodoro history stored in daily notes. Changed# Expanded the bug report template to ask for Obsidian \"Show debug info\" output, affected task frontmatter, relevant Bases file contents, reproduction steps, and related logs or screenshots. Release notes now show the default .base file regeneration reminder only on the current version section, keeping older bundled sections focused on their own changes. Updated the release notes GitHub prompt to invite feedback while still asking satisfied users to star the project. (#239) Ordered Kanban status and priority columns by the configured status order and priority weights when no manual column order is saved. Thanks to @ScumbagScalawag for asking about this, and to @nightroman, @lavir, and @elvarb for the follow-up discussion. (#269) Marked Kanban status columns that come from values outside the configured TaskNotes statuses, so manually edited or external status values are visible as non-standard instead of blending into the board. Thanks to @cstelmach for suggesting this and @digitaldoctors for the follow-up. Refined Kanban empty columns, swimlane rows, and column drag handles, and added a per-view compact card layout option for denser boards. Kept Kanban swimlane rows from shrinking to share the viewport so the Max Swimlane Height setting is respected. Added guidance in Pomodoro statistics and Base file settings explaining that Pomodoro Base views require daily notes storage. (#323) Reordered task modal action buttons to match the right-click task menu order. Thanks to @23426356587 for suggesting this. (#1189) Made the Create/Edit Task modal priority picker follow the priority order configured in Settings. Thanks to @n1njaznutz for suggesting this. Made task-card priority dots and configured priority icons slightly larger for better visibility. (#1244) Clarified the Task Properties documentation for custom property keys and status values in Bases filters and sorting. Thanks to @Arachnidai for suggesting this. (#1234) Kept right-aligned subtask chevrons visible on task cards instead of only showing them on hover. Thanks to @n1njaznutz for suggesting this. (#1237) Made today's date more visible in the Mini Calendar view when another day is selected. Thanks to @riekusr for suggesting this. (#1348) Let long task titles wrap inside the Create/Edit Task modal title field while keeping saved titles single-line, and widened the contexts and tags fields in the modal details area. Thanks to @hasanyilmaz for suggesting this. (#1392) Made TaskNotes date fields accept compact YYYYMMDD typing and pasted dates. Thanks to @kazerniel for suggesting this. (#1431) Showed the year on task-card due and scheduled dates when the date is outside the current year. Thanks to @kazerniel for suggesting this. (#1429) Opened TaskNotes view commands in a new tab when they load configured Base files, so they do not replace the active note. Thanks to @Ruboks-Cube for suggesting this. (#1426) Added copy actions for TaskNotes Bases views, including current-view filenames, links, and titles from the result count menu, plus selected-task copy actions in the batch menu, while keeping the native Bases copy and CSV export actions available. Thanks to @kmaustral for suggesting this. Improved keyboard access, mobile layout, and theme color consistency across task cards, TaskNotes Kanban, Bases Kanban, calendar controls, stats, settings, and filter popovers. (#1526) Made the Create/Edit Task modal due and scheduled date buttons open a calendar-first "},{"route":"/obsidian/releases/4.8.1/","title":"TaskNotes 4.8.1","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.8.1.md","namespace":"obsidian","relativePath":"releases/4.8.1.md","raw":"# TaskNotes 4.8.1\n\n## Fixed\n\n- (#1903) Improved the Edit Task modal on iPhone-sized screens so opening a task no longer automatically focuses the title field, and the mobile layout gives the title, fields, and action buttons more usable space.\n - Thanks to @3zra47 for reporting the issue and sharing the screen recording.\n- (#1909) Fixed compact Kanban task cards showing oversized status and priority indicators on touch devices.\n - Thanks to @pxxush for reporting the issue.\n- (#1908) Restored newly generated Calendar Bases to show the full day by default and inherit the calendar start/end settings instead of hard-coding 06:00-22:00.\n - Thanks to @AndreMonthy for the report.\n- (#1907) Fixed calendar time labels drifting away from the left axis in narrow sidebar calendar views.\n - Thanks to @kmaustral for reporting the issue.\n- (#1906) Fixed NLP priority shortcuts leaving partial text in task titles when custom priority values include words like `high` or `low`.\n - Thanks to @RumiaKitinari for reporting the issue.\n- (#1904, #1905) Fixed long tags in task cards wrapping instead of forcing horizontal scrolling in TaskNotes Bases views and note cards.\n - Long tag pills can now wrap across lines and break within very long tag names on narrow screens.\n - Thanks to @3zra47 for reporting the issue and to @zhouzhou626 for the contribution.\n- (#1901) Fixed the task context menu creating an `undefined` property when adding or removing tags.\n - Hardened task property updates so invalid frontmatter property names are rejected instead of written.\n - Thanks to @mgrecar for reporting the issue.\n- (#1902) Fixed Markdown-style project links in task frontmatter not appearing as subtasks on project pages.\n - Thanks to @minchinweb for reporting the issue.\n\n## Changed\n\n- Improved the internal structure around service notifications, vault writes, and shared utilities to make future fixes easier to test and maintain.\n","aliases":["/releases/4.8.1/","/releases/4.8.1/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"changed","text":"Changed"}],"html":"

Fixed#

\n
    \n
  • (#1903) Improved the Edit Task modal on iPhone-sized screens so opening a task no longer automatically focuses the title field, and the mobile layout gives the title, fields, and action buttons more usable space.
      \n
    • Thanks to @3zra47 for reporting the issue and sharing the screen recording.
    • \n
    \n
  • \n
  • (#1909) Fixed compact Kanban task cards showing oversized status and priority indicators on touch devices.
      \n
    • Thanks to @pxxush for reporting the issue.
    • \n
    \n
  • \n
  • (#1908) Restored newly generated Calendar Bases to show the full day by default and inherit the calendar start/end settings instead of hard-coding 06:00-22:00.
      \n
    • Thanks to @AndreMonthy for the report.
    • \n
    \n
  • \n
  • (#1907) Fixed calendar time labels drifting away from the left axis in narrow sidebar calendar views.
      \n
    • Thanks to @kmaustral for reporting the issue.
    • \n
    \n
  • \n
  • (#1906) Fixed NLP priority shortcuts leaving partial text in task titles when custom priority values include words like high or low.
      \n
    • Thanks to @RumiaKitinari for reporting the issue.
    • \n
    \n
  • \n
  • (#1904, #1905) Fixed long tags in task cards wrapping instead of forcing horizontal scrolling in TaskNotes Bases views and note cards.
      \n
    • Long tag pills can now wrap across lines and break within very long tag names on narrow screens.
    • \n
    • Thanks to @3zra47 for reporting the issue and to @zhouzhou626 for the contribution.
    • \n
    \n
  • \n
  • (#1901) Fixed the task context menu creating an undefined property when adding or removing tags.
      \n
    • Hardened task property updates so invalid frontmatter property names are rejected instead of written.
    • \n
    • Thanks to @mgrecar for reporting the issue.
    • \n
    \n
  • \n
  • (#1902) Fixed Markdown-style project links in task frontmatter not appearing as subtasks on project pages.
      \n
    • Thanks to @minchinweb for reporting the issue.
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Improved the internal structure around service notifications, vault writes, and shared utilities to make future fixes easier to test and maintain.
  • \n
\n","text":"Fixed# (#1903) Improved the Edit Task modal on iPhone-sized screens so opening a task no longer automatically focuses the title field, and the mobile layout gives the title, fields, and action buttons more usable space. Thanks to @3zra47 for reporting the issue and sharing the screen recording. (#1909) Fixed compact Kanban task cards showing oversized status and priority indicators on touch devices. Thanks to @pxxush for reporting the issue. (#1908) Restored newly generated Calendar Bases to show the full day by default and inherit the calendar start/end settings instead of hard-coding 06:00-22:00. Thanks to @AndreMonthy for the report. (#1907) Fixed calendar time labels drifting away from the left axis in narrow sidebar calendar views. Thanks to @kmaustral for reporting the issue. (#1906) Fixed NLP priority shortcuts leaving partial text in task titles when custom priority values include words like high or low. Thanks to @RumiaKitinari for reporting the issue. (#1904, #1905) Fixed long tags in task cards wrapping instead of forcing horizontal scrolling in TaskNotes Bases views and note cards. Long tag pills can now wrap across lines and break within very long tag names on narrow screens. Thanks to @3zra47 for reporting the issue and to @zhouzhou626 for the contribution. (#1901) Fixed the task context menu creating an undefined property when adding or removing tags. Hardened task property updates so invalid frontmatter property names are rejected instead of written. Thanks to @mgrecar for reporting the issue. (#1902) Fixed Markdown-style project links in task frontmatter not appearing as subtasks on project pages. Thanks to @minchinweb for reporting the issue. Changed# Improved the internal structure around service notifications, vault writes, and shared utilities to make future fixes easier to test and maintain."},{"route":"/obsidian/releases/4.9.0/","title":"TaskNotes 4.9.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.9.0.md","namespace":"obsidian","relativePath":"releases/4.9.0.md","raw":"# TaskNotes 4.9.0\n\n## Security\n\n- (#1923) Restricted the HTTP API server to loopback and limited browser CORS access to loopback origins.\n - Thanks to @martin-forge for reporting.\n\n## Added\n\n- (#1932) Added middle-click support for opening task cards in a new tab.\n - Thanks to @imsuck for the request.\n\n## Fixed\n\n- (#1934) Fixed custom priority colors being overridden by default task-card priority styles in views.\n - Thanks to @KittehBit for reporting.\n- (#1933) Added the note path to fallback frontmatter parse warnings so malformed task YAML is easier to find.\n - Thanks to @rayvermey for reporting.\n- (#1931) Made the Pomodoro task chooser open from cached task data and ignore repeated clicks while it is already opening.\n - Thanks to @sumiyalairu03 for reporting.\n- (#1930) Fixed starting the Pomodoro timer from its hotkey without starting time tracking for the selected Pomodoro task.\n - Thanks to @sumiyalairu03 for reporting.\n- (#1929) Fixed the bottom Relationships widget overlapping embedded content such as Bases/Kanban views in task notes.\n - Thanks to @rchaklashiya for reporting and following up with the embed case.\n- (#1922) Restored the native color picker alongside manual color text entry in Create/Edit Timeblock fields.\n - Thanks to @AndreMonthy for reporting.\n- (#1921) Fixed direct frontmatter edits to lifecycle-relevant task fields not triggering Google Calendar sync or auto-archive side effects.\n - Thanks to @martin-forge for reporting and verifying the direct-edit reproduction.\n- (#1919) Fixed the Pomodoro view rapidly resizing at certain sidebar sizes.\n - Thanks to @RumiaKitinari for reporting.\n- (#1898, #1907) Fixed Calendar time labels shifting into the middle of Day and sidebar calendar grids after switching views.\n - Thanks to @ddevaal for reporting and confirming the regression, and to @kmaustral for confirming the sidebar case in 4.8.1.\n- (#1936) Added a Calendar Base drag/drop resolution option so events can snap to smaller increments than the visible time slot grid.\n - Thanks to @benmartinek for suggesting this.\n- Improved mobile task cards, inline widgets, modals, and settings layouts so dense controls and long labels fit more comfortably on small screens.\n- (#1916) Fixed Markdown task links using Obsidian's generated filename label instead of the TaskNote title in the task link overlay.\n - Thanks to @minchinweb for reporting.\n- (#1911) Fixed recurrence choices starting from today instead of the selected calendar date when creating a task from Calendar view.\n - Thanks to @mikhailmarka for reporting.\n- (#1912) Fixed \"Create subtask\" pre-filling the parent task's full folder path in the Projects field instead of using the normal Obsidian link text.\n - Thanks to @pkuehne for reporting and @benmartinek for confirming.\n","aliases":["/releases/4.9.0/","/releases/4.9.0/"],"toc":[{"level":2,"id":"security","text":"Security"},{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Security#

\n
    \n
  • (#1923) Restricted the HTTP API server to loopback and limited browser CORS access to loopback origins.
      \n
    • Thanks to @martin-forge for reporting.
    • \n
    \n
  • \n
\n

Added#

\n
    \n
  • (#1932) Added middle-click support for opening task cards in a new tab.
      \n
    • Thanks to @imsuck for the request.
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1934) Fixed custom priority colors being overridden by default task-card priority styles in views.
      \n
    • Thanks to @KittehBit for reporting.
    • \n
    \n
  • \n
  • (#1933) Added the note path to fallback frontmatter parse warnings so malformed task YAML is easier to find.
      \n
    • Thanks to @rayvermey for reporting.
    • \n
    \n
  • \n
  • (#1931) Made the Pomodoro task chooser open from cached task data and ignore repeated clicks while it is already opening.
      \n
    • Thanks to @sumiyalairu03 for reporting.
    • \n
    \n
  • \n
  • (#1930) Fixed starting the Pomodoro timer from its hotkey without starting time tracking for the selected Pomodoro task.
      \n
    • Thanks to @sumiyalairu03 for reporting.
    • \n
    \n
  • \n
  • (#1929) Fixed the bottom Relationships widget overlapping embedded content such as Bases/Kanban views in task notes.
      \n
    • Thanks to @rchaklashiya for reporting and following up with the embed case.
    • \n
    \n
  • \n
  • (#1922) Restored the native color picker alongside manual color text entry in Create/Edit Timeblock fields.
      \n
    • Thanks to @AndreMonthy for reporting.
    • \n
    \n
  • \n
  • (#1921) Fixed direct frontmatter edits to lifecycle-relevant task fields not triggering Google Calendar sync or auto-archive side effects.
      \n
    • Thanks to @martin-forge for reporting and verifying the direct-edit reproduction.
    • \n
    \n
  • \n
  • (#1919) Fixed the Pomodoro view rapidly resizing at certain sidebar sizes.
      \n
    • Thanks to @RumiaKitinari for reporting.
    • \n
    \n
  • \n
  • (#1898, #1907) Fixed Calendar time labels shifting into the middle of Day and sidebar calendar grids after switching views.
      \n
    • Thanks to @ddevaal for reporting and confirming the regression, and to @kmaustral for confirming the sidebar case in 4.8.1.
    • \n
    \n
  • \n
  • (#1936) Added a Calendar Base drag/drop resolution option so events can snap to smaller increments than the visible time slot grid.
      \n
    • Thanks to @benmartinek for suggesting this.
    • \n
    \n
  • \n
  • Improved mobile task cards, inline widgets, modals, and settings layouts so dense controls and long labels fit more comfortably on small screens.
  • \n
  • (#1916) Fixed Markdown task links using Obsidian's generated filename label instead of the TaskNote title in the task link overlay.
      \n
    • Thanks to @minchinweb for reporting.
    • \n
    \n
  • \n
  • (#1911) Fixed recurrence choices starting from today instead of the selected calendar date when creating a task from Calendar view.
      \n
    • Thanks to @mikhailmarka for reporting.
    • \n
    \n
  • \n
  • (#1912) Fixed "Create subtask" pre-filling the parent task's full folder path in the Projects field instead of using the normal Obsidian link text.
      \n
    • Thanks to @pkuehne for reporting and @benmartinek for confirming.
    • \n
    \n
  • \n
\n","text":"Security# (#1923) Restricted the HTTP API server to loopback and limited browser CORS access to loopback origins. Thanks to @martin-forge for reporting. Added# (#1932) Added middle-click support for opening task cards in a new tab. Thanks to @imsuck for the request. Fixed# (#1934) Fixed custom priority colors being overridden by default task-card priority styles in views. Thanks to @KittehBit for reporting. (#1933) Added the note path to fallback frontmatter parse warnings so malformed task YAML is easier to find. Thanks to @rayvermey for reporting. (#1931) Made the Pomodoro task chooser open from cached task data and ignore repeated clicks while it is already opening. Thanks to @sumiyalairu03 for reporting. (#1930) Fixed starting the Pomodoro timer from its hotkey without starting time tracking for the selected Pomodoro task. Thanks to @sumiyalairu03 for reporting. (#1929) Fixed the bottom Relationships widget overlapping embedded content such as Bases/Kanban views in task notes. Thanks to @rchaklashiya for reporting and following up with the embed case. (#1922) Restored the native color picker alongside manual color text entry in Create/Edit Timeblock fields. Thanks to @AndreMonthy for reporting. (#1921) Fixed direct frontmatter edits to lifecycle-relevant task fields not triggering Google Calendar sync or auto-archive side effects. Thanks to @martin-forge for reporting and verifying the direct-edit reproduction. (#1919) Fixed the Pomodoro view rapidly resizing at certain sidebar sizes. Thanks to @RumiaKitinari for reporting. (#1898, #1907) Fixed Calendar time labels shifting into the middle of Day and sidebar calendar grids after switching views. Thanks to @ddevaal for reporting and confirming the regression, and to @kmaustral for confirming the sidebar case in 4.8.1. (#1936) Added a Calendar Base drag/drop resolution option so events can snap to smaller increments than the visible time slot grid. Thanks to @benmartinek for suggesting this. Improved mobile task cards, inline widgets, modals, and settings layouts so dense controls and long labels fit more comfortably on small screens. (#1916) Fixed Markdown task links using Obsidian's generated filename label instead of the TaskNote title in the task link overlay. Thanks to @minchinweb for reporting. (#1911) Fixed recurrence choices starting from today instead of the selected calendar date when creating a task from Calendar view. Thanks to @mikhailmarka for reporting. (#1912) Fixed \"Create subtask\" pre-filling the parent task's full folder path in the Projects field instead of using the normal Obsidian link text. Thanks to @pkuehne for reporting and @benmartinek for confirming."},{"route":"/obsidian/releases/4.9.1/","title":"TaskNotes 4.9.1","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.9.1.md","namespace":"obsidian","relativePath":"releases/4.9.1.md","raw":"# TaskNotes 4.9.1\n\n## Added\n\n- (#1885) Added Shift+arrow keyboard range selection while bulk task selection mode is active.\n - Thanks to @chrabia for suggesting bulk selection improvements and @sumiyalairu03 for the keyboard selection idea.\n\n## Fixed\n\n- (#781, #1085) Fixed Outlook-published ICS calendar events appearing at the wrong time when their feed used Windows timezone names without matching timezone definitions.\n - Thanks to @chrlaney for reporting and @mjkrasny for confirming the Outlook timezone case.\n- (#1696) Fixed Google Calendar export for scheduled recurring tasks when a single occurrence is moved to a different date.\n - Keeps the recurring master event on its original rule, excludes the original occurrence date, and syncs the moved occurrence as a detached event.\n - Thanks to @martin-forge for reporting and contributing the fix.\n- (#1912) Fixed \"Create subtask\" inserting the full path of the parent task in the Projects field instead of using the normal Obsidian link text.\n - Thanks to @pkuehne for reporting and @benmartinek for confirming.\n- (#1921) Fixed Google Calendar and auto-archive updates not running after direct task file edits.\n - TaskNotes now picks up status, completion, and date changes made directly in a task file without triggering a large one-time Google Calendar rewrite at startup.\n - Recovery also removes stale Google Calendar links when task files were deleted or replaced outside TaskNotes.\n - Thanks to @martin-forge for reporting and contributing the fix.\n- (#1938) Fixed partial HTTP API task updates rewriting native tags with `#` prefixes or duplicate task tags.\n - Thanks to @joseluisgonzalezdelgado-ctrl for reporting.\n- (#1939) Fixed the task Details field rendering as a small nested textarea when the embedded editor falls back.\n - Thanks to @g-arthurvanderbilt for reporting and @cookbr for confirming the desktop impact.\n- Fixed tag and modal preview edge cases found during validation: double-hash tags no longer match the task tag, empty tag lists stay empty when read back, and natural-language previews remain visible when enabled.\n- (#1941) Fixed mobile Kanban boards scrolling the whole board vertically instead of keeping each list independently scrollable.\n - Thanks to @pxxush for reporting.\n- (#1943) Fixed MCP task-query tool instructions so filter operators match the operators TaskNotes actually accepts.\n - Thanks to @jordankbartos for reporting and proposing a fix in #1944.\n- (#1945) Fixed Google Calendar export so overlapping sync services do not create duplicate events for the same task while the saved event ID is still catching up.\n - Thanks to @martin-forge for reporting and contributing the fix.\n- (#1946) Fixed the bottom task in virtualized Task List Bases being partially hidden behind Obsidian's mobile bottom bar.\n - Thanks to @3zra47 for reporting.\n- (#1947) Fixed mobile Task List cards with left-positioned subtask chevrons so the chevron remains visible and project/detail badges stay on the main row.\n - Thanks to @Jomo94 for reporting.\n- (#1948) Fixed Agenda Calendar Bases so completed recurring instances can appear on their recorded completion dates, even when recurring task projections are hidden or the completion date is outside the recurrence pattern.\n - Thanks to @Jomo94 for reporting.\n","aliases":["/releases/4.9.1/","/releases/4.9.1/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • (#1885) Added Shift+arrow keyboard range selection while bulk task selection mode is active.
      \n
    • Thanks to @chrabia for suggesting bulk selection improvements and @sumiyalairu03 for the keyboard selection idea.
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#781, #1085) Fixed Outlook-published ICS calendar events appearing at the wrong time when their feed used Windows timezone names without matching timezone definitions.
      \n
    • Thanks to @chrlaney for reporting and @mjkrasny for confirming the Outlook timezone case.
    • \n
    \n
  • \n
  • (#1696) Fixed Google Calendar export for scheduled recurring tasks when a single occurrence is moved to a different date.
      \n
    • Keeps the recurring master event on its original rule, excludes the original occurrence date, and syncs the moved occurrence as a detached event.
    • \n
    • Thanks to @martin-forge for reporting and contributing the fix.
    • \n
    \n
  • \n
  • (#1912) Fixed "Create subtask" inserting the full path of the parent task in the Projects field instead of using the normal Obsidian link text.
      \n
    • Thanks to @pkuehne for reporting and @benmartinek for confirming.
    • \n
    \n
  • \n
  • (#1921) Fixed Google Calendar and auto-archive updates not running after direct task file edits.
      \n
    • TaskNotes now picks up status, completion, and date changes made directly in a task file without triggering a large one-time Google Calendar rewrite at startup.
    • \n
    • Recovery also removes stale Google Calendar links when task files were deleted or replaced outside TaskNotes.
    • \n
    • Thanks to @martin-forge for reporting and contributing the fix.
    • \n
    \n
  • \n
  • (#1938) Fixed partial HTTP API task updates rewriting native tags with # prefixes or duplicate task tags.
      \n
    • Thanks to @joseluisgonzalezdelgado-ctrl for reporting.
    • \n
    \n
  • \n
  • (#1939) Fixed the task Details field rendering as a small nested textarea when the embedded editor falls back.
      \n
    • Thanks to @g-arthurvanderbilt for reporting and @cookbr for confirming the desktop impact.
    • \n
    \n
  • \n
  • Fixed tag and modal preview edge cases found during validation: double-hash tags no longer match the task tag, empty tag lists stay empty when read back, and natural-language previews remain visible when enabled.
  • \n
  • (#1941) Fixed mobile Kanban boards scrolling the whole board vertically instead of keeping each list independently scrollable.
      \n
    • Thanks to @pxxush for reporting.
    • \n
    \n
  • \n
  • (#1943) Fixed MCP task-query tool instructions so filter operators match the operators TaskNotes actually accepts.
      \n
    • Thanks to @jordankbartos for reporting and proposing a fix in #1944.
    • \n
    \n
  • \n
  • (#1945) Fixed Google Calendar export so overlapping sync services do not create duplicate events for the same task while the saved event ID is still catching up.
      \n
    • Thanks to @martin-forge for reporting and contributing the fix.
    • \n
    \n
  • \n
  • (#1946) Fixed the bottom task in virtualized Task List Bases being partially hidden behind Obsidian's mobile bottom bar.
      \n
    • Thanks to @3zra47 for reporting.
    • \n
    \n
  • \n
  • (#1947) Fixed mobile Task List cards with left-positioned subtask chevrons so the chevron remains visible and project/detail badges stay on the main row.
      \n
    • Thanks to @Jomo94 for reporting.
    • \n
    \n
  • \n
  • (#1948) Fixed Agenda Calendar Bases so completed recurring instances can appear on their recorded completion dates, even when recurring task projections are hidden or the completion date is outside the recurrence pattern.
      \n
    • Thanks to @Jomo94 for reporting.
    • \n
    \n
  • \n
\n","text":"Added# (#1885) Added Shift+arrow keyboard range selection while bulk task selection mode is active. Thanks to @chrabia for suggesting bulk selection improvements and @sumiyalairu03 for the keyboard selection idea. Fixed# (#781, #1085) Fixed Outlook-published ICS calendar events appearing at the wrong time when their feed used Windows timezone names without matching timezone definitions. Thanks to @chrlaney for reporting and @mjkrasny for confirming the Outlook timezone case. (#1696) Fixed Google Calendar export for scheduled recurring tasks when a single occurrence is moved to a different date. Keeps the recurring master event on its original rule, excludes the original occurrence date, and syncs the moved occurrence as a detached event. Thanks to @martin-forge for reporting and contributing the fix. (#1912) Fixed \"Create subtask\" inserting the full path of the parent task in the Projects field instead of using the normal Obsidian link text. Thanks to @pkuehne for reporting and @benmartinek for confirming. (#1921) Fixed Google Calendar and auto-archive updates not running after direct task file edits. TaskNotes now picks up status, completion, and date changes made directly in a task file without triggering a large one-time Google Calendar rewrite at startup. Recovery also removes stale Google Calendar links when task files were deleted or replaced outside TaskNotes. Thanks to @martin-forge for reporting and contributing the fix. (#1938) Fixed partial HTTP API task updates rewriting native tags with # prefixes or duplicate task tags. Thanks to @joseluisgonzalezdelgado-ctrl for reporting. (#1939) Fixed the task Details field rendering as a small nested textarea when the embedded editor falls back. Thanks to @g-arthurvanderbilt for reporting and @cookbr for confirming the desktop impact. Fixed tag and modal preview edge cases found during validation: double-hash tags no longer match the task tag, empty tag lists stay empty when read back, and natural-language previews remain visible when enabled. (#1941) Fixed mobile Kanban boards scrolling the whole board vertically instead of keeping each list independently scrollable. Thanks to @pxxush for reporting. (#1943) Fixed MCP task-query tool instructions so filter operators match the operators TaskNotes actually accepts. Thanks to @jordankbartos for reporting and proposing a fix in #1944. (#1945) Fixed Google Calendar export so overlapping sync services do not create duplicate events for the same task while the saved event ID is still catching up. Thanks to @martin-forge for reporting and contributing the fix. (#1946) Fixed the bottom task in virtualized Task List Bases being partially hidden behind Obsidian's mobile bottom bar. Thanks to @3zra47 for reporting. (#1947) Fixed mobile Task List cards with left-positioned subtask chevrons so the chevron remains visible and project/detail badges stay on the main row. Thanks to @Jomo94 for reporting. (#1948) Fixed Agenda Calendar Bases so completed recurring instances can appear on their recorded completion dates, even when recurring task projections are hidden or the completion date is outside the recurrence pattern. Thanks to @Jomo94 for reporting."},{"route":"/obsidian/releases/4.9.2/","title":"TaskNotes 4.9.2","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.9.2.md","namespace":"obsidian","relativePath":"releases/4.9.2.md","raw":"# TaskNotes 4.9.2\n\n## Added\n\n- (#1791) Added collapse and expand controls for grouped Bases Task List views, including a default collapsed state option.\n - Thanks to @renatomen for the contribution.\n\n## Fixed\n\n- Fixed Pomodoro storage migration so existing plugin-data history is written to daily notes before switching storage, and clarified that daily notes can come from either the core Daily Notes plugin or Periodic Notes.\n- (#1964) Fixed Microsoft Calendar OAuth so connecting no longer forces a fresh consent prompt every time, and clarified the Microsoft desktop app setup steps.\n - Thanks to @thechonta for reporting.\n- (#1966) Fixed custom priority icons so they render as icons instead of filled squares on task cards.\n - Thanks to @sruiz-savia for reporting.\n- (#1963) Fixed Google Calendar sync so duplicate event ID fields are repaired when saving task calendar metadata.\n - Thanks to @christenbc for reporting.\n- (#1961) Fixed the default custom filename template so it uses the recommended double-brace syntax and no longer warns on first use.\n - Thanks to @chmac for reporting.\n- (#1962) Fixed task tag normalization so tags entered with spaces are saved with hyphens for Obsidian tag compatibility.\n - Thanks to @christenbc for reporting.\n- (#1959) Fixed the MCP `tasknotes_list_tasks` tool so circular internal task data and live Obsidian object references no longer break task-list responses.\n - Thanks to @kmaustral for reporting.\n- (#1957) Fixed the Pomodoro timer layout in vertically split panes so the timer header and progress circle remain reachable when the pane is short.\n - Thanks to @sumiyalairu03 for reporting.\n- (#1956) Fixed Google Calendar sync so completing a recurring task updates the linked event title with the completion checkmark.\n - Thanks to @jacksoluke for reporting.\n- (#1953) Fixed inline task conversion so source-line wikilinks no longer create nested wikilinks in the replacement link text.\n - Thanks to @bgk0018 for reporting.\n- (#1952) Fixed Pomodoro task picker search results so matching task titles are ranked and sorted ahead of due-date ordering.\n - Thanks to @KFrancoD for reporting.\n- (#1392, #1949) Fixed due and scheduled date picker fields so typed or pasted date edits stay open until you choose Select, including compact `YYYYMMDD` entry when a date is already set.\n - Thanks to @kazerniel for reporting and following up.\n- (#982, #1947) Restored larger mobile task-card typography and let secondary card icons wrap below the task details when they no longer fit comfortably on mobile.\n - Thanks to @3zra47 for reporting the font-size regression, @chrsdk and @scottaltham-payroc for confirming the mobile font-size issue, and @Jomo94 for reporting the mobile card layout problem.\n","aliases":["/releases/4.9.2/","/releases/4.9.2/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • (#1791) Added collapse and expand controls for grouped Bases Task List views, including a default collapsed state option.
      \n
    • Thanks to @renatomen for the contribution.
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • Fixed Pomodoro storage migration so existing plugin-data history is written to daily notes before switching storage, and clarified that daily notes can come from either the core Daily Notes plugin or Periodic Notes.
  • \n
  • (#1964) Fixed Microsoft Calendar OAuth so connecting no longer forces a fresh consent prompt every time, and clarified the Microsoft desktop app setup steps.
      \n
    • Thanks to @thechonta for reporting.
    • \n
    \n
  • \n
  • (#1966) Fixed custom priority icons so they render as icons instead of filled squares on task cards.
      \n
    • Thanks to @sruiz-savia for reporting.
    • \n
    \n
  • \n
  • (#1963) Fixed Google Calendar sync so duplicate event ID fields are repaired when saving task calendar metadata.
      \n
    • Thanks to @christenbc for reporting.
    • \n
    \n
  • \n
  • (#1961) Fixed the default custom filename template so it uses the recommended double-brace syntax and no longer warns on first use.
      \n
    • Thanks to @chmac for reporting.
    • \n
    \n
  • \n
  • (#1962) Fixed task tag normalization so tags entered with spaces are saved with hyphens for Obsidian tag compatibility.
      \n
    • Thanks to @christenbc for reporting.
    • \n
    \n
  • \n
  • (#1959) Fixed the MCP tasknotes_list_tasks tool so circular internal task data and live Obsidian object references no longer break task-list responses.
      \n
    • Thanks to @kmaustral for reporting.
    • \n
    \n
  • \n
  • (#1957) Fixed the Pomodoro timer layout in vertically split panes so the timer header and progress circle remain reachable when the pane is short.
      \n
    • Thanks to @sumiyalairu03 for reporting.
    • \n
    \n
  • \n
  • (#1956) Fixed Google Calendar sync so completing a recurring task updates the linked event title with the completion checkmark.
      \n
    • Thanks to @jacksoluke for reporting.
    • \n
    \n
  • \n
  • (#1953) Fixed inline task conversion so source-line wikilinks no longer create nested wikilinks in the replacement link text.
      \n
    • Thanks to @bgk0018 for reporting.
    • \n
    \n
  • \n
  • (#1952) Fixed Pomodoro task picker search results so matching task titles are ranked and sorted ahead of due-date ordering.
      \n
    • Thanks to @KFrancoD for reporting.
    • \n
    \n
  • \n
  • (#1392, #1949) Fixed due and scheduled date picker fields so typed or pasted date edits stay open until you choose Select, including compact YYYYMMDD entry when a date is already set.
      \n
    • Thanks to @kazerniel for reporting and following up.
    • \n
    \n
  • \n
  • (#982, #1947) Restored larger mobile task-card typography and let secondary card icons wrap below the task details when they no longer fit comfortably on mobile.
      \n
    • Thanks to @3zra47 for reporting the font-size regression, @chrsdk and @scottaltham-payroc for confirming the mobile font-size issue, and @Jomo94 for reporting the mobile card layout problem.
    • \n
    \n
  • \n
\n","text":"Added# (#1791) Added collapse and expand controls for grouped Bases Task List views, including a default collapsed state option. Thanks to @renatomen for the contribution. Fixed# Fixed Pomodoro storage migration so existing plugin-data history is written to daily notes before switching storage, and clarified that daily notes can come from either the core Daily Notes plugin or Periodic Notes. (#1964) Fixed Microsoft Calendar OAuth so connecting no longer forces a fresh consent prompt every time, and clarified the Microsoft desktop app setup steps. Thanks to @thechonta for reporting. (#1966) Fixed custom priority icons so they render as icons instead of filled squares on task cards. Thanks to @sruiz-savia for reporting. (#1963) Fixed Google Calendar sync so duplicate event ID fields are repaired when saving task calendar metadata. Thanks to @christenbc for reporting. (#1961) Fixed the default custom filename template so it uses the recommended double-brace syntax and no longer warns on first use. Thanks to @chmac for reporting. (#1962) Fixed task tag normalization so tags entered with spaces are saved with hyphens for Obsidian tag compatibility. Thanks to @christenbc for reporting. (#1959) Fixed the MCP tasknotes_list_tasks tool so circular internal task data and live Obsidian object references no longer break task-list responses. Thanks to @kmaustral for reporting. (#1957) Fixed the Pomodoro timer layout in vertically split panes so the timer header and progress circle remain reachable when the pane is short. Thanks to @sumiyalairu03 for reporting. (#1956) Fixed Google Calendar sync so completing a recurring task updates the linked event title with the completion checkmark. Thanks to @jacksoluke for reporting. (#1953) Fixed inline task conversion so source-line wikilinks no longer create nested wikilinks in the replacement link text. Thanks to @bgk0018 for reporting. (#1952) Fixed Pomodoro task picker search results so matching task titles are ranked and sorted ahead of due-date ordering. Thanks to @KFrancoD for reporting. (#1392, #1949) Fixed due and scheduled date picker fields so typed or pasted date edits stay open until you choose Select, including compact YYYYMMDD entry when a date is already set. Thanks to @kazerniel for reporting and following up. (#982, #1947) Restored larger mobile task-card typography and let secondary card icons wrap below the task details when they no longer fit comfortably on mobile. Thanks to @3zra47 for reporting the font-size regression, @chrsdk and @scottaltham-payroc for confirming the mobile font-size issue, and @Jomo94 for reporting the mobile card layout problem."},{"route":"/obsidian/releases/unreleased/","title":"TaskNotes - Unreleased","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/unreleased.md","namespace":"obsidian","relativePath":"releases/unreleased.md","raw":"# TaskNotes - Unreleased\n\n\n","aliases":["/releases/unreleased/","/releases/unreleased/"],"toc":[],"html":"\n","text":""},{"route":"/obsidian/settings/","title":"Settings","description":"TaskNotes settings are organized into tabs. Each tab controls a different part of plugin behavior.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/settings.md","namespace":"obsidian","relativePath":"settings.md","raw":"# Settings\n\nTaskNotes settings are organized into tabs. Each tab controls a different part of plugin behavior.\n\n\n## General\n\nThe General tab controls task identification, storage locations, and task-card click behavior. Use this tab when your vault already has conventions such as custom tags, property-based identification, or specific folder structures.\n\nFor more information, see the [General Settings](settings/general.md) documentation.\n\n## Task Properties\n\nTask Properties defines the schema TaskNotes writes to frontmatter, including status, priority, dates, reminders, projects, and user fields. Each property card lets you remap key names and behavior so TaskNotes can match existing metadata rather than forcing a migration.\n\nFor more detailed information, see the [Task Properties Settings](settings/task-properties.md) documentation.\n\n## Modal Fields\n\nModal Fields controls the task create/edit experience by deciding which fields are visible and in what order. If your workflow depends on a handful of fields, you can surface only those and reduce form noise.\n\nFor more information, see the [Modal Fields Settings](settings/modal-fields.md) documentation.\n\n## Appearance & UI\n\nAppearance & UI handles task card density, calendar defaults, time formatting, and visual toggles for supporting widgets. Use this tab to tune how much information is visible at a glance.\n\nFor more detailed information, see the [Appearance & UI Settings](settings/appearance.md) documentation.\n\n## Features\n\nFeatures groups behavior toggles for inline tasks, natural language input, Pomodoro, reminders, and performance-related options. It is where you enable advanced workflow capabilities and then refine defaults.\n\nFor more information, see the [Features Settings](settings/features.md) documentation.\n\n## Integrations\n\nIntegrations covers external connectivity: Bases view wiring, Google/Microsoft OAuth calendar sync, ICS subscriptions, automatic ICS export, HTTP API settings, and webhook endpoints.\n\nFor more detailed information, see the [Integrations Settings](settings/integrations.md) documentation.\n","aliases":["/settings/"],"toc":[{"level":2,"id":"general","text":"General"},{"level":2,"id":"task-properties","text":"Task Properties"},{"level":2,"id":"modal-fields","text":"Modal Fields"},{"level":2,"id":"appearance-ui","text":"Appearance & UI"},{"level":2,"id":"features","text":"Features"},{"level":2,"id":"integrations","text":"Integrations"}],"html":"

TaskNotes settings are organized into tabs. Each tab controls a different part of plugin behavior.

\n

General#

\n

The General tab controls task identification, storage locations, and task-card click behavior. Use this tab when your vault already has conventions such as custom tags, property-based identification, or specific folder structures.

\n

For more information, see the General Settings documentation.

\n

Task Properties#

\n

Task Properties defines the schema TaskNotes writes to frontmatter, including status, priority, dates, reminders, projects, and user fields. Each property card lets you remap key names and behavior so TaskNotes can match existing metadata rather than forcing a migration.

\n

For more detailed information, see the Task Properties Settings documentation.

\n

Modal Fields#

\n

Modal Fields controls the task create/edit experience by deciding which fields are visible and in what order. If your workflow depends on a handful of fields, you can surface only those and reduce form noise.

\n

For more information, see the Modal Fields Settings documentation.

\n

Appearance & UI#

\n

Appearance & UI handles task card density, calendar defaults, time formatting, and visual toggles for supporting widgets. Use this tab to tune how much information is visible at a glance.

\n

For more detailed information, see the Appearance & UI Settings documentation.

\n

Features#

\n

Features groups behavior toggles for inline tasks, natural language input, Pomodoro, reminders, and performance-related options. It is where you enable advanced workflow capabilities and then refine defaults.

\n

For more information, see the Features Settings documentation.

\n

Integrations#

\n

Integrations covers external connectivity: Bases view wiring, Google/Microsoft OAuth calendar sync, ICS subscriptions, automatic ICS export, HTTP API settings, and webhook endpoints.

\n

For more detailed information, see the Integrations Settings documentation.

\n","text":"TaskNotes settings are organized into tabs. Each tab controls a different part of plugin behavior. General# The General tab controls task identification, storage locations, and task-card click behavior. Use this tab when your vault already has conventions such as custom tags, property-based identification, or specific folder structures. For more information, see the General Settings documentation. Task Properties# Task Properties defines the schema TaskNotes writes to frontmatter, including status, priority, dates, reminders, projects, and user fields. Each property card lets you remap key names and behavior so TaskNotes can match existing metadata rather than forcing a migration. For more detailed information, see the Task Properties Settings documentation. Modal Fields# Modal Fields controls the task create/edit experience by deciding which fields are visible and in what order. If your workflow depends on a handful of fields, you can surface only those and reduce form noise. For more information, see the Modal Fields Settings documentation. Appearance & UI# Appearance & UI handles task card density, calendar defaults, time formatting, and visual toggles for supporting widgets. Use this tab to tune how much information is visible at a glance. For more detailed information, see the Appearance & UI Settings documentation. Features# Features groups behavior toggles for inline tasks, natural language input, Pomodoro, reminders, and performance-related options. It is where you enable advanced workflow capabilities and then refine defaults. For more information, see the Features Settings documentation. Integrations# Integrations covers external connectivity: Bases view wiring, Google/Microsoft OAuth calendar sync, ICS subscriptions, automatic ICS export, HTTP API settings, and webhook endpoints. For more detailed information, see the Integrations Settings documentation."},{"route":"/obsidian/settings/appearance/","title":"Appearance & UI Settings","description":"These settings control the visual appearance of the plugin, including the calendar, task cards, and other UI elements.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/settings/appearance.md","namespace":"obsidian","relativePath":"settings/appearance.md","raw":"# Appearance & UI Settings\n\nThese settings control the visual appearance of the plugin, including the calendar, task cards, and other UI elements.\n\n\n![Appearance Settings](../assets/settings-appearance.png)\n\n## Task Cards\n\nUse **Default visible properties** to decide what metadata appears on task cards without opening each task. This is the primary control for card density.\n\nChecklist progress is available as a visible property in task cards. In Bases view `order` arrays, the corresponding source property is `file.tasks` (shown as `tasks` in Bases property pickers once present in the view `order` list).\n\nNested task cards use CSS variables for their indentation. Add a CSS snippet if\nyou want a denser hierarchy than the default:\n\n```css\n.tasknotes-plugin {\n --tn-nested-task-indent: 12px;\n --tn-nested-task-padding: 8px;\n}\n\nbody.is-mobile .tasknotes-plugin {\n --tn-nested-task-indent: 8px;\n --tn-nested-task-padding: 6px;\n}\n```\n\nIf task links inside normal markdown lists feel visually doubled with both a\nlist marker and the task status indicator, a CSS snippet can hide those markers\nfor task-link lines:\n\n```css\n.markdown-reading-view li:has(.task-inline-preview--reading-mode)::marker {\n content: \"\";\n}\n\n.markdown-source-view.mod-cm6 .cm-line:has(.tasknotes-inline-widget) .cm-formatting-list {\n display: none;\n}\n```\n\n## Display Formatting\n\nUse **Time format** to switch between 12-hour and 24-hour display across all TaskNotes surfaces.\n\n## Calendar View\n\nCalendar view settings determine the default landing mode, day/week framing, and timeline affordances. You can choose the default view, custom day span, first day of week, weekend visibility, week numbers, and whether today/current-time markers are shown. **Selection mirror** controls whether drag selections show a visual preview before committing.\n\nUse **Calendar locale** for region-specific formatting and calendar systems (for example `en`, `de`, or `fa`). Leave it empty to use automatic detection.\n\n## Default Event Visibility\n\nThis section controls which event layers are enabled when a calendar view opens. You can independently toggle scheduled tasks, due dates, due dates for already-scheduled tasks, time entries, recurring tasks, and ICS events.\n\n## Time Settings\n\nTime settings define the structure of timeline views: slot duration, earliest visible time, latest visible time, and initial scroll position. Use these together to match your workday shape.\n\n## UI Elements\n\nUI element toggles control auxiliary surfaces such as the tracked-task status bar entry, the project subtasks widget and its placement, expandable subtasks in cards, chevron position, and the alignment of the views/filters button.\n\n## Related Settings\n\nSome appearance-related settings are configured elsewhere:\n\n- **Task filename format**: Configured in [Task Properties](task-properties.md) → Title card\n- **Project autosuggest display**: Configured in [Task Properties](task-properties.md) → Projects card\n","aliases":["/settings/appearance/"],"toc":[{"level":2,"id":"task-cards","text":"Task Cards"},{"level":2,"id":"display-formatting","text":"Display Formatting"},{"level":2,"id":"calendar-view","text":"Calendar View"},{"level":2,"id":"default-event-visibility","text":"Default Event Visibility"},{"level":2,"id":"time-settings","text":"Time Settings"},{"level":2,"id":"ui-elements","text":"UI Elements"},{"level":2,"id":"related-settings","text":"Related Settings"}],"html":"

These settings control the visual appearance of the plugin, including the calendar, task cards, and other UI elements.

\n

\"Appearance

\n

Task Cards#

\n

Use Default visible properties to decide what metadata appears on task cards without opening each task. This is the primary control for card density.

\n

Checklist progress is available as a visible property in task cards. In Bases view order arrays, the corresponding source property is file.tasks (shown as tasks in Bases property pickers once present in the view order list).

\n

Nested task cards use CSS variables for their indentation. Add a CSS snippet if\nyou want a denser hierarchy than the default:

\n
.tasknotes-plugin {\n  --tn-nested-task-indent: 12px;\n  --tn-nested-task-padding: 8px;\n}\n\nbody.is-mobile .tasknotes-plugin {\n  --tn-nested-task-indent: 8px;\n  --tn-nested-task-padding: 6px;\n}\n

If task links inside normal markdown lists feel visually doubled with both a\nlist marker and the task status indicator, a CSS snippet can hide those markers\nfor task-link lines:

\n
.markdown-reading-view li:has(.task-inline-preview--reading-mode)::marker {\n  content: "";\n}\n\n.markdown-source-view.mod-cm6 .cm-line:has(.tasknotes-inline-widget) .cm-formatting-list {\n  display: none;\n}\n

Display Formatting#

\n

Use Time format to switch between 12-hour and 24-hour display across all TaskNotes surfaces.

\n

Calendar View#

\n

Calendar view settings determine the default landing mode, day/week framing, and timeline affordances. You can choose the default view, custom day span, first day of week, weekend visibility, week numbers, and whether today/current-time markers are shown. Selection mirror controls whether drag selections show a visual preview before committing.

\n

Use Calendar locale for region-specific formatting and calendar systems (for example en, de, or fa). Leave it empty to use automatic detection.

\n

Default Event Visibility#

\n

This section controls which event layers are enabled when a calendar view opens. You can independently toggle scheduled tasks, due dates, due dates for already-scheduled tasks, time entries, recurring tasks, and ICS events.

\n

Time Settings#

\n

Time settings define the structure of timeline views: slot duration, earliest visible time, latest visible time, and initial scroll position. Use these together to match your workday shape.

\n

UI Elements#

\n

UI element toggles control auxiliary surfaces such as the tracked-task status bar entry, the project subtasks widget and its placement, expandable subtasks in cards, chevron position, and the alignment of the views/filters button.

\n

Related Settings#

\n

Some appearance-related settings are configured elsewhere:

\n\n","text":"These settings control the visual appearance of the plugin, including the calendar, task cards, and other UI elements. Task Cards# Use Default visible properties to decide what metadata appears on task cards without opening each task. This is the primary control for card density. Checklist progress is available as a visible property in task cards. In Bases view order arrays, the corresponding source property is file.tasks (shown as tasks in Bases property pickers once present in the view order list). Nested task cards use CSS variables for their indentation. Add a CSS snippet if you want a denser hierarchy than the default: .tasknotes-plugin { --tn-nested-task-indent: 12px; --tn-nested-task-padding: 8px; } body.is-mobile .tasknotes-plugin { --tn-nested-task-indent: 8px; --tn-nested-task-padding: 6px; } If task links inside normal markdown lists feel visually doubled with both a list marker and the task status indicator, a CSS snippet can hide those markers for task-link lines: .markdown-reading-view li:has(.task-inline-preview--reading-mode)::marker { content: \"\"; } .markdown-source-view.mod-cm6 .cm-line:has(.tasknotes-inline-widget) .cm-formatting-list { display: none; } Display Formatting# Use Time format to switch between 12-hour and 24-hour display across all TaskNotes surfaces. Calendar View# Calendar view settings determine the default landing mode, day/week framing, and timeline affordances. You can choose the default view, custom day span, first day of week, weekend visibility, week numbers, and whether today/current-time markers are shown. Selection mirror controls whether drag selections show a visual preview before committing. Use Calendar locale for region-specific formatting and calendar systems (for example en, de, or fa). Leave it empty to use automatic detection. Default Event Visibility# This section controls which event layers are enabled when a calendar view opens. You can independently toggle scheduled tasks, due dates, due dates for already-scheduled tasks, time entries, recurring tasks, and ICS events. Time Settings# Time settings define the structure of timeline views: slot duration, earliest visible time, latest visible time, and initial scroll position. Use these together to match your workday shape. UI Elements# UI element toggles control auxiliary surfaces such as the tracked-task status bar entry, the project subtasks widget and its placement, expandable subtasks in cards, chevron position, and the alignment of the views/filters button. Related Settings# Some appearance-related settings are configured elsewhere: Task filename format: Configured in Task Properties → Title card Project autosuggest display: Configured in Task Properties → Projects card"},{"route":"/obsidian/settings/features/","title":"Features Settings","description":"These settings allow you to enable, disable, and configure the various features of the plugin, such as inline tasks, natural language processing, the Pomodoro timer, and notific...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/settings/features.md","namespace":"obsidian","relativePath":"settings/features.md","raw":"# Features Settings\n\nThese settings allow you to enable, disable, and configure the various features of the plugin, such as inline tasks, natural language processing, the Pomodoro timer, and notifications.\n\n\n![Features Settings](../assets/settings-features.png)\n\n## Inline Tasks\n\nInline task settings control how aggressively TaskNotes turns plain note content into structured task interactions. **Task link overlay** enables the Live Preview card behavior for task links, while **Instant task convert** surfaces conversion buttons next to list items and checkboxes. **Keep checkbox when converting** leaves the original Markdown checkbox marker in the source note when a checkbox becomes a TaskNote link. For conversion output, **Inline task convert folder** sets destination behavior and supports `{{currentNotePath}}`, and **Use task defaults on instant convert** applies your default task values at conversion time.\n\nThe separate **Convert current note to task** command keeps the current note body as the task details. If the note has no `scheduled` frontmatter, the command uses the Scheduled Date default from **Task Properties**; it does not apply body templates.\n\n## Body Template\n\nBody template settings let you scaffold newly created tasks with consistent note content. When enabled, TaskNotes reads the configured template file and expands variables like `{{title}}`, `{{date}}`, `{{time}}`, `{{priority}}`, `{{status}}`, `{{contexts}}`, `{{tags}}`, and `{{projects}}`.\n\nMaterialized occurrence notes can use a separate template. Set **Occurrence note template file** to provide a global fallback for occurrence notes; a recurring task's `occurrence_template` frontmatter field takes priority when it is set. If neither occurrence-specific template is configured, occurrence notes continue through the normal body template behavior.\n\n## Natural Language Processing\n\nNLP settings define how text input is interpreted during task capture. **Enable natural language task input** activates date and metadata parsing, **Default to scheduled** changes ambiguous date handling, **NLP language** selects parsing patterns, and **Status suggestion trigger** controls optional status autocomplete activation.\n\nWrap text in double quotes, single quotes, or backticks to keep it as literal title text during NLP parsing. For example, `BIO \"123H\" - HW1` keeps `123H` in the title instead of treating it as a 123-hour estimate, while `Review \"Today\" notes` keeps `Today` as text instead of parsing it as a date.\n\n## Pomodoro Timer\n\nPomodoro settings control interval lengths, long-break cadence, optional auto-start behavior, and end-of-session notifications/sound. **Pomodoro data storage** chooses whether history is kept in plugin data or daily notes.\n\n## Notifications\n\nUse this section to enable reminders globally, choose whether notices are shown in-app or through system notifications, and optionally play a built-in reminder sound with its own volume control.\n\n## Performance & Behavior\n\nPerformance and behavior toggles let you refine overhead and interaction feel: exclude completed tasks from overdue calculations, disable indexing for very large vaults, and tune suggestion debounce timing.\n\n## Time Tracking\n\nTime tracking options handle completion behavior. You can automatically stop running timers when a task is completed and optionally show a confirmation notification.\n\n## Recurring Tasks\n\nUse **Maintain due date offset in recurring tasks** to keep due/scheduled spacing consistent when recurring tasks roll forward.\n\nOccurrence note behavior is configured per recurring task from the task context menu: open **Recurrence → Occurrence notes** to choose manual creation or automatic creation of the next materialized occurrence after completion. See [Recurring Tasks](../features/recurring-tasks.md#materialized-occurrence-notes) for the workflow and storage model.\n\n## Timeblocking\n\nTimeblocking enables lightweight daily-note scheduling blocks and controls whether those blocks are visible by default in calendar views.\n\n### Usage\n\nIn the calendar view, click and drag on a time slot to select a time range. A context menu will appear—select \"Create timeblock\" to create a timeblock (this option only appears if timeblocking is enabled in settings). Drag existing timeblocks to move them. Resize edges to adjust duration.\n","aliases":["/settings/features/"],"toc":[{"level":2,"id":"inline-tasks","text":"Inline Tasks"},{"level":2,"id":"body-template","text":"Body Template"},{"level":2,"id":"natural-language-processing","text":"Natural Language Processing"},{"level":2,"id":"pomodoro-timer","text":"Pomodoro Timer"},{"level":2,"id":"notifications","text":"Notifications"},{"level":2,"id":"performance-behavior","text":"Performance & Behavior"},{"level":2,"id":"time-tracking","text":"Time Tracking"},{"level":2,"id":"recurring-tasks","text":"Recurring Tasks"},{"level":2,"id":"timeblocking","text":"Timeblocking"},{"level":3,"id":"usage","text":"Usage"}],"html":"

These settings allow you to enable, disable, and configure the various features of the plugin, such as inline tasks, natural language processing, the Pomodoro timer, and notifications.

\n

\"Features

\n

Inline Tasks#

\n

Inline task settings control how aggressively TaskNotes turns plain note content into structured task interactions. Task link overlay enables the Live Preview card behavior for task links, while Instant task convert surfaces conversion buttons next to list items and checkboxes. Keep checkbox when converting leaves the original Markdown checkbox marker in the source note when a checkbox becomes a TaskNote link. For conversion output, Inline task convert folder sets destination behavior and supports {{currentNotePath}}, and Use task defaults on instant convert applies your default task values at conversion time.

\n

The separate Convert current note to task command keeps the current note body as the task details. If the note has no scheduled frontmatter, the command uses the Scheduled Date default from Task Properties; it does not apply body templates.

\n

Body Template#

\n

Body template settings let you scaffold newly created tasks with consistent note content. When enabled, TaskNotes reads the configured template file and expands variables like {{title}}, {{date}}, {{time}}, {{priority}}, {{status}}, {{contexts}}, {{tags}}, and {{projects}}.

\n

Materialized occurrence notes can use a separate template. Set Occurrence note template file to provide a global fallback for occurrence notes; a recurring task's occurrence_template frontmatter field takes priority when it is set. If neither occurrence-specific template is configured, occurrence notes continue through the normal body template behavior.

\n

Natural Language Processing#

\n

NLP settings define how text input is interpreted during task capture. Enable natural language task input activates date and metadata parsing, Default to scheduled changes ambiguous date handling, NLP language selects parsing patterns, and Status suggestion trigger controls optional status autocomplete activation.

\n

Wrap text in double quotes, single quotes, or backticks to keep it as literal title text during NLP parsing. For example, BIO "123H" - HW1 keeps 123H in the title instead of treating it as a 123-hour estimate, while Review "Today" notes keeps Today as text instead of parsing it as a date.

\n

Pomodoro Timer#

\n

Pomodoro settings control interval lengths, long-break cadence, optional auto-start behavior, and end-of-session notifications/sound. Pomodoro data storage chooses whether history is kept in plugin data or daily notes.

\n

Notifications#

\n

Use this section to enable reminders globally, choose whether notices are shown in-app or through system notifications, and optionally play a built-in reminder sound with its own volume control.

\n

Performance & Behavior#

\n

Performance and behavior toggles let you refine overhead and interaction feel: exclude completed tasks from overdue calculations, disable indexing for very large vaults, and tune suggestion debounce timing.

\n

Time Tracking#

\n

Time tracking options handle completion behavior. You can automatically stop running timers when a task is completed and optionally show a confirmation notification.

\n

Recurring Tasks#

\n

Use Maintain due date offset in recurring tasks to keep due/scheduled spacing consistent when recurring tasks roll forward.

\n

Occurrence note behavior is configured per recurring task from the task context menu: open Recurrence → Occurrence notes to choose manual creation or automatic creation of the next materialized occurrence after completion. See Recurring Tasks for the workflow and storage model.

\n

Timeblocking#

\n

Timeblocking enables lightweight daily-note scheduling blocks and controls whether those blocks are visible by default in calendar views.

\n

Usage#

\n

In the calendar view, click and drag on a time slot to select a time range. A context menu will appear—select "Create timeblock" to create a timeblock (this option only appears if timeblocking is enabled in settings). Drag existing timeblocks to move them. Resize edges to adjust duration.

\n","text":"These settings allow you to enable, disable, and configure the various features of the plugin, such as inline tasks, natural language processing, the Pomodoro timer, and notifications. Inline Tasks# Inline task settings control how aggressively TaskNotes turns plain note content into structured task interactions. Task link overlay enables the Live Preview card behavior for task links, while Instant task convert surfaces conversion buttons next to list items and checkboxes. Keep checkbox when converting leaves the original Markdown checkbox marker in the source note when a checkbox becomes a TaskNote link. For conversion output, Inline task convert folder sets destination behavior and supports {{currentNotePath}}, and Use task defaults on instant convert applies your default task values at conversion time. The separate Convert current note to task command keeps the current note body as the task details. If the note has no scheduled frontmatter, the command uses the Scheduled Date default from Task Properties; it does not apply body templates. Body Template# Body template settings let you scaffold newly created tasks with consistent note content. When enabled, TaskNotes reads the configured template file and expands variables like {{title}}, {{date}}, {{time}}, {{priority}}, {{status}}, {{contexts}}, {{tags}}, and {{projects}}. Materialized occurrence notes can use a separate template. Set Occurrence note template file to provide a global fallback for occurrence notes; a recurring task's occurrence_template frontmatter field takes priority when it is set. If neither occurrence-specific template is configured, occurrence notes continue through the normal body template behavior. Natural Language Processing# NLP settings define how text input is interpreted during task capture. Enable natural language task input activates date and metadata parsing, Default to scheduled changes ambiguous date handling, NLP language selects parsing patterns, and Status suggestion trigger controls optional status autocomplete activation. Wrap text in double quotes, single quotes, or backticks to keep it as literal title text during NLP parsing. For example, BIO \"123H\" - HW1 keeps 123H in the title instead of treating it as a 123-hour estimate, while Review \"Today\" notes keeps Today as text instead of parsing it as a date. Pomodoro Timer# Pomodoro settings control interval lengths, long-break cadence, optional auto-start behavior, and end-of-session notifications/sound. Pomodoro data storage chooses whether history is kept in plugin data or daily notes. Notifications# Use this section to enable reminders globally, choose whether notices are shown in-app or through system notifications, and optionally play a built-in reminder sound with its own volume control. Performance & Behavior# Performance and behavior toggles let you refine overhead and interaction feel: exclude completed tasks from overdue calculations, disable indexing for very large vaults, and tune suggestion debounce timing. Time Tracking# Time tracking options handle completion behavior. You can automatically stop running timers when a task is completed and optionally show a confirmation notification. Recurring Tasks# Use Maintain due date offset in recurring tasks to keep due/scheduled spacing consistent when recurring tasks roll forward. Occurrence note behavior is configured per recurring task from the task context menu: open Recurrence → Occurrence notes to choose manual creation or automatic creation of the next materialized occurrence after completion. See Recurring Tasks for the workflow and storage model. Timeblocking# Timeblocking enables lightweight daily-note scheduling blocks and controls whether those blocks are visible by default in calendar views. Usage# In the calendar view, click and drag on a time slot to select a time range. A context menu will appear—select \"Create timeblock\" to create a timeblock (this option only appears if timeblocking is enabled in settings). Drag existing timeblocks to move them. Resize edges to adjust duration."},{"route":"/obsidian/settings/general/","title":"General Settings","description":"These settings control the foundational aspects of the plugin, such as task identification, file storage, and click behavior.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/settings/general.md","namespace":"obsidian","relativePath":"settings/general.md","raw":"# General Settings\n\nThese settings control the foundational aspects of the plugin, such as task identification, file storage, and click behavior.\n\n\n![General Settings](../assets/settings-general.png)\n\n## Task Storage\n\nTask storage settings define where new and inline-created task files are created and how archived tasks are relocated. **Default tasks folder** sets the base location and supports folder template variables, including `{{currentNotePath}}` and `{{currentNoteTitle}}` for creating command-palette or ribbon tasks beside the active note. It also supports date variables such as `{{year}}` and Daily Notes-style date tokens such as `YYYY/MM/DD`. **Folder for inline-created tasks** controls the Create Inline Task command and instant conversion output. Leave it empty to use the default tasks folder, set a fixed folder path to centralize inline tasks, or use `{{currentNotePath}}` and `{{currentNoteTitle}}` placeholders for contextual routing. Relative path segments such as `../` are normalized after variables are expanded. If archive moves are enabled, completed archived tasks are moved automatically to your configured archive folder.\n\n## Task Identification\n\nTaskNotes can identify task notes using either a tag or a frontmatter property.\n\nUse **Identify tasks by** to select a strategy.\n\n- **Tag mode** uses a configured task tag (for example `task`) and can optionally hide that identifying tag in card displays.\n- **Property mode** matches a property/value pair (for example `isTask: true` or `category: task`) and is useful when you avoid tag-based identification.\n\nIf you change the task tag after creating default Base views, existing `.base` filters will still point at the old tag until you update the default Base files or edit those filters.\n\n### Hide Identification Tags\n\nWhen using tag-based identification, you may want to keep your task identification tags in the frontmatter for organizational purposes, but hide them from the visual display in task cards to reduce clutter.\n\nThe **Hide identification tags in task cards** setting allows you to do this. When enabled:\n\n- Tags that exactly match your task identification tag (e.g., `#task`) will be hidden\n- Hierarchical child tags (e.g., `#task/project`, `#task/work/urgent`) will also be hidden\n- Other tags that don't match the identification pattern will still be displayed\n- The setting only affects the visual display—tags remain in the frontmatter\n\n![Hide identification tags demo](../assets/demo-hide-identification-tags.gif)\n\n**Example:**\n\nIf your task identification tag is `task` and a task has the tags `#task`, `#task/project`, `#important`, and `#review`:\n\n- With the setting **disabled** (default): All tags are shown: `#task`, `#task/project`, `#important`, `#review`\n- With the setting **enabled**: Only non-identifying tags are shown: `#important`, `#review`\n\n## Folder Management\n\nUse **Excluded folders** to omit paths from Notes tab indexing and keep large archive areas out of regular task browsing.\n\n## Views & Base Files\n\nTaskNotes uses Obsidian Bases files (`.base`) to power its task views. By default, missing view files are created automatically on startup.\n\nUse **Create files** to generate missing default files in `TaskNotes/Views/` without overwriting existing files. Use **Update files** to overwrite the configured default files with templates generated from your current TaskNotes settings.\n\n## Frontmatter\n\nThis section only appears when you have markdown links enabled globally in Obsidian settings.\n\n**Use markdown links in frontmatter** switches project/dependency serialization from wikilinks (`[[path]]`) to markdown links (`[text](path)`). This requires the `obsidian-frontmatter-markdown-links` plugin.\n\n## Task Interaction\n\nTask interaction settings define default click behavior on task cards. You can independently choose single-click and double-click actions (edit task, open note, or no action for double click).\n\n## Release Notes\n\n**View release notes** opens the release notes view for the current version. Notes also open automatically after updates and remain available from the command palette.\n","aliases":["/settings/general/"],"toc":[{"level":2,"id":"task-storage","text":"Task Storage"},{"level":2,"id":"task-identification","text":"Task Identification"},{"level":3,"id":"hide-identification-tags","text":"Hide Identification Tags"},{"level":2,"id":"folder-management","text":"Folder Management"},{"level":2,"id":"views-base-files","text":"Views & Base Files"},{"level":2,"id":"frontmatter","text":"Frontmatter"},{"level":2,"id":"task-interaction","text":"Task Interaction"},{"level":2,"id":"release-notes","text":"Release Notes"}],"html":"

These settings control the foundational aspects of the plugin, such as task identification, file storage, and click behavior.

\n

\"General

\n

Task Storage#

\n

Task storage settings define where new and inline-created task files are created and how archived tasks are relocated. Default tasks folder sets the base location and supports folder template variables, including {{currentNotePath}} and {{currentNoteTitle}} for creating command-palette or ribbon tasks beside the active note. It also supports date variables such as {{year}} and Daily Notes-style date tokens such as YYYY/MM/DD. Folder for inline-created tasks controls the Create Inline Task command and instant conversion output. Leave it empty to use the default tasks folder, set a fixed folder path to centralize inline tasks, or use {{currentNotePath}} and {{currentNoteTitle}} placeholders for contextual routing. Relative path segments such as ../ are normalized after variables are expanded. If archive moves are enabled, completed archived tasks are moved automatically to your configured archive folder.

\n

Task Identification#

\n

TaskNotes can identify task notes using either a tag or a frontmatter property.

\n

Use Identify tasks by to select a strategy.

\n
    \n
  • Tag mode uses a configured task tag (for example task) and can optionally hide that identifying tag in card displays.
  • \n
  • Property mode matches a property/value pair (for example isTask: true or category: task) and is useful when you avoid tag-based identification.
  • \n
\n

If you change the task tag after creating default Base views, existing .base filters will still point at the old tag until you update the default Base files or edit those filters.

\n

Hide Identification Tags#

\n

When using tag-based identification, you may want to keep your task identification tags in the frontmatter for organizational purposes, but hide them from the visual display in task cards to reduce clutter.

\n

The Hide identification tags in task cards setting allows you to do this. When enabled:

\n
    \n
  • Tags that exactly match your task identification tag (e.g., #task) will be hidden
  • \n
  • Hierarchical child tags (e.g., #task/project, #task/work/urgent) will also be hidden
  • \n
  • Other tags that don't match the identification pattern will still be displayed
  • \n
  • The setting only affects the visual display—tags remain in the frontmatter
  • \n
\n

\"Hide

\n

Example:

\n

If your task identification tag is task and a task has the tags #task, #task/project, #important, and #review:

\n
    \n
  • With the setting disabled (default): All tags are shown: #task, #task/project, #important, #review
  • \n
  • With the setting enabled: Only non-identifying tags are shown: #important, #review
  • \n
\n

Folder Management#

\n

Use Excluded folders to omit paths from Notes tab indexing and keep large archive areas out of regular task browsing.

\n

Views & Base Files#

\n

TaskNotes uses Obsidian Bases files (.base) to power its task views. By default, missing view files are created automatically on startup.

\n

Use Create files to generate missing default files in TaskNotes/Views/ without overwriting existing files. Use Update files to overwrite the configured default files with templates generated from your current TaskNotes settings.

\n

Frontmatter#

\n

This section only appears when you have markdown links enabled globally in Obsidian settings.

\n

Use markdown links in frontmatter switches project/dependency serialization from wikilinks ([[path]]) to markdown links ([text](path)). This requires the obsidian-frontmatter-markdown-links plugin.

\n

Task Interaction#

\n

Task interaction settings define default click behavior on task cards. You can independently choose single-click and double-click actions (edit task, open note, or no action for double click).

\n

Release Notes#

\n

View release notes opens the release notes view for the current version. Notes also open automatically after updates and remain available from the command palette.

\n","text":"These settings control the foundational aspects of the plugin, such as task identification, file storage, and click behavior. Task Storage# Task storage settings define where new and inline-created task files are created and how archived tasks are relocated. Default tasks folder sets the base location and supports folder template variables, including {{currentNotePath}} and {{currentNoteTitle}} for creating command-palette or ribbon tasks beside the active note. It also supports date variables such as {{year}} and Daily Notes-style date tokens such as YYYY/MM/DD. Folder for inline-created tasks controls the Create Inline Task command and instant conversion output. Leave it empty to use the default tasks folder, set a fixed folder path to centralize inline tasks, or use {{currentNotePath}} and {{currentNoteTitle}} placeholders for contextual routing. Relative path segments such as ../ are normalized after variables are expanded. If archive moves are enabled, completed archived tasks are moved automatically to your configured archive folder. Task Identification# TaskNotes can identify task notes using either a tag or a frontmatter property. Use Identify tasks by to select a strategy. Tag mode uses a configured task tag (for example task) and can optionally hide that identifying tag in card displays. Property mode matches a property/value pair (for example isTask: true or category: task) and is useful when you avoid tag-based identification. If you change the task tag after creating default Base views, existing .base filters will still point at the old tag until you update the default Base files or edit those filters. Hide Identification Tags# When using tag-based identification, you may want to keep your task identification tags in the frontmatter for organizational purposes, but hide them from the visual display in task cards to reduce clutter. The Hide identification tags in task cards setting allows you to do this. When enabled: Tags that exactly match your task identification tag (e.g., #task) will be hidden Hierarchical child tags (e.g., #task/project, #task/work/urgent) will also be hidden Other tags that don't match the identification pattern will still be displayed The setting only affects the visual display—tags remain in the frontmatter Example: If your task identification tag is task and a task has the tags #task, #task/project, #important, and #review: With the setting disabled (default): All tags are shown: #task, #task/project, #important, #review With the setting enabled: Only non-identifying tags are shown: #important, #review Folder Management# Use Excluded folders to omit paths from Notes tab indexing and keep large archive areas out of regular task browsing. Views & Base Files# TaskNotes uses Obsidian Bases files (.base) to power its task views. By default, missing view files are created automatically on startup. Use Create files to generate missing default files in TaskNotes/Views/ without overwriting existing files. Use Update files to overwrite the configured default files with templates generated from your current TaskNotes settings. Frontmatter# This section only appears when you have markdown links enabled globally in Obsidian settings. Use markdown links in frontmatter switches project/dependency serialization from wikilinks ([[path]]) to markdown links ([text](path)). This requires the obsidian-frontmatter-markdown-links plugin. Task Interaction# Task interaction settings define default click behavior on task cards. You can independently choose single-click and double-click actions (edit task, open note, or no action for double click). Release Notes# View release notes opens the release notes view for the current version. Notes also open automatically after updates and remain available from the command palette."},{"route":"/obsidian/settings/integrations/","title":"Integrations Settings","description":"These settings control the integration with other plugins and services, such as Bases and external calendars.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/settings/integrations.md","namespace":"obsidian","relativePath":"settings/integrations.md","raw":"# Integrations Settings\n\nThese settings control the integration with other plugins and services, such as Bases and external calendars.\n\n\n![Integrations Settings](../assets/settings-integrations.png)\n\n## Bases\n\nTaskNotes v4 uses Obsidian's Bases core plugin for its main views. For setup instructions, see [Core Concepts](../core-concepts.md#bases-integration).\n\n### View Commands Configuration\n\nView command settings map TaskNotes commands and ribbon actions to specific `.base` files. This is useful when you maintain custom variants of the default views and want first-class command access to those files.\n\nAccess these settings in **Settings → TaskNotes → General → Views & base files**.\n\nDefault mappings:\n\n- **Open Mini Calendar View** → `TaskNotes/Views/mini-calendar-default.base`\n- **Open Kanban View** → `TaskNotes/Views/kanban-default.base`\n- **Open Tasks View** → `TaskNotes/Views/tasks-default.base`\n- **Open Calendar View** → `TaskNotes/Views/calendar-default.base`\n- **Open Agenda View** → `TaskNotes/Views/agenda-default.base`\n- **Pomodoro Statistics Base** → `TaskNotes/Views/pomodoro-stats.base`\n- **Relationships Widget** → `TaskNotes/Views/relationships.base`\n\nEach command allows you to specify a custom `.base` file path and includes a reset button to restore the default path.\n\n**Auto-create default files**: When enabled, TaskNotes creates missing default `.base` files automatically on startup.\n\n**Create files**: Button to generate all default `.base` files in the `TaskNotes/Views/` directory. Existing files are not overwritten.\n\nThe generated Pomodoro statistics Base reads Pomodoro sessions from daily notes frontmatter. If your Pomodoro history is still stored in plugin data, migrate it from **Settings → TaskNotes → Features** before using that Base file.\n\n## OAuth Calendar Integration\n\nConnect Google Calendar or Microsoft Outlook to sync events bidirectionally with TaskNotes. Events automatically refresh every 15 minutes and sync when local changes are made (such as dragging events to reschedule).\n\nEnable **Disable calendar integrations on mobile** when you sync TaskNotes settings between desktop and mobile but do not want Obsidian Mobile to load external calendars on startup. The setting only affects mobile devices; desktop calendar integrations continue to run normally.\n\n### Setup Requirements\n\nOAuth integration requires creating your own OAuth application with Google and/or Microsoft. Initial setup takes approximately 15 minutes per provider.\n\n**Setup Guide**: See [Calendar Integration Setup](../calendar-setup.md) for detailed instructions on creating OAuth credentials with Google Cloud Console and Azure Portal.\n\n### Google Calendar\n\nProvide **Client ID** and **Client Secret** from Google Cloud Console, then use **Connect Google Calendar** to complete OAuth loopback authentication. **Disconnect** revokes account tokens while retaining the OAuth app credentials for reconnection. Use **Forget saved credentials** to remove the client ID and client secret.\n\nThe **Target calendar** setting used for exporting tasks to Google Calendar is also used as the default selection when creating a manual external calendar event from the calendar view. If the target calendar is unavailable, TaskNotes falls back to the provider's primary calendar.\n\nFor timed task exports, **Default reminder** accepts one or more minute offsets separated by commas, such as `60, 1440`. All-day task exports use the target Google Calendar's default reminder settings.\n\nWhen connected, displays:\n- Connected account email\n- Connection time\n- Last sync time\n- Manual refresh button\n\n### Microsoft Outlook Calendar\n\nProvide **Client ID** and **Client Secret** from Azure App Registration, then use **Connect Microsoft Calendar** to authenticate. **Disconnect** revokes account tokens while retaining the OAuth app credentials for reconnection. Use **Forget saved credentials** to remove the client ID and client secret.\n\nWhen connected, displays:\n- Connected account email\n- Connection time\n- Last sync time\n\n### Security\n\n- OAuth client credentials and account tokens are stored in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system\n- OAuth credentials and account tokens are not written to TaskNotes' `data.json`\n- Access tokens refresh automatically\n- Calendar data syncs directly between Obsidian and the calendar provider (no intermediary servers)\n- Disconnect at any time to revoke account access; use **Forget saved credentials** to remove the OAuth app credentials\n\n## Calendar subscriptions (ICS)\n\nICS settings define how subscribed calendar events are represented in your vault. You can set a default template, destination folder, filename strategy, and custom filename template for generated notes. Use **Add Calendar Subscription** to register URLs or local files, and **Refresh all subscriptions** for manual synchronization.\n\n**Recurring event related notes** controls how notes linked from recurring external calendar events are matched. **Series-wide** keeps the current behavior: a note linked to one loaded recurrence can appear on the other loaded recurrences from the same Google, Microsoft, or ICS event series. **Selected instance only** limits related notes and counts to the exact recurrence instance that was linked.\n\n## Automatic ICS export\n\nAutomatic export keeps an ICS feed of your tasks updated on a schedule. Configure whether it is enabled, where the file is written (vault-relative path), the refresh interval, and use **Export now** for immediate output.\n\nExport filters can omit archived tasks, completed tasks, tasks without due dates, or tasks without scheduled dates. When both due-date and scheduled-date requirements are enabled, exported tasks must have both dates.\n\n## HTTP API\n\nHTTP API settings control the local server lifecycle, listening port, and request authentication token.\n\nChanges to API enablement or port require an Obsidian restart to take effect.\n\n!!! warning\n The HTTP API binds to loopback only and browser CORS is limited to loopback origins. If the authentication token is empty, local API requests are still unauthenticated. Set a token unless your local environment is fully trusted.\n\n## Webhooks\n\n- **Add Webhook**: Register a new webhook endpoint.\n","aliases":["/settings/integrations/"],"toc":[{"level":2,"id":"bases","text":"Bases"},{"level":3,"id":"view-commands-configuration","text":"View Commands Configuration"},{"level":2,"id":"oauth-calendar-integration","text":"OAuth Calendar Integration"},{"level":3,"id":"setup-requirements","text":"Setup Requirements"},{"level":3,"id":"google-calendar","text":"Google Calendar"},{"level":3,"id":"microsoft-outlook-calendar","text":"Microsoft Outlook Calendar"},{"level":3,"id":"security","text":"Security"},{"level":2,"id":"calendar-subscriptions-ics","text":"Calendar subscriptions (ICS)"},{"level":2,"id":"automatic-ics-export","text":"Automatic ICS export"},{"level":2,"id":"http-api","text":"HTTP API"},{"level":2,"id":"webhooks","text":"Webhooks"}],"html":"

These settings control the integration with other plugins and services, such as Bases and external calendars.

\n

\"Integrations

\n

Bases#

\n

TaskNotes v4 uses Obsidian's Bases core plugin for its main views. For setup instructions, see Core Concepts.

\n

View Commands Configuration#

\n

View command settings map TaskNotes commands and ribbon actions to specific .base files. This is useful when you maintain custom variants of the default views and want first-class command access to those files.

\n

Access these settings in Settings → TaskNotes → General → Views & base files.

\n

Default mappings:

\n
    \n
  • Open Mini Calendar View → TaskNotes/Views/mini-calendar-default.base
  • \n
  • Open Kanban View → TaskNotes/Views/kanban-default.base
  • \n
  • Open Tasks View → TaskNotes/Views/tasks-default.base
  • \n
  • Open Calendar View → TaskNotes/Views/calendar-default.base
  • \n
  • Open Agenda View → TaskNotes/Views/agenda-default.base
  • \n
  • Pomodoro Statistics Base → TaskNotes/Views/pomodoro-stats.base
  • \n
  • Relationships Widget → TaskNotes/Views/relationships.base
  • \n
\n

Each command allows you to specify a custom .base file path and includes a reset button to restore the default path.

\n

Auto-create default files: When enabled, TaskNotes creates missing default .base files automatically on startup.

\n

Create files: Button to generate all default .base files in the TaskNotes/Views/ directory. Existing files are not overwritten.

\n

The generated Pomodoro statistics Base reads Pomodoro sessions from daily notes frontmatter. If your Pomodoro history is still stored in plugin data, migrate it from Settings → TaskNotes → Features before using that Base file.

\n

OAuth Calendar Integration#

\n

Connect Google Calendar or Microsoft Outlook to sync events bidirectionally with TaskNotes. Events automatically refresh every 15 minutes and sync when local changes are made (such as dragging events to reschedule).

\n

Enable Disable calendar integrations on mobile when you sync TaskNotes settings between desktop and mobile but do not want Obsidian Mobile to load external calendars on startup. The setting only affects mobile devices; desktop calendar integrations continue to run normally.

\n

Setup Requirements#

\n

OAuth integration requires creating your own OAuth application with Google and/or Microsoft. Initial setup takes approximately 15 minutes per provider.

\n

Setup Guide: See Calendar Integration Setup for detailed instructions on creating OAuth credentials with Google Cloud Console and Azure Portal.

\n

Google Calendar#

\n

Provide Client ID and Client Secret from Google Cloud Console, then use Connect Google Calendar to complete OAuth loopback authentication. Disconnect revokes account tokens while retaining the OAuth app credentials for reconnection. Use Forget saved credentials to remove the client ID and client secret.

\n

The Target calendar setting used for exporting tasks to Google Calendar is also used as the default selection when creating a manual external calendar event from the calendar view. If the target calendar is unavailable, TaskNotes falls back to the provider's primary calendar.

\n

For timed task exports, Default reminder accepts one or more minute offsets separated by commas, such as 60, 1440. All-day task exports use the target Google Calendar's default reminder settings.

\n

When connected, displays:

\n
    \n
  • Connected account email
  • \n
  • Connection time
  • \n
  • Last sync time
  • \n
  • Manual refresh button
  • \n
\n

Microsoft Outlook Calendar#

\n

Provide Client ID and Client Secret from Azure App Registration, then use Connect Microsoft Calendar to authenticate. Disconnect revokes account tokens while retaining the OAuth app credentials for reconnection. Use Forget saved credentials to remove the client ID and client secret.

\n

When connected, displays:

\n
    \n
  • Connected account email
  • \n
  • Connection time
  • \n
  • Last sync time
  • \n
\n

Security#

\n
    \n
  • OAuth client credentials and account tokens are stored in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system
  • \n
  • OAuth credentials and account tokens are not written to TaskNotes' data.json
  • \n
  • Access tokens refresh automatically
  • \n
  • Calendar data syncs directly between Obsidian and the calendar provider (no intermediary servers)
  • \n
  • Disconnect at any time to revoke account access; use Forget saved credentials to remove the OAuth app credentials
  • \n
\n

Calendar subscriptions (ICS)#

\n

ICS settings define how subscribed calendar events are represented in your vault. You can set a default template, destination folder, filename strategy, and custom filename template for generated notes. Use Add Calendar Subscription to register URLs or local files, and Refresh all subscriptions for manual synchronization.

\n

Recurring event related notes controls how notes linked from recurring external calendar events are matched. Series-wide keeps the current behavior: a note linked to one loaded recurrence can appear on the other loaded recurrences from the same Google, Microsoft, or ICS event series. Selected instance only limits related notes and counts to the exact recurrence instance that was linked.

\n

Automatic ICS export#

\n

Automatic export keeps an ICS feed of your tasks updated on a schedule. Configure whether it is enabled, where the file is written (vault-relative path), the refresh interval, and use Export now for immediate output.

\n

Export filters can omit archived tasks, completed tasks, tasks without due dates, or tasks without scheduled dates. When both due-date and scheduled-date requirements are enabled, exported tasks must have both dates.

\n

HTTP API#

\n

HTTP API settings control the local server lifecycle, listening port, and request authentication token.

\n

Changes to API enablement or port require an Obsidian restart to take effect.

\n\n

Webhooks#

\n
    \n
  • Add Webhook: Register a new webhook endpoint.
  • \n
\n","text":"These settings control the integration with other plugins and services, such as Bases and external calendars. Bases# TaskNotes v4 uses Obsidian's Bases core plugin for its main views. For setup instructions, see Core Concepts. View Commands Configuration# View command settings map TaskNotes commands and ribbon actions to specific .base files. This is useful when you maintain custom variants of the default views and want first-class command access to those files. Access these settings in Settings → TaskNotes → General → Views & base files. Default mappings: Open Mini Calendar View → TaskNotes/Views/mini-calendar-default.base Open Kanban View → TaskNotes/Views/kanban-default.base Open Tasks View → TaskNotes/Views/tasks-default.base Open Calendar View → TaskNotes/Views/calendar-default.base Open Agenda View → TaskNotes/Views/agenda-default.base Pomodoro Statistics Base → TaskNotes/Views/pomodoro-stats.base Relationships Widget → TaskNotes/Views/relationships.base Each command allows you to specify a custom .base file path and includes a reset button to restore the default path. Auto-create default files: When enabled, TaskNotes creates missing default .base files automatically on startup. Create files: Button to generate all default .base files in the TaskNotes/Views/ directory. Existing files are not overwritten. The generated Pomodoro statistics Base reads Pomodoro sessions from daily notes frontmatter. If your Pomodoro history is still stored in plugin data, migrate it from Settings → TaskNotes → Features before using that Base file. OAuth Calendar Integration# Connect Google Calendar or Microsoft Outlook to sync events bidirectionally with TaskNotes. Events automatically refresh every 15 minutes and sync when local changes are made (such as dragging events to reschedule). Enable Disable calendar integrations on mobile when you sync TaskNotes settings between desktop and mobile but do not want Obsidian Mobile to load external calendars on startup. The setting only affects mobile devices; desktop calendar integrations continue to run normally. Setup Requirements# OAuth integration requires creating your own OAuth application with Google and/or Microsoft. Initial setup takes approximately 15 minutes per provider. Setup Guide: See Calendar Integration Setup for detailed instructions on creating OAuth credentials with Google Cloud Console and Azure Portal. Google Calendar# Provide Client ID and Client Secret from Google Cloud Console, then use Connect Google Calendar to complete OAuth loopback authentication. Disconnect revokes account tokens while retaining the OAuth app credentials for reconnection. Use Forget saved credentials to remove the client ID and client secret. The Target calendar setting used for exporting tasks to Google Calendar is also used as the default selection when creating a manual external calendar event from the calendar view. If the target calendar is unavailable, TaskNotes falls back to the provider's primary calendar. For timed task exports, Default reminder accepts one or more minute offsets separated by commas, such as 60, 1440. All-day task exports use the target Google Calendar's default reminder settings. When connected, displays: Connected account email Connection time Last sync time Manual refresh button Microsoft Outlook Calendar# Provide Client ID and Client Secret from Azure App Registration, then use Connect Microsoft Calendar to authenticate. Disconnect revokes account tokens while retaining the OAuth app credentials for reconnection. Use Forget saved credentials to remove the client ID and client secret. When connected, displays: Connected account email Connection time Last sync time Security# OAuth client credentials and account tokens are stored in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system OAuth credentials and account tokens are not written to TaskNotes' data.json Access tokens refresh automatically Calendar data syncs directly between Obsidian and the calendar provider (no intermediary servers) Disconnect at any time to revoke account access; use Forget saved credentials to remove the OAuth app credentials Calendar subscriptions (ICS)# ICS settings define how subscribed calendar events are represented in your vault. You can set a default template, destination folder, filename strategy, and custom filename template for generated notes. Use Add Calendar Subscription to register URLs or local files, and Refresh all subscriptions for manual synchronization. Recurring event related notes controls how notes linked from recurring external calendar events are matched. Series-wide keeps the current behavior: a note linked to one loaded recurrence can appear on the other loaded recurrences from the same Google, Microsoft, or ICS event series. Selected instance only limits related notes and counts to the exact recurrence instance that was linked. Automatic ICS export# Automatic export keeps an ICS feed of your tasks updated on a schedule. Configure whether it is enabled, where the file is written (vault-relative path), the refresh interval, and use Export now for immediate output. Export filters can omit archived tasks, completed tasks, tasks without due dates, or tasks without scheduled dates. When both due-date and scheduled-date requirements are enabled, exported tasks must have both dates. HTTP API# HTTP API settings control the local server lifecycle, listening port, and request authentication token. Changes to API enablement or port require an Obsidian restart to take effect. WarningThe HTTP API binds to loopback only and browser CORS is limited to loopback origins. If the authentication token is empty, local API requests are still unauthenticated. Set a token unless your local environment is fully trusted. Webhooks# Add Webhook: Register a new webhook endpoint."},{"route":"/obsidian/settings/modal-fields/","title":"Modal Fields Settings","description":"The Modal Fields tab lets you decide exactly which fields appear in the task creation and edit modals. Open Settings → TaskNotes → Modal Fields to manage the configuration.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/settings/modal-fields.md","namespace":"obsidian","relativePath":"settings/modal-fields.md","raw":"# Modal Fields Settings\n\nThe Modal Fields tab lets you decide exactly which fields appear in the task creation and edit modals. Open **Settings → TaskNotes → Modal Fields** to manage the configuration.\n\n![Modal Fields Settings](../assets/settings-modal-fields.png)\n\n## Field Groups\n\nFields are organized into draggable groups:\n\n- **Basic Information** – Title and Details\n- **Metadata** – Contexts, Tags, Time Estimate\n- **Organization** – Projects and Subtasks\n- **Dependencies** – Blocked By and Blocking\n- **Custom Fields** – Any user-defined fields that you add through Task Properties\n\nEach group can be collapsed, and their order in the manager matches the order shown in the modal.\n\n## Managing Fields\n\nEvery field entry includes:\n\n- **Visibility toggles** for creation and edit modals\n- **Enable/disable** checkbox\n- **Drag handle** for ordering within its group\n- **Required** toggle (where applicable, e.g., Title)\n\nChanges are saved automatically. Use this to hide fields you never touch, ensure required metadata appears up front, or reorder fields to match your workflow.\n\n## Syncing User Fields\n\nThe **Sync User Fields** button pulls the latest user-defined fields from the Task Properties tab into the Custom Fields group. New user fields are appended, renamed fields update in place, and removed fields drop out of the configuration. Re-run the sync whenever you add or rename custom fields.\n\n## Resetting to Defaults\n\nSelect **Reset to Defaults** to restore the stock configuration (all built-in fields enabled plus empty custom slots). The reset keeps your existing user field definitions; it only reverts modal layout and visibility.\n","aliases":["/settings/modal-fields/"],"toc":[{"level":2,"id":"field-groups","text":"Field Groups"},{"level":2,"id":"managing-fields","text":"Managing Fields"},{"level":2,"id":"syncing-user-fields","text":"Syncing User Fields"},{"level":2,"id":"resetting-to-defaults","text":"Resetting to Defaults"}],"html":"

The Modal Fields tab lets you decide exactly which fields appear in the task creation and edit modals. Open Settings → TaskNotes → Modal Fields to manage the configuration.

\n

\"Modal

\n

Field Groups#

\n

Fields are organized into draggable groups:

\n
    \n
  • Basic Information – Title and Details
  • \n
  • Metadata – Contexts, Tags, Time Estimate
  • \n
  • Organization – Projects and Subtasks
  • \n
  • Dependencies – Blocked By and Blocking
  • \n
  • Custom Fields – Any user-defined fields that you add through Task Properties
  • \n
\n

Each group can be collapsed, and their order in the manager matches the order shown in the modal.

\n

Managing Fields#

\n

Every field entry includes:

\n
    \n
  • Visibility toggles for creation and edit modals
  • \n
  • Enable/disable checkbox
  • \n
  • Drag handle for ordering within its group
  • \n
  • Required toggle (where applicable, e.g., Title)
  • \n
\n

Changes are saved automatically. Use this to hide fields you never touch, ensure required metadata appears up front, or reorder fields to match your workflow.

\n

Syncing User Fields#

\n

The Sync User Fields button pulls the latest user-defined fields from the Task Properties tab into the Custom Fields group. New user fields are appended, renamed fields update in place, and removed fields drop out of the configuration. Re-run the sync whenever you add or rename custom fields.

\n

Resetting to Defaults#

\n

Select Reset to Defaults to restore the stock configuration (all built-in fields enabled plus empty custom slots). The reset keeps your existing user field definitions; it only reverts modal layout and visibility.

\n","text":"The Modal Fields tab lets you decide exactly which fields appear in the task creation and edit modals. Open Settings → TaskNotes → Modal Fields to manage the configuration. Field Groups# Fields are organized into draggable groups: Basic Information – Title and Details Metadata – Contexts, Tags, Time Estimate Organization – Projects and Subtasks Dependencies – Blocked By and Blocking Custom Fields – Any user-defined fields that you add through Task Properties Each group can be collapsed, and their order in the manager matches the order shown in the modal. Managing Fields# Every field entry includes: Visibility toggles for creation and edit modals Enable/disable checkbox Drag handle for ordering within its group Required toggle (where applicable, e.g., Title) Changes are saved automatically. Use this to hide fields you never touch, ensure required metadata appears up front, or reorder fields to match your workflow. Syncing User Fields# The Sync User Fields button pulls the latest user-defined fields from the Task Properties tab into the Custom Fields group. New user fields are appended, renamed fields update in place, and removed fields drop out of the configuration. Re-run the sync whenever you add or rename custom fields. Resetting to Defaults# Select Reset to Defaults to restore the stock configuration (all built-in fields enabled plus empty custom slots). The reset keeps your existing user field definitions; it only reverts modal layout and visibility."},{"route":"/obsidian/settings/property-identification/","title":"Property-based Task Identification","description":"When you choose to identify task files by a frontmatter property (instead of a tag), TaskNotes will match notes whose frontmatter property equals the configured value.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/settings/property-identification.md","namespace":"obsidian","relativePath":"settings/property-identification.md","raw":"# Property-based Task Identification\n\nWhen you choose to identify task files by a frontmatter property (instead of a tag), TaskNotes will match notes whose frontmatter property equals the configured value.\n\n## Boolean values\n- Enter the setting value as true or false (without quotes) in the settings UI.\n- Obsidian stores checkbox properties as real booleans, not strings. The plugin compares booleans correctly:\n - \"true\" in settings matches frontmatter boolean true\n - \"false\" in settings matches frontmatter boolean false\n - Arrays are supported (e.g., property: [false, true])\n\nTip: You don’t need to quote boolean values in frontmatter. Use plain true/false to keep Obsidian’s property types consistent.\n\n## Examples\n- Setting: Property Name = isTask, Property Value = true\n - Matches: `isTask: true`\n - Does not match: `isTask: false`\n- Setting: Property Name = isTask, Property Value = false\n - Matches: `isTask: false`\n - Does not match: `isTask: true`\n\nFor related configuration details, see [Task Properties](task-properties.md).\n","aliases":["/settings/property-identification/"],"toc":[{"level":2,"id":"boolean-values","text":"Boolean values"},{"level":2,"id":"examples","text":"Examples"}],"html":"

When you choose to identify task files by a frontmatter property (instead of a tag), TaskNotes will match notes whose frontmatter property equals the configured value.

\n

Boolean values#

\n
    \n
  • Enter the setting value as true or false (without quotes) in the settings UI.
  • \n
  • Obsidian stores checkbox properties as real booleans, not strings. The plugin compares booleans correctly:
      \n
    • "true" in settings matches frontmatter boolean true
    • \n
    • "false" in settings matches frontmatter boolean false
    • \n
    • Arrays are supported (e.g., property: [false, true])
    • \n
    \n
  • \n
\n

Tip: You don’t need to quote boolean values in frontmatter. Use plain true/false to keep Obsidian’s property types consistent.

\n

Examples#

\n
    \n
  • Setting: Property Name = isTask, Property Value = true
      \n
    • Matches: isTask: true
    • \n
    • Does not match: isTask: false
    • \n
    \n
  • \n
  • Setting: Property Name = isTask, Property Value = false
      \n
    • Matches: isTask: false
    • \n
    • Does not match: isTask: true
    • \n
    \n
  • \n
\n

For related configuration details, see Task Properties.

\n","text":"When you choose to identify task files by a frontmatter property (instead of a tag), TaskNotes will match notes whose frontmatter property equals the configured value. Boolean values# Enter the setting value as true or false (without quotes) in the settings UI. Obsidian stores checkbox properties as real booleans, not strings. The plugin compares booleans correctly: \"true\" in settings matches frontmatter boolean true \"false\" in settings matches frontmatter boolean false Arrays are supported (e.g., property: [false, true]) Tip: You don’t need to quote boolean values in frontmatter. Use plain true/false to keep Obsidian’s property types consistent. Examples# Setting: Property Name = isTask, Property Value = true Matches: isTask: true Does not match: isTask: false Setting: Property Name = isTask, Property Value = false Matches: isTask: false Does not match: isTask: true For related configuration details, see Task Properties."},{"route":"/obsidian/settings/property-types-reference/","title":"Property Types Reference","description":"This reference documents the expected data types for each frontmatter property that TaskNotes uses.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/settings/property-types-reference.md","namespace":"obsidian","relativePath":"settings/property-types-reference.md","raw":"# Property Types Reference\n\nThis reference documents the expected data types for each frontmatter property that TaskNotes uses.\n\n\n## Quick Reference\n\n| Property | Type | Example |\n|----------|------|---------|\n| title | text | `\"My Task\"` |\n| status | text | `\"open\"`, `\"in-progress\"`, `\"done\"` |\n| priority | text | `\"low\"`, `\"normal\"`, `\"high\"` |\n| due | text (date) | `\"2025-01-15\"` |\n| scheduled | text (date) | `\"2025-01-10\"` |\n| completedDate | text (date) | `\"2025-01-20\"` |\n| dateCreated | text (datetime) | `\"2025-01-01T08:00:00Z\"` |\n| dateModified | text (datetime) | `\"2025-01-15T10:30:00Z\"` |\n| tags | list | `[\"work\", \"urgent\"]` |\n| contexts | list | `[\"office\", \"home\"]` |\n| projects | list | `[\"[[Project A]]\"]` |\n| timeEstimate | number | `120` (minutes) |\n| recurrence | text | `\"FREQ=WEEKLY;BYDAY=MO\"` |\n| recurrence_anchor | text | `\"scheduled\"` or `\"completion\"` |\n| timeEntries | list (objects) | See [Time Entries](#time-entries) |\n| blockedBy | list (objects) | See [Dependencies](#dependencies-blockedby) |\n| reminders | list (objects) | See [Reminders](#reminders) |\n| complete_instances | list | `[\"2025-01-08\", \"2025-01-15\"]` |\n| skipped_instances | list | `[\"2025-01-22\"]` |\n| recurrence_parent | text (link/path) | `\"[[Tasks/Weekly review]]\"` |\n| occurrence_date | text (date) | `\"2025-01-15\"` |\n| occurrence_materialization | text | `\"manual\"` or `\"on_completion\"` |\n| occurrence_next_trigger | text | `\"completion\"` or `\"completion_or_skip\"` |\n| occurrence_template | text (link/path) | `\"[[Templates/Occurrence]]\"` |\n| occurrence_past_horizon | text (duration) | `\"P7D\"` |\n| occurrence_future_horizon | text (duration) | `\"P14D\"` |\n| icsEventId | list | `[\"event-abc123\"]` |\n\nUse this table for fast validation when a field is not behaving as expected in views or API calls. Most parsing issues come from shape mismatches (for example scalar vs list) rather than missing values.\n\n---\n\n## Property Details\n\nThe sections below describe storage formats, but there is flexibility in authoring style. TaskNotes normalizes many equivalent YAML representations as long as the resulting data type is correct.\n\n### Text Properties\n\n#### title\n- **Type:** text (string)\n- **Description:** The task's title or name\n- **Example:** `title: \"Complete project documentation\"`\n\n#### status\n- **Type:** text (string)\n- **Description:** The task's current status. Must match one of the status values configured in your settings.\n- **Default values:** `\"open\"`, `\"in-progress\"`, `\"done\"`\n- **Example:** `status: \"in-progress\"`\n- **Note:** Also supports boolean values (`true`/`false`) for Obsidian checkbox compatibility. See [Boolean Status Values](task-properties.md#boolean-status-values).\n\n#### priority\n- **Type:** text (string)\n- **Description:** The task's priority level. Must match one of the priority values configured in your settings.\n- **Default values:** `\"low\"`, `\"normal\"`, `\"high\"`\n- **Example:** `priority: \"high\"`\n\n---\n\n### Date Properties\n\nAll date properties are stored as **text strings** in your frontmatter. TaskNotes expects specific formats:\nWhen in doubt, prefer ISO-style values. They sort correctly as text, travel well through APIs, and are easiest to parse consistently.\n\n#### due\n\n- **Type:** text (date string)\n- **Format:** `YYYY-MM-DD` or ISO 8601 timestamp\n- **Description:** The task's due date\n- **Examples:**\n\n ```yaml\n due: \"2025-01-15\"\n due: \"2025-01-15T17:00:00\"\n ```\n\n#### scheduled\n\n- **Type:** text (date string)\n- **Format:** `YYYY-MM-DD` or ISO 8601 timestamp\n- **Description:** When the task is scheduled to be worked on\n- **Examples:**\n\n ```yaml\n scheduled: \"2025-01-10\"\n scheduled: \"2025-01-10T09:00:00\"\n ```\n\n#### completedDate\n\n- **Type:** text (date string)\n- **Format:** `YYYY-MM-DD`\n- **Description:** The date when the task was completed\n- **Example:** `completedDate: \"2025-01-20\"`\n\n#### dateCreated\n\n- **Type:** text (datetime string)\n- **Format:** ISO 8601 timestamp\n- **Description:** When the task was created\n- **Example:** `dateCreated: \"2025-01-01T08:00:00Z\"`\n\n#### dateModified\n\n- **Type:** text (datetime string)\n- **Format:** ISO 8601 timestamp\n- **Description:** When the task was last modified\n- **Example:** `dateModified: \"2025-01-15T10:30:00Z\"`\n\n---\n\n### List Properties\n\nList properties must be arrays, even when containing a single value.\nSingle-item arrays may look verbose, but they prevent edge cases when filters and formulas assume list semantics.\n\n#### tags\n\n- **Type:** list (array of strings)\n- **Description:** Tags associated with the task\n- **Examples:**\n\n ```yaml\n tags: [\"work\", \"documentation\"]\n tags:\n - work\n - documentation\n ```\n\n#### contexts\n\n- **Type:** list (array of strings)\n- **Description:** Context labels for the task\n- **Examples:**\n\n ```yaml\n contexts: [\"office\", \"computer\"]\n contexts:\n - \"office\"\n - \"computer\"\n ```\n\n#### projects\n\n- **Type:** list (array of strings)\n- **Description:** Project references (typically wiki-links)\n- **Examples:**\n\n ```yaml\n projects: [\"[[Website Redesign]]\", \"[[Q1 Planning]]\"]\n projects:\n - \"[[Website Redesign]]\"\n - \"[[Q1 Planning]]\"\n ```\n\n---\n\n### Numeric Properties\n\n#### timeEstimate\n- **Type:** number\n- **Unit:** minutes\n- **Description:** Estimated time to complete the task\n- **Example:** `timeEstimate: 120` (2 hours)\n\n---\n\n### Recurrence Properties\n\n#### recurrence\n\n- **Type:** text (string)\n- **Format:** RFC 5545 RRULE format\n- **Description:** Defines how the task repeats\n- **Examples:**\n\n ```yaml\n recurrence: \"FREQ=DAILY\"\n recurrence: \"FREQ=WEEKLY;BYDAY=MO,WE,FR\"\n recurrence: \"FREQ=MONTHLY;BYMONTHDAY=1\"\n ```\n\n#### recurrence_anchor\n\n- **Type:** text (string)\n- **Valid values:** `\"scheduled\"` or `\"completion\"`\n- **Description:** Determines whether the next occurrence is calculated from the scheduled date or when the task was completed\n- **Example:** `recurrence_anchor: \"scheduled\"`\n\n#### complete_instances\n\n- **Type:** list (array of date strings)\n- **Format:** `YYYY-MM-DD`\n- **Description:** Dates when recurring task instances were completed\n- **Example:**\n\n ```yaml\n complete_instances:\n - \"2025-01-08\"\n - \"2025-01-15\"\n ```\n\n#### skipped_instances\n\n- **Type:** list (array of date strings)\n- **Format:** `YYYY-MM-DD`\n- **Description:** Dates when recurring task instances were skipped\n- **Example:**\n\n ```yaml\n skipped_instances:\n - \"2025-01-22\"\n ```\n\n### Materialized Occurrence Properties\n\nMaterialized occurrence notes are ordinary task notes created for one date in a recurring series. The parent recurring task owns the recurrence rule; the occurrence note owns date-specific state such as status, completed date, body content, time entries, reminders, and comments.\n\nWhen an occurrence note is created, TaskNotes inherits parent planning metadata such as scheduled time, due offset, priority, tags, contexts, projects, reminders, dependencies, details, custom properties, and time estimate. It does not copy parent recurrence/history/runtime fields such as `recurrence`, `complete_instances`, `skipped_instances`, `completedDate`, provider event IDs, or `timeEntries`.\n\n#### recurrence_parent\n\n- **Type:** text (link or path string)\n- **Description:** Parent recurring task for a materialized occurrence note\n- **Example:** `recurrence_parent: \"[[Tasks/Weekly review]]\"`\n\n#### occurrence_date\n\n- **Type:** text (date string)\n- **Format:** `YYYY-MM-DD`\n- **Description:** Target recurrence date represented by a materialized occurrence note\n- **Example:** `occurrence_date: \"2025-01-15\"`\n\n#### occurrence_materialization\n\n- **Type:** text (string)\n- **Valid values:** `\"manual\"`, `\"on_completion\"`, `\"rolling\"`\n- **Description:** Parent task policy for creating occurrence notes. The plugin currently supports manual creation and creating the next note after completion; rolling windows are defined by the spec but are not automated yet.\n- **Example:** `occurrence_materialization: \"on_completion\"`\n\n#### occurrence_next_trigger\n\n- **Type:** text (string)\n- **Valid values:** `\"completion\"` or `\"completion_or_skip\"`\n- **Description:** Parent task policy for whether skip actions should also create the next occurrence note when occurrence materialization is set to `on_completion`\n- **Example:** `occurrence_next_trigger: \"completion_or_skip\"`\n\n#### occurrence_template\n\n- **Type:** text (link or path string)\n- **Description:** Optional template reference used when creating materialized occurrence notes. This parent-level template takes priority over the global occurrence note template fallback in Features settings.\n- **Example:** `occurrence_template: \"[[Templates/Weekly occurrence]]\"`\n\n#### occurrence_past_horizon and occurrence_future_horizon\n\n- **Type:** text (ISO 8601 duration string)\n- **Description:** Optional rolling-window bounds for occurrence materialization. These fields are part of the TaskNotes spec; automated rolling materialization is not currently enabled in the plugin.\n- **Examples:**\n\n ```yaml\n occurrence_past_horizon: \"P7D\"\n occurrence_future_horizon: \"P14D\"\n ```\n\n---\n\n### Complex Properties\n\nThese properties contain structured data with multiple fields.\nFor these fields, copy known-good examples before editing manually. Minor schema deviations can break downstream features such as reminders, recurrence, or dependency checks.\n\n#### Time Entries\n\n- **Type:** list (array of objects)\n- **Description:** Time tracking entries for the task\n- **Structure:**\n\n ```yaml\n timeEntries:\n - startTime: \"2025-01-15T10:30:00Z\" # Required: ISO 8601 timestamp\n endTime: \"2025-01-15T11:15:00Z\" # Optional: ISO 8601 timestamp\n description: \"Initial work\" # Optional: text\n ```\n\n#### Dependencies (blockedBy)\n\n- **Type:** list (array of objects)\n- **Description:** Tasks that must be completed before this task can start\n- **Structure:**\n\n ```yaml\n blockedBy:\n - uid: \"path/to/blocking-task.md\" # Required: path to blocking task\n reltype: \"FINISHTOSTART\" # Required: relationship type\n gap: \"P1D\" # Optional: ISO 8601 duration offset\n ```\n\n- **Relationship types accepted in stored data:** `FINISHTOSTART`, `STARTTOSTART`, `FINISHTOFINISH`, `STARTTOFINISH`\n- **Current behavior:** Dependencies created from the UI use `FINISHTOSTART`. Blocking evaluation is based on dependency presence/completion state and does not currently apply distinct scheduling semantics for different `reltype` values or `gap`.\n\n#### Reminders\n\n- **Type:** list (array of objects)\n- **Description:** Reminder notifications for the task\n- **Structure for relative reminders:**\n\n ```yaml\n reminders:\n - id: \"rem_1\" # Required: unique identifier\n type: \"relative\" # Required: \"relative\" or \"absolute\"\n relatedTo: \"due\" # Required for relative: \"due\" or \"scheduled\"\n offset: \"-PT1H\" # Required for relative: ISO 8601 duration\n description: \"1 hour before due\" # Optional: description\n ```\n\n- **Structure for absolute reminders:**\n\n ```yaml\n reminders:\n - id: \"rem_2\"\n type: \"absolute\"\n absoluteTime: \"2025-01-15T09:00:00Z\" # Required for absolute: ISO 8601 timestamp\n description: \"Morning reminder\"\n ```\n\n#### icsEventId\n\n- **Type:** list (array of strings)\n- **Description:** ICS calendar event IDs linked to this task\n- **Example:**\n \n ```yaml\n icsEventId:\n - \"event-abc123\"\n - \"event-def456\"\n ```\n\n\n---\n\n## Complete Example\n\nHere's a complete task with all property types:\n\n```yaml\n---\ntitle: \"Complete quarterly report\"\nstatus: \"in-progress\"\npriority: \"high\"\ndue: \"2025-01-31\"\nscheduled: \"2025-01-25\"\ntags:\n - work\n - reports\ncontexts:\n - office\nprojects:\n - \"[[Q1 Planning]]\"\ntimeEstimate: 240\ndateCreated: \"2025-01-01T08:00:00Z\"\ndateModified: \"2025-01-20T14:30:00Z\"\ntimeEntries:\n - startTime: \"2025-01-20T10:00:00Z\"\n endTime: \"2025-01-20T11:30:00Z\"\nblockedBy:\n - uid: \"tasks/gather-data.md\"\n reltype: \"FINISHTOSTART\"\nreminders:\n - id: \"rem_1\"\n type: \"relative\"\n relatedTo: \"due\"\n offset: \"-P1D\"\n description: \"Due tomorrow\"\n---\n```\n\n---\n\n## Field Mapping\n\nAll property names can be customized via **Settings → Task Properties → Field Mapping**. If you change a field mapping, TaskNotes will read and write using your custom property name.\n\nCustom property names are frontmatter keys, so names with spaces or punctuation are valid in task files. When you write your own Bases filters or formulas for those keys, use bracket notation such as `note[\"TN-status\"]` or `note[\"Task Type\"]` instead of dot notation. Dot notation only works reliably for simple identifier-style names.\n\nFor example, if you map `due` to `dueDate`, TaskNotes will expect:\n\n```yaml\ndueDate: \"2025-01-15\"\n```\n\nSee [Task Properties settings](task-properties.md) for configuration details.\n\n---\n\n## Custom User Fields\n\nYou can define additional properties with these types:\n\n- **text** - Single text value\n- **number** - Numeric value\n- **date** - Date string (YYYY-MM-DD)\n- **boolean** - true/false\n- **list** - Array of values\n\nSee [Custom User Fields](task-properties.md#custom-user-fields) for configuration details.\n","aliases":["/settings/property-types-reference/"],"toc":[{"level":2,"id":"quick-reference","text":"Quick Reference"},{"level":2,"id":"property-details","text":"Property Details"},{"level":3,"id":"text-properties","text":"Text Properties"},{"level":3,"id":"date-properties","text":"Date Properties"},{"level":3,"id":"list-properties","text":"List Properties"},{"level":3,"id":"numeric-properties","text":"Numeric Properties"},{"level":3,"id":"recurrence-properties","text":"Recurrence Properties"},{"level":3,"id":"materialized-occurrence-properties","text":"Materialized Occurrence Properties"},{"level":3,"id":"complex-properties","text":"Complex Properties"},{"level":2,"id":"complete-example","text":"Complete Example"},{"level":2,"id":"field-mapping","text":"Field Mapping"},{"level":2,"id":"custom-user-fields","text":"Custom User Fields"}],"html":"

This reference documents the expected data types for each frontmatter property that TaskNotes uses.

\n

Quick Reference#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
PropertyTypeExample
titletext"My Task"
statustext"open", "in-progress", "done"
prioritytext"low", "normal", "high"
duetext (date)"2025-01-15"
scheduledtext (date)"2025-01-10"
completedDatetext (date)"2025-01-20"
dateCreatedtext (datetime)"2025-01-01T08:00:00Z"
dateModifiedtext (datetime)"2025-01-15T10:30:00Z"
tagslist["work", "urgent"]
contextslist["office", "home"]
projectslist["[[Project A]]"]
timeEstimatenumber120 (minutes)
recurrencetext"FREQ=WEEKLY;BYDAY=MO"
recurrence_anchortext"scheduled" or "completion"
timeEntrieslist (objects)See Time Entries
blockedBylist (objects)See Dependencies
reminderslist (objects)See Reminders
complete_instanceslist["2025-01-08", "2025-01-15"]
skipped_instanceslist["2025-01-22"]
recurrence_parenttext (link/path)"[[Tasks/Weekly review]]"
occurrence_datetext (date)"2025-01-15"
occurrence_materializationtext"manual" or "on_completion"
occurrence_next_triggertext"completion" or "completion_or_skip"
occurrence_templatetext (link/path)"[[Templates/Occurrence]]"
occurrence_past_horizontext (duration)"P7D"
occurrence_future_horizontext (duration)"P14D"
icsEventIdlist["event-abc123"]
\n

Use this table for fast validation when a field is not behaving as expected in views or API calls. Most parsing issues come from shape mismatches (for example scalar vs list) rather than missing values.

\n
\n

Property Details#

\n

The sections below describe storage formats, but there is flexibility in authoring style. TaskNotes normalizes many equivalent YAML representations as long as the resulting data type is correct.

\n

Text Properties#

\n

title#

\n
    \n
  • Type: text (string)
  • \n
  • Description: The task's title or name
  • \n
  • Example: title: "Complete project documentation"
  • \n
\n

status#

\n
    \n
  • Type: text (string)
  • \n
  • Description: The task's current status. Must match one of the status values configured in your settings.
  • \n
  • Default values: "open", "in-progress", "done"
  • \n
  • Example: status: "in-progress"
  • \n
  • Note: Also supports boolean values (true/false) for Obsidian checkbox compatibility. See Boolean Status Values.
  • \n
\n

priority#

\n
    \n
  • Type: text (string)
  • \n
  • Description: The task's priority level. Must match one of the priority values configured in your settings.
  • \n
  • Default values: "low", "normal", "high"
  • \n
  • Example: priority: "high"
  • \n
\n
\n

Date Properties#

\n

All date properties are stored as text strings in your frontmatter. TaskNotes expects specific formats:\nWhen in doubt, prefer ISO-style values. They sort correctly as text, travel well through APIs, and are easiest to parse consistently.

\n

due#

\n
    \n
  • Type: text (date string)

    \n
  • \n
  • Format: YYYY-MM-DD or ISO 8601 timestamp

    \n
  • \n
  • Description: The task's due date

    \n
  • \n
  • Examples:

    \n
    due: "2025-01-15"\ndue: "2025-01-15T17:00:00"\n
  • \n
\n

scheduled#

\n
    \n
  • Type: text (date string)

    \n
  • \n
  • Format: YYYY-MM-DD or ISO 8601 timestamp

    \n
  • \n
  • Description: When the task is scheduled to be worked on

    \n
  • \n
  • Examples:

    \n
    scheduled: "2025-01-10"\nscheduled: "2025-01-10T09:00:00"\n
  • \n
\n

completedDate#

\n
    \n
  • Type: text (date string)
  • \n
  • Format: YYYY-MM-DD
  • \n
  • Description: The date when the task was completed
  • \n
  • Example: completedDate: "2025-01-20"
  • \n
\n

dateCreated#

\n
    \n
  • Type: text (datetime string)
  • \n
  • Format: ISO 8601 timestamp
  • \n
  • Description: When the task was created
  • \n
  • Example: dateCreated: "2025-01-01T08:00:00Z"
  • \n
\n

dateModified#

\n
    \n
  • Type: text (datetime string)
  • \n
  • Format: ISO 8601 timestamp
  • \n
  • Description: When the task was last modified
  • \n
  • Example: dateModified: "2025-01-15T10:30:00Z"
  • \n
\n
\n

List Properties#

\n

List properties must be arrays, even when containing a single value.\nSingle-item arrays may look verbose, but they prevent edge cases when filters and formulas assume list semantics.

\n

tags#

\n
    \n
  • Type: list (array of strings)

    \n
  • \n
  • Description: Tags associated with the task

    \n
  • \n
  • Examples:

    \n
    tags: ["work", "documentation"]\ntags:\n  - work\n  - documentation\n
  • \n
\n

contexts#

\n
    \n
  • Type: list (array of strings)

    \n
  • \n
  • Description: Context labels for the task

    \n
  • \n
  • Examples:

    \n
    contexts: ["office", "computer"]\ncontexts:\n  - "office"\n  - "computer"\n
  • \n
\n

projects#

\n
    \n
  • Type: list (array of strings)

    \n
  • \n
  • Description: Project references (typically wiki-links)

    \n
  • \n
  • Examples:

    \n
    projects: ["[[Website Redesign]]", "[[Q1 Planning]]"]\nprojects:\n  - "[[Website Redesign]]"\n  - "[[Q1 Planning]]"\n
  • \n
\n
\n

Numeric Properties#

\n

timeEstimate#

\n
    \n
  • Type: number
  • \n
  • Unit: minutes
  • \n
  • Description: Estimated time to complete the task
  • \n
  • Example: timeEstimate: 120 (2 hours)
  • \n
\n
\n

Recurrence Properties#

\n

recurrence#

\n
    \n
  • Type: text (string)

    \n
  • \n
  • Format: RFC 5545 RRULE format

    \n
  • \n
  • Description: Defines how the task repeats

    \n
  • \n
  • Examples:

    \n
    recurrence: "FREQ=DAILY"\nrecurrence: "FREQ=WEEKLY;BYDAY=MO,WE,FR"\nrecurrence: "FREQ=MONTHLY;BYMONTHDAY=1"\n
  • \n
\n

recurrence_anchor#

\n
    \n
  • Type: text (string)
  • \n
  • Valid values: "scheduled" or "completion"
  • \n
  • Description: Determines whether the next occurrence is calculated from the scheduled date or when the task was completed
  • \n
  • Example: recurrence_anchor: "scheduled"
  • \n
\n

complete_instances#

\n
    \n
  • Type: list (array of date strings)

    \n
  • \n
  • Format: YYYY-MM-DD

    \n
  • \n
  • Description: Dates when recurring task instances were completed

    \n
  • \n
  • Example:

    \n
    complete_instances:\n  - "2025-01-08"\n  - "2025-01-15"\n
  • \n
\n

skipped_instances#

\n
    \n
  • Type: list (array of date strings)

    \n
  • \n
  • Format: YYYY-MM-DD

    \n
  • \n
  • Description: Dates when recurring task instances were skipped

    \n
  • \n
  • Example:

    \n
    skipped_instances:\n  - "2025-01-22"\n
  • \n
\n

Materialized Occurrence Properties#

\n

Materialized occurrence notes are ordinary task notes created for one date in a recurring series. The parent recurring task owns the recurrence rule; the occurrence note owns date-specific state such as status, completed date, body content, time entries, reminders, and comments.

\n

When an occurrence note is created, TaskNotes inherits parent planning metadata such as scheduled time, due offset, priority, tags, contexts, projects, reminders, dependencies, details, custom properties, and time estimate. It does not copy parent recurrence/history/runtime fields such as recurrence, complete_instances, skipped_instances, completedDate, provider event IDs, or timeEntries.

\n

recurrence_parent#

\n
    \n
  • Type: text (link or path string)
  • \n
  • Description: Parent recurring task for a materialized occurrence note
  • \n
  • Example: recurrence_parent: "[[Tasks/Weekly review]]"
  • \n
\n

occurrence_date#

\n
    \n
  • Type: text (date string)
  • \n
  • Format: YYYY-MM-DD
  • \n
  • Description: Target recurrence date represented by a materialized occurrence note
  • \n
  • Example: occurrence_date: "2025-01-15"
  • \n
\n

occurrence_materialization#

\n
    \n
  • Type: text (string)
  • \n
  • Valid values: "manual", "on_completion", "rolling"
  • \n
  • Description: Parent task policy for creating occurrence notes. The plugin currently supports manual creation and creating the next note after completion; rolling windows are defined by the spec but are not automated yet.
  • \n
  • Example: occurrence_materialization: "on_completion"
  • \n
\n

occurrence_next_trigger#

\n
    \n
  • Type: text (string)
  • \n
  • Valid values: "completion" or "completion_or_skip"
  • \n
  • Description: Parent task policy for whether skip actions should also create the next occurrence note when occurrence materialization is set to on_completion
  • \n
  • Example: occurrence_next_trigger: "completion_or_skip"
  • \n
\n

occurrence_template#

\n
    \n
  • Type: text (link or path string)
  • \n
  • Description: Optional template reference used when creating materialized occurrence notes. This parent-level template takes priority over the global occurrence note template fallback in Features settings.
  • \n
  • Example: occurrence_template: "[[Templates/Weekly occurrence]]"
  • \n
\n

occurrence_past_horizon and occurrence_future_horizon#

\n
    \n
  • Type: text (ISO 8601 duration string)

    \n
  • \n
  • Description: Optional rolling-window bounds for occurrence materialization. These fields are part of the TaskNotes spec; automated rolling materialization is not currently enabled in the plugin.

    \n
  • \n
  • Examples:

    \n
    occurrence_past_horizon: "P7D"\noccurrence_future_horizon: "P14D"\n
  • \n
\n
\n

Complex Properties#

\n

These properties contain structured data with multiple fields.\nFor these fields, copy known-good examples before editing manually. Minor schema deviations can break downstream features such as reminders, recurrence, or dependency checks.

\n

Time Entries#

\n
    \n
  • Type: list (array of objects)

    \n
  • \n
  • Description: Time tracking entries for the task

    \n
  • \n
  • Structure:

    \n
    timeEntries:\n  - startTime: "2025-01-15T10:30:00Z"    # Required: ISO 8601 timestamp\n    endTime: "2025-01-15T11:15:00Z"      # Optional: ISO 8601 timestamp\n    description: "Initial work"          # Optional: text\n
  • \n
\n

Dependencies (blockedBy)#

\n
    \n
  • Type: list (array of objects)

    \n
  • \n
  • Description: Tasks that must be completed before this task can start

    \n
  • \n
  • Structure:

    \n
    blockedBy:\n  - uid: "path/to/blocking-task.md"    # Required: path to blocking task\n    reltype: "FINISHTOSTART"           # Required: relationship type\n    gap: "P1D"                         # Optional: ISO 8601 duration offset\n
  • \n
  • Relationship types accepted in stored data: FINISHTOSTART, STARTTOSTART, FINISHTOFINISH, STARTTOFINISH

    \n
  • \n
  • Current behavior: Dependencies created from the UI use FINISHTOSTART. Blocking evaluation is based on dependency presence/completion state and does not currently apply distinct scheduling semantics for different reltype values or gap.

    \n
  • \n
\n

Reminders#

\n
    \n
  • Type: list (array of objects)

    \n
  • \n
  • Description: Reminder notifications for the task

    \n
  • \n
  • Structure for relative reminders:

    \n
    reminders:\n  - id: "rem_1"                        # Required: unique identifier\n    type: "relative"                   # Required: "relative" or "absolute"\n    relatedTo: "due"                   # Required for relative: "due" or "scheduled"\n    offset: "-PT1H"                    # Required for relative: ISO 8601 duration\n    description: "1 hour before due"   # Optional: description\n
  • \n
  • Structure for absolute reminders:

    \n
    reminders:\n  - id: "rem_2"\n    type: "absolute"\n    absoluteTime: "2025-01-15T09:00:00Z"  # Required for absolute: ISO 8601 timestamp\n    description: "Morning reminder"\n
  • \n
\n

icsEventId#

\n
    \n
  • Type: list (array of strings)

    \n
  • \n
  • Description: ICS calendar event IDs linked to this task

    \n
  • \n
  • Example:

    \n
    icsEventId:\n  - "event-abc123"\n  - "event-def456"\n
  • \n
\n
\n

Complete Example#

\n

Here's a complete task with all property types:

\n
---\ntitle: "Complete quarterly report"\nstatus: "in-progress"\npriority: "high"\ndue: "2025-01-31"\nscheduled: "2025-01-25"\ntags:\n  - work\n  - reports\ncontexts:\n  - office\nprojects:\n  - "[[Q1 Planning]]"\ntimeEstimate: 240\ndateCreated: "2025-01-01T08:00:00Z"\ndateModified: "2025-01-20T14:30:00Z"\ntimeEntries:\n  - startTime: "2025-01-20T10:00:00Z"\n    endTime: "2025-01-20T11:30:00Z"\nblockedBy:\n  - uid: "tasks/gather-data.md"\n    reltype: "FINISHTOSTART"\nreminders:\n  - id: "rem_1"\n    type: "relative"\n    relatedTo: "due"\n    offset: "-P1D"\n    description: "Due tomorrow"\n---\n

\n

Field Mapping#

\n

All property names can be customized via Settings → Task Properties → Field Mapping. If you change a field mapping, TaskNotes will read and write using your custom property name.

\n

Custom property names are frontmatter keys, so names with spaces or punctuation are valid in task files. When you write your own Bases filters or formulas for those keys, use bracket notation such as note["TN-status"] or note["Task Type"] instead of dot notation. Dot notation only works reliably for simple identifier-style names.

\n

For example, if you map due to dueDate, TaskNotes will expect:

\n
dueDate: "2025-01-15"\n

See Task Properties settings for configuration details.

\n
\n

Custom User Fields#

\n

You can define additional properties with these types:

\n
    \n
  • text - Single text value
  • \n
  • number - Numeric value
  • \n
  • date - Date string (YYYY-MM-DD)
  • \n
  • boolean - true/false
  • \n
  • list - Array of values
  • \n
\n

See Custom User Fields for configuration details.

\n","text":"This reference documents the expected data types for each frontmatter property that TaskNotes uses. Quick Reference# Property Type Example title text \"My Task\" status text \"open\", \"in-progress\", \"done\" priority text \"low\", \"normal\", \"high\" due text (date) \"2025-01-15\" scheduled text (date) \"2025-01-10\" completedDate text (date) \"2025-01-20\" dateCreated text (datetime) \"2025-01-01T08:00:00Z\" dateModified text (datetime) \"2025-01-15T10:30:00Z\" tags list [\"work\", \"urgent\"] contexts list [\"office\", \"home\"] projects list [\"[[Project A]]\"] timeEstimate number 120 (minutes) recurrence text \"FREQ=WEEKLY;BYDAY=MO\" recurrence_anchor text \"scheduled\" or \"completion\" timeEntries list (objects) See Time Entries blockedBy list (objects) See Dependencies reminders list (objects) See Reminders complete_instances list [\"2025-01-08\", \"2025-01-15\"] skipped_instances list [\"2025-01-22\"] recurrence_parent text (link/path) \"[[Tasks/Weekly review]]\" occurrence_date text (date) \"2025-01-15\" occurrence_materialization text \"manual\" or \"on_completion\" occurrence_next_trigger text \"completion\" or \"completion_or_skip\" occurrence_template text (link/path) \"[[Templates/Occurrence]]\" occurrence_past_horizon text (duration) \"P7D\" occurrence_future_horizon text (duration) \"P14D\" icsEventId list [\"event-abc123\"] Use this table for fast validation when a field is not behaving as expected in views or API calls. Most parsing issues come from shape mismatches (for example scalar vs list) rather than missing values. Property Details# The sections below describe storage formats, but there is flexibility in authoring style. TaskNotes normalizes many equivalent YAML representations as long as the resulting data type is correct. Text Properties# title# Type: text (string) Description: The task's title or name Example: title: \"Complete project documentation\" status# Type: text (string) Description: The task's current status. Must match one of the status values configured in your settings. Default values: \"open\", \"in-progress\", \"done\" Example: status: \"in-progress\" Note: Also supports boolean values (true/false) for Obsidian checkbox compatibility. See Boolean Status Values. priority# Type: text (string) Description: The task's priority level. Must match one of the priority values configured in your settings. Default values: \"low\", \"normal\", \"high\" Example: priority: \"high\" Date Properties# All date properties are stored as text strings in your frontmatter. TaskNotes expects specific formats: When in doubt, prefer ISO-style values. They sort correctly as text, travel well through APIs, and are easiest to parse consistently. due# Type: text (date string) Format: YYYY-MM-DD or ISO 8601 timestamp Description: The task's due date Examples: due: \"2025-01-15\" due: \"2025-01-15T17:00:00\" scheduled# Type: text (date string) Format: YYYY-MM-DD or ISO 8601 timestamp Description: When the task is scheduled to be worked on Examples: scheduled: \"2025-01-10\" scheduled: \"2025-01-10T09:00:00\" completedDate# Type: text (date string) Format: YYYY-MM-DD Description: The date when the task was completed Example: completedDate: \"2025-01-20\" dateCreated# Type: text (datetime string) Format: ISO 8601 timestamp Description: When the task was created Example: dateCreated: \"2025-01-01T08:00:00Z\" dateModified# Type: text (datetime string) Format: ISO 8601 timestamp Description: When the task was last modified Example: dateModified: \"2025-01-15T10:30:00Z\" List Properties# List properties must be arrays, even when containing a single value. Single-item arrays may look verbose, but they prevent edge cases when filters and formulas assume list semantics. tags# Type: list (array of strings) Description: Tags associated with the task Examples: tags: [\"work\", \"documentation\"] tags: - work - documentation contexts# Type: list (array of strings) Description: Context labels for the task Examples: contexts: [\"office\", \"computer\"] contexts: - \"office\" - \"computer\" projects# Type: list (array of strings) Description: Project references (typically wiki-links) Examples: projects: [\"[[Website Redesign]]\", \"[[Q1 Planning]]\"] projects: - \"[[Website Redesign]]\" - \"[[Q1 Planning]]\" Numeric Properties# timeEstimate# Type: number Unit: minutes Description: Estimated time to complete the task Example: timeEstimate: 120 (2 hours) Recurrence Properties# recurrence# Type: text (string) Format: RFC 5545 RRULE format Description: Defines how the task repeats Examples: recurrence: \"FREQ=DAILY\" recurrence: \"FREQ=WEEKLY;BYDAY=MO,WE,FR\" recurrence: \"FREQ=MONTHLY;BYMONTHDAY=1\" recurrence_anchor# Type: text (string) Valid values: \"scheduled\" or \"completion\" Description: Determines whether the next occurrence is calculated from the scheduled date or when the task was completed Example: recurrence_anchor: \"scheduled\" complete_instances# Type: list (array of date strings) Format: YYYY-MM-DD Description: Dates when recurring task instances were completed Example: complete_instances: - \"2025-01-08\" - \"2025-01-15\" skipped_instances# Type: list (array of date strings) Format: YYYY-MM-DD Description: Dates when recurring task instances were skipped Example: skipped_instances: - \"2025-01-22\" Materialized Occurrence Properties# Materialized occurrence notes are ordinary task notes created for one date in a recurring series. The parent recurring task owns the recurrence rule; the occurrence note owns date-specific state such as status, completed date, body content, time entries, reminders, and comments. When an occurrence note is created, TaskNotes inherits parent planning metadata such as scheduled time, due offset, priority, tags, contexts, projects, reminders, dependencies, details, custom properties, and time estimate. It does not copy parent recurrence/history/runtime fields such as recurrence, complete_instances, skipped_instances, completedDate, provider event IDs, or timeEntries. recurrence_parent# Type: text (link or path string) Description: Parent recurring task for a materialized occurrence note Example: recurrence_parent: \"[[Tasks/Weekly review]]\" occurrence_date# Type: text (date string) Format: YYYY-MM-DD Description: Target recurrence date represented by a materialized occurrence note Example: occurrence_date: \"2025-01-15\" occurrence_materialization# Type: text (string) Valid values: \"manual\", \"on_completion\", \"rolling\" Description: Parent task policy for creating occurrence notes. The plugin currently supports manual creation and creating the next note after completion; rolling windows are defined by the spec but are not automated yet. Example: occurrence_materialization: \"on_completion\" occurrence_next_trigger# Type: text (string) Valid values: \"completion\" or \"completion_or_skip\" Description: Parent task policy for whether skip actions should also create the next occurrence note when occurrence materialization is set to on_completion Example: occurrence_next_trigger: \"completion_or_skip\" occurrence_template# Type: text (link or path string) Description: Optional template reference used when creating materialized occurrence notes. This parent-level template takes priority over the global occurrence note template fallback in Features settings. Example: occurrence_template: \"[[Templates/Weekly occurrence]]\" occurrence_past_horizon and occurrence_future_horizon# Type: text (ISO 8601 duration string) Description: Optional rolling-window bounds for occurrence materialization. These fields are part of the TaskNotes spec; automated rolling materialization is not currently enabled in the plugin. Examples: occurrence_past_horizon: \"P7D\" occurrence_future_horizon: \"P14D\" Complex Properties# These properties contain structured data with multiple fields. For these fields, copy known-good examples before editing manually. Minor schema deviations can break downstream features such as reminders, recurrence, or dependency checks. Time Entries# Type: list (array of objects) Description: Time tracking entries for the task Structure: timeEntries: - startTime: \"2025-01-15T10:30:00Z\" # Required: ISO 8601 timestamp endTime: \"2025-01-15T11:15:00Z\" # Optional: ISO 8601 timestamp description: \"Initial work\" # Optional: text Dependencies (blockedBy)# Type: list (array of objects) Description: Tasks that must be completed before this task can start Structure: blockedBy: - uid: \"path/to/blocking-task.md\" # Required: path to blocking task reltype: \"FINISHTOSTART\" # Required: relationship type gap: \"P1D\" # Optional: ISO 8601 duration offset Relationship types accepted in stored data: FINISHTOSTART, STARTTOSTART, FINISHTOFINISH, STARTTOFINISH Current behavior: Dependencies created from the UI use FINISHTOSTART. Blocking evaluation is based on dependency presence/completion state and does not currently apply distinct scheduling semantics for different reltype values or gap. Reminders# Type: list (array of objects) Description: Reminder notifications for the task Structure for relative reminders: reminders: - id: \"rem_1\" # Required: unique identifier type: \"relative\" # Required: \"relative\" or \"absolute\" relatedTo: \"due\" # Required for relative: \"due\" or \"scheduled\" offset: \"-PT1H\" # Required for relative: ISO 8601 duration description: \"1 hour before due\" # Optional: description Structure for absolute reminders: reminders: - id: \"rem_2\" type: \"absolute\" absoluteTime: \"2025-01-15T09:00:00Z\" # Required for absolute: ISO 8601 timestamp description: \"Morning reminder\" icsEventId# Type: list (array of strings) Description: ICS calendar event IDs linked to this task Example: icsEventId: - \"event-abc123\" - \"event-def456\" Complete Example# Here's a complete task with all property types: --- title: \"Complete quarterly report\" status: \"in-progress\" priority: \"high\" due: \"2025-01-31\" scheduled: \"2025-01-25\" tags: - work - reports contexts: - office projects: - \"[[Q1 Planning]]\" timeEstimate: 240 dateCreated: \"2025-01-01T08:00:00Z\" dateModified: \"2025-01-20T14:30:00Z\" timeEntries: - startTime: \"2025-01-20T10:00:00Z\" endTime: \"2025-01-20T11:30:00Z\" blockedBy: - uid: \"tasks/gather-data.md\" reltype: \"FINISHTOSTART\" reminders: - id: \"rem_1\" type: \"relative\" relatedTo: \"due\" offset: \"-P1D\" description: \"Due tomorrow\" --- Field Mapping# All property names can be customized via Settings → Task Properties → Field Mapping. If you change a field mapping, TaskNotes will read and write using your custom property name. Custom property names are frontmatter keys, so names with spaces or punctuation are valid in task files. When you write your own Bases filters or formulas for those keys, use bracket notation such as note[\"TN-status\"] or note[\"Task Type\"] instead of dot notation. Dot notation only works reliably for simple identifier-style names. For example, if you map due to dueDate, TaskNotes will expect: dueDate: \"2025-01-15\" See Task Properties settings for configuration details. Custom User Fields# You can define additional properties with these types: text - Single text value number - Numeric value date - Date string (YYYY-MM-DD) boolean - true/false list - Array of values See Custom User Fields for configuration details."},{"route":"/obsidian/settings/task-properties/","title":"Task Properties Settings","description":"This tab configures all task properties. Each property is displayed as a card containing its configuration options.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/settings/task-properties.md","namespace":"obsidian","relativePath":"settings/task-properties.md","raw":"# Task Properties Settings\n\nThis tab configures all task properties. Each property is displayed as a card containing its configuration options.\n\n\n![Task Properties Settings](../assets/settings-task-properties.png)\n\n!!! tip \"Looking for property type documentation?\"\n See the [Property Types Reference](property-types-reference.md) for detailed documentation on the expected data types (text, list, date, etc.) for each frontmatter property.\n\n## Property Card Structure\n\nEach property card contains:\n\n- **Property key**: The frontmatter field name used to store this property\n- **Default**: The default value applied to new tasks (where applicable)\n- **NLP trigger**: Toggle and character configuration for natural language parsing (where applicable)\n- **Property-specific settings**: Additional configuration options specific to that property\nThis tab defines the task schema used by creation flows, NLP parsing, views, and API payloads.\n\nProperty keys are YAML/frontmatter keys. TaskNotes can read and write keys that contain spaces or punctuation, but hand-written Bases filters and formulas must reference those keys with bracket syntax, for example `note[\"TN-status\"]`, rather than dot syntax such as `note.TN-status`.\n\n## Core Properties\n\n### Title\n\nThe task title property. Configuration options:\n\n- **Property key**: Frontmatter field name (default: `title`)\n- **Store title in filename**: When enabled, the task title is stored in the filename instead of frontmatter. The filename updates when the title changes.\n- **Filename format**: When \"Store title in filename\" is disabled, choose how filenames are generated:\n - Title-based\n - Zettelkasten-style\n - Timestamp-based\n - UUID v4\n - Custom template\n- **Custom template**: Define a custom filename pattern using variables (shown when \"custom\" format is selected)\n\n### Status\n\nTask completion state. Configuration options:\n\n- **Property key**: Frontmatter field name (default: `status`)\n- **Default**: Default status for new tasks\n- **NLP trigger**: Character that triggers status parsing (default: `*`)\n- **Status Values**: Expandable section containing individual status cards\n\nEach status value has:\n\n- **Value**: Internal identifier stored in frontmatter (e.g., \"in-progress\")\n- **Label**: Display name shown in the interface (e.g., \"In Progress\")\n- **Color**: Visual indicator color\n- **Icon**: Optional icon identifier\n- **Completed**: Whether this status represents a finished task\n- **Skip when cycling**: Exclude this status from the click-to-cycle order on task cards while keeping it available in menus, suggestions, and direct edits\n- **Next status**: Optional override for the status used when cycling forward from this status; leave it set to the status order to use the normal sequence\n- **Auto-archive**: Automatically archive tasks after a delay (1-1440 minutes)\n\nStatus cards support drag-and-drop reordering.\n\nUse the **Value** field as the stable stored identifier and the **Label** field for display text with spaces or title casing. TaskNotes status menus and cycling use the configured order, and TaskNotes Kanban views can preserve dragged column order. Native Bases grouping/sorting may still order status values alphabetically by their stored **Value**, so use prefixes such as `1-open`, `2-doing`, `3-done` if you need predictable native Bases order.\n\n#### Boolean Status Values\n\nTaskNotes supports using boolean values (`true` and `false`) as status values, which integrates with Obsidian's native checkbox property format:\n\n- When you set a task's status to `\"true\"` or `\"false\"` (case-insensitive), TaskNotes automatically converts it to a boolean in frontmatter\n- When reading tasks with boolean status values from frontmatter, they are converted back to the strings `\"true\"` or `\"false\"`\n- This allows you to use Obsidian's native checkbox property toggles in the Properties panel while maintaining compatibility with TaskNotes\n\n**Example:**\n```yaml\n---\nstatus: true # Boolean checkbox in Obsidian\n---\n```\n\n### Priority\n\nTask priority level. Configuration options:\n\n- **Property key**: Frontmatter field name (default: `priority`)\n- **Default**: Default priority for new tasks (can be set to \"No default\")\n- **NLP trigger**: Character that triggers priority parsing (default: `!`, disabled by default)\n- **Priority Values**: Expandable section containing individual priority cards\n\nEach priority value has:\n\n- **Value**: Internal identifier stored in frontmatter (e.g., \"high\")\n- **Label**: Display name shown in the interface (e.g., \"High Priority\")\n- **Color**: Visual indicator color\n\nPriority cards support drag-and-drop reordering.\nStatus and priority values are stored in frontmatter; renaming them later may require migration of existing task files.\n\n> **Note for Bases plugin users:** Obsidian's Bases plugin sorts priorities alphabetically by their **Value**. To control sort order, name values to sort alphabetically in the desired order:\n> - Example: `1-urgent`, `2-high`, `3-medium`, `4-normal`, `5-low`\n> - Or: `a-urgent`, `b-high`, `c-medium`, `d-normal`, `e-low`\n\n## Date Properties\n\n### Due Date\n\nWhen the task must be completed. Configuration options:\n\n- **Property key**: Frontmatter field name (default: `due`)\n- **Default**: Default due date for new tasks (None, Today, Tomorrow, Next Week)\n\n### Scheduled Date\n\nWhen to work on the task. Configuration options:\n\n- **Property key**: Frontmatter field name (default: `scheduled`)\n- **Default**: Default scheduled date for new tasks (None, Today, Tomorrow, Next Week)\n\nWhen you use **Convert current note to task**, this default is also applied if the source note does not already have `scheduled` frontmatter. Choose **None** to keep converted notes unscheduled by default.\n\n`due` tracks commitment deadlines, while `scheduled` tracks intended execution time.\n\n## Organization Properties\n\n### Contexts\n\nWhere or how the task can be done. Configuration options:\n\n- **Property key**: Frontmatter field name (default: `contexts`)\n- **Default**: Comma-separated list of default contexts (e.g., @home, @work)\n- **NLP trigger**: Character that triggers context parsing (default: `@`)\n\n### Projects\n\nProjects the task belongs to. Configuration options:\n\n- **Property key**: Frontmatter field name (default: `projects`)\n- **Default projects**: Select project notes to automatically link to new tasks\n- **Use active note for new tasks**: Automatically link the active note as a project when opening task creation from the command palette or ribbon\n- **Use parent note for inline/instant conversion**: Automatically link the source note as a project when using inline task creation or instant task conversion\n- **NLP trigger**: Character that triggers project parsing (default: `+`)\n- **Autosuggest Filters**: Expandable section to filter which notes appear in project suggestions\n- **Customize Display**: Expandable section to configure how project suggestions appear\n\n#### Autosuggest Filters\n\nControl which notes appear when selecting projects:\n\n- **Required tags**: Comma-separated list of tags (shows notes with ANY of these tags)\n- **Include folders**: Comma-separated list of folder paths (shows notes in ANY of these folders)\n- **Required property key**: Frontmatter property that must exist\n- **Required property value**: Expected value for the property (optional)\nThese filters reduce suggestion noise in large vaults.\n\nA \"Filters On\" badge appears when any filters are configured.\n\n#### Customize Display\n\nConfigure project suggestion appearance:\n\n- **Enable fuzzy matching**: Allow typos and partial matches in project search\n- **Row 1, 2, 3**: Configure up to 3 lines of information for each project suggestion\n\n### Tags\n\nObsidian tags for categorization. Configuration options:\n\n- **Default**: Comma-separated list of default tags (without #)\n- **NLP trigger**: Character that triggers tag parsing (default: `#`)\n\nNote: Tags use native Obsidian tags and do not have a separate property key setting.\n\n## Task Details\n\n### Time Estimate\n\nEstimated time to complete the task. Configuration options:\n\n- **Property key**: Frontmatter field name (default: `timeEstimate`)\n- **Default**: Default time estimate in minutes (0 = no default)\n\n### Recurrence\n\nPattern for repeating tasks. Configuration options:\n\n- **Property key**: Frontmatter field name (default: `recurrence`)\n- **Default**: Default recurrence pattern (None, Daily, Weekly, Monthly, Yearly)\n\nRecurring tasks also use the **Recurrence anchor** metadata property to decide whether the series advances from the scheduled date or the completion date. Materialized occurrence note controls live on each recurring task's context menu under **Recurrence → Occurrence notes** rather than as a global default.\n\n### Reminders\n\nNotifications before task deadlines. Configuration options:\n\n- **Property key**: Frontmatter field name (default: `reminders`)\n- **Default Reminders**: Expandable section containing default reminder cards\n\nEach default reminder can be:\n\n**Relative reminders** (triggered relative to due or scheduled date):\n\n- Anchor date (due date or scheduled date)\n- Offset amount and unit (minutes, hours, days)\n- Direction (before or after)\n- Description\n\n**Absolute reminders** (triggered at specific times):\n\n- Date\n- Time\n- Description\n\n## Metadata Properties\n\nThese properties are system-managed and typically only require property key configuration:\n\n- **Date Created**: When the task was created\n- **Date Modified**: When the task was last modified\n- **Completed Date**: When the task was completed\n- **Archive Tag**: Tag used to mark archived tasks\n- **Time Entries**: Time tracking entries for the task\n- **Complete Instances**: Completion history for recurring tasks\n- **Skipped Instances**: Skip history for recurring tasks\n- **Recurrence Anchor**: Whether recurring progression is based on scheduled date or completion date\n- **Blocked By**: Tasks that must be completed first\n\nMaterialized occurrence notes also use system-managed frontmatter fields such as `recurrence_parent`, `occurrence_date`, `occurrence_materialization`, `occurrence_next_trigger`, and optional occurrence template/horizon fields. Occurrence notes inherit parent planning metadata when they are created, but keep their own status, completion date, and time entries. These fields are documented in the [Property Types Reference](property-types-reference.md#materialized-occurrence-properties) and are normally changed through recurrence and occurrence-note controls instead of by hand.\n\n## Feature Properties\n\nThese properties are used by specific TaskNotes features and are not stored in task frontmatter:\n\n- **Pomodoros**: Property key for Pomodoro session counts. When Pomodoro data storage is set to \"Daily notes\", this property is written to daily notes rather than task files.\n- **ICS Event ID**: Property key for calendar event identifiers. Added to notes created from ICS calendar events to link them back to the source event.\n- **ICS Event Tag**: Property key for calendar event tags. Added to notes created from ICS calendar events for identification.\n\n## Custom User Fields\n\nDefine custom frontmatter properties to appear as filter options across views. Configuration options for each field:\n\n- **Display Name**: How the field appears in the UI\n- **Property Key**: The frontmatter property name\n- **Type**: Data type (text, number, boolean, date, or list)\n- **Default Value**: Pre-fill value for new tasks (format varies by type)\n- **NLP trigger**: Toggle and character for natural language parsing\n- **Autosuggest Filters**: Filter which files appear when using `[[` wikilink autocomplete\nCustom fields are most maintainable when they map to repeated workflow decisions (for example `effort`, `owner`, or `client`).\n\n### Link Values\n\nUse a **Text** custom field for a single link and a **List** custom field for multiple links. Task cards render `[[wikilinks]]`, `[label](https://example.com)`, ``, and bare `https://example.com` values as clickable links.\n\nAutosuggest filters work with text and list fields when entering `[[` wikilinks, so a field such as `Related Note` can suggest only files from a chosen folder or tag.\n\n### Default Values\n\nEach field type has a different input format for default values:\n\n- **Text**: Enter the default text value\n- **Number**: Enter the default number\n- **Boolean**: Toggle switch to set default checked/unchecked state\n- **Date**: Select from presets (None, Today, Tomorrow, Next Week)\n- **List**: Enter comma-separated default values\n\nDefault values are applied when creating tasks via:\n\n- Task creation modal\n- Instant task conversion\n- \"Create or open task\" command\n- HTTP API (when using task creation defaults)\n\n### Autosuggestion Filters\n\nEach custom field can configure filters to control which files appear in wikilink suggestions:\n\n- **Required tags**: Comma-separated list of tags (shows files with ANY of these tags)\n- **Include folders**: Comma-separated list of folder paths (shows files in ANY of these folders)\n- **Required property key**: Frontmatter property that must exist\n- **Required property value**: Expected value for the property (optional)\n\nA \"Filters On\" badge appears when filters are configured.\n\nSee [User Fields Feature Documentation](../features/user-fields.md#file-suggestion-filtering-advanced) for detailed examples.\n","aliases":["/settings/task-properties/"],"toc":[{"level":2,"id":"property-card-structure","text":"Property Card Structure"},{"level":2,"id":"core-properties","text":"Core Properties"},{"level":3,"id":"title","text":"Title"},{"level":3,"id":"status","text":"Status"},{"level":3,"id":"priority","text":"Priority"},{"level":2,"id":"date-properties","text":"Date Properties"},{"level":3,"id":"due-date","text":"Due Date"},{"level":3,"id":"scheduled-date","text":"Scheduled Date"},{"level":2,"id":"organization-properties","text":"Organization Properties"},{"level":3,"id":"contexts","text":"Contexts"},{"level":3,"id":"projects","text":"Projects"},{"level":3,"id":"tags","text":"Tags"},{"level":2,"id":"task-details","text":"Task Details"},{"level":3,"id":"time-estimate","text":"Time Estimate"},{"level":3,"id":"recurrence","text":"Recurrence"},{"level":3,"id":"reminders","text":"Reminders"},{"level":2,"id":"metadata-properties","text":"Metadata Properties"},{"level":2,"id":"feature-properties","text":"Feature Properties"},{"level":2,"id":"custom-user-fields","text":"Custom User Fields"},{"level":3,"id":"link-values","text":"Link Values"},{"level":3,"id":"default-values","text":"Default Values"},{"level":3,"id":"autosuggestion-filters","text":"Autosuggestion Filters"}],"html":"

This tab configures all task properties. Each property is displayed as a card containing its configuration options.

\n

\"Task

\n\n

Property Card Structure#

\n

Each property card contains:

\n
    \n
  • Property key: The frontmatter field name used to store this property
  • \n
  • Default: The default value applied to new tasks (where applicable)
  • \n
  • NLP trigger: Toggle and character configuration for natural language parsing (where applicable)
  • \n
  • Property-specific settings: Additional configuration options specific to that property\nThis tab defines the task schema used by creation flows, NLP parsing, views, and API payloads.
  • \n
\n

Property keys are YAML/frontmatter keys. TaskNotes can read and write keys that contain spaces or punctuation, but hand-written Bases filters and formulas must reference those keys with bracket syntax, for example note["TN-status"], rather than dot syntax such as note.TN-status.

\n

Core Properties#

\n

Title#

\n

The task title property. Configuration options:

\n
    \n
  • Property key: Frontmatter field name (default: title)
  • \n
  • Store title in filename: When enabled, the task title is stored in the filename instead of frontmatter. The filename updates when the title changes.
  • \n
  • Filename format: When "Store title in filename" is disabled, choose how filenames are generated:
      \n
    • Title-based
    • \n
    • Zettelkasten-style
    • \n
    • Timestamp-based
    • \n
    • UUID v4
    • \n
    • Custom template
    • \n
    \n
  • \n
  • Custom template: Define a custom filename pattern using variables (shown when "custom" format is selected)
  • \n
\n

Status#

\n

Task completion state. Configuration options:

\n
    \n
  • Property key: Frontmatter field name (default: status)
  • \n
  • Default: Default status for new tasks
  • \n
  • NLP trigger: Character that triggers status parsing (default: *)
  • \n
  • Status Values: Expandable section containing individual status cards
  • \n
\n

Each status value has:

\n
    \n
  • Value: Internal identifier stored in frontmatter (e.g., "in-progress")
  • \n
  • Label: Display name shown in the interface (e.g., "In Progress")
  • \n
  • Color: Visual indicator color
  • \n
  • Icon: Optional icon identifier
  • \n
  • Completed: Whether this status represents a finished task
  • \n
  • Skip when cycling: Exclude this status from the click-to-cycle order on task cards while keeping it available in menus, suggestions, and direct edits
  • \n
  • Next status: Optional override for the status used when cycling forward from this status; leave it set to the status order to use the normal sequence
  • \n
  • Auto-archive: Automatically archive tasks after a delay (1-1440 minutes)
  • \n
\n

Status cards support drag-and-drop reordering.

\n

Use the Value field as the stable stored identifier and the Label field for display text with spaces or title casing. TaskNotes status menus and cycling use the configured order, and TaskNotes Kanban views can preserve dragged column order. Native Bases grouping/sorting may still order status values alphabetically by their stored Value, so use prefixes such as 1-open, 2-doing, 3-done if you need predictable native Bases order.

\n

Boolean Status Values#

\n

TaskNotes supports using boolean values (true and false) as status values, which integrates with Obsidian's native checkbox property format:

\n
    \n
  • When you set a task's status to "true" or "false" (case-insensitive), TaskNotes automatically converts it to a boolean in frontmatter
  • \n
  • When reading tasks with boolean status values from frontmatter, they are converted back to the strings "true" or "false"
  • \n
  • This allows you to use Obsidian's native checkbox property toggles in the Properties panel while maintaining compatibility with TaskNotes
  • \n
\n

Example:

\n
---\nstatus: true    # Boolean checkbox in Obsidian\n---\n

Priority#

\n

Task priority level. Configuration options:

\n
    \n
  • Property key: Frontmatter field name (default: priority)
  • \n
  • Default: Default priority for new tasks (can be set to "No default")
  • \n
  • NLP trigger: Character that triggers priority parsing (default: !, disabled by default)
  • \n
  • Priority Values: Expandable section containing individual priority cards
  • \n
\n

Each priority value has:

\n
    \n
  • Value: Internal identifier stored in frontmatter (e.g., "high")
  • \n
  • Label: Display name shown in the interface (e.g., "High Priority")
  • \n
  • Color: Visual indicator color
  • \n
\n

Priority cards support drag-and-drop reordering.\nStatus and priority values are stored in frontmatter; renaming them later may require migration of existing task files.

\n
\n

Note for Bases plugin users: Obsidian's Bases plugin sorts priorities alphabetically by their Value. To control sort order, name values to sort alphabetically in the desired order:

\n
    \n
  • Example: 1-urgent, 2-high, 3-medium, 4-normal, 5-low
  • \n
  • Or: a-urgent, b-high, c-medium, d-normal, e-low
  • \n
\n
\n

Date Properties#

\n

Due Date#

\n

When the task must be completed. Configuration options:

\n
    \n
  • Property key: Frontmatter field name (default: due)
  • \n
  • Default: Default due date for new tasks (None, Today, Tomorrow, Next Week)
  • \n
\n

Scheduled Date#

\n

When to work on the task. Configuration options:

\n
    \n
  • Property key: Frontmatter field name (default: scheduled)
  • \n
  • Default: Default scheduled date for new tasks (None, Today, Tomorrow, Next Week)
  • \n
\n

When you use Convert current note to task, this default is also applied if the source note does not already have scheduled frontmatter. Choose None to keep converted notes unscheduled by default.

\n

due tracks commitment deadlines, while scheduled tracks intended execution time.

\n

Organization Properties#

\n

Contexts#

\n

Where or how the task can be done. Configuration options:

\n
    \n
  • Property key: Frontmatter field name (default: contexts)
  • \n
  • Default: Comma-separated list of default contexts (e.g., @home, @work)
  • \n
  • NLP trigger: Character that triggers context parsing (default: @)
  • \n
\n

Projects#

\n

Projects the task belongs to. Configuration options:

\n
    \n
  • Property key: Frontmatter field name (default: projects)
  • \n
  • Default projects: Select project notes to automatically link to new tasks
  • \n
  • Use active note for new tasks: Automatically link the active note as a project when opening task creation from the command palette or ribbon
  • \n
  • Use parent note for inline/instant conversion: Automatically link the source note as a project when using inline task creation or instant task conversion
  • \n
  • NLP trigger: Character that triggers project parsing (default: +)
  • \n
  • Autosuggest Filters: Expandable section to filter which notes appear in project suggestions
  • \n
  • Customize Display: Expandable section to configure how project suggestions appear
  • \n
\n

Autosuggest Filters#

\n

Control which notes appear when selecting projects:

\n
    \n
  • Required tags: Comma-separated list of tags (shows notes with ANY of these tags)
  • \n
  • Include folders: Comma-separated list of folder paths (shows notes in ANY of these folders)
  • \n
  • Required property key: Frontmatter property that must exist
  • \n
  • Required property value: Expected value for the property (optional)\nThese filters reduce suggestion noise in large vaults.
  • \n
\n

A "Filters On" badge appears when any filters are configured.

\n

Customize Display#

\n

Configure project suggestion appearance:

\n
    \n
  • Enable fuzzy matching: Allow typos and partial matches in project search
  • \n
  • Row 1, 2, 3: Configure up to 3 lines of information for each project suggestion
  • \n
\n

Tags#

\n

Obsidian tags for categorization. Configuration options:

\n
    \n
  • Default: Comma-separated list of default tags (without #)
  • \n
  • NLP trigger: Character that triggers tag parsing (default: #)
  • \n
\n

Note: Tags use native Obsidian tags and do not have a separate property key setting.

\n

Task Details#

\n

Time Estimate#

\n

Estimated time to complete the task. Configuration options:

\n
    \n
  • Property key: Frontmatter field name (default: timeEstimate)
  • \n
  • Default: Default time estimate in minutes (0 = no default)
  • \n
\n

Recurrence#

\n

Pattern for repeating tasks. Configuration options:

\n
    \n
  • Property key: Frontmatter field name (default: recurrence)
  • \n
  • Default: Default recurrence pattern (None, Daily, Weekly, Monthly, Yearly)
  • \n
\n

Recurring tasks also use the Recurrence anchor metadata property to decide whether the series advances from the scheduled date or the completion date. Materialized occurrence note controls live on each recurring task's context menu under Recurrence → Occurrence notes rather than as a global default.

\n

Reminders#

\n

Notifications before task deadlines. Configuration options:

\n
    \n
  • Property key: Frontmatter field name (default: reminders)
  • \n
  • Default Reminders: Expandable section containing default reminder cards
  • \n
\n

Each default reminder can be:

\n

Relative reminders (triggered relative to due or scheduled date):

\n
    \n
  • Anchor date (due date or scheduled date)
  • \n
  • Offset amount and unit (minutes, hours, days)
  • \n
  • Direction (before or after)
  • \n
  • Description
  • \n
\n

Absolute reminders (triggered at specific times):

\n
    \n
  • Date
  • \n
  • Time
  • \n
  • Description
  • \n
\n

Metadata Properties#

\n

These properties are system-managed and typically only require property key configuration:

\n
    \n
  • Date Created: When the task was created
  • \n
  • Date Modified: When the task was last modified
  • \n
  • Completed Date: When the task was completed
  • \n
  • Archive Tag: Tag used to mark archived tasks
  • \n
  • Time Entries: Time tracking entries for the task
  • \n
  • Complete Instances: Completion history for recurring tasks
  • \n
  • Skipped Instances: Skip history for recurring tasks
  • \n
  • Recurrence Anchor: Whether recurring progression is based on scheduled date or completion date
  • \n
  • Blocked By: Tasks that must be completed first
  • \n
\n

Materialized occurrence notes also use system-managed frontmatter fields such as recurrence_parent, occurrence_date, occurrence_materialization, occurrence_next_trigger, and optional occurrence template/horizon fields. Occurrence notes inherit parent planning metadata when they are created, but keep their own status, completion date, and time entries. These fields are documented in the Property Types Reference and are normally changed through recurrence and occurrence-note controls instead of by hand.

\n

Feature Properties#

\n

These properties are used by specific TaskNotes features and are not stored in task frontmatter:

\n
    \n
  • Pomodoros: Property key for Pomodoro session counts. When Pomodoro data storage is set to "Daily notes", this property is written to daily notes rather than task files.
  • \n
  • ICS Event ID: Property key for calendar event identifiers. Added to notes created from ICS calendar events to link them back to the source event.
  • \n
  • ICS Event Tag: Property key for calendar event tags. Added to notes created from ICS calendar events for identification.
  • \n
\n

Custom User Fields#

\n

Define custom frontmatter properties to appear as filter options across views. Configuration options for each field:

\n
    \n
  • Display Name: How the field appears in the UI
  • \n
  • Property Key: The frontmatter property name
  • \n
  • Type: Data type (text, number, boolean, date, or list)
  • \n
  • Default Value: Pre-fill value for new tasks (format varies by type)
  • \n
  • NLP trigger: Toggle and character for natural language parsing
  • \n
  • Autosuggest Filters: Filter which files appear when using [[ wikilink autocomplete\nCustom fields are most maintainable when they map to repeated workflow decisions (for example effort, owner, or client).
  • \n
\n\n

Use a Text custom field for a single link and a List custom field for multiple links. Task cards render [[wikilinks]], [label](https://example.com), <https://example.com>, and bare https://example.com values as clickable links.

\n

Autosuggest filters work with text and list fields when entering [[ wikilinks, so a field such as Related Note can suggest only files from a chosen folder or tag.

\n

Default Values#

\n

Each field type has a different input format for default values:

\n
    \n
  • Text: Enter the default text value
  • \n
  • Number: Enter the default number
  • \n
  • Boolean: Toggle switch to set default checked/unchecked state
  • \n
  • Date: Select from presets (None, Today, Tomorrow, Next Week)
  • \n
  • List: Enter comma-separated default values
  • \n
\n

Default values are applied when creating tasks via:

\n
    \n
  • Task creation modal
  • \n
  • Instant task conversion
  • \n
  • "Create or open task" command
  • \n
  • HTTP API (when using task creation defaults)
  • \n
\n

Autosuggestion Filters#

\n

Each custom field can configure filters to control which files appear in wikilink suggestions:

\n
    \n
  • Required tags: Comma-separated list of tags (shows files with ANY of these tags)
  • \n
  • Include folders: Comma-separated list of folder paths (shows files in ANY of these folders)
  • \n
  • Required property key: Frontmatter property that must exist
  • \n
  • Required property value: Expected value for the property (optional)
  • \n
\n

A "Filters On" badge appears when filters are configured.

\n

See User Fields Feature Documentation for detailed examples.

\n","text":"This tab configures all task properties. Each property is displayed as a card containing its configuration options. Looking for property type documentation?See the Property Types Reference for detailed documentation on the expected data types (text, list, date, etc.) for each frontmatter property. Property Card Structure# Each property card contains: Property key: The frontmatter field name used to store this property Default: The default value applied to new tasks (where applicable) NLP trigger: Toggle and character configuration for natural language parsing (where applicable) Property-specific settings: Additional configuration options specific to that property This tab defines the task schema used by creation flows, NLP parsing, views, and API payloads. Property keys are YAML/frontmatter keys. TaskNotes can read and write keys that contain spaces or punctuation, but hand-written Bases filters and formulas must reference those keys with bracket syntax, for example note[\"TN-status\"], rather than dot syntax such as note.TN-status. Core Properties# Title# The task title property. Configuration options: Property key: Frontmatter field name (default: title) Store title in filename: When enabled, the task title is stored in the filename instead of frontmatter. The filename updates when the title changes. Filename format: When \"Store title in filename\" is disabled, choose how filenames are generated: Title-based Zettelkasten-style Timestamp-based UUID v4 Custom template Custom template: Define a custom filename pattern using variables (shown when \"custom\" format is selected) Status# Task completion state. Configuration options: Property key: Frontmatter field name (default: status) Default: Default status for new tasks NLP trigger: Character that triggers status parsing (default: *) Status Values: Expandable section containing individual status cards Each status value has: Value: Internal identifier stored in frontmatter (e.g., \"in-progress\") Label: Display name shown in the interface (e.g., \"In Progress\") Color: Visual indicator color Icon: Optional icon identifier Completed: Whether this status represents a finished task Skip when cycling: Exclude this status from the click-to-cycle order on task cards while keeping it available in menus, suggestions, and direct edits Next status: Optional override for the status used when cycling forward from this status; leave it set to the status order to use the normal sequence Auto-archive: Automatically archive tasks after a delay (1-1440 minutes) Status cards support drag-and-drop reordering. Use the Value field as the stable stored identifier and the Label field for display text with spaces or title casing. TaskNotes status menus and cycling use the configured order, and TaskNotes Kanban views can preserve dragged column order. Native Bases grouping/sorting may still order status values alphabetically by their stored Value, so use prefixes such as 1-open, 2-doing, 3-done if you need predictable native Bases order. Boolean Status Values# TaskNotes supports using boolean values (true and false) as status values, which integrates with Obsidian's native checkbox property format: When you set a task's status to \"true\" or \"false\" (case-insensitive), TaskNotes automatically converts it to a boolean in frontmatter When reading tasks with boolean status values from frontmatter, they are converted back to the strings \"true\" or \"false\" This allows you to use Obsidian's native checkbox property toggles in the Properties panel while maintaining compatibility with TaskNotes Example: --- status: true # Boolean checkbox in Obsidian --- Priority# Task priority level. Configuration options: Property key: Frontmatter field name (default: priority) Default: Default priority for new tasks (can be set to \"No default\") NLP trigger: Character that triggers priority parsing (default: !, disabled by default) Priority Values: Expandable section containing individual priority cards Each priority value has: Value: Internal identifier stored in frontmatter (e.g., \"high\") Label: Display name shown in the interface (e.g., \"High Priority\") Color: Visual indicator color Priority cards support drag-and-drop reordering. Status and priority values are stored in frontmatter; renaming them later may require migration of existing task files. Note for Bases plugin users: Obsidian's Bases plugin sorts priorities alphabetically by their Value. To control sort order, name values to sort alphabetically in the desired order: Example: 1-urgent, 2-high, 3-medium, 4-normal, 5-low Or: a-urgent, b-high, c-medium, d-normal, e-low Date Properties# Due Date# When the task must be completed. Configuration options: Property key: Frontmatter field name (default: due) Default: Default due date for new tasks (None, Today, Tomorrow, Next Week) Scheduled Date# When to work on the task. Configuration options: Property key: Frontmatter field name (default: scheduled) Default: Default scheduled date for new tasks (None, Today, Tomorrow, Next Week) When you use Convert current note to task, this default is also applied if the source note does not already have scheduled frontmatter. Choose None to keep converted notes unscheduled by default. due tracks commitment deadlines, while scheduled tracks intended execution time. Organization Properties# Contexts# Where or how the task can be done. Configuration options: Property key: Frontmatter field name (default: contexts) Default: Comma-separated list of default contexts (e.g., @home, @work) NLP trigger: Character that triggers context parsing (default: @) Projects# Projects the task belongs to. Configuration options: Property key: Frontmatter field name (default: projects) Default projects: Select project notes to automatically link to new tasks Use active note for new tasks: Automatically link the active note as a project when opening task creation from the command palette or ribbon Use parent note for inline/instant conversion: Automatically link the source note as a project when using inline task creation or instant task conversion NLP trigger: Character that triggers project parsing (default: +) Autosuggest Filters: Expandable section to filter which notes appear in project suggestions Customize Display: Expandable section to configure how project suggestions appear Autosuggest Filters# Control which notes appear when selecting projects: Required tags: Comma-separated list of tags (shows notes with ANY of these tags) Include folders: Comma-separated list of folder paths (shows notes in ANY of these folders) Required property key: Frontmatter property that must exist Required property value: Expected value for the property (optional) These filters reduce suggestion noise in large vaults. A \"Filters On\" badge appears when any filters are configured. Customize Display# Configure project suggestion appearance: Enable fuzzy matching: Allow typos and partial matches in project search Row 1, 2, 3: Configure up to 3 lines of information for each project suggestion Tags# Obsidian tags for categorization. Configuration options: Default: Comma-separated list of default tags (without #) NLP trigger: Character that triggers tag parsing (default: #) Note: Tags use native Obsidian tags and do not have a separate property key setting. Task Details# Time Estimate# Estimated time to complete the task. Configuration options: Property key: Frontmatter field name (default: timeEstimate) Default: Default time estimate in minutes (0 = no default) Recurrence# Pattern for repeating tasks. Configuration options: Property key: Frontmatter field name (default: recurrence) Default: Default recurrence pattern (None, Daily, Weekly, Monthly, Yearly) Recurring tasks also use the Recurrence anchor metadata property to decide whether the series advances from the scheduled date or the completion date. Materialized occurrence note controls live on each recurring task's context menu under Recurrence → Occurrence notes rather than as a global default. Reminders# Notifications before task deadlines. Configuration options: Property key: Frontmatter field name (default: reminders) Default Reminders: Expandable section containing default reminder cards Each default reminder can be: Relative reminders (triggered relative to due or scheduled date): Anchor date (due date or scheduled date) Offset amount and unit (minutes, hours, days) Direction (before or after) Description Absolute reminders (triggered at specific times): Date Time Description Metadata Properties# These properties are system-managed and typically only require property key configuration: Date Created: When the task was created Date Modified: When the task was last modified Completed Date: When the task was completed Archive Tag: Tag used to mark archived tasks Time Entries: Time tracking entries for the task Complete Instances: Completion history for recurring tasks Skipped Instances: Skip history for recurring tasks Recurrence Anchor: Whether recurring progression is based on scheduled date or completion date Blocked By: Tasks that must be completed first Materialized occurrence notes also use system-managed frontmatter fields such as recurrence_parent, occurrence_date, occurrence_materialization, occurrence_next_trigger, and optional occurrence template/horizon fields. Occurrence notes inherit parent planning metadata when they are created, but keep their own status, completion date, and time entries. These fields are documented in the Property Types Reference and are normally changed through recurrence and occurrence-note controls instead of by hand. Feature Properties# These properties are used by specific TaskNotes features and are not stored in task frontmatter: Pomodoros: Property key for Pomodoro session counts. When Pomodoro data storage is set to \"Daily notes\", this property is written to daily notes rather than task files. ICS Event ID: Property key for calendar event identifiers. Added to notes created from ICS calendar events to link them back to the source event. ICS Event Tag: Property key for calendar event tags. Added to notes created from ICS calendar events for identification. Custom User Fields# Define custom frontmatter properties to appear as filter options across views. Configuration options for each field: Display Name: How the field appears in the UI Property Key: The frontmatter property name Type: Data type (text, number, boolean, date, or list) Default Value: Pre-fill value for new tasks (format varies by type) NLP trigger: Toggle and character for natural language parsing Autosuggest Filters: Filter which files appear when using [[ wikilink autocomplete Custom fields are most maintainable when they map to repeated workflow decisions (for example effort, owner, or client). Link Values# Use a Text custom field for a single link and a List custom field for multiple links. Task cards render [[wikilinks]], [label](https://example.com), , and bare https://example.com values as clickable links. Autosuggest filters work with text and list fields when entering [[ wikilinks, so a field such as Related Note can suggest only files from a chosen folder or tag. Default Values# Each field type has a different input format for default values: Text: Enter the default text value Number: Enter the default number Boolean: Toggle switch to set default checked/unchecked state Date: Select from presets (None, Today, Tomorrow, Next Week) List: Enter comma-separated default values Default values are applied when creating tasks via: Task creation modal Instant task conversion \"Create or open task\" command HTTP API (when using task creation defaults) Autosuggestion Filters# Each custom field can configure filters to control which files appear in wikilink suggestions: Required tags: Comma-separated list of tags (shows files with ANY of these tags) Include folders: Comma-separated list of folder paths (shows files in ANY of these folders) Required property key: Frontmatter property that must exist Required property value: Expected value for the property (optional) A \"Filters On\" badge appears when filters are configured. See User Fields Feature Documentation for detailed examples."},{"route":"/obsidian/troubleshooting/","title":"Troubleshooting","description":"Common issues and solutions for TaskNotes.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/troubleshooting.md","namespace":"obsidian","relativePath":"troubleshooting.md","raw":"# Troubleshooting\n\nCommon issues and solutions for TaskNotes.\n\nWhen debugging, start with one affected task and one affected view. Record the TaskNotes version from the plugin list, the Obsidian version from **About**, the operating system, and whether the problem also occurs in a fresh default Base.\n\n## First checks\n\n1. Confirm Obsidian meets the current [version requirement](reference/compatibility.md) and **Bases** is enabled.\n2. Open the affected task as Markdown and validate the `---` frontmatter delimiters and indentation.\n3. Confirm the task matches **Settings → TaskNotes → General → Task identification** and is not in an excluded folder.\n4. Run **TaskNotes: Refresh cache** from the command palette.\n5. Close and reopen the affected `.base` file.\n6. Restart Obsidian only after the targeted checks above.\n\nIf the issue remains, enable **Settings → TaskNotes → Features → Debug logging**, reproduce it once, and inspect the developer console with `Ctrl/Cmd + Shift + I`. Disable debug logging after collecting the relevant entries.\n\n## Bases and Views (v4)\n\n### Views Not Loading\n\n**Symptoms**: TaskNotes views show errors or don't display tasks\n\nFirst confirm Bases is enabled (`Settings -> Core Plugins -> Bases`), then restart Obsidian once. If views are still missing, verify `.base` files exist in `TaskNotes/Views/`. If needed, regenerate defaults from `Settings -> TaskNotes -> General -> Views & base files` (`Create files`).\n\n### Commands Open Wrong Files\n\n**Symptoms**: Ribbon icons or commands open unexpected files\n\nCheck command mappings in `Settings -> TaskNotes -> General` (`View Commands`). Reset mappings that were changed unintentionally, then verify each referenced `.base` file exists at the configured path.\n\n## Common Issues\n\n### Tasks Not Appearing in Views\n\n**Symptoms**: Tasks you've created don't show up in TaskNotes views\n\nFollow this decision tree:\n\n1. **Does Quick actions for current task work on the note?**\n - **No:** compare its tag or identification property with **General → Task identification**.\n - **Yes:** task recognition works; continue to the Base filter.\n2. **Is the note inside an excluded folder?**\n - **Yes:** move it or update **Excluded folders**.\n - **No:** continue.\n3. **Does a newly generated default task Base show it?**\n - **Yes:** the custom Base has a stale property name or filter.\n - **No:** run **TaskNotes: Refresh cache** and validate the frontmatter.\n4. **Did identification or field mapping change recently?**\n - **Yes:** update the default Base files or edit their filters and columns. Generated files do not update automatically when settings change.\n\n### Task Link Widgets Not Working\n\n**Symptoms**: Links to task files appear as normal wikilinks instead of interactive widgets\n\nCheck that **Task link overlay** is enabled, then verify linked files are actually recognized as tasks (matching tag/property configuration). Links to normal notes will render as normal links by design.\n\n### Instant Conversion Buttons Missing\n\n**Symptoms**: Convert buttons don't appear next to checkbox tasks\n\nInstant convert buttons only appear when the feature is enabled, in edit mode, and with cursor proximity to list items. Enable the feature, switch from reading mode to edit mode, and place the cursor near the target checkbox.\n\n### Calendar View Performance Issues\n\n**Symptoms**: Calendar views are slow or unresponsive\n\nReduce visible event layers first (scheduled/due/recurring/time entries), then increase ICS refresh intervals and shorten displayed date ranges. If slowness persists, apply the general performance guidance below.\n\n### Natural Language Parsing Not Working\n\n**Symptoms**: Natural language input doesn't extract expected task properties\n\nEnable NLP in `Settings -> TaskNotes -> Features`, then verify your trigger characters (`@`, `#`, `!` by default) and any custom status/priority mappings. If parsing still seems inconsistent, compare input against the syntax in [NLP API](nlp-api.md).\n\n### Time Tracking Issues\n\n**Symptoms**: Time tracking doesn't start/stop properly or data is lost\n\nMost tracking issues come from overlapping sessions, interrupted shutdowns, or save failures. Stop active sessions before starting new ones, confirm files are writable, and restart interrupted sessions. If needed, repair malformed time entries directly in frontmatter.\n\n## Data Issues\n\n### Corrupted Task Files\n\n**Symptoms**: Tasks appear broken or cause errors in views\n\nOpen the task file directly and validate frontmatter syntax. Quote values that include special characters, validate YAML if necessary, and restore from backup for severe corruption.\n\n### Missing Task Properties\n\n**Symptoms**: Tasks missing expected properties or using default values unexpectedly\n\nCheck field mappings first, then confirm Task Defaults. If properties are absent on older notes, add them manually or re-save through TaskNotes so current mapping rules are applied.\n\n### Date Format Issues\n\n**Symptoms**: Dates not displaying correctly or causing parse errors\n\nUse supported formats (`YYYY-MM-DD` or `YYYY-MM-DDTHH:MM:SS`), quote where needed, and re-enter problematic dates via TaskNotes date pickers to normalize formatting and timezone handling.\n\n## Performance Troubleshooting\n\n### Slow View Loading\n\nTo improve loading times, reduce external calendar subscriptions, increase ICS refresh intervals, exclude large folders, and disable event types you do not use.\n\n## External Calendar Issues\n\n### OAuth Calendar Not Connecting\n\n**Symptoms**: Google Calendar or Microsoft Outlook won't connect\n\nVerify credentials and loopback redirect configuration (`127.0.0.1` with dynamic local port), ensure app publication/test-user access is correct, and retry after disconnecting. Also check popup blockers. For provider-specific setup details, use [Calendar Setup](calendar-setup.md).\n\n### OAuth Calendar Not Syncing\n\n**Symptoms**: Connected calendar shows old events or doesn't update\n\nRun manual refresh, check last-sync timestamps, reconnect if needed, and verify events exist in the source provider before debugging TaskNotes behavior.\n\n### ICS Subscriptions Not Loading\n\n**Symptoms**: ICS calendar events don't appear in calendar views\n\nConfirm the ICS URL/file is reachable, run manual refresh, validate the feed format, and inspect subscription status errors for provider-side failures.\n\n### Calendar Sync Problems\n\n**Symptoms**: External calendar changes not reflected in TaskNotes\n\nCheck refresh intervals and force a manual refresh first. If source data is current but TaskNotes remains stale, remove and re-add the subscription to clear cached state.\n\n## Getting Help\n\n### Reporting Issues\n\nReport bugs on [GitHub Issues](https://github.com/callumalpass/tasknotes/issues). Include:\n\n- Exact TaskNotes and Obsidian versions\n- Operating system\n- The smallest affected task frontmatter with private values removed\n- The `.base` path and whether a regenerated default has the same problem\n- Steps to reproduce from a fresh Obsidian start\n- Relevant console errors and TaskNotes debug entries\n- Screenshots if relevant\n\n### Configuration Reset\n\nUse a reversible reset only after the checks above:\n\n1. Close Obsidian\n2. Navigate to `.obsidian/plugins/tasknotes/`\n3. Copy `data.json` to a backup outside the plugin directory\n4. Rename the original to `data.json.backup-YYYY-MM-DD`\n5. Restart Obsidian\n\n!!! warning\n A reset affects settings, status and priority configurations, integration state, saved views, and plugin-stored Pomodoro history. Keep the backup until the problem is resolved. Restore it only while Obsidian is closed.\n\nFor full restore and uninstall guidance, see [Backup, restore, and removal](guides/backup-recovery.md).\n","aliases":["/troubleshooting/"],"toc":[{"level":2,"id":"first-checks","text":"First checks"},{"level":2,"id":"bases-and-views-v4","text":"Bases and Views (v4)"},{"level":3,"id":"views-not-loading","text":"Views Not Loading"},{"level":3,"id":"commands-open-wrong-files","text":"Commands Open Wrong Files"},{"level":2,"id":"common-issues","text":"Common Issues"},{"level":3,"id":"tasks-not-appearing-in-views","text":"Tasks Not Appearing in Views"},{"level":3,"id":"task-link-widgets-not-working","text":"Task Link Widgets Not Working"},{"level":3,"id":"instant-conversion-buttons-missing","text":"Instant Conversion Buttons Missing"},{"level":3,"id":"calendar-view-performance-issues","text":"Calendar View Performance Issues"},{"level":3,"id":"natural-language-parsing-not-working","text":"Natural Language Parsing Not Working"},{"level":3,"id":"time-tracking-issues","text":"Time Tracking Issues"},{"level":2,"id":"data-issues","text":"Data Issues"},{"level":3,"id":"corrupted-task-files","text":"Corrupted Task Files"},{"level":3,"id":"missing-task-properties","text":"Missing Task Properties"},{"level":3,"id":"date-format-issues","text":"Date Format Issues"},{"level":2,"id":"performance-troubleshooting","text":"Performance Troubleshooting"},{"level":3,"id":"slow-view-loading","text":"Slow View Loading"},{"level":2,"id":"external-calendar-issues","text":"External Calendar Issues"},{"level":3,"id":"oauth-calendar-not-connecting","text":"OAuth Calendar Not Connecting"},{"level":3,"id":"oauth-calendar-not-syncing","text":"OAuth Calendar Not Syncing"},{"level":3,"id":"ics-subscriptions-not-loading","text":"ICS Subscriptions Not Loading"},{"level":3,"id":"calendar-sync-problems","text":"Calendar Sync Problems"},{"level":2,"id":"getting-help","text":"Getting Help"},{"level":3,"id":"reporting-issues","text":"Reporting Issues"},{"level":3,"id":"configuration-reset","text":"Configuration Reset"}],"html":"

Common issues and solutions for TaskNotes.

\n

When debugging, start with one affected task and one affected view. Record the TaskNotes version from the plugin list, the Obsidian version from About, the operating system, and whether the problem also occurs in a fresh default Base.

\n

First checks#

\n
    \n
  1. Confirm Obsidian meets the current version requirement and Bases is enabled.
  2. \n
  3. Open the affected task as Markdown and validate the --- frontmatter delimiters and indentation.
  4. \n
  5. Confirm the task matches Settings → TaskNotes → General → Task identification and is not in an excluded folder.
  6. \n
  7. Run TaskNotes: Refresh cache from the command palette.
  8. \n
  9. Close and reopen the affected .base file.
  10. \n
  11. Restart Obsidian only after the targeted checks above.
  12. \n
\n

If the issue remains, enable Settings → TaskNotes → Features → Debug logging, reproduce it once, and inspect the developer console with Ctrl/Cmd + Shift + I. Disable debug logging after collecting the relevant entries.

\n

Bases and Views (v4)#

\n

Views Not Loading#

\n

Symptoms: TaskNotes views show errors or don't display tasks

\n

First confirm Bases is enabled (Settings -> Core Plugins -> Bases), then restart Obsidian once. If views are still missing, verify .base files exist in TaskNotes/Views/. If needed, regenerate defaults from Settings -> TaskNotes -> General -> Views & base files (Create files).

\n

Commands Open Wrong Files#

\n

Symptoms: Ribbon icons or commands open unexpected files

\n

Check command mappings in Settings -> TaskNotes -> General (View Commands). Reset mappings that were changed unintentionally, then verify each referenced .base file exists at the configured path.

\n

Common Issues#

\n

Tasks Not Appearing in Views#

\n

Symptoms: Tasks you've created don't show up in TaskNotes views

\n

Follow this decision tree:

\n
    \n
  1. Does Quick actions for current task work on the note?
      \n
    • No: compare its tag or identification property with General → Task identification.
    • \n
    • Yes: task recognition works; continue to the Base filter.
    • \n
    \n
  2. \n
  3. Is the note inside an excluded folder?
      \n
    • Yes: move it or update Excluded folders.
    • \n
    • No: continue.
    • \n
    \n
  4. \n
  5. Does a newly generated default task Base show it?
      \n
    • Yes: the custom Base has a stale property name or filter.
    • \n
    • No: run TaskNotes: Refresh cache and validate the frontmatter.
    • \n
    \n
  6. \n
  7. Did identification or field mapping change recently?
      \n
    • Yes: update the default Base files or edit their filters and columns. Generated files do not update automatically when settings change.
    • \n
    \n
  8. \n
\n\n

Symptoms: Links to task files appear as normal wikilinks instead of interactive widgets

\n

Check that Task link overlay is enabled, then verify linked files are actually recognized as tasks (matching tag/property configuration). Links to normal notes will render as normal links by design.

\n

Instant Conversion Buttons Missing#

\n

Symptoms: Convert buttons don't appear next to checkbox tasks

\n

Instant convert buttons only appear when the feature is enabled, in edit mode, and with cursor proximity to list items. Enable the feature, switch from reading mode to edit mode, and place the cursor near the target checkbox.

\n

Calendar View Performance Issues#

\n

Symptoms: Calendar views are slow or unresponsive

\n

Reduce visible event layers first (scheduled/due/recurring/time entries), then increase ICS refresh intervals and shorten displayed date ranges. If slowness persists, apply the general performance guidance below.

\n

Natural Language Parsing Not Working#

\n

Symptoms: Natural language input doesn't extract expected task properties

\n

Enable NLP in Settings -> TaskNotes -> Features, then verify your trigger characters (@, #, ! by default) and any custom status/priority mappings. If parsing still seems inconsistent, compare input against the syntax in NLP API.

\n

Time Tracking Issues#

\n

Symptoms: Time tracking doesn't start/stop properly or data is lost

\n

Most tracking issues come from overlapping sessions, interrupted shutdowns, or save failures. Stop active sessions before starting new ones, confirm files are writable, and restart interrupted sessions. If needed, repair malformed time entries directly in frontmatter.

\n

Data Issues#

\n

Corrupted Task Files#

\n

Symptoms: Tasks appear broken or cause errors in views

\n

Open the task file directly and validate frontmatter syntax. Quote values that include special characters, validate YAML if necessary, and restore from backup for severe corruption.

\n

Missing Task Properties#

\n

Symptoms: Tasks missing expected properties or using default values unexpectedly

\n

Check field mappings first, then confirm Task Defaults. If properties are absent on older notes, add them manually or re-save through TaskNotes so current mapping rules are applied.

\n

Date Format Issues#

\n

Symptoms: Dates not displaying correctly or causing parse errors

\n

Use supported formats (YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS), quote where needed, and re-enter problematic dates via TaskNotes date pickers to normalize formatting and timezone handling.

\n

Performance Troubleshooting#

\n

Slow View Loading#

\n

To improve loading times, reduce external calendar subscriptions, increase ICS refresh intervals, exclude large folders, and disable event types you do not use.

\n

External Calendar Issues#

\n

OAuth Calendar Not Connecting#

\n

Symptoms: Google Calendar or Microsoft Outlook won't connect

\n

Verify credentials and loopback redirect configuration (127.0.0.1 with dynamic local port), ensure app publication/test-user access is correct, and retry after disconnecting. Also check popup blockers. For provider-specific setup details, use Calendar Setup.

\n

OAuth Calendar Not Syncing#

\n

Symptoms: Connected calendar shows old events or doesn't update

\n

Run manual refresh, check last-sync timestamps, reconnect if needed, and verify events exist in the source provider before debugging TaskNotes behavior.

\n

ICS Subscriptions Not Loading#

\n

Symptoms: ICS calendar events don't appear in calendar views

\n

Confirm the ICS URL/file is reachable, run manual refresh, validate the feed format, and inspect subscription status errors for provider-side failures.

\n

Calendar Sync Problems#

\n

Symptoms: External calendar changes not reflected in TaskNotes

\n

Check refresh intervals and force a manual refresh first. If source data is current but TaskNotes remains stale, remove and re-add the subscription to clear cached state.

\n

Getting Help#

\n

Reporting Issues#

\n

Report bugs on GitHub Issues. Include:

\n
    \n
  • Exact TaskNotes and Obsidian versions
  • \n
  • Operating system
  • \n
  • The smallest affected task frontmatter with private values removed
  • \n
  • The .base path and whether a regenerated default has the same problem
  • \n
  • Steps to reproduce from a fresh Obsidian start
  • \n
  • Relevant console errors and TaskNotes debug entries
  • \n
  • Screenshots if relevant
  • \n
\n

Configuration Reset#

\n

Use a reversible reset only after the checks above:

\n
    \n
  1. Close Obsidian
  2. \n
  3. Navigate to .obsidian/plugins/tasknotes/
  4. \n
  5. Copy data.json to a backup outside the plugin directory
  6. \n
  7. Rename the original to data.json.backup-YYYY-MM-DD
  8. \n
  9. Restart Obsidian
  10. \n
\n\n

For full restore and uninstall guidance, see Backup, restore, and removal.

\n","text":"Common issues and solutions for TaskNotes. When debugging, start with one affected task and one affected view. Record the TaskNotes version from the plugin list, the Obsidian version from About, the operating system, and whether the problem also occurs in a fresh default Base. First checks# Confirm Obsidian meets the current version requirement and Bases is enabled. Open the affected task as Markdown and validate the --- frontmatter delimiters and indentation. Confirm the task matches Settings → TaskNotes → General → Task identification and is not in an excluded folder. Run TaskNotes: Refresh cache from the command palette. Close and reopen the affected .base file. Restart Obsidian only after the targeted checks above. If the issue remains, enable Settings → TaskNotes → Features → Debug logging, reproduce it once, and inspect the developer console with Ctrl/Cmd + Shift + I. Disable debug logging after collecting the relevant entries. Bases and Views (v4)# Views Not Loading# Symptoms: TaskNotes views show errors or don't display tasks First confirm Bases is enabled (Settings -> Core Plugins -> Bases), then restart Obsidian once. If views are still missing, verify .base files exist in TaskNotes/Views/. If needed, regenerate defaults from Settings -> TaskNotes -> General -> Views & base files (Create files). Commands Open Wrong Files# Symptoms: Ribbon icons or commands open unexpected files Check command mappings in Settings -> TaskNotes -> General (View Commands). Reset mappings that were changed unintentionally, then verify each referenced .base file exists at the configured path. Common Issues# Tasks Not Appearing in Views# Symptoms: Tasks you've created don't show up in TaskNotes views Follow this decision tree: Does Quick actions for current task work on the note? No: compare its tag or identification property with General → Task identification. Yes: task recognition works; continue to the Base filter. Is the note inside an excluded folder? Yes: move it or update Excluded folders. No: continue. Does a newly generated default task Base show it? Yes: the custom Base has a stale property name or filter. No: run TaskNotes: Refresh cache and validate the frontmatter. Did identification or field mapping change recently? Yes: update the default Base files or edit their filters and columns. Generated files do not update automatically when settings change. Task Link Widgets Not Working# Symptoms: Links to task files appear as normal wikilinks instead of interactive widgets Check that Task link overlay is enabled, then verify linked files are actually recognized as tasks (matching tag/property configuration). Links to normal notes will render as normal links by design. Instant Conversion Buttons Missing# Symptoms: Convert buttons don't appear next to checkbox tasks Instant convert buttons only appear when the feature is enabled, in edit mode, and with cursor proximity to list items. Enable the feature, switch from reading mode to edit mode, and place the cursor near the target checkbox. Calendar View Performance Issues# Symptoms: Calendar views are slow or unresponsive Reduce visible event layers first (scheduled/due/recurring/time entries), then increase ICS refresh intervals and shorten displayed date ranges. If slowness persists, apply the general performance guidance below. Natural Language Parsing Not Working# Symptoms: Natural language input doesn't extract expected task properties Enable NLP in Settings -> TaskNotes -> Features, then verify your trigger characters (@, #, ! by default) and any custom status/priority mappings. If parsing still seems inconsistent, compare input against the syntax in NLP API. Time Tracking Issues# Symptoms: Time tracking doesn't start/stop properly or data is lost Most tracking issues come from overlapping sessions, interrupted shutdowns, or save failures. Stop active sessions before starting new ones, confirm files are writable, and restart interrupted sessions. If needed, repair malformed time entries directly in frontmatter. Data Issues# Corrupted Task Files# Symptoms: Tasks appear broken or cause errors in views Open the task file directly and validate frontmatter syntax. Quote values that include special characters, validate YAML if necessary, and restore from backup for severe corruption. Missing Task Properties# Symptoms: Tasks missing expected properties or using default values unexpectedly Check field mappings first, then confirm Task Defaults. If properties are absent on older notes, add them manually or re-save through TaskNotes so current mapping rules are applied. Date Format Issues# Symptoms: Dates not displaying correctly or causing parse errors Use supported formats (YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS), quote where needed, and re-enter problematic dates via TaskNotes date pickers to normalize formatting and timezone handling. Performance Troubleshooting# Slow View Loading# To improve loading times, reduce external calendar subscriptions, increase ICS refresh intervals, exclude large folders, and disable event types you do not use. External Calendar Issues# OAuth Calendar Not Connecting# Symptoms: Google Calendar or Microsoft Outlook won't connect Verify credentials and loopback redirect configuration (127.0.0.1 with dynamic local port), ensure app publication/test-user access is correct, and retry after disconnecting. Also check popup blockers. For provider-specific setup details, use Calendar Setup. OAuth Calendar Not Syncing# Symptoms: Connected calendar shows old events or doesn't update Run manual refresh, check last-sync timestamps, reconnect if needed, and verify events exist in the source provider before debugging TaskNotes behavior. ICS Subscriptions Not Loading# Symptoms: ICS calendar events don't appear in calendar views Confirm the ICS URL/file is reachable, run manual refresh, validate the feed format, and inspect subscription status errors for provider-side failures. Calendar Sync Problems# Symptoms: External calendar changes not reflected in TaskNotes Check refresh intervals and force a manual refresh first. If source data is current but TaskNotes remains stale, remove and re-add the subscription to clear cached state. Getting Help# Reporting Issues# Report bugs on GitHub Issues. Include: Exact TaskNotes and Obsidian versions Operating system The smallest affected task frontmatter with private values removed The .base path and whether a regenerated default has the same problem Steps to reproduce from a fresh Obsidian start Relevant console errors and TaskNotes debug entries Screenshots if relevant Configuration Reset# Use a reversible reset only after the checks above: Close Obsidian Navigate to .obsidian/plugins/tasknotes/ Copy data.json to a backup outside the plugin directory Rename the original to data.json.backup-YYYY-MM-DD Restart Obsidian WarningA reset affects settings, status and priority configurations, integration state, saved views, and plugin-stored Pomodoro history. Keep the backup until the problem is resolved. Restore it only while Obsidian is closed. For full restore and uninstall guidance, see Backup, restore, and removal."},{"route":"/obsidian/views/","title":"Views","description":"TaskNotes provides multiple views for managing tasks and tracking productivity. All task-focused views operate as .base files located in the TaskNotes/Views/ directory and requi...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/views.md","namespace":"obsidian","relativePath":"views.md","raw":"# Views\n\nTaskNotes provides multiple views for managing tasks and tracking productivity. All task-focused views operate as `.base` files located in the `TaskNotes/Views/` directory and require Obsidian's Bases core plugin to be enabled.\n\n\nFor details on Bases integration and how to enable it, see [Core Concepts](core-concepts.md#bases-integration). For view templates and configuration examples, see [Default Base Templates](views/default-base-templates.md).\n\n## Task-Focused Views\n\nTask-focused views are different entry points into the same underlying task notes. The [Task List View](views/task-list.md) is a common starting view for day-to-day planning because it exposes filters, sorting, and grouping in list format.\n\nWhen you want workflow by status, [Kanban View](views/kanban-view.md) organizes cards into columns and can optionally add swimlanes for an extra organizational layer. [Calendar Views](views/calendar-views.md) are useful when schedule and timing matter more than backlog shape, with month/week/day/year/list modes plus drag-and-drop scheduling and time-block support.\n\n[Agenda View](views/agenda-view.md) is a preconfigured list-oriented calendar layout designed for short-horizon planning, while [MiniCalendar View](views/calendar-views.md#mini-calendar-view) gives a compact month heatmap and fast keyboard navigation.\n\n![Task List view](assets/views-tasks-list.png)\n\n![Calendar week view](assets/views-calendar-week.png)\n\n## Productivity-Focused Views\n\nThese views support time management and work tracking.\n\n[Pomodoro View](views/pomodoro-view.md) supports focused intervals directly inside Obsidian, and [Pomodoro Stats View](views/pomodoro-view.md#pomodoro-stats-view) summarizes completed sessions so you can see pace and consistency over time.\n\n![Pomodoro view](assets/feature-pomodoro-timer.png)\n\nScreenshots in this section are captured via the Playwright docs suite (`npm run e2e:docs`).\n","aliases":["/views/"],"toc":[{"level":2,"id":"task-focused-views","text":"Task-Focused Views"},{"level":2,"id":"productivity-focused-views","text":"Productivity-Focused Views"}],"html":"

TaskNotes provides multiple views for managing tasks and tracking productivity. All task-focused views operate as .base files located in the TaskNotes/Views/ directory and require Obsidian's Bases core plugin to be enabled.

\n

For details on Bases integration and how to enable it, see Core Concepts. For view templates and configuration examples, see Default Base Templates.

\n

Task-Focused Views#

\n

Task-focused views are different entry points into the same underlying task notes. The Task List View is a common starting view for day-to-day planning because it exposes filters, sorting, and grouping in list format.

\n

When you want workflow by status, Kanban View organizes cards into columns and can optionally add swimlanes for an extra organizational layer. Calendar Views are useful when schedule and timing matter more than backlog shape, with month/week/day/year/list modes plus drag-and-drop scheduling and time-block support.

\n

Agenda View is a preconfigured list-oriented calendar layout designed for short-horizon planning, while MiniCalendar View gives a compact month heatmap and fast keyboard navigation.

\n

\"Task

\n

\"Calendar

\n

Productivity-Focused Views#

\n

These views support time management and work tracking.

\n

Pomodoro View supports focused intervals directly inside Obsidian, and Pomodoro Stats View summarizes completed sessions so you can see pace and consistency over time.

\n

\"Pomodoro

\n

Screenshots in this section are captured via the Playwright docs suite (npm run e2e:docs).

\n","text":"TaskNotes provides multiple views for managing tasks and tracking productivity. All task-focused views operate as .base files located in the TaskNotes/Views/ directory and require Obsidian's Bases core plugin to be enabled. For details on Bases integration and how to enable it, see Core Concepts. For view templates and configuration examples, see Default Base Templates. Task-Focused Views# Task-focused views are different entry points into the same underlying task notes. The Task List View is a common starting view for day-to-day planning because it exposes filters, sorting, and grouping in list format. When you want workflow by status, Kanban View organizes cards into columns and can optionally add swimlanes for an extra organizational layer. Calendar Views are useful when schedule and timing matter more than backlog shape, with month/week/day/year/list modes plus drag-and-drop scheduling and time-block support. Agenda View is a preconfigured list-oriented calendar layout designed for short-horizon planning, while MiniCalendar View gives a compact month heatmap and fast keyboard navigation. Productivity-Focused Views# These views support time management and work tracking. Pomodoro View supports focused intervals directly inside Obsidian, and Pomodoro Stats View summarizes completed sessions so you can see pace and consistency over time. Screenshots in this section are captured via the Playwright docs suite (npm run e2e:docs)."},{"route":"/obsidian/views/agenda-view/","title":"Agenda View","description":"The Agenda view is a dedicated .base file that opens the calendar in list mode. It provides a scrollable agenda of upcoming tasks, notes, and external calendar events without ne...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/views/agenda-view.md","namespace":"obsidian","relativePath":"views/agenda-view.md","raw":"# Agenda View\n\n\nThe Agenda view is a dedicated `.base` file that opens the calendar in list mode. It provides a scrollable agenda of upcoming tasks, notes, and external calendar events without needing to switch the primary calendar into list view manually.\n\n![Agenda View](../assets/views-agenda.png)\n\n## File Location\n\n- Default file: `TaskNotes/Views/agenda-default.base`\n- Command: **Open Agenda View** (ribbon icon and command palette)\n- Configure the file path in **Settings → TaskNotes → General → View Commands**\n\nTaskNotes creates missing default `.base` files automatically on startup when **Auto-create default files** is enabled. You can replace the command path with your own `.base` file if you maintain multiple agendas.\n\n## Default Configuration\n\nThe stock agenda file renders the calendar in `listWeek` mode:\n\n```yaml\nviews:\n - type: tasknotesCalendar\n name: \"Agenda\"\n calendarView: \"listWeek\"\n listDayCount: 7\n startDateProperty: file.ctime\n titleProperty: file.basename\n order:\n - note.status\n - note.priority\n - note.due\n - formula.dueIn\n - note.scheduled\n```\n\nThis configuration displays seven days at a time, derives entries from `file.ctime`/`file.basename`, shows the generated `Due in` countdown next to due dates, and inherits the same display options (show scheduled/due/recurring/timeblocks/time entries/ICS events) as the primary calendar view.\n\n## Customization\n\nEdit the `.base` file to tailor the agenda:\n\n- Change `calendarView` to `listDay` or `listMonth` for different spans\n- Adjust `listDayCount` for shorter or longer agendas; the Bases option supports up to 365 days\n- Add `filters` to focus on specific projects, tags, or statuses\n- Modify `order` to control which task properties appear in the row layout\n\nBecause the view runs inside Bases, any YAML changes are applied immediately after saving the file.\n\n## Usage Tips\n\n- Use the calendar toolbar arrows (Previous/Next) to move the agenda window forward or backward, or simply scroll the list to review upcoming entries\n- Saved views within Bases let you maintain multiple agenda variants (e.g., \"Work Week\" vs. \"Personal\")\n- Calendar display options (show due, show scheduled, etc.) persist when you save the `.base` file, so you can maintain one agenda that includes external events and another that focuses strictly on TaskNotes tasks\n","aliases":["/views/agenda-view/"],"toc":[{"level":2,"id":"file-location","text":"File Location"},{"level":2,"id":"default-configuration","text":"Default Configuration"},{"level":2,"id":"customization","text":"Customization"},{"level":2,"id":"usage-tips","text":"Usage Tips"}],"html":"

The Agenda view is a dedicated .base file that opens the calendar in list mode. It provides a scrollable agenda of upcoming tasks, notes, and external calendar events without needing to switch the primary calendar into list view manually.

\n

\"Agenda

\n

File Location#

\n
    \n
  • Default file: TaskNotes/Views/agenda-default.base
  • \n
  • Command: Open Agenda View (ribbon icon and command palette)
  • \n
  • Configure the file path in Settings → TaskNotes → General → View Commands
  • \n
\n

TaskNotes creates missing default .base files automatically on startup when Auto-create default files is enabled. You can replace the command path with your own .base file if you maintain multiple agendas.

\n

Default Configuration#

\n

The stock agenda file renders the calendar in listWeek mode:

\n
views:\n  - type: tasknotesCalendar\n    name: "Agenda"\n    calendarView: "listWeek"\n    listDayCount: 7\n    startDateProperty: file.ctime\n    titleProperty: file.basename\n    order:\n      - note.status\n      - note.priority\n      - note.due\n      - formula.dueIn\n      - note.scheduled\n

This configuration displays seven days at a time, derives entries from file.ctime/file.basename, shows the generated Due in countdown next to due dates, and inherits the same display options (show scheduled/due/recurring/timeblocks/time entries/ICS events) as the primary calendar view.

\n

Customization#

\n

Edit the .base file to tailor the agenda:

\n
    \n
  • Change calendarView to listDay or listMonth for different spans
  • \n
  • Adjust listDayCount for shorter or longer agendas; the Bases option supports up to 365 days
  • \n
  • Add filters to focus on specific projects, tags, or statuses
  • \n
  • Modify order to control which task properties appear in the row layout
  • \n
\n

Because the view runs inside Bases, any YAML changes are applied immediately after saving the file.

\n

Usage Tips#

\n
    \n
  • Use the calendar toolbar arrows (Previous/Next) to move the agenda window forward or backward, or simply scroll the list to review upcoming entries
  • \n
  • Saved views within Bases let you maintain multiple agenda variants (e.g., "Work Week" vs. "Personal")
  • \n
  • Calendar display options (show due, show scheduled, etc.) persist when you save the .base file, so you can maintain one agenda that includes external events and another that focuses strictly on TaskNotes tasks
  • \n
\n","text":"The Agenda view is a dedicated .base file that opens the calendar in list mode. It provides a scrollable agenda of upcoming tasks, notes, and external calendar events without needing to switch the primary calendar into list view manually. File Location# Default file: TaskNotes/Views/agenda-default.base Command: Open Agenda View (ribbon icon and command palette) Configure the file path in Settings → TaskNotes → General → View Commands TaskNotes creates missing default .base files automatically on startup when Auto-create default files is enabled. You can replace the command path with your own .base file if you maintain multiple agendas. Default Configuration# The stock agenda file renders the calendar in listWeek mode: views: - type: tasknotesCalendar name: \"Agenda\" calendarView: \"listWeek\" listDayCount: 7 startDateProperty: file.ctime titleProperty: file.basename order: - note.status - note.priority - note.due - formula.dueIn - note.scheduled This configuration displays seven days at a time, derives entries from file.ctime/file.basename, shows the generated Due in countdown next to due dates, and inherits the same display options (show scheduled/due/recurring/timeblocks/time entries/ICS events) as the primary calendar view. Customization# Edit the .base file to tailor the agenda: Change calendarView to listDay or listMonth for different spans Adjust listDayCount for shorter or longer agendas; the Bases option supports up to 365 days Add filters to focus on specific projects, tags, or statuses Modify order to control which task properties appear in the row layout Because the view runs inside Bases, any YAML changes are applied immediately after saving the file. Usage Tips# Use the calendar toolbar arrows (Previous/Next) to move the agenda window forward or backward, or simply scroll the list to review upcoming entries Saved views within Bases let you maintain multiple agenda variants (e.g., \"Work Week\" vs. \"Personal\") Calendar display options (show due, show scheduled, etc.) persist when you save the .base file, so you can maintain one agenda that includes external events and another that focuses strictly on TaskNotes tasks"},{"route":"/obsidian/views/calendar-views/","title":"Calendar Views","description":"TaskNotes provides two calendar-based views: the Mini Calendar and the Calendar View. Both operate as Bases views (.base files) and require the Bases core plugin to be enabled i...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/views/calendar-views.md","namespace":"obsidian","relativePath":"views/calendar-views.md","raw":"# Calendar Views\n\n\nTaskNotes provides two calendar-based views: the **Mini Calendar** and the **Calendar View**. Both operate as Bases views (`.base` files) and require the Bases core plugin to be enabled in Obsidian.\nMini Calendar is date-density and navigation focused, while Calendar View is scheduling focused.\n\n![Calendar Month View](../assets/views-calendar-month.png)\n\n## Bases View Architecture\n\nCalendar views in TaskNotes v4 are implemented as Bases views, which means:\n\n- Calendar views are created as `.base` files in your vault\n- Configuration is controlled through YAML frontmatter in the base file\n- The Bases plugin is an official Obsidian core plugin and must be enabled\n- Views can be opened in tabs, pinned, and managed like other Obsidian views\nThis architecture makes calendar behavior auditable. Filters, formulas, and display options are stored with the view file, so they are versionable and easy to share across vault setups.\n\n## Mini Calendar View\n\nThe Mini Calendar displays a month-based view that shows which days contain tasks or other dated notes. It provides navigation and an overview of your task distribution across time.\n\n![Mini Calendar View](../assets/views-mini-calendar.png)\n\n### Features\n\n- **Date Navigation**: Click any date to open a fuzzy selector modal showing all notes associated with that date\n- **Keyboard Navigation**: Navigate the calendar using arrow keys and select dates with Enter\n- **Heatmap Styling**: Visual indicators show the density of tasks or notes on each day\n- **Configurable Date Property**: Set which date property to track (not limited to tasks - can display any dated notes based on configured property)\n- **Month Navigation**: Browse forward and backward through months to view historical and future task distribution\nMini Calendar is commonly used as an entry view: select a date, then open Task List, Agenda, or Calendar for execution.\n\n## Calendar View\n\nThe Calendar View provides multiple view modes (month, week, day, year, list, and custom days) with drag-and-drop scheduling and time-blocking capabilities. Tasks can be created by clicking on dates or time slots, and rescheduled by dragging them to new dates or times.\n\n### View Modes\n\nThe Calendar View supports the following view modes:\n\n- **Month**: Month grid showing all-day and timed events\n- **Week**: Week view with hourly time slots for detailed scheduling\n- **Day**: Single day view with hourly breakdown\n- **Year**: Annual overview showing event distribution across months\n- **List**: Chronological list of events. TaskNotes also includes a dedicated Agenda command that opens this mode via its own `.base` file for quick reviews.\n- **Custom Days**: Configurable multi-day view (2-10 days)\nView modes can be switched within a single `.base` file based on planning horizon (day, week, month, year, or custom range).\n\n| Week View | Day View | Year View |\n|-----------|----------|-----------|\n| ![Week View](../assets/views-calendar-week.png) | ![Day View](../assets/views-calendar-day.png) | ![Year View](../assets/views-calendar-year.png) |\n\n### Performance Improvements\n\nThe Calendar View uses virtual scrolling to maintain performance when displaying large numbers of events. This allows the calendar to handle extensive task lists and long time ranges without degradation in responsiveness.\n\n### Custom Days View\n\nThe Custom Days view provides a configurable multi-day calendar that displays between 2-10 days at once. This view addresses screen space utilization by offering a middle ground between the single-day view and the full week view.\n\n#### Key Features\n\n- **Configurable Duration**: Set the number of days to display (2-10 days) via Settings > Calendar > Custom view day count\n- **TimeGrid Format**: Uses the same hourly time slots and time-based event layout as Week and Day views\n- **Real-time Updates**: The view updates immediately when the day count setting is changed\n- **Default Configuration**: Ships with 3 days displayed by default for optimal space utilization\n\n#### Use Cases\n\nThe Custom Days view is particularly useful for:\n- Users who find the single-day view too wide and wasteful of screen space\n- Planning workflows that require seeing a few days at a glance without the full week\n- Detailed scheduling tasks that benefit from the time-grid format\n- Customizing the viewing window to match personal preference and screen size\n\n#### Configuration\n\n1. **Select the View**: Choose \"Custom Days\" from the calendar toolbar alongside Month, Week, Day, and Year views\n2. **Adjust Day Count**: Navigate to Settings > Calendar > Custom view day count and use the slider to select 2-10 days\n3. **Set as Default**: Optionally set \"Custom Days\" as your default view in Settings > Calendar > Default view\n\n### Recurring Task Support\n\nThe Calendar View provides recurring task management with visual hierarchy and drag-and-drop behavior.\n\n#### Visual Hierarchy\n\nRecurring tasks are displayed with distinct visual styling:\n\n- **Next Scheduled Occurrence**: Solid border with full opacity, representing the specific date/time when you plan to work on the next instance\n- **Pattern Instances**: Dashed border with reduced opacity (70%), showing preview of when future recurring instances will appear based on the DTSTART and recurrence rule\n\n#### Drag and Drop Behavior\n\nThe calendar provides different behaviors depending on which type of recurring event you drag:\n\n**Dragging Next Scheduled Occurrence (Solid Border)**:\n\n- Updates only the `scheduled` field in the task\n- Reschedules just that specific occurrence to the new date/time\n- Leaves the recurrence pattern unchanged\n- Notice: \"Rescheduled next occurrence. This does not change the recurrence pattern.\"\n\n**Dragging Pattern Instances (Dashed Border)**:\n\n- Updates the DTSTART time in the recurrence rule\n- Changes when all future pattern instances appear\n- Does not affect the independently scheduled next occurrence\n- Notice: \"Updated recurring pattern time. All future instances now appear at this time.\"\n\n#### Flexible Scheduling\n\nThe next scheduled occurrence can appear on any date, even:\n\n- Before the DTSTART date\n- On days that don't match the recurring pattern (e.g., Tuesday for a weekly Monday pattern)\n- At different times than the pattern instances\n\nThis flexibility allows for complete control over both the recurring pattern and individual occurrence scheduling.\n\n### View Options\n\nThe Calendar View provides several display options that control what types of events appear on the calendar:\n\n- **Show scheduled**: Display tasks with scheduled dates\n- **Show due**: Display tasks with due dates\n- **Show timeblocks**: Display time-blocking entries\n- **Show recurring**: Display recurring task events\n- **Show ICS events**: Display events from imported ICS calendars\n- **Show time entries**: Display time tracking entries\n- **All-day slot**: Show or hide the all-day event area at the top of time grid views (Week, Day, and Custom views)\n- **Create daily notes from date links**: Let date header links create a missing daily note before opening it. Turn this off if date links should only open existing daily notes.\n- **Drag/drop resolution**: Set `snapDuration` when you want events to drag or resize in smaller increments than the visible `slotDuration`, such as 5-minute dragging on a 30-minute grid.\n- **Span tasks between scheduled and due dates**: Display tasks as multi-day bars spanning from their scheduled date to their due date (see below)\nMultiple saved calendar views can store different option sets (for example planning vs focus), avoiding repeated manual toggles.\n\nThe **All-day slot** option is particularly useful when you have many all-day tasks on a single date, as hiding it can resolve scrolling issues and make the hourly time slots more accessible. When disabled, all-day events will not be displayed in time grid views, but they will still appear in month view.\n\n#### Multi-Day Task Spans\n\nThe **Span tasks between scheduled and due dates** option provides a visual representation of task duration on the calendar. When enabled:\n\n- Tasks with both a scheduled date and a due date display as a single bar spanning across all days from the scheduled date to the due date\n- This replaces the separate scheduled and due markers for qualifying tasks\n- Tasks with only a scheduled date or only a due date continue to display as single-day events\n- Span events are shown as all-day bars with the task's priority color\n- Span events are read-only on the calendar (edit the underlying scheduled/due dates to modify)\n\nThis option is useful for project planning and visualizing how long tasks are expected to take, similar to Gantt chart-style views.\n\nThese display options are preserved when you save a view, allowing you to create specialized calendar views that show only specific types of events and maintain those preferences across sessions.\n\n### OAuth Calendar Integration\n\nThe Calendar View supports bidirectional synchronization with external calendar services through OAuth authentication:\n\n- **Google Calendar**: Connect to Google Calendar accounts to display and sync events\n- **Microsoft Outlook**: Connect to Microsoft Outlook accounts for calendar integration\n\n#### Synchronization Behavior\n\n- External calendar events appear alongside TaskNotes tasks in all calendar views\n- Drag and drop events to reschedule them - changes sync back to the external calendar service\n- Events from external calendars respect the same view options and display settings as native TaskNotes tasks\n\n#### Configuration\n\nOAuth calendar connections are configured through the TaskNotes settings panel. Authentication uses standard OAuth flows to securely connect to external services.\n\n### Time Entry Editor Modal\n\nThe Calendar View includes a Time Entry Editor Modal for creating time tracking entries directly from the calendar interface.\n\n#### Creating Time Entries\n\n- Drag on the calendar to select a time range\n- When the selection menu appears, choose **Create time entry**\n- The modal opens with the start and end times pre-populated based on the selection, and the entry can be linked to a task or left standalone\n\n#### Editing Time Entries\n\nTime entries displayed on the calendar can be selected to open the Time Entry Editor Modal for modification. The modal provides fields for adjusting start time, end time, associated task, and other time entry metadata.\n\n### Filtering and View Configuration\n\nCalendar filtering is configured through the Bases YAML frontmatter in the `.base` file. This allows you to define which tasks and events appear in each calendar view. Filtering options include task properties, date ranges, tags, and other criteria supported by the Bases plugin.\n\nSaved calendar views retain their filter configuration, display options, and view mode, allowing you to create specialized calendar views for different purposes.\n","aliases":["/views/calendar-views/"],"toc":[{"level":2,"id":"bases-view-architecture","text":"Bases View Architecture"},{"level":2,"id":"mini-calendar-view","text":"Mini Calendar View"},{"level":3,"id":"features","text":"Features"},{"level":2,"id":"calendar-view","text":"Calendar View"},{"level":3,"id":"view-modes","text":"View Modes"},{"level":3,"id":"performance-improvements","text":"Performance Improvements"},{"level":3,"id":"custom-days-view","text":"Custom Days View"},{"level":3,"id":"recurring-task-support","text":"Recurring Task Support"},{"level":3,"id":"view-options","text":"View Options"},{"level":3,"id":"oauth-calendar-integration","text":"OAuth Calendar Integration"},{"level":3,"id":"time-entry-editor-modal","text":"Time Entry Editor Modal"},{"level":3,"id":"filtering-and-view-configuration","text":"Filtering and View Configuration"}],"html":"

TaskNotes provides two calendar-based views: the Mini Calendar and the Calendar View. Both operate as Bases views (.base files) and require the Bases core plugin to be enabled in Obsidian.\nMini Calendar is date-density and navigation focused, while Calendar View is scheduling focused.

\n

\"Calendar

\n

Bases View Architecture#

\n

Calendar views in TaskNotes v4 are implemented as Bases views, which means:

\n
    \n
  • Calendar views are created as .base files in your vault
  • \n
  • Configuration is controlled through YAML frontmatter in the base file
  • \n
  • The Bases plugin is an official Obsidian core plugin and must be enabled
  • \n
  • Views can be opened in tabs, pinned, and managed like other Obsidian views\nThis architecture makes calendar behavior auditable. Filters, formulas, and display options are stored with the view file, so they are versionable and easy to share across vault setups.
  • \n
\n

Mini Calendar View#

\n

The Mini Calendar displays a month-based view that shows which days contain tasks or other dated notes. It provides navigation and an overview of your task distribution across time.

\n

\"Mini

\n

Features#

\n
    \n
  • Date Navigation: Click any date to open a fuzzy selector modal showing all notes associated with that date
  • \n
  • Keyboard Navigation: Navigate the calendar using arrow keys and select dates with Enter
  • \n
  • Heatmap Styling: Visual indicators show the density of tasks or notes on each day
  • \n
  • Configurable Date Property: Set which date property to track (not limited to tasks - can display any dated notes based on configured property)
  • \n
  • Month Navigation: Browse forward and backward through months to view historical and future task distribution\nMini Calendar is commonly used as an entry view: select a date, then open Task List, Agenda, or Calendar for execution.
  • \n
\n

Calendar View#

\n

The Calendar View provides multiple view modes (month, week, day, year, list, and custom days) with drag-and-drop scheduling and time-blocking capabilities. Tasks can be created by clicking on dates or time slots, and rescheduled by dragging them to new dates or times.

\n

View Modes#

\n

The Calendar View supports the following view modes:

\n
    \n
  • Month: Month grid showing all-day and timed events
  • \n
  • Week: Week view with hourly time slots for detailed scheduling
  • \n
  • Day: Single day view with hourly breakdown
  • \n
  • Year: Annual overview showing event distribution across months
  • \n
  • List: Chronological list of events. TaskNotes also includes a dedicated Agenda command that opens this mode via its own .base file for quick reviews.
  • \n
  • Custom Days: Configurable multi-day view (2-10 days)\nView modes can be switched within a single .base file based on planning horizon (day, week, month, year, or custom range).
  • \n
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n
Week ViewDay ViewYear View
\"Week\"Day\"Year
\n

Performance Improvements#

\n

The Calendar View uses virtual scrolling to maintain performance when displaying large numbers of events. This allows the calendar to handle extensive task lists and long time ranges without degradation in responsiveness.

\n

Custom Days View#

\n

The Custom Days view provides a configurable multi-day calendar that displays between 2-10 days at once. This view addresses screen space utilization by offering a middle ground between the single-day view and the full week view.

\n

Key Features#

\n
    \n
  • Configurable Duration: Set the number of days to display (2-10 days) via Settings > Calendar > Custom view day count
  • \n
  • TimeGrid Format: Uses the same hourly time slots and time-based event layout as Week and Day views
  • \n
  • Real-time Updates: The view updates immediately when the day count setting is changed
  • \n
  • Default Configuration: Ships with 3 days displayed by default for optimal space utilization
  • \n
\n

Use Cases#

\n

The Custom Days view is particularly useful for:

\n
    \n
  • Users who find the single-day view too wide and wasteful of screen space
  • \n
  • Planning workflows that require seeing a few days at a glance without the full week
  • \n
  • Detailed scheduling tasks that benefit from the time-grid format
  • \n
  • Customizing the viewing window to match personal preference and screen size
  • \n
\n

Configuration#

\n
    \n
  1. Select the View: Choose "Custom Days" from the calendar toolbar alongside Month, Week, Day, and Year views
  2. \n
  3. Adjust Day Count: Navigate to Settings > Calendar > Custom view day count and use the slider to select 2-10 days
  4. \n
  5. Set as Default: Optionally set "Custom Days" as your default view in Settings > Calendar > Default view
  6. \n
\n

Recurring Task Support#

\n

The Calendar View provides recurring task management with visual hierarchy and drag-and-drop behavior.

\n

Visual Hierarchy#

\n

Recurring tasks are displayed with distinct visual styling:

\n
    \n
  • Next Scheduled Occurrence: Solid border with full opacity, representing the specific date/time when you plan to work on the next instance
  • \n
  • Pattern Instances: Dashed border with reduced opacity (70%), showing preview of when future recurring instances will appear based on the DTSTART and recurrence rule
  • \n
\n

Drag and Drop Behavior#

\n

The calendar provides different behaviors depending on which type of recurring event you drag:

\n

Dragging Next Scheduled Occurrence (Solid Border):

\n
    \n
  • Updates only the scheduled field in the task
  • \n
  • Reschedules just that specific occurrence to the new date/time
  • \n
  • Leaves the recurrence pattern unchanged
  • \n
  • Notice: "Rescheduled next occurrence. This does not change the recurrence pattern."
  • \n
\n

Dragging Pattern Instances (Dashed Border):

\n
    \n
  • Updates the DTSTART time in the recurrence rule
  • \n
  • Changes when all future pattern instances appear
  • \n
  • Does not affect the independently scheduled next occurrence
  • \n
  • Notice: "Updated recurring pattern time. All future instances now appear at this time."
  • \n
\n

Flexible Scheduling#

\n

The next scheduled occurrence can appear on any date, even:

\n
    \n
  • Before the DTSTART date
  • \n
  • On days that don't match the recurring pattern (e.g., Tuesday for a weekly Monday pattern)
  • \n
  • At different times than the pattern instances
  • \n
\n

This flexibility allows for complete control over both the recurring pattern and individual occurrence scheduling.

\n

View Options#

\n

The Calendar View provides several display options that control what types of events appear on the calendar:

\n
    \n
  • Show scheduled: Display tasks with scheduled dates
  • \n
  • Show due: Display tasks with due dates
  • \n
  • Show timeblocks: Display time-blocking entries
  • \n
  • Show recurring: Display recurring task events
  • \n
  • Show ICS events: Display events from imported ICS calendars
  • \n
  • Show time entries: Display time tracking entries
  • \n
  • All-day slot: Show or hide the all-day event area at the top of time grid views (Week, Day, and Custom views)
  • \n
  • Create daily notes from date links: Let date header links create a missing daily note before opening it. Turn this off if date links should only open existing daily notes.
  • \n
  • Drag/drop resolution: Set snapDuration when you want events to drag or resize in smaller increments than the visible slotDuration, such as 5-minute dragging on a 30-minute grid.
  • \n
  • Span tasks between scheduled and due dates: Display tasks as multi-day bars spanning from their scheduled date to their due date (see below)\nMultiple saved calendar views can store different option sets (for example planning vs focus), avoiding repeated manual toggles.
  • \n
\n

The All-day slot option is particularly useful when you have many all-day tasks on a single date, as hiding it can resolve scrolling issues and make the hourly time slots more accessible. When disabled, all-day events will not be displayed in time grid views, but they will still appear in month view.

\n

Multi-Day Task Spans#

\n

The Span tasks between scheduled and due dates option provides a visual representation of task duration on the calendar. When enabled:

\n
    \n
  • Tasks with both a scheduled date and a due date display as a single bar spanning across all days from the scheduled date to the due date
  • \n
  • This replaces the separate scheduled and due markers for qualifying tasks
  • \n
  • Tasks with only a scheduled date or only a due date continue to display as single-day events
  • \n
  • Span events are shown as all-day bars with the task's priority color
  • \n
  • Span events are read-only on the calendar (edit the underlying scheduled/due dates to modify)
  • \n
\n

This option is useful for project planning and visualizing how long tasks are expected to take, similar to Gantt chart-style views.

\n

These display options are preserved when you save a view, allowing you to create specialized calendar views that show only specific types of events and maintain those preferences across sessions.

\n

OAuth Calendar Integration#

\n

The Calendar View supports bidirectional synchronization with external calendar services through OAuth authentication:

\n
    \n
  • Google Calendar: Connect to Google Calendar accounts to display and sync events
  • \n
  • Microsoft Outlook: Connect to Microsoft Outlook accounts for calendar integration
  • \n
\n

Synchronization Behavior#

\n
    \n
  • External calendar events appear alongside TaskNotes tasks in all calendar views
  • \n
  • Drag and drop events to reschedule them - changes sync back to the external calendar service
  • \n
  • Events from external calendars respect the same view options and display settings as native TaskNotes tasks
  • \n
\n

Configuration#

\n

OAuth calendar connections are configured through the TaskNotes settings panel. Authentication uses standard OAuth flows to securely connect to external services.

\n

Time Entry Editor Modal#

\n

The Calendar View includes a Time Entry Editor Modal for creating time tracking entries directly from the calendar interface.

\n

Creating Time Entries#

\n
    \n
  • Drag on the calendar to select a time range
  • \n
  • When the selection menu appears, choose Create time entry
  • \n
  • The modal opens with the start and end times pre-populated based on the selection, and the entry can be linked to a task or left standalone
  • \n
\n

Editing Time Entries#

\n

Time entries displayed on the calendar can be selected to open the Time Entry Editor Modal for modification. The modal provides fields for adjusting start time, end time, associated task, and other time entry metadata.

\n

Filtering and View Configuration#

\n

Calendar filtering is configured through the Bases YAML frontmatter in the .base file. This allows you to define which tasks and events appear in each calendar view. Filtering options include task properties, date ranges, tags, and other criteria supported by the Bases plugin.

\n

Saved calendar views retain their filter configuration, display options, and view mode, allowing you to create specialized calendar views for different purposes.

\n","text":"TaskNotes provides two calendar-based views: the Mini Calendar and the Calendar View. Both operate as Bases views (.base files) and require the Bases core plugin to be enabled in Obsidian. Mini Calendar is date-density and navigation focused, while Calendar View is scheduling focused. Bases View Architecture# Calendar views in TaskNotes v4 are implemented as Bases views, which means: Calendar views are created as .base files in your vault Configuration is controlled through YAML frontmatter in the base file The Bases plugin is an official Obsidian core plugin and must be enabled Views can be opened in tabs, pinned, and managed like other Obsidian views This architecture makes calendar behavior auditable. Filters, formulas, and display options are stored with the view file, so they are versionable and easy to share across vault setups. Mini Calendar View# The Mini Calendar displays a month-based view that shows which days contain tasks or other dated notes. It provides navigation and an overview of your task distribution across time. Features# Date Navigation: Click any date to open a fuzzy selector modal showing all notes associated with that date Keyboard Navigation: Navigate the calendar using arrow keys and select dates with Enter Heatmap Styling: Visual indicators show the density of tasks or notes on each day Configurable Date Property: Set which date property to track (not limited to tasks - can display any dated notes based on configured property) Month Navigation: Browse forward and backward through months to view historical and future task distribution Mini Calendar is commonly used as an entry view: select a date, then open Task List, Agenda, or Calendar for execution. Calendar View# The Calendar View provides multiple view modes (month, week, day, year, list, and custom days) with drag-and-drop scheduling and time-blocking capabilities. Tasks can be created by clicking on dates or time slots, and rescheduled by dragging them to new dates or times. View Modes# The Calendar View supports the following view modes: Month: Month grid showing all-day and timed events Week: Week view with hourly time slots for detailed scheduling Day: Single day view with hourly breakdown Year: Annual overview showing event distribution across months List: Chronological list of events. TaskNotes also includes a dedicated Agenda command that opens this mode via its own .base file for quick reviews. Custom Days: Configurable multi-day view (2-10 days) View modes can be switched within a single .base file based on planning horizon (day, week, month, year, or custom range). Week View Day View Year View Performance Improvements# The Calendar View uses virtual scrolling to maintain performance when displaying large numbers of events. This allows the calendar to handle extensive task lists and long time ranges without degradation in responsiveness. Custom Days View# The Custom Days view provides a configurable multi-day calendar that displays between 2-10 days at once. This view addresses screen space utilization by offering a middle ground between the single-day view and the full week view. Key Features# Configurable Duration: Set the number of days to display (2-10 days) via Settings > Calendar > Custom view day count TimeGrid Format: Uses the same hourly time slots and time-based event layout as Week and Day views Real-time Updates: The view updates immediately when the day count setting is changed Default Configuration: Ships with 3 days displayed by default for optimal space utilization Use Cases# The Custom Days view is particularly useful for: Users who find the single-day view too wide and wasteful of screen space Planning workflows that require seeing a few days at a glance without the full week Detailed scheduling tasks that benefit from the time-grid format Customizing the viewing window to match personal preference and screen size Configuration# Select the View: Choose \"Custom Days\" from the calendar toolbar alongside Month, Week, Day, and Year views Adjust Day Count: Navigate to Settings > Calendar > Custom view day count and use the slider to select 2-10 days Set as Default: Optionally set \"Custom Days\" as your default view in Settings > Calendar > Default view Recurring Task Support# The Calendar View provides recurring task management with visual hierarchy and drag-and-drop behavior. Visual Hierarchy# Recurring tasks are displayed with distinct visual styling: Next Scheduled Occurrence: Solid border with full opacity, representing the specific date/time when you plan to work on the next instance Pattern Instances: Dashed border with reduced opacity (70%), showing preview of when future recurring instances will appear based on the DTSTART and recurrence rule Drag and Drop Behavior# The calendar provides different behaviors depending on which type of recurring event you drag: Dragging Next Scheduled Occurrence (Solid Border): Updates only the scheduled field in the task Reschedules just that specific occurrence to the new date/time Leaves the recurrence pattern unchanged Notice: \"Rescheduled next occurrence. This does not change the recurrence pattern.\" Dragging Pattern Instances (Dashed Border): Updates the DTSTART time in the recurrence rule Changes when all future pattern instances appear Does not affect the independently scheduled next occurrence Notice: \"Updated recurring pattern time. All future instances now appear at this time.\" Flexible Scheduling# The next scheduled occurrence can appear on any date, even: Before the DTSTART date On days that don't match the recurring pattern (e.g., Tuesday for a weekly Monday pattern) At different times than the pattern instances This flexibility allows for complete control over both the recurring pattern and individual occurrence scheduling. View Options# The Calendar View provides several display options that control what types of events appear on the calendar: Show scheduled: Display tasks with scheduled dates Show due: Display tasks with due dates Show timeblocks: Display time-blocking entries Show recurring: Display recurring task events Show ICS events: Display events from imported ICS calendars Show time entries: Display time tracking entries All-day slot: Show or hide the all-day event area at the top of time grid views (Week, Day, and Custom views) Create daily notes from date links: Let date header links create a missing daily note before opening it. Turn this off if date links should only open existing daily notes. Drag/drop resolution: Set snapDuration when you want events to drag or resize in smaller increments than the visible slotDuration, such as 5-minute dragging on a 30-minute grid. Span tasks between scheduled and due dates: Display tasks as multi-day bars spanning from their scheduled date to their due date (see below) Multiple saved calendar views can store different option sets (for example planning vs focus), avoiding repeated manual toggles. The All-day slot option is particularly useful when you have many all-day tasks on a single date, as hiding it can resolve scrolling issues and make the hourly time slots more accessible. When disabled, all-day events will not be displayed in time grid views, but they will still appear in month view. Multi-Day Task Spans# The Span tasks between scheduled and due dates option provides a visual representation of task duration on the calendar. When enabled: Tasks with both a scheduled date and a due date display as a single bar spanning across all days from the scheduled date to the due date This replaces the separate scheduled and due markers for qualifying tasks Tasks with only a scheduled date or only a due date continue to display as single-day events Span events are shown as all-day bars with the task's priority color Span events are read-only on the calendar (edit the underlying scheduled/due dates to modify) This option is useful for project planning and visualizing how long tasks are expected to take, similar to Gantt chart-style views. These display options are preserved when you save a view, allowing you to create specialized calendar views that show only specific types of events and maintain those preferences across sessions. OAuth Calendar Integration# The Calendar View supports bidirectional synchronization with external calendar services through OAuth authentication: Google Calendar: Connect to Google Calendar accounts to display and sync events Microsoft Outlook: Connect to Microsoft Outlook accounts for calendar integration Synchronization Behavior# External calendar events appear alongside TaskNotes tasks in all calendar views Drag and drop events to reschedule them - changes sync back to the external calendar service Events from external calendars respect the same view options and display settings as native TaskNotes tasks Configuration# OAuth calendar connections are configured through the TaskNotes settings panel. Authentication uses standard OAuth flows to securely connect to external services. Time Entry Editor Modal# The Calendar View includes a Time Entry Editor Modal for creating time tracking entries directly from the calendar interface. Creating Time Entries# Drag on the calendar to select a time range When the selection menu appears, choose Create time entry The modal opens with the start and end times pre-populated based on the selection, and the entry can be linked to a task or left standalone Editing Time Entries# Time entries displayed on the calendar can be selected to open the Time Entry Editor Modal for modification. The modal provides fields for adjusting start time, end time, associated task, and other time entry metadata. Filtering and View Configuration# Calendar filtering is configured through the Bases YAML frontmatter in the .base file. This allows you to define which tasks and events appear in each calendar view. Filtering options include task properties, date ranges, tags, and other criteria supported by the Bases plugin. Saved calendar views retain their filter configuration, display options, and view mode, allowing you to create specialized calendar views for different purposes."},{"route":"/obsidian/views/kanban-view/","title":"Kanban View","description":"The Kanban View displays tasks as cards organized in columns, where each column represents a distinct value of a grouped property. Kanban emphasizes state transitions and drag o...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/views/kanban-view.md","namespace":"obsidian","relativePath":"views/kanban-view.md","raw":"# Kanban View\n\n\nThe Kanban View displays tasks as cards organized in columns, where each column represents a distinct value of a grouped property.\nKanban emphasizes state transitions and drag operations over dense list scanning.\n\n![Kanban View](../assets/views-kanban.png)\n\n## Configuration\n\nKanban views are stored as `.base` files in `TaskNotes/Views/`. The `groupBy` property determines the column structure—each unique value becomes a column in the board. Open a `.base` file and access the view settings panel to configure options.\n\n### Core Settings (Bases)\n\n- **Data source**: Select which files or folders to include in the view\n- **Filter**: Define criteria to include or exclude specific tasks\n- **Sort**: Specify the order of tasks within each column\n- **Group by**: Required. Defines the property that creates columns (e.g., status, priority)\nChoosing a stable `groupBy` field is the most important design decision. Frequent changes to this field create column churn and make historical comparisons harder.\n\n### Kanban-Specific Options\n\nAccess these options through the Bases view settings panel:\n\n- **Swim Lane**: Optional property for horizontal grouping. Creates a two-dimensional layout where tasks are organized by both column (groupBy) and row (swimLane)\n- **Column Width**: Controls the width of columns in pixels. Range: 200-500px. Default: 280px\n- **Max Swimlane Height**: Caps each swimlane row before the task area scrolls. Range: 300-1200px. Default: 600px\n- **Hide Empty Columns**: When enabled, columns containing no tasks are hidden from the view\n- **Pinned Columns**: Optional comma-separated list of column values that should stay visible even when empty. This is useful with **Hide Empty Columns** when each board needs a small stable subset of shared statuses or categories\n- **WIP Limits**: Advanced JSON configuration for showing per-column work-in-progress limits in column headers\n- **Hide Empty Swimlanes**: When enabled, ordered swimlanes with no tasks are hidden from the view\n- **Card Layout**: Chooses the task card density for this board. **Default** uses the standard TaskNotes card layout. **Compact** uses a tighter card layout for denser boards\n- **Show items in multiple columns**: When enabled (default), tasks with multiple values in list properties (contexts, tags, projects) appear in each individual column. For example, a task with `contexts: [work, call]` appears in both the \"work\" and \"call\" columns. When disabled, tasks appear in a single combined column (e.g., \"work, call\")\n- **Hide top-level subtasks**: When enabled, tasks whose Projects field links to another task in the current filtered board are hidden as standalone cards and remain available through the parent task's expanded subtasks\n- **Column Order**: Managed automatically when dragging column headers. Stores custom column ordering\n- **Swim Lane Order**: Advanced JSON configuration for pinning swimlane rows in a stable order\nA common setup is to keep one board grouped by status and another grouped by project or context, each in a separate `.base` file.\n\n## Interface Layout\n\n### Standard Layout\n\nIn standard mode, the Kanban board displays a horizontal row of columns. Each column corresponds to a unique value of the `groupBy` property.\n\nEach column includes:\n- A header showing the property value and task count\n- A scrollable area containing task cards\n- An add button that opens the TaskNotes creation modal with the column value filled in\n- Drag-and-drop functionality for reordering columns or moving tasks between columns\n\n### Swimlane Layout\n\nWhen a `swimLane` property is configured, the board displays a grid layout. The horizontal axis represents columns (groupBy values), and the vertical axis represents swimlanes.\n\nEach swimlane row includes:\n- A label cell showing the swimlane property value and total task count\n- Multiple cells, each representing a column within that swimlane\n- Scrollable cells containing task cards\n- Add buttons inside cells that fill in both the column value and swimlane value\n\nTo pin swimlanes in a stable order, set the advanced `swimLaneOrder` option to a JSON object keyed by the swimlane property:\n\n```yaml\nconfig:\n swimLane: note.contexts\n swimLaneOrder: '{\"note.contexts\":[\"transitcal\",\"bill\",\"cycles-research\",\"astrolabe\"]}'\n```\n\nListed swimlane values render first in the configured order. Values not listed in `swimLaneOrder` render below them using the default order for status and priority swimlanes, or alphabetically for other properties. If `hideEmptySwimLanes` is disabled, listed values can remain visible even when no matching tasks are currently present.\n\nTo show WIP limits in column headers, set the advanced `wipLimits` option to a JSON object keyed by column value:\n\n```yaml\nconfig:\n wipLimits: '{\"in-progress\":5,\"review\":2}'\n```\n\nColumns with limits display counts as `(current/limit)`. When the current count is above the configured limit, the count uses the error color. In swimlane boards, the column header count is the total for that column across all swimlanes.\n\n## Task Cards\n\nEach task card displays information based on the visible properties configured in the Bases view. Standard task information includes title, priority, due date, and scheduled date.\n\nUse the **Card Layout** setting when a board needs a different density from other task views. Existing boards use **Default** unless `cardLayout: compact` is set in the view options.\n\nTo show checklist progress on cards, include `file.tasks` in the view `order` array.\nFor existing `.base` files, add this in YAML manually first; after it is in `order`, it appears in the Bases picker as `tasks`.\n\nClick a card to open the task file for editing. Right-click to access the context menu for task actions. Drag cards between columns or swimlane cells to update the task's properties.\n\n## Column Operations\n\n### Reordering Columns\n\nDrag column headers to reorder columns. The new order persists across sessions and is stored in the `columnOrder` configuration.\n\n### Drag-and-Drop Tasks\n\nDrag task cards between columns to update the `groupBy` property value. In swimlane mode, dragging a task to a different cell updates both the `groupBy` and `swimLane` properties.\n\nWhen grouping by a list property (contexts, tags, projects) with \"Show items in multiple columns\" enabled, dragging a task between columns modifies the list rather than replacing it. The source column's value is removed and the target column's value is added. For example, dragging a task from the \"work\" column to the \"home\" column changes `contexts: [work, call]` to `contexts: [call, home]`.\nDrag operations write directly to task metadata, so consistent grouping values reduce ambiguity.\n\nThe add button at the bottom of a column or swimlane cell keeps deterministic view filter defaults and fills in the grouped values for that location.\n\n### Manual Reordering Within Columns\n\nKanban also supports drag-to-reorder within a column or swimlane cell when the view is sorted by the manual-order property. With the default field mapping, that property is `tasknotes_manual_order`.\n\nTo enable persistent manual ordering within Kanban columns:\n\n```yaml\nsort:\n - column: tasknotes_manual_order\n direction: DESC\n```\n\nOnce the first sort criterion is the manual-order property, dragging a card within the same column updates stored frontmatter values so the new order persists across refreshes and sessions.\n\nIn swimlane mode, the reorder scope is a single cell, not the entire board. A reorder inside the \"In Progress\" column for the \"High\" swimlane only adjusts the tasks in that cell.\n\nImportant constraints:\n\n- Manual drag-to-reorder only works when the view sort includes the manual-order property.\n- Moving a card to a different column or swimlane still updates the grouped property values as usual.\n- In filtered or partially visible columns, TaskNotes may also update hidden or filtered notes in the same reorder scope to preserve a stable persistent order.\n- Large reorder operations may show a confirmation dialog before writing changes.\n\nThe default generated TaskNotes templates use manual-order sorting in places where drag-to-reorder should work immediately, such as relationship views and manual-order task lists.\n\n## Performance Optimization\n\nThe Kanban view implements virtual scrolling for columns or swimlane cells containing 30 or more tasks. This optimization reduces memory usage by approximately 85% and maintains 60fps scrolling performance for columns with 200+ tasks.\n\nVirtual scrolling activates automatically based on task count. No configuration is required.\n\n## Example Configuration\n\nA typical Kanban view `.base` file includes:\n\n```yaml\n---\ntype: query\nsource: TaskNotes\nview: TaskNotes Kanban\nviews:\n - name: TaskNotes Kanban\n type: tasknotesKanban\n groupBy:\n property: task.status\n config:\n swimLane: task.priority\n swimLaneOrder: '{\"task.priority\":[\"high\",\"normal\",\"low\"]}'\n columnWidth: 300\n hideEmptyColumns: true\n pinnedColumns: to-do, in-progress, done\n wipLimits: '{\"in-progress\":5}'\n---\n```\n\nThis configuration creates a Kanban board with:\n- Columns based on task status\n- Swimlanes based on task priority\n- Priority swimlanes pinned in high, normal, low order\n- 300px column width\n- Empty unpinned columns hidden, while the to-do, in-progress, and done columns stay visible as drop targets\n- A WIP limit of 5 tasks on the in-progress column\n\n## Filtering and Sorting\n\nFiltering and sorting are configured through the Bases view settings, not through a separate FilterBar component. Use the Bases filter editor to define conditions based on task properties. Use the Bases sort editor to specify the order of tasks within each column.\n","aliases":["/views/kanban-view/"],"toc":[{"level":2,"id":"configuration","text":"Configuration"},{"level":3,"id":"core-settings-bases","text":"Core Settings (Bases)"},{"level":3,"id":"kanban-specific-options","text":"Kanban-Specific Options"},{"level":2,"id":"interface-layout","text":"Interface Layout"},{"level":3,"id":"standard-layout","text":"Standard Layout"},{"level":3,"id":"swimlane-layout","text":"Swimlane Layout"},{"level":2,"id":"task-cards","text":"Task Cards"},{"level":2,"id":"column-operations","text":"Column Operations"},{"level":3,"id":"reordering-columns","text":"Reordering Columns"},{"level":3,"id":"drag-and-drop-tasks","text":"Drag-and-Drop Tasks"},{"level":3,"id":"manual-reordering-within-columns","text":"Manual Reordering Within Columns"},{"level":2,"id":"performance-optimization","text":"Performance Optimization"},{"level":2,"id":"example-configuration","text":"Example Configuration"},{"level":2,"id":"filtering-and-sorting","text":"Filtering and Sorting"}],"html":"

The Kanban View displays tasks as cards organized in columns, where each column represents a distinct value of a grouped property.\nKanban emphasizes state transitions and drag operations over dense list scanning.

\n

\"Kanban

\n

Configuration#

\n

Kanban views are stored as .base files in TaskNotes/Views/. The groupBy property determines the column structure—each unique value becomes a column in the board. Open a .base file and access the view settings panel to configure options.

\n

Core Settings (Bases)#

\n
    \n
  • Data source: Select which files or folders to include in the view
  • \n
  • Filter: Define criteria to include or exclude specific tasks
  • \n
  • Sort: Specify the order of tasks within each column
  • \n
  • Group by: Required. Defines the property that creates columns (e.g., status, priority)\nChoosing a stable groupBy field is the most important design decision. Frequent changes to this field create column churn and make historical comparisons harder.
  • \n
\n

Kanban-Specific Options#

\n

Access these options through the Bases view settings panel:

\n
    \n
  • Swim Lane: Optional property for horizontal grouping. Creates a two-dimensional layout where tasks are organized by both column (groupBy) and row (swimLane)
  • \n
  • Column Width: Controls the width of columns in pixels. Range: 200-500px. Default: 280px
  • \n
  • Max Swimlane Height: Caps each swimlane row before the task area scrolls. Range: 300-1200px. Default: 600px
  • \n
  • Hide Empty Columns: When enabled, columns containing no tasks are hidden from the view
  • \n
  • Pinned Columns: Optional comma-separated list of column values that should stay visible even when empty. This is useful with Hide Empty Columns when each board needs a small stable subset of shared statuses or categories
  • \n
  • WIP Limits: Advanced JSON configuration for showing per-column work-in-progress limits in column headers
  • \n
  • Hide Empty Swimlanes: When enabled, ordered swimlanes with no tasks are hidden from the view
  • \n
  • Card Layout: Chooses the task card density for this board. Default uses the standard TaskNotes card layout. Compact uses a tighter card layout for denser boards
  • \n
  • Show items in multiple columns: When enabled (default), tasks with multiple values in list properties (contexts, tags, projects) appear in each individual column. For example, a task with contexts: [work, call] appears in both the "work" and "call" columns. When disabled, tasks appear in a single combined column (e.g., "work, call")
  • \n
  • Hide top-level subtasks: When enabled, tasks whose Projects field links to another task in the current filtered board are hidden as standalone cards and remain available through the parent task's expanded subtasks
  • \n
  • Column Order: Managed automatically when dragging column headers. Stores custom column ordering
  • \n
  • Swim Lane Order: Advanced JSON configuration for pinning swimlane rows in a stable order\nA common setup is to keep one board grouped by status and another grouped by project or context, each in a separate .base file.
  • \n
\n

Interface Layout#

\n

Standard Layout#

\n

In standard mode, the Kanban board displays a horizontal row of columns. Each column corresponds to a unique value of the groupBy property.

\n

Each column includes:

\n
    \n
  • A header showing the property value and task count
  • \n
  • A scrollable area containing task cards
  • \n
  • An add button that opens the TaskNotes creation modal with the column value filled in
  • \n
  • Drag-and-drop functionality for reordering columns or moving tasks between columns
  • \n
\n

Swimlane Layout#

\n

When a swimLane property is configured, the board displays a grid layout. The horizontal axis represents columns (groupBy values), and the vertical axis represents swimlanes.

\n

Each swimlane row includes:

\n
    \n
  • A label cell showing the swimlane property value and total task count
  • \n
  • Multiple cells, each representing a column within that swimlane
  • \n
  • Scrollable cells containing task cards
  • \n
  • Add buttons inside cells that fill in both the column value and swimlane value
  • \n
\n

To pin swimlanes in a stable order, set the advanced swimLaneOrder option to a JSON object keyed by the swimlane property:

\n
config:\n  swimLane: note.contexts\n  swimLaneOrder: '{"note.contexts":["transitcal","bill","cycles-research","astrolabe"]}'\n

Listed swimlane values render first in the configured order. Values not listed in swimLaneOrder render below them using the default order for status and priority swimlanes, or alphabetically for other properties. If hideEmptySwimLanes is disabled, listed values can remain visible even when no matching tasks are currently present.

\n

To show WIP limits in column headers, set the advanced wipLimits option to a JSON object keyed by column value:

\n
config:\n  wipLimits: '{"in-progress":5,"review":2}'\n

Columns with limits display counts as (current/limit). When the current count is above the configured limit, the count uses the error color. In swimlane boards, the column header count is the total for that column across all swimlanes.

\n

Task Cards#

\n

Each task card displays information based on the visible properties configured in the Bases view. Standard task information includes title, priority, due date, and scheduled date.

\n

Use the Card Layout setting when a board needs a different density from other task views. Existing boards use Default unless cardLayout: compact is set in the view options.

\n

To show checklist progress on cards, include file.tasks in the view order array.\nFor existing .base files, add this in YAML manually first; after it is in order, it appears in the Bases picker as tasks.

\n

Click a card to open the task file for editing. Right-click to access the context menu for task actions. Drag cards between columns or swimlane cells to update the task's properties.

\n

Column Operations#

\n

Reordering Columns#

\n

Drag column headers to reorder columns. The new order persists across sessions and is stored in the columnOrder configuration.

\n

Drag-and-Drop Tasks#

\n

Drag task cards between columns to update the groupBy property value. In swimlane mode, dragging a task to a different cell updates both the groupBy and swimLane properties.

\n

When grouping by a list property (contexts, tags, projects) with "Show items in multiple columns" enabled, dragging a task between columns modifies the list rather than replacing it. The source column's value is removed and the target column's value is added. For example, dragging a task from the "work" column to the "home" column changes contexts: [work, call] to contexts: [call, home].\nDrag operations write directly to task metadata, so consistent grouping values reduce ambiguity.

\n

The add button at the bottom of a column or swimlane cell keeps deterministic view filter defaults and fills in the grouped values for that location.

\n

Manual Reordering Within Columns#

\n

Kanban also supports drag-to-reorder within a column or swimlane cell when the view is sorted by the manual-order property. With the default field mapping, that property is tasknotes_manual_order.

\n

To enable persistent manual ordering within Kanban columns:

\n
sort:\n  - column: tasknotes_manual_order\n    direction: DESC\n

Once the first sort criterion is the manual-order property, dragging a card within the same column updates stored frontmatter values so the new order persists across refreshes and sessions.

\n

In swimlane mode, the reorder scope is a single cell, not the entire board. A reorder inside the "In Progress" column for the "High" swimlane only adjusts the tasks in that cell.

\n

Important constraints:

\n
    \n
  • Manual drag-to-reorder only works when the view sort includes the manual-order property.
  • \n
  • Moving a card to a different column or swimlane still updates the grouped property values as usual.
  • \n
  • In filtered or partially visible columns, TaskNotes may also update hidden or filtered notes in the same reorder scope to preserve a stable persistent order.
  • \n
  • Large reorder operations may show a confirmation dialog before writing changes.
  • \n
\n

The default generated TaskNotes templates use manual-order sorting in places where drag-to-reorder should work immediately, such as relationship views and manual-order task lists.

\n

Performance Optimization#

\n

The Kanban view implements virtual scrolling for columns or swimlane cells containing 30 or more tasks. This optimization reduces memory usage by approximately 85% and maintains 60fps scrolling performance for columns with 200+ tasks.

\n

Virtual scrolling activates automatically based on task count. No configuration is required.

\n

Example Configuration#

\n

A typical Kanban view .base file includes:

\n
---\ntype: query\nsource: TaskNotes\nview: TaskNotes Kanban\nviews:\n  - name: TaskNotes Kanban\n    type: tasknotesKanban\n    groupBy:\n      property: task.status\n    config:\n      swimLane: task.priority\n      swimLaneOrder: '{"task.priority":["high","normal","low"]}'\n      columnWidth: 300\n      hideEmptyColumns: true\n      pinnedColumns: to-do, in-progress, done\n      wipLimits: '{"in-progress":5}'\n---\n

This configuration creates a Kanban board with:

\n
    \n
  • Columns based on task status
  • \n
  • Swimlanes based on task priority
  • \n
  • Priority swimlanes pinned in high, normal, low order
  • \n
  • 300px column width
  • \n
  • Empty unpinned columns hidden, while the to-do, in-progress, and done columns stay visible as drop targets
  • \n
  • A WIP limit of 5 tasks on the in-progress column
  • \n
\n

Filtering and Sorting#

\n

Filtering and sorting are configured through the Bases view settings, not through a separate FilterBar component. Use the Bases filter editor to define conditions based on task properties. Use the Bases sort editor to specify the order of tasks within each column.

\n","text":"The Kanban View displays tasks as cards organized in columns, where each column represents a distinct value of a grouped property. Kanban emphasizes state transitions and drag operations over dense list scanning. Configuration# Kanban views are stored as .base files in TaskNotes/Views/. The groupBy property determines the column structure—each unique value becomes a column in the board. Open a .base file and access the view settings panel to configure options. Core Settings (Bases)# Data source: Select which files or folders to include in the view Filter: Define criteria to include or exclude specific tasks Sort: Specify the order of tasks within each column Group by: Required. Defines the property that creates columns (e.g., status, priority) Choosing a stable groupBy field is the most important design decision. Frequent changes to this field create column churn and make historical comparisons harder. Kanban-Specific Options# Access these options through the Bases view settings panel: Swim Lane: Optional property for horizontal grouping. Creates a two-dimensional layout where tasks are organized by both column (groupBy) and row (swimLane) Column Width: Controls the width of columns in pixels. Range: 200-500px. Default: 280px Max Swimlane Height: Caps each swimlane row before the task area scrolls. Range: 300-1200px. Default: 600px Hide Empty Columns: When enabled, columns containing no tasks are hidden from the view Pinned Columns: Optional comma-separated list of column values that should stay visible even when empty. This is useful with Hide Empty Columns when each board needs a small stable subset of shared statuses or categories WIP Limits: Advanced JSON configuration for showing per-column work-in-progress limits in column headers Hide Empty Swimlanes: When enabled, ordered swimlanes with no tasks are hidden from the view Card Layout: Chooses the task card density for this board. Default uses the standard TaskNotes card layout. Compact uses a tighter card layout for denser boards Show items in multiple columns: When enabled (default), tasks with multiple values in list properties (contexts, tags, projects) appear in each individual column. For example, a task with contexts: [work, call] appears in both the \"work\" and \"call\" columns. When disabled, tasks appear in a single combined column (e.g., \"work, call\") Hide top-level subtasks: When enabled, tasks whose Projects field links to another task in the current filtered board are hidden as standalone cards and remain available through the parent task's expanded subtasks Column Order: Managed automatically when dragging column headers. Stores custom column ordering Swim Lane Order: Advanced JSON configuration for pinning swimlane rows in a stable order A common setup is to keep one board grouped by status and another grouped by project or context, each in a separate .base file. Interface Layout# Standard Layout# In standard mode, the Kanban board displays a horizontal row of columns. Each column corresponds to a unique value of the groupBy property. Each column includes: A header showing the property value and task count A scrollable area containing task cards An add button that opens the TaskNotes creation modal with the column value filled in Drag-and-drop functionality for reordering columns or moving tasks between columns Swimlane Layout# When a swimLane property is configured, the board displays a grid layout. The horizontal axis represents columns (groupBy values), and the vertical axis represents swimlanes. Each swimlane row includes: A label cell showing the swimlane property value and total task count Multiple cells, each representing a column within that swimlane Scrollable cells containing task cards Add buttons inside cells that fill in both the column value and swimlane value To pin swimlanes in a stable order, set the advanced swimLaneOrder option to a JSON object keyed by the swimlane property: config: swimLane: note.contexts swimLaneOrder: '{\"note.contexts\":[\"transitcal\",\"bill\",\"cycles-research\",\"astrolabe\"]}' Listed swimlane values render first in the configured order. Values not listed in swimLaneOrder render below them using the default order for status and priority swimlanes, or alphabetically for other properties. If hideEmptySwimLanes is disabled, listed values can remain visible even when no matching tasks are currently present. To show WIP limits in column headers, set the advanced wipLimits option to a JSON object keyed by column value: config: wipLimits: '{\"in-progress\":5,\"review\":2}' Columns with limits display counts as (current/limit). When the current count is above the configured limit, the count uses the error color. In swimlane boards, the column header count is the total for that column across all swimlanes. Task Cards# Each task card displays information based on the visible properties configured in the Bases view. Standard task information includes title, priority, due date, and scheduled date. Use the Card Layout setting when a board needs a different density from other task views. Existing boards use Default unless cardLayout: compact is set in the view options. To show checklist progress on cards, include file.tasks in the view order array. For existing .base files, add this in YAML manually first; after it is in order, it appears in the Bases picker as tasks. Click a card to open the task file for editing. Right-click to access the context menu for task actions. Drag cards between columns or swimlane cells to update the task's properties. Column Operations# Reordering Columns# Drag column headers to reorder columns. The new order persists across sessions and is stored in the columnOrder configuration. Drag-and-Drop Tasks# Drag task cards between columns to update the groupBy property value. In swimlane mode, dragging a task to a different cell updates both the groupBy and swimLane properties. When grouping by a list property (contexts, tags, projects) with \"Show items in multiple columns\" enabled, dragging a task between columns modifies the list rather than replacing it. The source column's value is removed and the target column's value is added. For example, dragging a task from the \"work\" column to the \"home\" column changes contexts: [work, call] to contexts: [call, home]. Drag operations write directly to task metadata, so consistent grouping values reduce ambiguity. The add button at the bottom of a column or swimlane cell keeps deterministic view filter defaults and fills in the grouped values for that location. Manual Reordering Within Columns# Kanban also supports drag-to-reorder within a column or swimlane cell when the view is sorted by the manual-order property. With the default field mapping, that property is tasknotes_manual_order. To enable persistent manual ordering within Kanban columns: sort: - column: tasknotes_manual_order direction: DESC Once the first sort criterion is the manual-order property, dragging a card within the same column updates stored frontmatter values so the new order persists across refreshes and sessions. In swimlane mode, the reorder scope is a single cell, not the entire board. A reorder inside the \"In Progress\" column for the \"High\" swimlane only adjusts the tasks in that cell. Important constraints: Manual drag-to-reorder only works when the view sort includes the manual-order property. Moving a card to a different column or swimlane still updates the grouped property values as usual. In filtered or partially visible columns, TaskNotes may also update hidden or filtered notes in the same reorder scope to preserve a stable persistent order. Large reorder operations may show a confirmation dialog before writing changes. The default generated TaskNotes templates use manual-order sorting in places where drag-to-reorder should work immediately, such as relationship views and manual-order task lists. Performance Optimization# The Kanban view implements virtual scrolling for columns or swimlane cells containing 30 or more tasks. This optimization reduces memory usage by approximately 85% and maintains 60fps scrolling performance for columns with 200+ tasks. Virtual scrolling activates automatically based on task count. No configuration is required. Example Configuration# A typical Kanban view .base file includes: --- type: query source: TaskNotes view: TaskNotes Kanban views: - name: TaskNotes Kanban type: tasknotesKanban groupBy: property: task.status config: swimLane: task.priority swimLaneOrder: '{\"task.priority\":[\"high\",\"normal\",\"low\"]}' columnWidth: 300 hideEmptyColumns: true pinnedColumns: to-do, in-progress, done wipLimits: '{\"in-progress\":5}' --- This configuration creates a Kanban board with: Columns based on task status Swimlanes based on task priority Priority swimlanes pinned in high, normal, low order 300px column width Empty unpinned columns hidden, while the to-do, in-progress, and done columns stay visible as drop targets A WIP limit of 5 tasks on the in-progress column Filtering and Sorting# Filtering and sorting are configured through the Bases view settings, not through a separate FilterBar component. Use the Bases filter editor to define conditions based on task properties. Use the Bases sort editor to specify the order of tasks within each column."},{"route":"/obsidian/views/pomodoro-view/","title":"Pomodoro View","description":"The Pomodoro View provides a timer for working in focused intervals, based on the Pomodoro Technique.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/views/pomodoro-view.md","namespace":"obsidian","relativePath":"views/pomodoro-view.md","raw":"# Pomodoro View\n\n\nThe Pomodoro View provides a timer for working in focused intervals, based on the Pomodoro Technique.\n\n## Timer Interface\n\nThe Pomodoro View includes a timer with controls to start, stop, and reset the timer. While a timer is running, the view shows both the remaining duration and the projected local finish time. You can also associate a task with the timer, and the time will be automatically recorded in the task's time tracking data when the session is complete.\n\n![Pomodoro Timer](../assets/feature-pomodoro-timer.png)\n\n## Pomodoro Stats View\n\nThe Pomodoro Stats View provides analytics and historical data about your Pomodoro sessions. This includes a history of completed sessions, as well as metrics like completion rates and total time spent on tasks.\n\n![Pomodoro Statistics](../assets/feature-pomodoro-stats.png)\n","aliases":["/views/pomodoro-view/"],"toc":[{"level":2,"id":"timer-interface","text":"Timer Interface"},{"level":2,"id":"pomodoro-stats-view","text":"Pomodoro Stats View"}],"html":"

The Pomodoro View provides a timer for working in focused intervals, based on the Pomodoro Technique.

\n

Timer Interface#

\n

The Pomodoro View includes a timer with controls to start, stop, and reset the timer. While a timer is running, the view shows both the remaining duration and the projected local finish time. You can also associate a task with the timer, and the time will be automatically recorded in the task's time tracking data when the session is complete.

\n

\"Pomodoro

\n

Pomodoro Stats View#

\n

The Pomodoro Stats View provides analytics and historical data about your Pomodoro sessions. This includes a history of completed sessions, as well as metrics like completion rates and total time spent on tasks.

\n

\"Pomodoro

\n","text":"The Pomodoro View provides a timer for working in focused intervals, based on the Pomodoro Technique. Timer Interface# The Pomodoro View includes a timer with controls to start, stop, and reset the timer. While a timer is running, the view shows both the remaining duration and the projected local finish time. You can also associate a task with the timer, and the time will be automatically recorded in the task's time tracking data when the session is complete. Pomodoro Stats View# The Pomodoro Stats View provides analytics and historical data about your Pomodoro sessions. This includes a history of completed sessions, as well as metrics like completion rates and total time spent on tasks."},{"route":"/obsidian/views/task-list/","title":"Task List View","description":"The Task List View displays tasks in a scrollable list format with filtering, sorting, and grouping capabilities. In TaskNotes v4, this view operates as a Bases view configured...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/views/task-list.md","namespace":"obsidian","relativePath":"views/task-list.md","raw":"# Task List View\n\n\nThe Task List View displays tasks in a scrollable list format with filtering, sorting, and grouping capabilities. In TaskNotes v4, this view operates as a Bases view configured through YAML.\nThis view is optimized for high task volume and explicit filter definitions.\n\n![Task List View](../assets/views-tasks-list.png)\n\n## Bases Architecture\n\nTask List is implemented as a `.base` file located in `TaskNotes/Views/tasks-default.base` by default. It requires the Bases core plugin to be enabled.\n\n### What is Bases?\n\nBases is an official Obsidian core plugin built directly into Obsidian (not a community plugin). It provides a framework for creating database views of notes and tasks.\n\nTo enable Bases:\n1. Open `Settings -> Core Plugins`\n2. Enable \"Bases\"\n3. TaskNotes view commands will now open `.base` files from `TaskNotes/Views/`\nIf commands open empty or unexpected views, first confirm Bases is enabled and the command path points to the intended `.base` file.\n\n### View File Location\n\nWhen you use the \"Open Tasks View\" command or ribbon icon, TaskNotes opens the `.base` file configured under `Settings -> TaskNotes -> General -> Views & base files` (initially `TaskNotes/Views/tasks-default.base`). TaskNotes creates missing default `.base` files automatically on startup when **Auto-create default files** is enabled, and you can point the command to any other `.base` file if you maintain multiple task-list layouts.\n\n## Configuration\n\nTask List views are configured through YAML frontmatter in the `.base` file. The YAML defines which tasks to show, how to sort them, and how to group them.\n\n### Basic Structure\n\n```yaml\n# All Tasks\n\nviews:\n - type: tasknotesTaskList\n name: \"All Tasks\"\n order:\n - note.status\n - note.priority\n - note.due\n - note.scheduled\n - note.projects\n - note.contexts\n - file.tags\n sort:\n - column: due\n direction: ASC\n```\n\n### Configuration Options\n\n**`type`**: Must be `tasknotesTaskList` for Task List views\n\n**`name`**: Display name shown in the view header\n\n**`order`**: Array of property names that control which task properties are visible in the task cards. Properties are referenced using their Bases property paths (e.g., `note.status`, `note.priority`, `note.due`, `file.tasks`).\nFor existing `.base` files, add `file.tasks` in YAML manually; once present in `order`, it appears in the Bases picker as `tasks`.\n\n**`sort`**: Array of sort criteria. Tasks are sorted by the first criterion, with ties broken by subsequent criteria.\n- `column`: Property to sort by (e.g., `due`, `scheduled`, `priority`, `title`)\n- `direction`: `ASC` (ascending) or `DESC` (descending)\n\n**`groupBy`**: Optional grouping configuration\n- `property`: Property to group by (e.g., `note.status`, `note.priority`)\n- `direction`: Sort direction for group headers\n\n**`hideTopLevelSubtasks`**: Optional boolean. When `true`, tasks whose Projects field links to another task in the current filtered result set are hidden as top-level rows and remain available through the parent task's expanded subtasks.\n\n**`filters`**: Optional filter conditions using Bases query syntax\n```yaml\nfilters:\n and:\n - note.status == \"Open\"\n - note.priority == \"High\"\n```\nStart with one or two simple filters, verify results, then layer complexity. Incremental edits are much easier to debug than large one-shot query rewrites.\n\n### Property Mapping\n\nTaskNotes properties are accessed in Bases YAML using these paths:\n\n| TaskNotes Property | Bases Property Path | Description |\n|-------------------|-------------------|-------------|\n| Status | `note.status` | Task status value |\n| Priority | `note.priority` | Priority level |\n| Due date | `note.due` | Due date/time |\n| Scheduled date | `note.scheduled` | Scheduled date/time |\n| Projects | `note.projects` | Associated projects |\n| Contexts | `note.contexts` | Task contexts |\n| Tags | `file.tags` | File tags |\n| Checklist progress | `file.tasks` | First-level markdown checkbox progress shown as the TaskNotes checklist progress bar |\n| Time estimate | `note.timeEstimate` | Estimated duration |\n| Recurrence | `note.recurrence` | Recurrence pattern |\n| Blocked by | `note.blockedBy` | Blocking dependencies |\n| Title | `file.name` | Task title (file name) |\n| Created | `file.ctime` | File creation date |\n| Modified | `file.mtime` | File modification date |\n\nThe exact property names depend on your TaskNotes field mapping settings (`Settings -> TaskNotes -> Task Properties`). The table above shows default mappings.\n\n## Filtering and Sorting\n\n### Adding Filters\n\nEdit the `.base` file to add filter conditions using Bases query syntax:\n\n```yaml\nviews:\n - type: tasknotesTaskList\n name: \"High Priority Tasks\"\n filters:\n and:\n - note.priority == \"High\"\n - note.status != \"Completed\"\n order:\n - note.status\n - note.priority\n - note.due\n```\n\n### Filter Operators\n\nBases supports standard comparison operators:\n- `==` (equals), `!=` (not equals)\n- `>`, `<`, `>=`, `<=` (comparison)\n- `contains()` (substring/array membership)\n- Boolean logic: `and`, `or`\n\nFor detailed filter syntax, see the [Bases documentation](https://help.obsidian.md/Plugins/Bases).\n\n### Sorting Examples\n\nSingle sort criterion:\n```yaml\nsort:\n - column: due\n direction: ASC\n```\n\nMultiple sort criteria:\n```yaml\nsort:\n - column: priority\n direction: DESC\n - column: due\n direction: ASC\n - column: title\n direction: ASC\n```\n\n### Drag-to-Reorder\n\nTask List supports drag-to-reorder when the view is sorted by the manual-order property. With the default field mapping, that property is `tasknotes_manual_order`.\n\nTo enable persistent manual ordering in a Task List view:\n\n```yaml\nsort:\n - column: tasknotes_manual_order\n direction: DESC\n```\n\nOnce the first sort criterion is the manual-order property, you can drag task cards to reorder them. TaskNotes writes updated LexoRank-style values into task frontmatter so the order persists across refreshes and sessions.\n\nIf your field mapping changes the sort-order property name, use that mapped property name instead of `tasknotes_manual_order`.\n\n### Drag-to-Reorder with Grouping\n\nGrouped Task List views can also be reordered, but the reorder scope is the current group. For example, when grouping by status, dragging within the \"In Progress\" group updates the manual order for tasks in that group.\n\nImportant constraints:\n\n- Drag-to-reorder only works when the view sort includes the manual-order property.\n- Reordering in formula-based groups is blocked because formula values are computed and cannot be edited directly.\n- In filtered or partially visible lists, TaskNotes may also update hidden or filtered notes in the same reorder scope to preserve a stable persistent order.\n- Large reorder operations may show a confirmation dialog before writing changes.\n\nThe default generated TaskNotes task-list templates include a **Manual Order** view that is already configured for this behavior.\n\n## Grouping\n\nGroups organize tasks under collapsible headers based on a property value.\n\n### Enable Grouping\n\nAdd `groupBy` configuration to your view:\n\n```yaml\nviews:\n - type: tasknotesTaskList\n name: \"Tasks by Status\"\n groupBy:\n property: note.status\n direction: ASC\n order:\n - note.status\n - note.priority\n - note.due\n```\n\n### Available Grouping Properties\n\nCommon grouping properties:\n- `note.status` - Group by task status\n- `note.priority` - Group by priority level\n- `note.contexts` - Group by first context\n- `note.projects` - Group by project (tasks can appear in multiple groups)\n\n### Interactive Group Headers\n\nGroup headers support interaction:\n- Click to expand/collapse the group\n- Click on project links in headers to navigate to project notes\n- Hover over project links with Ctrl to preview project notes\n\n### Collapsed State Persistence\n\nCollapsed/expanded state for each group is preserved across sessions.\n\n## Creating Multiple Views\n\nYou can create multiple `.base` files for different task perspectives:\n\n1. Duplicate an existing `.base` file in `TaskNotes/Views/`\n2. Rename it (e.g., `High Priority.base`)\n3. Edit the YAML configuration for that view\n4. Open the file to see the customized view\n\n### Example: Context-Specific View\n\n```yaml\n# Work Tasks\n\nviews:\n - type: tasknotesTaskList\n name: \"Work Context\"\n filters:\n and:\n - note.contexts.contains(\"work\")\n groupBy:\n property: note.priority\n direction: DESC\n order:\n - note.status\n - note.priority\n - note.due\n```\n\n## Migrating from v3 Saved Views\n\nTaskNotes v3 stored filter configurations in plugin settings. These saved views are **not automatically migrated** to v4.\n\nTo recreate a v3 saved view:\n1. Create a new `.base` file in `TaskNotes/Views/`\n2. Translate your v3 filter conditions to Bases YAML syntax\n3. Configure sorting and grouping through YAML\n4. Save the file\n\nThe v3 FilterBar UI component no longer exists - all configuration is done through YAML editing.\n\n## Task Actions\n\nThe Task List View provides interaction with tasks through clicking and context menus:\n\n- **Click on a task**: Opens the task for editing or navigates to the task note (behavior configured in `Settings -> TaskNotes -> General` in click-action controls)\n- **Right-click on a task**: Opens a context menu with actions:\n - Mark as complete\n - Change priority\n - Change status\n - Edit dates\n - Delete task\n - And more\n\nContext menu availability depends on your TaskNotes settings and task properties.\n\n## Virtual Scrolling\n\nThe Task List View automatically enables virtual scrolling when displaying 100 or more items (tasks + group headers). Virtual scrolling provides:\n\n- Approximately 90% memory reduction for large lists\n- Elimination of UI lag when scrolling through hundreds of tasks\n- Smooth performance with unlimited task counts\n\nVirtual scrolling activates automatically and requires no configuration. When active, only visible tasks are rendered to the DOM, with off-screen tasks rendered on-demand as you scroll.\n\n## Further Reading\n\n- [Default Base Templates](default-base-templates.md) - Complete templates for all TaskNotes views\n- [Bases Plugin Documentation](https://help.obsidian.md/Plugins/Bases) - Official Obsidian documentation for Bases syntax and features\n- [Kanban View](kanban-view.md) - Alternative board-based task visualization\n- [Calendar Views](calendar-views.md) - Time-based task visualization\n- [Views Overview](../views.md) - All available TaskNotes views\n","aliases":["/views/task-list/"],"toc":[{"level":2,"id":"bases-architecture","text":"Bases Architecture"},{"level":3,"id":"what-is-bases","text":"What is Bases?"},{"level":3,"id":"view-file-location","text":"View File Location"},{"level":2,"id":"configuration","text":"Configuration"},{"level":3,"id":"basic-structure","text":"Basic Structure"},{"level":3,"id":"configuration-options","text":"Configuration Options"},{"level":3,"id":"property-mapping","text":"Property Mapping"},{"level":2,"id":"filtering-and-sorting","text":"Filtering and Sorting"},{"level":3,"id":"adding-filters","text":"Adding Filters"},{"level":3,"id":"filter-operators","text":"Filter Operators"},{"level":3,"id":"sorting-examples","text":"Sorting Examples"},{"level":3,"id":"drag-to-reorder","text":"Drag-to-Reorder"},{"level":3,"id":"drag-to-reorder-with-grouping","text":"Drag-to-Reorder with Grouping"},{"level":2,"id":"grouping","text":"Grouping"},{"level":3,"id":"enable-grouping","text":"Enable Grouping"},{"level":3,"id":"available-grouping-properties","text":"Available Grouping Properties"},{"level":3,"id":"interactive-group-headers","text":"Interactive Group Headers"},{"level":3,"id":"collapsed-state-persistence","text":"Collapsed State Persistence"},{"level":2,"id":"creating-multiple-views","text":"Creating Multiple Views"},{"level":3,"id":"example-context-specific-view","text":"Example: Context-Specific View"},{"level":2,"id":"migrating-from-v3-saved-views","text":"Migrating from v3 Saved Views"},{"level":2,"id":"task-actions","text":"Task Actions"},{"level":2,"id":"virtual-scrolling","text":"Virtual Scrolling"},{"level":2,"id":"further-reading","text":"Further Reading"}],"html":"

The Task List View displays tasks in a scrollable list format with filtering, sorting, and grouping capabilities. In TaskNotes v4, this view operates as a Bases view configured through YAML.\nThis view is optimized for high task volume and explicit filter definitions.

\n

\"Task

\n

Bases Architecture#

\n

Task List is implemented as a .base file located in TaskNotes/Views/tasks-default.base by default. It requires the Bases core plugin to be enabled.

\n

What is Bases?#

\n

Bases is an official Obsidian core plugin built directly into Obsidian (not a community plugin). It provides a framework for creating database views of notes and tasks.

\n

To enable Bases:

\n
    \n
  1. Open Settings -> Core Plugins
  2. \n
  3. Enable "Bases"
  4. \n
  5. TaskNotes view commands will now open .base files from TaskNotes/Views/\nIf commands open empty or unexpected views, first confirm Bases is enabled and the command path points to the intended .base file.
  6. \n
\n

View File Location#

\n

When you use the "Open Tasks View" command or ribbon icon, TaskNotes opens the .base file configured under Settings -> TaskNotes -> General -> Views & base files (initially TaskNotes/Views/tasks-default.base). TaskNotes creates missing default .base files automatically on startup when Auto-create default files is enabled, and you can point the command to any other .base file if you maintain multiple task-list layouts.

\n

Configuration#

\n

Task List views are configured through YAML frontmatter in the .base file. The YAML defines which tasks to show, how to sort them, and how to group them.

\n

Basic Structure#

\n
# All Tasks\n\nviews:\n  - type: tasknotesTaskList\n    name: "All Tasks"\n    order:\n      - note.status\n      - note.priority\n      - note.due\n      - note.scheduled\n      - note.projects\n      - note.contexts\n      - file.tags\n    sort:\n      - column: due\n        direction: ASC\n

Configuration Options#

\n

type: Must be tasknotesTaskList for Task List views

\n

name: Display name shown in the view header

\n

order: Array of property names that control which task properties are visible in the task cards. Properties are referenced using their Bases property paths (e.g., note.status, note.priority, note.due, file.tasks).\nFor existing .base files, add file.tasks in YAML manually; once present in order, it appears in the Bases picker as tasks.

\n

sort: Array of sort criteria. Tasks are sorted by the first criterion, with ties broken by subsequent criteria.

\n
    \n
  • column: Property to sort by (e.g., due, scheduled, priority, title)
  • \n
  • direction: ASC (ascending) or DESC (descending)
  • \n
\n

groupBy: Optional grouping configuration

\n
    \n
  • property: Property to group by (e.g., note.status, note.priority)
  • \n
  • direction: Sort direction for group headers
  • \n
\n

hideTopLevelSubtasks: Optional boolean. When true, tasks whose Projects field links to another task in the current filtered result set are hidden as top-level rows and remain available through the parent task's expanded subtasks.

\n

filters: Optional filter conditions using Bases query syntax

\n
filters:\n  and:\n    - note.status == "Open"\n    - note.priority == "High"\n

Start with one or two simple filters, verify results, then layer complexity. Incremental edits are much easier to debug than large one-shot query rewrites.

\n

Property Mapping#

\n

TaskNotes properties are accessed in Bases YAML using these paths:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
TaskNotes PropertyBases Property PathDescription
Statusnote.statusTask status value
Prioritynote.priorityPriority level
Due datenote.dueDue date/time
Scheduled datenote.scheduledScheduled date/time
Projectsnote.projectsAssociated projects
Contextsnote.contextsTask contexts
Tagsfile.tagsFile tags
Checklist progressfile.tasksFirst-level markdown checkbox progress shown as the TaskNotes checklist progress bar
Time estimatenote.timeEstimateEstimated duration
Recurrencenote.recurrenceRecurrence pattern
Blocked bynote.blockedByBlocking dependencies
Titlefile.nameTask title (file name)
Createdfile.ctimeFile creation date
Modifiedfile.mtimeFile modification date
\n

The exact property names depend on your TaskNotes field mapping settings (Settings -> TaskNotes -> Task Properties). The table above shows default mappings.

\n

Filtering and Sorting#

\n

Adding Filters#

\n

Edit the .base file to add filter conditions using Bases query syntax:

\n
views:\n  - type: tasknotesTaskList\n    name: "High Priority Tasks"\n    filters:\n      and:\n        - note.priority == "High"\n        - note.status != "Completed"\n    order:\n      - note.status\n      - note.priority\n      - note.due\n

Filter Operators#

\n

Bases supports standard comparison operators:

\n
    \n
  • == (equals), != (not equals)
  • \n
  • >, <, >=, <= (comparison)
  • \n
  • contains() (substring/array membership)
  • \n
  • Boolean logic: and, or
  • \n
\n

For detailed filter syntax, see the Bases documentation.

\n

Sorting Examples#

\n

Single sort criterion:

\n
sort:\n  - column: due\n    direction: ASC\n

Multiple sort criteria:

\n
sort:\n  - column: priority\n    direction: DESC\n  - column: due\n    direction: ASC\n  - column: title\n    direction: ASC\n

Drag-to-Reorder#

\n

Task List supports drag-to-reorder when the view is sorted by the manual-order property. With the default field mapping, that property is tasknotes_manual_order.

\n

To enable persistent manual ordering in a Task List view:

\n
sort:\n  - column: tasknotes_manual_order\n    direction: DESC\n

Once the first sort criterion is the manual-order property, you can drag task cards to reorder them. TaskNotes writes updated LexoRank-style values into task frontmatter so the order persists across refreshes and sessions.

\n

If your field mapping changes the sort-order property name, use that mapped property name instead of tasknotes_manual_order.

\n

Drag-to-Reorder with Grouping#

\n

Grouped Task List views can also be reordered, but the reorder scope is the current group. For example, when grouping by status, dragging within the "In Progress" group updates the manual order for tasks in that group.

\n

Important constraints:

\n
    \n
  • Drag-to-reorder only works when the view sort includes the manual-order property.
  • \n
  • Reordering in formula-based groups is blocked because formula values are computed and cannot be edited directly.
  • \n
  • In filtered or partially visible lists, TaskNotes may also update hidden or filtered notes in the same reorder scope to preserve a stable persistent order.
  • \n
  • Large reorder operations may show a confirmation dialog before writing changes.
  • \n
\n

The default generated TaskNotes task-list templates include a Manual Order view that is already configured for this behavior.

\n

Grouping#

\n

Groups organize tasks under collapsible headers based on a property value.

\n

Enable Grouping#

\n

Add groupBy configuration to your view:

\n
views:\n  - type: tasknotesTaskList\n    name: "Tasks by Status"\n    groupBy:\n      property: note.status\n      direction: ASC\n    order:\n      - note.status\n      - note.priority\n      - note.due\n

Available Grouping Properties#

\n

Common grouping properties:

\n
    \n
  • note.status - Group by task status
  • \n
  • note.priority - Group by priority level
  • \n
  • note.contexts - Group by first context
  • \n
  • note.projects - Group by project (tasks can appear in multiple groups)
  • \n
\n

Interactive Group Headers#

\n

Group headers support interaction:

\n
    \n
  • Click to expand/collapse the group
  • \n
  • Click on project links in headers to navigate to project notes
  • \n
  • Hover over project links with Ctrl to preview project notes
  • \n
\n

Collapsed State Persistence#

\n

Collapsed/expanded state for each group is preserved across sessions.

\n

Creating Multiple Views#

\n

You can create multiple .base files for different task perspectives:

\n
    \n
  1. Duplicate an existing .base file in TaskNotes/Views/
  2. \n
  3. Rename it (e.g., High Priority.base)
  4. \n
  5. Edit the YAML configuration for that view
  6. \n
  7. Open the file to see the customized view
  8. \n
\n

Example: Context-Specific View#

\n
# Work Tasks\n\nviews:\n  - type: tasknotesTaskList\n    name: "Work Context"\n    filters:\n      and:\n        - note.contexts.contains("work")\n    groupBy:\n      property: note.priority\n      direction: DESC\n    order:\n      - note.status\n      - note.priority\n      - note.due\n

Migrating from v3 Saved Views#

\n

TaskNotes v3 stored filter configurations in plugin settings. These saved views are not automatically migrated to v4.

\n

To recreate a v3 saved view:

\n
    \n
  1. Create a new .base file in TaskNotes/Views/
  2. \n
  3. Translate your v3 filter conditions to Bases YAML syntax
  4. \n
  5. Configure sorting and grouping through YAML
  6. \n
  7. Save the file
  8. \n
\n

The v3 FilterBar UI component no longer exists - all configuration is done through YAML editing.

\n

Task Actions#

\n

The Task List View provides interaction with tasks through clicking and context menus:

\n
    \n
  • Click on a task: Opens the task for editing or navigates to the task note (behavior configured in Settings -> TaskNotes -> General in click-action controls)
  • \n
  • Right-click on a task: Opens a context menu with actions:
      \n
    • Mark as complete
    • \n
    • Change priority
    • \n
    • Change status
    • \n
    • Edit dates
    • \n
    • Delete task
    • \n
    • And more
    • \n
    \n
  • \n
\n

Context menu availability depends on your TaskNotes settings and task properties.

\n

Virtual Scrolling#

\n

The Task List View automatically enables virtual scrolling when displaying 100 or more items (tasks + group headers). Virtual scrolling provides:

\n
    \n
  • Approximately 90% memory reduction for large lists
  • \n
  • Elimination of UI lag when scrolling through hundreds of tasks
  • \n
  • Smooth performance with unlimited task counts
  • \n
\n

Virtual scrolling activates automatically and requires no configuration. When active, only visible tasks are rendered to the DOM, with off-screen tasks rendered on-demand as you scroll.

\n

Further Reading#

\n\n","text":"The Task List View displays tasks in a scrollable list format with filtering, sorting, and grouping capabilities. In TaskNotes v4, this view operates as a Bases view configured through YAML. This view is optimized for high task volume and explicit filter definitions. Bases Architecture# Task List is implemented as a .base file located in TaskNotes/Views/tasks-default.base by default. It requires the Bases core plugin to be enabled. What is Bases?# Bases is an official Obsidian core plugin built directly into Obsidian (not a community plugin). It provides a framework for creating database views of notes and tasks. To enable Bases: Open Settings -> Core Plugins Enable \"Bases\" TaskNotes view commands will now open .base files from TaskNotes/Views/ If commands open empty or unexpected views, first confirm Bases is enabled and the command path points to the intended .base file. View File Location# When you use the \"Open Tasks View\" command or ribbon icon, TaskNotes opens the .base file configured under Settings -> TaskNotes -> General -> Views & base files (initially TaskNotes/Views/tasks-default.base). TaskNotes creates missing default .base files automatically on startup when Auto-create default files is enabled, and you can point the command to any other .base file if you maintain multiple task-list layouts. Configuration# Task List views are configured through YAML frontmatter in the .base file. The YAML defines which tasks to show, how to sort them, and how to group them. Basic Structure# # All Tasks views: - type: tasknotesTaskList name: \"All Tasks\" order: - note.status - note.priority - note.due - note.scheduled - note.projects - note.contexts - file.tags sort: - column: due direction: ASC Configuration Options# type: Must be tasknotesTaskList for Task List views name: Display name shown in the view header order: Array of property names that control which task properties are visible in the task cards. Properties are referenced using their Bases property paths (e.g., note.status, note.priority, note.due, file.tasks). For existing .base files, add file.tasks in YAML manually; once present in order, it appears in the Bases picker as tasks. sort: Array of sort criteria. Tasks are sorted by the first criterion, with ties broken by subsequent criteria. column: Property to sort by (e.g., due, scheduled, priority, title) direction: ASC (ascending) or DESC (descending) groupBy: Optional grouping configuration property: Property to group by (e.g., note.status, note.priority) direction: Sort direction for group headers hideTopLevelSubtasks: Optional boolean. When true, tasks whose Projects field links to another task in the current filtered result set are hidden as top-level rows and remain available through the parent task's expanded subtasks. filters: Optional filter conditions using Bases query syntax filters: and: - note.status == \"Open\" - note.priority == \"High\" Start with one or two simple filters, verify results, then layer complexity. Incremental edits are much easier to debug than large one-shot query rewrites. Property Mapping# TaskNotes properties are accessed in Bases YAML using these paths: TaskNotes Property Bases Property Path Description Status note.status Task status value Priority note.priority Priority level Due date note.due Due date/time Scheduled date note.scheduled Scheduled date/time Projects note.projects Associated projects Contexts note.contexts Task contexts Tags file.tags File tags Checklist progress file.tasks First-level markdown checkbox progress shown as the TaskNotes checklist progress bar Time estimate note.timeEstimate Estimated duration Recurrence note.recurrence Recurrence pattern Blocked by note.blockedBy Blocking dependencies Title file.name Task title (file name) Created file.ctime File creation date Modified file.mtime File modification date The exact property names depend on your TaskNotes field mapping settings (Settings -> TaskNotes -> Task Properties). The table above shows default mappings. Filtering and Sorting# Adding Filters# Edit the .base file to add filter conditions using Bases query syntax: views: - type: tasknotesTaskList name: \"High Priority Tasks\" filters: and: - note.priority == \"High\" - note.status != \"Completed\" order: - note.status - note.priority - note.due Filter Operators# Bases supports standard comparison operators: == (equals), != (not equals) >, <, >=, <= (comparison) contains() (substring/array membership) Boolean logic: and, or For detailed filter syntax, see the Bases documentation. Sorting Examples# Single sort criterion: sort: - column: due direction: ASC Multiple sort criteria: sort: - column: priority direction: DESC - column: due direction: ASC - column: title direction: ASC Drag-to-Reorder# Task List supports drag-to-reorder when the view is sorted by the manual-order property. With the default field mapping, that property is tasknotes_manual_order. To enable persistent manual ordering in a Task List view: sort: - column: tasknotes_manual_order direction: DESC Once the first sort criterion is the manual-order property, you can drag task cards to reorder them. TaskNotes writes updated LexoRank-style values into task frontmatter so the order persists across refreshes and sessions. If your field mapping changes the sort-order property name, use that mapped property name instead of tasknotes_manual_order. Drag-to-Reorder with Grouping# Grouped Task List views can also be reordered, but the reorder scope is the current group. For example, when grouping by status, dragging within the \"In Progress\" group updates the manual order for tasks in that group. Important constraints: Drag-to-reorder only works when the view sort includes the manual-order property. Reordering in formula-based groups is blocked because formula values are computed and cannot be edited directly. In filtered or partially visible lists, TaskNotes may also update hidden or filtered notes in the same reorder scope to preserve a stable persistent order. Large reorder operations may show a confirmation dialog before writing changes. The default generated TaskNotes task-list templates include a Manual Order view that is already configured for this behavior. Grouping# Groups organize tasks under collapsible headers based on a property value. Enable Grouping# Add groupBy configuration to your view: views: - type: tasknotesTaskList name: \"Tasks by Status\" groupBy: property: note.status direction: ASC order: - note.status - note.priority - note.due Available Grouping Properties# Common grouping properties: note.status - Group by task status note.priority - Group by priority level note.contexts - Group by first context note.projects - Group by project (tasks can appear in multiple groups) Interactive Group Headers# Group headers support interaction: Click to expand/collapse the group Click on project links in headers to navigate to project notes Hover over project links with Ctrl to preview project notes Collapsed State Persistence# Collapsed/expanded state for each group is preserved across sessions. Creating Multiple Views# You can create multiple .base files for different task perspectives: Duplicate an existing .base file in TaskNotes/Views/ Rename it (e.g., High Priority.base) Edit the YAML configuration for that view Open the file to see the customized view Example: Context-Specific View# # Work Tasks views: - type: tasknotesTaskList name: \"Work Context\" filters: and: - note.contexts.contains(\"work\") groupBy: property: note.priority direction: DESC order: - note.status - note.priority - note.due Migrating from v3 Saved Views# TaskNotes v3 stored filter configurations in plugin settings. These saved views are not automatically migrated to v4. To recreate a v3 saved view: Create a new .base file in TaskNotes/Views/ Translate your v3 filter conditions to Bases YAML syntax Configure sorting and grouping through YAML Save the file The v3 FilterBar UI component no longer exists - all configuration is done through YAML editing. Task Actions# The Task List View provides interaction with tasks through clicking and context menus: Click on a task: Opens the task for editing or navigates to the task note (behavior configured in Settings -> TaskNotes -> General in click-action controls) Right-click on a task: Opens a context menu with actions: Mark as complete Change priority Change status Edit dates Delete task And more Context menu availability depends on your TaskNotes settings and task properties. Virtual Scrolling# The Task List View automatically enables virtual scrolling when displaying 100 or more items (tasks + group headers). Virtual scrolling provides: Approximately 90% memory reduction for large lists Elimination of UI lag when scrolling through hundreds of tasks Smooth performance with unlimited task counts Virtual scrolling activates automatically and requires no configuration. When active, only visible tasks are rendered to the DOM, with off-screen tasks rendered on-demand as you scroll. Further Reading# Default Base Templates - Complete templates for all TaskNotes views Bases Plugin Documentation - Official Obsidian documentation for Bases syntax and features Kanban View - Alternative board-based task visualization Calendar Views - Time-based task visualization Views Overview - All available TaskNotes views"},{"route":"/obsidian/webhooks/","title":"TaskNotes Webhooks","description":"TaskNotes webhooks send HTTP POST requests when selected events occur.","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/webhooks.md","namespace":"obsidian","relativePath":"webhooks.md","raw":"# TaskNotes Webhooks\n\nTaskNotes webhooks send HTTP POST requests when selected events occur.\n\n## Prerequisites\n\n1. Enable HTTP API in `Settings -> TaskNotes -> Integrations -> HTTP API`.\n2. Create at least one webhook (settings UI or API).\n3. Subscribe it to one or more events.\n\n## Event Types\n\nTask events:\n\n- `task.created`\n- `task.updated`\n- `task.deleted`\n- `task.completed`\n- `task.archived`\n- `task.unarchived`\n\nTime events:\n\n- `time.started`\n- `time.stopped`\n\nPomodoro events:\n\n- `pomodoro.started`\n- `pomodoro.completed`\n- `pomodoro.interrupted`\n\nRecurring events:\n\n- `recurring.instance.completed`\n- `recurring.instance.skipped`\n\nCompleting a materialized occurrence note emits `recurring.instance.completed` with the reconciled parent task plus the completed `occurrence` and `date` in the event data. Skipping virtual recurring instances emits `recurring.instance.skipped`; materialized occurrence skip currently reconciles the parent and occurrence note without emitting a separate skip webhook.\n\nReminder events:\n\n- `reminder.triggered`\n\n## Payload Shape\n\nAll webhook payloads use the same top-level envelope:\n\n```json\n{\n \"event\": \"task.created\",\n \"timestamp\": \"2026-02-21T10:30:00.000Z\",\n \"vault\": {\n \"name\": \"My Vault\",\n \"path\": \"/path/to/vault\"\n },\n \"data\": {}\n}\n```\n\n`data` is event-specific.\n\n## Register and Manage Webhooks via API\n\n### Create\n\n`POST /api/webhooks`\n\nRequired fields:\n\n- `url` (string)\n- `events` (non-empty array)\n\nOptional fields:\n\n- `id`\n- `secret` (auto-generated if omitted)\n- `active` (default `true`)\n- `transformFile`\n- `corsHeaders` (default `true`)\n\nExample:\n\n```bash\ncurl -X POST http://localhost:8080/api/webhooks \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"url\": \"https://example.com/tasknotes\",\n \"events\": [\"task.completed\", \"task.created\"],\n \"transformFile\": \"TaskNotes/webhooks/slack.json\"\n }'\n```\n\n### List\n\n`GET /api/webhooks`\n\nReturns registered hooks. Secrets are not returned.\n\n### Delete\n\n`DELETE /api/webhooks/:id`\n\n### Delivery History\n\n`GET /api/webhooks/deliveries`\n\nReturns last 100 in-memory deliveries.\n\n## Delivery Behavior\n\nCurrent implementation behavior:\n\n- Webhook processing is asynchronous (fire-and-forget from task operation).\n- Each delivery starts with one attempt.\n- Failed deliveries retry with exponential backoff: `1s`, `2s`, `4s`.\n- Maximum retries: `3` retries after initial attempt (up to 4 attempts total).\n- If cumulative `failureCount` for a webhook exceeds `10`, webhook is auto-disabled.\n- No explicit request timeout is set in delivery fetch.\n\nBecause retries and duplicates are possible, handlers should be idempotent.\n\n## Signature Verification\n\nWhen `corsHeaders` is enabled (default), delivery includes:\n\n- `X-TaskNotes-Event`\n- `X-TaskNotes-Signature`\n- `X-TaskNotes-Delivery-ID`\n\nSignature is HMAC-SHA256 over `JSON.stringify(payload)` using webhook `secret`.\n\nNode.js example:\n\n```javascript\nconst crypto = require(\"crypto\");\n\nfunction verifyWebhook(payload, signature, secret) {\n const expected = crypto\n .createHmac(\"sha256\", secret)\n .update(JSON.stringify(payload))\n .digest(\"hex\");\n return signature === expected;\n}\n```\n\n## Payload Transformations\n\nA webhook can specify `transformFile` pointing to a file in your vault.\n\nSupported file types:\n\n- `.json`: event template map with variable interpolation\n\nIf transform execution fails, TaskNotes falls back to original payload.\n\nJavaScript transform files are no longer supported.\n\n### JSON Transform Files\n\nStructure:\n\n```json\n{\n \"task.completed\": {\n \"text\": \"Task completed: ${data.task.title}\",\n \"vault\": \"${vault.name}\"\n },\n \"default\": {\n \"text\": \"TaskNotes event: ${event}\"\n }\n}\n```\n\nRules:\n\n- Matching order: exact event key, then `default`.\n- Variables use `${path.to.value}`.\n- Missing variables are left unchanged.\n\n## CORS and Headers\n\nWebhook delivery requests are outbound server-side requests from TaskNotes.\n\n`corsHeaders` behavior:\n\n- `true` (default): sends TaskNotes custom headers including signature.\n- `false`: only sends `Content-Type: application/json`.\n\nDisable custom headers for endpoints that reject non-standard headers.\n\n## Testing\n\n### Local Test Server\n\nUse repository script:\n\n```bash\nnode test-webhook.js\n```\n\nOptional custom port:\n\n```bash\nnode test-webhook.js 8080\n```\n\nDefault server values:\n\n- URL: `http://localhost:3000/webhook`\n- Test secret: `test-secret-key-for-tasknotes-webhooks`\n\n### External Inspection\n\nFor quick inspection, use a request-bin tool such as `webhook.site`.\n\n## Troubleshooting\n\n### No deliveries\n\n1. Confirm HTTP API is enabled.\n2. Confirm webhook is active.\n3. Confirm event is subscribed.\n\n### Signature mismatch\n\n1. Confirm secret matches webhook config.\n2. Verify your verifier hashes the exact JSON body.\n3. Verify hex digest comparison.\n\n### Webhook disabled automatically\n\nIf failures continue and `failureCount` exceeds 10, webhook is disabled.\n\n1. Fix endpoint availability or response handling.\n2. Re-enable webhook in TaskNotes settings, or recreate it via `POST /api/webhooks`.\n\n### Transform errors\n\n1. Confirm `transformFile` exists in vault.\n2. Confirm the file is a `.json` transform template.\n3. Check Obsidian console logs for transform exceptions.\n","aliases":["/webhooks/"],"toc":[{"level":2,"id":"prerequisites","text":"Prerequisites"},{"level":2,"id":"event-types","text":"Event Types"},{"level":2,"id":"payload-shape","text":"Payload Shape"},{"level":2,"id":"register-and-manage-webhooks-via-api","text":"Register and Manage Webhooks via API"},{"level":3,"id":"create","text":"Create"},{"level":3,"id":"list","text":"List"},{"level":3,"id":"delete","text":"Delete"},{"level":3,"id":"delivery-history","text":"Delivery History"},{"level":2,"id":"delivery-behavior","text":"Delivery Behavior"},{"level":2,"id":"signature-verification","text":"Signature Verification"},{"level":2,"id":"payload-transformations","text":"Payload Transformations"},{"level":3,"id":"json-transform-files","text":"JSON Transform Files"},{"level":2,"id":"cors-and-headers","text":"CORS and Headers"},{"level":2,"id":"testing","text":"Testing"},{"level":3,"id":"local-test-server","text":"Local Test Server"},{"level":3,"id":"external-inspection","text":"External Inspection"},{"level":2,"id":"troubleshooting","text":"Troubleshooting"},{"level":3,"id":"no-deliveries","text":"No deliveries"},{"level":3,"id":"signature-mismatch","text":"Signature mismatch"},{"level":3,"id":"webhook-disabled-automatically","text":"Webhook disabled automatically"},{"level":3,"id":"transform-errors","text":"Transform errors"}],"html":"

TaskNotes webhooks send HTTP POST requests when selected events occur.

\n

Prerequisites#

\n
    \n
  1. Enable HTTP API in Settings -> TaskNotes -> Integrations -> HTTP API.
  2. \n
  3. Create at least one webhook (settings UI or API).
  4. \n
  5. Subscribe it to one or more events.
  6. \n
\n

Event Types#

\n

Task events:

\n
    \n
  • task.created
  • \n
  • task.updated
  • \n
  • task.deleted
  • \n
  • task.completed
  • \n
  • task.archived
  • \n
  • task.unarchived
  • \n
\n

Time events:

\n
    \n
  • time.started
  • \n
  • time.stopped
  • \n
\n

Pomodoro events:

\n
    \n
  • pomodoro.started
  • \n
  • pomodoro.completed
  • \n
  • pomodoro.interrupted
  • \n
\n

Recurring events:

\n
    \n
  • recurring.instance.completed
  • \n
  • recurring.instance.skipped
  • \n
\n

Completing a materialized occurrence note emits recurring.instance.completed with the reconciled parent task plus the completed occurrence and date in the event data. Skipping virtual recurring instances emits recurring.instance.skipped; materialized occurrence skip currently reconciles the parent and occurrence note without emitting a separate skip webhook.

\n

Reminder events:

\n
    \n
  • reminder.triggered
  • \n
\n

Payload Shape#

\n

All webhook payloads use the same top-level envelope:

\n
{\n  "event": "task.created",\n  "timestamp": "2026-02-21T10:30:00.000Z",\n  "vault": {\n    "name": "My Vault",\n    "path": "/path/to/vault"\n  },\n  "data": {}\n}\n

data is event-specific.

\n

Register and Manage Webhooks via API#

\n

Create#

\n

POST /api/webhooks

\n

Required fields:

\n
    \n
  • url (string)
  • \n
  • events (non-empty array)
  • \n
\n

Optional fields:

\n
    \n
  • id
  • \n
  • secret (auto-generated if omitted)
  • \n
  • active (default true)
  • \n
  • transformFile
  • \n
  • corsHeaders (default true)
  • \n
\n

Example:

\n
curl -X POST http://localhost:8080/api/webhooks \\\n  -H "Content-Type: application/json" \\\n  -d '{\n    "url": "https://example.com/tasknotes",\n    "events": ["task.completed", "task.created"],\n    "transformFile": "TaskNotes/webhooks/slack.json"\n  }'\n

List#

\n

GET /api/webhooks

\n

Returns registered hooks. Secrets are not returned.

\n

Delete#

\n

DELETE /api/webhooks/:id

\n

Delivery History#

\n

GET /api/webhooks/deliveries

\n

Returns last 100 in-memory deliveries.

\n

Delivery Behavior#

\n

Current implementation behavior:

\n
    \n
  • Webhook processing is asynchronous (fire-and-forget from task operation).
  • \n
  • Each delivery starts with one attempt.
  • \n
  • Failed deliveries retry with exponential backoff: 1s, 2s, 4s.
  • \n
  • Maximum retries: 3 retries after initial attempt (up to 4 attempts total).
  • \n
  • If cumulative failureCount for a webhook exceeds 10, webhook is auto-disabled.
  • \n
  • No explicit request timeout is set in delivery fetch.
  • \n
\n

Because retries and duplicates are possible, handlers should be idempotent.

\n

Signature Verification#

\n

When corsHeaders is enabled (default), delivery includes:

\n
    \n
  • X-TaskNotes-Event
  • \n
  • X-TaskNotes-Signature
  • \n
  • X-TaskNotes-Delivery-ID
  • \n
\n

Signature is HMAC-SHA256 over JSON.stringify(payload) using webhook secret.

\n

Node.js example:

\n
const crypto = require("crypto");\n\nfunction verifyWebhook(payload, signature, secret) {\n  const expected = crypto\n    .createHmac("sha256", secret)\n    .update(JSON.stringify(payload))\n    .digest("hex");\n  return signature === expected;\n}\n

Payload Transformations#

\n

A webhook can specify transformFile pointing to a file in your vault.

\n

Supported file types:

\n
    \n
  • .json: event template map with variable interpolation
  • \n
\n

If transform execution fails, TaskNotes falls back to original payload.

\n

JavaScript transform files are no longer supported.

\n

JSON Transform Files#

\n

Structure:

\n
{\n  "task.completed": {\n    "text": "Task completed: ${data.task.title}",\n    "vault": "${vault.name}"\n  },\n  "default": {\n    "text": "TaskNotes event: ${event}"\n  }\n}\n

Rules:

\n
    \n
  • Matching order: exact event key, then default.
  • \n
  • Variables use ${path.to.value}.
  • \n
  • Missing variables are left unchanged.
  • \n
\n

CORS and Headers#

\n

Webhook delivery requests are outbound server-side requests from TaskNotes.

\n

corsHeaders behavior:

\n
    \n
  • true (default): sends TaskNotes custom headers including signature.
  • \n
  • false: only sends Content-Type: application/json.
  • \n
\n

Disable custom headers for endpoints that reject non-standard headers.

\n

Testing#

\n

Local Test Server#

\n

Use repository script:

\n
node test-webhook.js\n

Optional custom port:

\n
node test-webhook.js 8080\n

Default server values:

\n
    \n
  • URL: http://localhost:3000/webhook
  • \n
  • Test secret: test-secret-key-for-tasknotes-webhooks
  • \n
\n

External Inspection#

\n

For quick inspection, use a request-bin tool such as webhook.site.

\n

Troubleshooting#

\n

No deliveries#

\n
    \n
  1. Confirm HTTP API is enabled.
  2. \n
  3. Confirm webhook is active.
  4. \n
  5. Confirm event is subscribed.
  6. \n
\n

Signature mismatch#

\n
    \n
  1. Confirm secret matches webhook config.
  2. \n
  3. Verify your verifier hashes the exact JSON body.
  4. \n
  5. Verify hex digest comparison.
  6. \n
\n

Webhook disabled automatically#

\n

If failures continue and failureCount exceeds 10, webhook is disabled.

\n
    \n
  1. Fix endpoint availability or response handling.
  2. \n
  3. Re-enable webhook in TaskNotes settings, or recreate it via POST /api/webhooks.
  4. \n
\n

Transform errors#

\n
    \n
  1. Confirm transformFile exists in vault.
  2. \n
  3. Confirm the file is a .json transform template.
  4. \n
  5. Check Obsidian console logs for transform exceptions.
  6. \n
\n","text":"TaskNotes webhooks send HTTP POST requests when selected events occur. Prerequisites# Enable HTTP API in Settings -> TaskNotes -> Integrations -> HTTP API. Create at least one webhook (settings UI or API). Subscribe it to one or more events. Event Types# Task events: task.created task.updated task.deleted task.completed task.archived task.unarchived Time events: time.started time.stopped Pomodoro events: pomodoro.started pomodoro.completed pomodoro.interrupted Recurring events: recurring.instance.completed recurring.instance.skipped Completing a materialized occurrence note emits recurring.instance.completed with the reconciled parent task plus the completed occurrence and date in the event data. Skipping virtual recurring instances emits recurring.instance.skipped; materialized occurrence skip currently reconciles the parent and occurrence note without emitting a separate skip webhook. Reminder events: reminder.triggered Payload Shape# All webhook payloads use the same top-level envelope: { \"event\": \"task.created\", \"timestamp\": \"2026-02-21T10:30:00.000Z\", \"vault\": { \"name\": \"My Vault\", \"path\": \"/path/to/vault\" }, \"data\": {} } data is event-specific. Register and Manage Webhooks via API# Create# POST /api/webhooks Required fields: url (string) events (non-empty array) Optional fields: id secret (auto-generated if omitted) active (default true) transformFile corsHeaders (default true) Example: curl -X POST http://localhost:8080/api/webhooks \\ -H \"Content-Type: application/json\" \\ -d '{ \"url\": \"https://example.com/tasknotes\", \"events\": [\"task.completed\", \"task.created\"], \"transformFile\": \"TaskNotes/webhooks/slack.json\" }' List# GET /api/webhooks Returns registered hooks. Secrets are not returned. Delete# DELETE /api/webhooks/:id Delivery History# GET /api/webhooks/deliveries Returns last 100 in-memory deliveries. Delivery Behavior# Current implementation behavior: Webhook processing is asynchronous (fire-and-forget from task operation). Each delivery starts with one attempt. Failed deliveries retry with exponential backoff: 1s, 2s, 4s. Maximum retries: 3 retries after initial attempt (up to 4 attempts total). If cumulative failureCount for a webhook exceeds 10, webhook is auto-disabled. No explicit request timeout is set in delivery fetch. Because retries and duplicates are possible, handlers should be idempotent. Signature Verification# When corsHeaders is enabled (default), delivery includes: X-TaskNotes-Event X-TaskNotes-Signature X-TaskNotes-Delivery-ID Signature is HMAC-SHA256 over JSON.stringify(payload) using webhook secret. Node.js example: const crypto = require(\"crypto\"); function verifyWebhook(payload, signature, secret) { const expected = crypto .createHmac(\"sha256\", secret) .update(JSON.stringify(payload)) .digest(\"hex\"); return signature === expected; } Payload Transformations# A webhook can specify transformFile pointing to a file in your vault. Supported file types: .json: event template map with variable interpolation If transform execution fails, TaskNotes falls back to original payload. JavaScript transform files are no longer supported. JSON Transform Files# Structure: { \"task.completed\": { \"text\": \"Task completed: ${data.task.title}\", \"vault\": \"${vault.name}\" }, \"default\": { \"text\": \"TaskNotes event: ${event}\" } } Rules: Matching order: exact event key, then default. Variables use ${path.to.value}. Missing variables are left unchanged. CORS and Headers# Webhook delivery requests are outbound server-side requests from TaskNotes. corsHeaders behavior: true (default): sends TaskNotes custom headers including signature. false: only sends Content-Type: application/json. Disable custom headers for endpoints that reject non-standard headers. Testing# Local Test Server# Use repository script: node test-webhook.js Optional custom port: node test-webhook.js 8080 Default server values: URL: http://localhost:3000/webhook Test secret: test-secret-key-for-tasknotes-webhooks External Inspection# For quick inspection, use a request-bin tool such as webhook.site. Troubleshooting# No deliveries# Confirm HTTP API is enabled. Confirm webhook is active. Confirm event is subscribed. Signature mismatch# Confirm secret matches webhook config. Verify your verifier hashes the exact JSON body. Verify hex digest comparison. Webhook disabled automatically# If failures continue and failureCount exceeds 10, webhook is disabled. Fix endpoint availability or response handling. Re-enable webhook in TaskNotes settings, or recreate it via POST /api/webhooks. Transform errors# Confirm transformFile exists in vault. Confirm the file is a .json transform template. Check Obsidian console logs for transform exceptions."},{"route":"/obsidian/workflows/","title":"Workflows","description":"This page describes practical ways to combine TaskNotes features into repeatable workflows. The goal is to show how recurring tasks, projects, filtering, and scheduling fit toge...","product":"obsidian","platforms":[],"version":"4.12.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/workflows.md","namespace":"obsidian","relativePath":"workflows.md","raw":"# Workflows\n\nThis page describes practical ways to combine TaskNotes features into repeatable workflows. The goal is to show how recurring tasks, projects, filtering, and scheduling fit together in everyday use.\n\n## Habit Tracking with Recurring Tasks\n\nHabit tracking in TaskNotes is built on recurring task notes. You can create a recurring task from natural language (for example, \"Exercise daily\" or \"Gym every Monday and Wednesday\") or configure recurrence explicitly in the task modal. The modal recurrence controls support frequency, interval, weekday selection, and end conditions.\n\nOnce a task has a recurrence rule, its edit modal shows a recurrence calendar. That calendar is where you mark completion per occurrence. Completion history is stored in `complete_instances`, so a recurring task can remain open while still recording daily/weekly completion behavior.\n\n![Recurring task calendar](assets/views-calendar-month.png)\n\n```yaml\ntitle: Morning Exercise\nrecurrence: \"FREQ=DAILY\"\nscheduled: \"07:00\"\ncomplete_instances:\n - \"2025-01-01\"\n - \"2025-01-02\"\n - \"2025-01-04\"\n```\n\nUse Calendar and Agenda views to review upcoming occurrences, and use recurring-task filters when you want a habit-only planning view.\n\nFor richer recurring work, such as a weekly review or maintenance visit, right-click the recurrence in a task card, calendar view, or the edit modal's completion calendar and choose **Open or create occurrence note**. The occurrence note inherits planning metadata such as scheduled time, due offset, projects, tags, reminders, details, and time estimate, then keeps its own checklist, completion state, and time entries while the parent recurring task keeps the long-term rule. On the calendar, the note-backed occurrence replaces the matching virtual parent occurrence; dragging it reschedules that note without rewriting the recurrence pattern.\n\n## Project-Centered Planning\n\nProjects in TaskNotes can be plain text values or wikilinks to project notes. Wikilinks are usually the better long-term option because they connect task execution to project context, backlinks, and graph navigation.\n\n```yaml\ntitle: \"Research competitors\"\nprojects: [\"[[Market Research]]\", \"[[Q1 Strategy]]\"]\n```\n\nDuring task creation, use the project picker to search and assign one or more projects. In day-to-day planning, open Task List or Kanban, then filter on `note.projects contains [[Project Name]]` to isolate one initiative. Save that filter as a Bases saved view if you revisit it regularly.\n\n![Task list view](assets/views-tasks-list.png)\n\nWhen work spans initiatives, assign multiple projects and combine with contexts or tags for secondary organization.\n\n```yaml\ntitle: \"Prepare presentation slides\"\nprojects: [\"[[Q4 Planning]]\"]\ncontexts: [\"computer\", \"office\"]\ntags: [\"review\"]\n```\n\n## Execution Workflow (Daily)\n\nA typical daily flow is to start in Task List for prioritization, move to Calendar for schedule placement, and finish in Agenda for near-term sequencing. This keeps backlog management, time allocation, and short-horizon execution in one system.\n\nIf you use timeboxing, drag-select on calendar timeline views and create timeblocks directly from the context menu. If you use Pomodoro, run sessions against active tasks so completion and timing data stay attached to task notes.\n\n![Calendar quick add workflow](assets/workflow-quick-add-calendar.png)\n\n## Maintenance Workflow (Weekly)\n\nA weekly review usually includes three steps: clean up completed/archived tasks, verify recurring-task completion patterns, and rebalance project filters/views. If calendar integrations are enabled, this is also a good point to refresh subscriptions and confirm sync health.\n\nFor teams or complex personal systems, keep project notes as source-of-truth documents and use TaskNotes views as execution dashboards derived from those notes.\n","aliases":["/workflows/"],"toc":[{"level":2,"id":"habit-tracking-with-recurring-tasks","text":"Habit Tracking with Recurring Tasks"},{"level":2,"id":"project-centered-planning","text":"Project-Centered Planning"},{"level":2,"id":"execution-workflow-daily","text":"Execution Workflow (Daily)"},{"level":2,"id":"maintenance-workflow-weekly","text":"Maintenance Workflow (Weekly)"}],"html":"

This page describes practical ways to combine TaskNotes features into repeatable workflows. The goal is to show how recurring tasks, projects, filtering, and scheduling fit together in everyday use.

\n

Habit Tracking with Recurring Tasks#

\n

Habit tracking in TaskNotes is built on recurring task notes. You can create a recurring task from natural language (for example, "Exercise daily" or "Gym every Monday and Wednesday") or configure recurrence explicitly in the task modal. The modal recurrence controls support frequency, interval, weekday selection, and end conditions.

\n

Once a task has a recurrence rule, its edit modal shows a recurrence calendar. That calendar is where you mark completion per occurrence. Completion history is stored in complete_instances, so a recurring task can remain open while still recording daily/weekly completion behavior.

\n

\"Recurring

\n
title: Morning Exercise\nrecurrence: "FREQ=DAILY"\nscheduled: "07:00"\ncomplete_instances:\n  - "2025-01-01"\n  - "2025-01-02"\n  - "2025-01-04"\n

Use Calendar and Agenda views to review upcoming occurrences, and use recurring-task filters when you want a habit-only planning view.

\n

For richer recurring work, such as a weekly review or maintenance visit, right-click the recurrence in a task card, calendar view, or the edit modal's completion calendar and choose Open or create occurrence note. The occurrence note inherits planning metadata such as scheduled time, due offset, projects, tags, reminders, details, and time estimate, then keeps its own checklist, completion state, and time entries while the parent recurring task keeps the long-term rule. On the calendar, the note-backed occurrence replaces the matching virtual parent occurrence; dragging it reschedules that note without rewriting the recurrence pattern.

\n

Project-Centered Planning#

\n

Projects in TaskNotes can be plain text values or wikilinks to project notes. Wikilinks are usually the better long-term option because they connect task execution to project context, backlinks, and graph navigation.

\n
title: "Research competitors"\nprojects: ["[[Market Research]]", "[[Q1 Strategy]]"]\n

During task creation, use the project picker to search and assign one or more projects. In day-to-day planning, open Task List or Kanban, then filter on note.projects contains [[Project Name]] to isolate one initiative. Save that filter as a Bases saved view if you revisit it regularly.

\n

\"Task

\n

When work spans initiatives, assign multiple projects and combine with contexts or tags for secondary organization.

\n
title: "Prepare presentation slides"\nprojects: ["[[Q4 Planning]]"]\ncontexts: ["computer", "office"]\ntags: ["review"]\n

Execution Workflow (Daily)#

\n

A typical daily flow is to start in Task List for prioritization, move to Calendar for schedule placement, and finish in Agenda for near-term sequencing. This keeps backlog management, time allocation, and short-horizon execution in one system.

\n

If you use timeboxing, drag-select on calendar timeline views and create timeblocks directly from the context menu. If you use Pomodoro, run sessions against active tasks so completion and timing data stay attached to task notes.

\n

\"Calendar

\n

Maintenance Workflow (Weekly)#

\n

A weekly review usually includes three steps: clean up completed/archived tasks, verify recurring-task completion patterns, and rebalance project filters/views. If calendar integrations are enabled, this is also a good point to refresh subscriptions and confirm sync health.

\n

For teams or complex personal systems, keep project notes as source-of-truth documents and use TaskNotes views as execution dashboards derived from those notes.

\n","text":"This page describes practical ways to combine TaskNotes features into repeatable workflows. The goal is to show how recurring tasks, projects, filtering, and scheduling fit together in everyday use. Habit Tracking with Recurring Tasks# Habit tracking in TaskNotes is built on recurring task notes. You can create a recurring task from natural language (for example, \"Exercise daily\" or \"Gym every Monday and Wednesday\") or configure recurrence explicitly in the task modal. The modal recurrence controls support frequency, interval, weekday selection, and end conditions. Once a task has a recurrence rule, its edit modal shows a recurrence calendar. That calendar is where you mark completion per occurrence. Completion history is stored in complete_instances, so a recurring task can remain open while still recording daily/weekly completion behavior. title: Morning Exercise recurrence: \"FREQ=DAILY\" scheduled: \"07:00\" complete_instances: - \"2025-01-01\" - \"2025-01-02\" - \"2025-01-04\" Use Calendar and Agenda views to review upcoming occurrences, and use recurring-task filters when you want a habit-only planning view. For richer recurring work, such as a weekly review or maintenance visit, right-click the recurrence in a task card, calendar view, or the edit modal's completion calendar and choose Open or create occurrence note. The occurrence note inherits planning metadata such as scheduled time, due offset, projects, tags, reminders, details, and time estimate, then keeps its own checklist, completion state, and time entries while the parent recurring task keeps the long-term rule. On the calendar, the note-backed occurrence replaces the matching virtual parent occurrence; dragging it reschedules that note without rewriting the recurrence pattern. Project-Centered Planning# Projects in TaskNotes can be plain text values or wikilinks to project notes. Wikilinks are usually the better long-term option because they connect task execution to project context, backlinks, and graph navigation. title: \"Research competitors\" projects: [\"[[Market Research]]\", \"[[Q1 Strategy]]\"] During task creation, use the project picker to search and assign one or more projects. In day-to-day planning, open Task List or Kanban, then filter on note.projects contains [[Project Name]] to isolate one initiative. Save that filter as a Bases saved view if you revisit it regularly. When work spans initiatives, assign multiple projects and combine with contexts or tags for secondary organization. title: \"Prepare presentation slides\" projects: [\"[[Q4 Planning]]\"] contexts: [\"computer\", \"office\"] tags: [\"review\"] Execution Workflow (Daily)# A typical daily flow is to start in Task List for prioritization, move to Calendar for schedule placement, and finish in Agenda for near-term sequencing. This keeps backlog management, time allocation, and short-horizon execution in one system. If you use timeboxing, drag-select on calendar timeline views and create timeblocks directly from the context menu. If you use Pomodoro, run sessions against active tasks so completion and timing data stay attached to task notes. Maintenance Workflow (Weekly)# A weekly review usually includes three steps: clean up completed/archived tasks, verify recurring-task completion patterns, and rebalance project filters/views. If calendar integrations are enabled, this is also a good point to refresh subscriptions and confirm sync health. For teams or complex personal systems, keep project notes as source-of-truth documents and use TaskNotes views as execution dashboards derived from those notes."},{"route":"/privacy/","title":"TaskNotes privacy overview","description":"How the TaskNotes app and Obsidian plugin store data and when optional services are involved.","product":"shared","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/policies/privacy.md","namespace":"policies","relativePath":"privacy.md","raw":"---\ntitle: TaskNotes privacy overview\ndescription: How the TaskNotes app and Obsidian plugin store data and when optional services are involved.\nroute: /privacy/\nproduct: shared\nlast_updated: 2026-08-06\n---\n\n# TaskNotes privacy overview\n\nLast updated: August 6, 2026\n\nTaskNotes products are built around portable Markdown records. The storage and\nnetwork boundaries depend on the client and collection you choose.\n\n## TaskNotes app\n\n- The TaskNotes app opens every collection through mdbase and requires a\n connection to read or change it.\n- A hosted collection stores the authoritative Markdown with the hosted\n provider.\n- A computer collection keeps the authoritative Markdown on that computer.\n TaskNotes reaches it through an end-to-end encrypted relay that cannot read\n record contents; the computer must remain reachable and run mdbase Connect.\n- TaskNotes keeps only a temporary in-memory session cache. It does not retain\n a separate offline collection after the app or page closes.\n- Reminder notifications for mdbase collections require explicit permission\n and use content-free event payloads. Task content is refreshed through the\n authorized collection connection.\n\n## Obsidian plugin\n\nThe plugin keeps task and note content in the local Obsidian vault. Plugin\nsettings live in Obsidian's plugin configuration. Network access occurs only\nfor enabled features that require it, including release checks, calendar\nproviders, ICS subscriptions, webhooks, and remotely loaded API documentation\nassets.\n\n## Analytics\n\nTaskNotes does not include a product telemetry or analytics pipeline. Services\nyou choose to connect may keep their own operational, account, security, or\nbilling records under their respective policies.\n\n## Removal\n\nRemoving a client does not necessarily remove its authoritative collection.\nUse the hosted provider's controls for a hosted collection, or manage the\nMarkdown folder on the computer that owns a computer collection. Back up\nrecords before removing an authoritative copy.\n\n## Questions and source code\n\nUse the relevant TaskNotes GitHub repository to report a privacy problem or\ninspect the implementation:\n\n- [TaskNotes app](https://github.com/callumalpass/tasknotes-app)\n- [TaskNotes Obsidian plugin](https://github.com/callumalpass/tasknotes)\n","aliases":[],"toc":[{"level":2,"id":"tasknotes-app","text":"TaskNotes app"},{"level":2,"id":"obsidian-plugin","text":"Obsidian plugin"},{"level":2,"id":"analytics","text":"Analytics"},{"level":2,"id":"removal","text":"Removal"},{"level":2,"id":"questions-and-source-code","text":"Questions and source code"}],"html":"

Last updated: August 6, 2026

\n

TaskNotes products are built around portable Markdown records. The storage and\nnetwork boundaries depend on the client and collection you choose.

\n

TaskNotes app#

\n
    \n
  • The TaskNotes app opens every collection through mdbase and requires a\nconnection to read or change it.
  • \n
  • A hosted collection stores the authoritative Markdown with the hosted\nprovider.
  • \n
  • A computer collection keeps the authoritative Markdown on that computer.\nTaskNotes reaches it through an end-to-end encrypted relay that cannot read\nrecord contents; the computer must remain reachable and run mdbase Connect.
  • \n
  • TaskNotes keeps only a temporary in-memory session cache. It does not retain\na separate offline collection after the app or page closes.
  • \n
  • Reminder notifications for mdbase collections require explicit permission\nand use content-free event payloads. Task content is refreshed through the\nauthorized collection connection.
  • \n
\n

Obsidian plugin#

\n

The plugin keeps task and note content in the local Obsidian vault. Plugin\nsettings live in Obsidian's plugin configuration. Network access occurs only\nfor enabled features that require it, including release checks, calendar\nproviders, ICS subscriptions, webhooks, and remotely loaded API documentation\nassets.

\n

Analytics#

\n

TaskNotes does not include a product telemetry or analytics pipeline. Services\nyou choose to connect may keep their own operational, account, security, or\nbilling records under their respective policies.

\n

Removal#

\n

Removing a client does not necessarily remove its authoritative collection.\nUse the hosted provider's controls for a hosted collection, or manage the\nMarkdown folder on the computer that owns a computer collection. Back up\nrecords before removing an authoritative copy.

\n

Questions and source code#

\n

Use the relevant TaskNotes GitHub repository to report a privacy problem or\ninspect the implementation:

\n\n","text":"Last updated: August 6, 2026 TaskNotes products are built around portable Markdown records. The storage and network boundaries depend on the client and collection you choose. TaskNotes app# The TaskNotes app opens every collection through mdbase and requires a connection to read or change it. A hosted collection stores the authoritative Markdown with the hosted provider. A computer collection keeps the authoritative Markdown on that computer. TaskNotes reaches it through an end-to-end encrypted relay that cannot read record contents; the computer must remain reachable and run mdbase Connect. TaskNotes keeps only a temporary in-memory session cache. It does not retain a separate offline collection after the app or page closes. Reminder notifications for mdbase collections require explicit permission and use content-free event payloads. Task content is refreshed through the authorized collection connection. Obsidian plugin# The plugin keeps task and note content in the local Obsidian vault. Plugin settings live in Obsidian's plugin configuration. Network access occurs only for enabled features that require it, including release checks, calendar providers, ICS subscriptions, webhooks, and remotely loaded API documentation assets. Analytics# TaskNotes does not include a product telemetry or analytics pipeline. Services you choose to connect may keep their own operational, account, security, or billing records under their respective policies. Removal# Removing a client does not necessarily remove its authoritative collection. Use the hosted provider's controls for a hosted collection, or manage the Markdown folder on the computer that owns a computer collection. Back up records before removing an authoritative copy. Questions and source code# Use the relevant TaskNotes GitHub repository to report a privacy problem or inspect the implementation: TaskNotes app TaskNotes Obsidian plugin"}]} +{"generatedAt":"2026-09-13T12:06:47.674Z","versions":{"app":"1.0.3","obsidian":"4.13.0"},"navigation":[{"label":"Start here","items":[{"title":"TaskNotes documentation","route":"/"},{"title":"TaskNotes app","route":"/app/"},{"title":"Obsidian plugin","route":"/obsidian/"},{"title":"Shared concepts","route":"/concepts/task-records/"}]},{"label":"TaskNotes app","items":[{"title":"Get started","route":"/app/getting-started/"},{"title":"Connect to mdbase","route":"/app/connect-mdbase/"},{"title":"Interactive demo","route":"/app/demo/"},{"title":"Choose a collection","route":"/app/collections/"},{"title":"What is mdbase?","route":"/app/mdbase/"},{"title":"Tasks","route":"/app/tasks/"},{"title":"Views and navigation","route":"/app/views/"},{"title":"Connection and availability","route":"/app/connection/"},{"title":"Reminders","route":"/app/reminders/"},{"title":"Troubleshooting","route":"/app/troubleshooting/"}]},{"label":"Obsidian plugin","items":[{"title":"Get started","route":"/obsidian/"},{"title":"Core concepts","route":"/obsidian/core-concepts/"},{"title":"Task management","route":"/obsidian/features/task-management/"},{"title":"Recurring tasks","route":"/obsidian/features/recurring-tasks/"},{"title":"Views","route":"/obsidian/views/"},{"title":"Settings","route":"/obsidian/settings/"},{"title":"APIs and automation","route":"/obsidian/HTTP_API/"},{"title":"Companion plugins","route":"/obsidian/companion-plugins/"},{"title":"Release notes","route":"/obsidian/releases/"},{"title":"Troubleshooting","route":"/obsidian/troubleshooting/"}]},{"label":"Developers","items":[{"title":"TaskNotes specification","route":"/developers/specification/"},{"title":"App integration manifest","route":"/app/reference/manifest/"},{"title":"Command reference","route":"/obsidian/reference/commands/"},{"title":"Settings source","route":"/obsidian/reference/settings-source/"},{"title":"HTTP route index","route":"/obsidian/reference/http-routes/"}]},{"label":"Policies","items":[{"title":"Privacy","route":"/privacy/"}]}],"redirects":{"/app/sync-and-conflicts/":"/app/connection/","/core-concepts/":"/obsidian/core-concepts/","/getting-started/existing-vault/":"/obsidian/getting-started/existing-vault/","/getting-started/mobile/":"/obsidian/getting-started/mobile/","/migration-v3-to-v4/":"/obsidian/migration-v3-to-v4/","/features/":"/obsidian/features/","/views/":"/obsidian/views/","/settings/":"/obsidian/settings/","/calendar-setup/":"/obsidian/calendar-setup/","/troubleshooting/":"/obsidian/troubleshooting/","/HTTP_API/":"/obsidian/HTTP_API/","/javascript-api/":"/obsidian/javascript-api/","/nlp-api/":"/obsidian/nlp-api/","/obsidian-cli/":"/obsidian/obsidian-cli/","/mdbase-tasknotes-cli/":"/obsidian/mdbase-tasknotes-cli/","/webhooks/":"/obsidian/webhooks/","/workflows/":"/obsidian/workflows/","/companion-plugins/":"/obsidian/companion-plugins/","/releases/":"/obsidian/releases/","/spec/":"/developers/specification/","/views/default-base-templates/":"/obsidian/reference/default-base-templates/","/settings/defaults/":"/obsidian/settings/task-properties/","/settings/task-defaults/":"/obsidian/settings/task-properties/","/settings/inline-task-settings/":"/obsidian/settings/features/","/settings/calendar-settings/":"/obsidian/settings/appearance/","/settings/misc-settings/":"/obsidian/settings/features/","/settings/advanced-settings/":"/obsidian/settings/features/","/companion-plugins/canvas-bases/":"/obsidian/companion-plugins/canvas-bases/","/companion-plugins/tasknotes-workflows/":"/obsidian/companion-plugins/tasknotes-workflows/","/features/calendar-integration/":"/obsidian/features/calendar-integration/","/features/ics-integration/":"/obsidian/features/ics-integration/","/features/inline-tasks/":"/obsidian/features/inline-tasks/","/features/integrations/":"/obsidian/features/integrations/","/features/recurring-tasks/":"/obsidian/features/recurring-tasks/","/features/reminders/":"/obsidian/features/reminders/","/features/task-management/":"/obsidian/features/task-management/","/features/template-variables/":"/obsidian/features/template-variables/","/features/time-management/":"/obsidian/features/time-management/","/features/user-fields/":"/obsidian/features/user-fields/","/guides/backup-recovery/":"/obsidian/guides/backup-recovery/","/guides/custom-bases/":"/obsidian/guides/custom-bases/","/settings/appearance/":"/obsidian/settings/appearance/","/settings/features/":"/obsidian/settings/features/","/settings/general/":"/obsidian/settings/general/","/settings/integrations/":"/obsidian/settings/integrations/","/settings/modal-fields/":"/obsidian/settings/modal-fields/","/settings/property-identification/":"/obsidian/settings/property-identification/","/settings/property-types-reference/":"/obsidian/settings/property-types-reference/","/settings/task-properties/":"/obsidian/settings/task-properties/","/views/agenda-view/":"/obsidian/views/agenda-view/","/views/calendar-views/":"/obsidian/views/calendar-views/","/views/kanban-view/":"/obsidian/views/kanban-view/","/views/pomodoro-view/":"/obsidian/views/pomodoro-view/","/views/task-list/":"/obsidian/views/task-list/","/releases/0.2.2/":"/obsidian/releases/0.2.2/","/releases/0.2.3/":"/obsidian/releases/0.2.3/","/releases/0.2.4/":"/obsidian/releases/0.2.4/","/releases/0.3.0/":"/obsidian/releases/0.3.0/","/releases/0.4.0/":"/obsidian/releases/0.4.0/","/releases/0.4.1/":"/obsidian/releases/0.4.1/","/releases/0.4.2/":"/obsidian/releases/0.4.2/","/releases/0.6.0/":"/obsidian/releases/0.6.0/","/releases/0.6.1/":"/obsidian/releases/0.6.1/","/releases/0.6.2/":"/obsidian/releases/0.6.2/","/releases/0.6.3/":"/obsidian/releases/0.6.3/","/releases/0.7.0/":"/obsidian/releases/0.7.0/","/releases/0.8.0/":"/obsidian/releases/0.8.0/","/releases/1.0.0/":"/obsidian/releases/1.0.0/","/releases/1.1.0/":"/obsidian/releases/1.1.0/","/releases/1.2.0/":"/obsidian/releases/1.2.0/","/releases/2.0.0/":"/obsidian/releases/2.0.0/","/releases/2.0.1/":"/obsidian/releases/2.0.1/","/releases/2.0.2/":"/obsidian/releases/2.0.2/","/releases/2.0.3/":"/obsidian/releases/2.0.3/","/releases/2.0.4/":"/obsidian/releases/2.0.4/","/releases/2.1.0/":"/obsidian/releases/2.1.0/","/releases/2.2.0/":"/obsidian/releases/2.2.0/","/releases/2.2.1/":"/obsidian/releases/2.2.1/","/releases/2.2.2/":"/obsidian/releases/2.2.2/","/releases/2.2.3/":"/obsidian/releases/2.2.3/","/releases/3.0.0/":"/obsidian/releases/3.0.0/","/releases/3.0.1/":"/obsidian/releases/3.0.1/","/releases/3.1.0/":"/obsidian/releases/3.1.0/","/releases/3.1.1/":"/obsidian/releases/3.1.1/","/releases/3.10.0/":"/obsidian/releases/3.10.0/","/releases/3.11.0/":"/obsidian/releases/3.11.0/","/releases/3.11.1/":"/obsidian/releases/3.11.1/","/releases/3.11.2/":"/obsidian/releases/3.11.2/","/releases/3.12.0/":"/obsidian/releases/3.12.0/","/releases/3.12.1/":"/obsidian/releases/3.12.1/","/releases/3.12.2/":"/obsidian/releases/3.12.2/","/releases/3.13.0/":"/obsidian/releases/3.13.0/","/releases/3.13.1/":"/obsidian/releases/3.13.1/","/releases/3.13.2/":"/obsidian/releases/3.13.2/","/releases/3.13.3/":"/obsidian/releases/3.13.3/","/releases/3.13.4/":"/obsidian/releases/3.13.4/","/releases/3.14.0/":"/obsidian/releases/3.14.0/","/releases/3.15.0/":"/obsidian/releases/3.15.0/","/releases/3.15.1/":"/obsidian/releases/3.15.1/","/releases/3.16.0/":"/obsidian/releases/3.16.0/","/releases/3.16.1/":"/obsidian/releases/3.16.1/","/releases/3.16.2/":"/obsidian/releases/3.16.2/","/releases/3.16.3/":"/obsidian/releases/3.16.3/","/releases/3.16.4/":"/obsidian/releases/3.16.4/","/releases/3.17.0/":"/obsidian/releases/3.17.0/","/releases/3.17.1/":"/obsidian/releases/3.17.1/","/releases/3.18.0/":"/obsidian/releases/3.18.0/","/releases/3.18.1/":"/obsidian/releases/3.18.1/","/releases/3.18.2/":"/obsidian/releases/3.18.2/","/releases/3.19.0/":"/obsidian/releases/3.19.0/","/releases/3.19.1/":"/obsidian/releases/3.19.1/","/releases/3.20.0/":"/obsidian/releases/3.20.0/","/releases/3.20.1/":"/obsidian/releases/3.20.1/","/releases/3.21.0/":"/obsidian/releases/3.21.0/","/releases/3.22.0/":"/obsidian/releases/3.22.0/","/releases/3.22.1/":"/obsidian/releases/3.22.1/","/releases/3.23.0/":"/obsidian/releases/3.23.0/","/releases/3.23.1/":"/obsidian/releases/3.23.1/","/releases/3.23.2/":"/obsidian/releases/3.23.2/","/releases/3.23.3/":"/obsidian/releases/3.23.3/","/releases/3.23.4/":"/obsidian/releases/3.23.4/","/releases/3.24.0/":"/obsidian/releases/3.24.0/","/releases/3.24.1/":"/obsidian/releases/3.24.1/","/releases/3.24.2/":"/obsidian/releases/3.24.2/","/releases/3.24.3/":"/obsidian/releases/3.24.3/","/releases/3.24.4/":"/obsidian/releases/3.24.4/","/releases/3.24.5/":"/obsidian/releases/3.24.5/","/releases/3.24.6/":"/obsidian/releases/3.24.6/","/releases/3.25.0/":"/obsidian/releases/3.25.0/","/releases/3.25.1/":"/obsidian/releases/3.25.1/","/releases/3.25.2/":"/obsidian/releases/3.25.2/","/releases/3.25.3/":"/obsidian/releases/3.25.3/","/releases/3.25.4/":"/obsidian/releases/3.25.4/","/releases/3.25.6/":"/obsidian/releases/3.25.6/","/releases/3.3.0/":"/obsidian/releases/3.3.0/","/releases/3.4.0/":"/obsidian/releases/3.4.0/","/releases/3.4.1/":"/obsidian/releases/3.4.1/","/releases/3.4.2/":"/obsidian/releases/3.4.2/","/releases/3.5.1/":"/obsidian/releases/3.5.1/","/releases/3.6.0/":"/obsidian/releases/3.6.0/","/releases/3.7.0/":"/obsidian/releases/3.7.0/","/releases/3.7.1/":"/obsidian/releases/3.7.1/","/releases/3.8.1/":"/obsidian/releases/3.8.1/","/releases/3.8.5/":"/obsidian/releases/3.8.5/","/releases/3.8.6/":"/obsidian/releases/3.8.6/","/releases/3.8.7/":"/obsidian/releases/3.8.7/","/releases/3.9.0/":"/obsidian/releases/3.9.0/","/releases/3.9.1/":"/obsidian/releases/3.9.1/","/releases/4.0.0-beta.0/":"/obsidian/releases/4.0.0-beta.0/","/releases/4.0.0-beta.1/":"/obsidian/releases/4.0.0-beta.1/","/releases/4.0.0-beta.2/":"/obsidian/releases/4.0.0-beta.2/","/releases/4.0.0-beta.3/":"/obsidian/releases/4.0.0-beta.3/","/releases/4.0.1/":"/obsidian/releases/4.0.1/","/releases/4.0.2/":"/obsidian/releases/4.0.2/","/releases/4.0.3/":"/obsidian/releases/4.0.3/","/releases/4.0.4/":"/obsidian/releases/4.0.4/","/releases/4.0.5/":"/obsidian/releases/4.0.5/","/releases/4.1.0/":"/obsidian/releases/4.1.0/","/releases/4.1.1/":"/obsidian/releases/4.1.1/","/releases/4.1.2/":"/obsidian/releases/4.1.2/","/releases/4.1.3/":"/obsidian/releases/4.1.3/","/releases/4.10.0/":"/obsidian/releases/4.10.0/","/releases/4.10.1/":"/obsidian/releases/4.10.1/","/releases/4.10.2/":"/obsidian/releases/4.10.2/","/releases/4.11.0/":"/obsidian/releases/4.11.0/","/releases/4.11.1/":"/obsidian/releases/4.11.1/","/releases/4.12.0/":"/obsidian/releases/4.12.0/","/releases/4.12.1/":"/obsidian/releases/4.12.1/","/releases/4.12.2/":"/obsidian/releases/4.12.2/","/releases/4.12.3/":"/obsidian/releases/4.12.3/","/releases/4.12.4/":"/obsidian/releases/4.12.4/","/releases/4.12.5/":"/obsidian/releases/4.12.5/","/releases/4.13.0/":"/obsidian/releases/4.13.0/","/releases/4.2.0/":"/obsidian/releases/4.2.0/","/releases/4.2.1/":"/obsidian/releases/4.2.1/","/releases/4.3.0/":"/obsidian/releases/4.3.0/","/releases/4.3.1/":"/obsidian/releases/4.3.1/","/releases/4.3.2/":"/obsidian/releases/4.3.2/","/releases/4.3.3/":"/obsidian/releases/4.3.3/","/releases/4.4.0/":"/obsidian/releases/4.4.0/","/releases/4.5.0/":"/obsidian/releases/4.5.0/","/releases/4.5.1/":"/obsidian/releases/4.5.1/","/releases/4.5.2/":"/obsidian/releases/4.5.2/","/releases/4.5.3/":"/obsidian/releases/4.5.3/","/releases/4.6.0/":"/obsidian/releases/4.6.0/","/releases/4.7.0/":"/obsidian/releases/4.7.0/","/releases/4.7.1/":"/obsidian/releases/4.7.1/","/releases/4.7.2/":"/obsidian/releases/4.7.2/","/releases/4.8.0/":"/obsidian/releases/4.8.0/","/releases/4.8.1/":"/obsidian/releases/4.8.1/","/releases/4.9.0/":"/obsidian/releases/4.9.0/","/releases/4.9.1/":"/obsidian/releases/4.9.1/","/releases/4.9.2/":"/obsidian/releases/4.9.2/","/releases/unreleased/":"/obsidian/releases/unreleased/","/reference/commands/":"/obsidian/reference/commands/","/reference/compatibility/":"/obsidian/reference/compatibility/","/reference/settings-source/":"/obsidian/reference/settings-source/","/reference/http-routes/":"/obsidian/reference/http-routes/","/reference/default-base-templates/":"/obsidian/reference/default-base-templates/","/spec/00-overview/":"/developers/specification/","/spec/01-terminology/":"/developers/specification/01-terminology/","/spec/02-model-and-mapping/":"/developers/specification/02-model-and-mapping/","/spec/03-temporal-semantics/":"/developers/specification/03-temporal-semantics/","/spec/04-recurrence/":"/developers/specification/04-recurrence/","/spec/05-operations/":"/developers/specification/05-operations/","/spec/06-validation/":"/developers/specification/06-validation/","/spec/07-conformance/":"/developers/specification/07-conformance/","/spec/08-compatibility-and-migrations/":"/developers/specification/08-compatibility-and-migrations/","/spec/09-configuration/":"/developers/specification/09-configuration/","/spec/10-dependencies-and-reminders/":"/developers/specification/10-dependencies-and-reminders/","/spec/11-links/":"/developers/specification/11-links/","/spec/12-mdbase-v0.3-binding/":"/developers/specification/12-mdbase-v0.3-binding/","/spec/CHANGELOG/":"/developers/specification/CHANGELOG/"},"pages":[{"route":"/","title":"TaskNotes documentation","description":"Guides and reference material for the TaskNotes app, the Obsidian plugin, and the portable task format they share.","product":"shared","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":true,"source":"tasknotes.dev:content/index.md","namespace":"index.md","relativePath":"","raw":"---\ntitle: TaskNotes documentation\ndescription: Guides and reference material for the TaskNotes app, the Obsidian plugin, and the portable task format they share.\nroute: /\nproduct: shared\nhide_toc: true\n---\n\n# TaskNotes documentation\n\nTaskNotes keeps structured task information in portable Markdown records. Use\nthe dedicated app on the web, Android, or iOS, or work inside Obsidian with the\nTaskNotes plugin.\n\n\n\n## One portable task model\n\nBoth clients understand the same TaskNotes concepts: status, priority, dates,\nprojects, contexts, recurrence, reminders, relationships, and custom fields.\nThe interface and available integrations differ, but your task records are not\nlocked to one screen or application.\n\n- Start with [portable task records](/concepts/task-records/) if you want to\n understand what the products share.\n- Read the [formal specification](/developers/specification/) when implementing\n or integrating with TaskNotes.\n- Review the [privacy overview](/privacy/) before choosing a hosted or\n computer-connected collection.\n","aliases":[],"toc":[{"level":2,"id":"one-portable-task-model","text":"One portable task model"}],"html":"

TaskNotes keeps structured task information in portable Markdown records. Use\nthe dedicated app on the web, Android, or iOS, or work inside Obsidian with the\nTaskNotes plugin.

\n\n\n

One portable task model#

\n

Both clients understand the same TaskNotes concepts: status, priority, dates,\nprojects, contexts, recurrence, reminders, relationships, and custom fields.\nThe interface and available integrations differ, but your task records are not\nlocked to one screen or application.

\n\n","text":"TaskNotes keeps structured task information in portable Markdown records. Use the dedicated app on the web, Android, or iOS, or work inside Obsidian with the TaskNotes plugin. Beta · Web · Android · iOS TaskNotes app Manage portable TaskNotes v5 collections on the web, Android, and iOS through mdbase. Open the app guide → Obsidian TaskNotes plugin Task and note management inside an Obsidian vault using Bases and Markdown. Open the plugin guide → One portable task model# Both clients understand the same TaskNotes concepts: status, priority, dates, projects, contexts, recurrence, reminders, relationships, and custom fields. The interface and available integrations differ, but your task records are not locked to one screen or application. Start with portable task records if you want to understand what the products share. Read the formal specification when implementing or integrating with TaskNotes. Review the privacy overview before choosing a hosted or computer-connected collection."},{"route":"/app/","title":"TaskNotes app","description":"Use TaskNotes on the web, Android, and iOS with portable Markdown through mdbase.","product":"app","platforms":["web","android","ios"],"version":"1.0.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/app/index.md","namespace":"app","relativePath":"index.md","raw":"---\ntitle: TaskNotes app\ndescription: Use TaskNotes on the web, Android, and iOS with portable Markdown through mdbase.\nroute: /app/\nproduct: app\nplatforms: [web, android, ios]\n---\n\n# TaskNotes app\n\nThe TaskNotes app is currently in beta. It is a web-first client packaged for\nAndroid and iOS, designed for quick capture, daily review, editing, and\ncompletion while keeping task records portable.\n\nThe app is compatible with **TaskNotes v5 collections**, which use the\n**mdbase 0.3.0 specification**. The same collection can be used by other\ncompatible TaskNotes and mdbase tools.\n\nEvery TaskNotes session opens an mdbase collection. You can use a collection\nhosted online or connect to a Markdown collection on your computer through the\nencrypted mdbase relay. TaskNotes reads and writes that collection directly, so\nchanges require a connection.\n\n
\n \"TaskNotes\n
The Today workspace in the desktop layout.
\n
\n\n
\n Disposable sample collection\n Try TaskNotes before connecting your own collection.\n Explore Today, Scratchpad, search, and saved views with sample tasks. Your changes disappear when the demo resets.\n Open the interactive demo →\n
\n\n## Begin here\n\n1. [Try TaskNotes with sample tasks](/app/demo/) or [open or install TaskNotes](/app/getting-started/).\n2. [Learn how mdbase supports TaskNotes](/app/mdbase/).\n3. [Choose where your collection lives](/app/collections/), then follow the\n [connection walkthrough](/app/connect-mdbase/) with video and written steps.\n4. Create a task and open **Today**.\n5. Turn on reminders only if the collection and platform support delivery.\n\n## What the app includes\n\n- Today, Upcoming, Projects, lists, boards, and calendars\n- Capture, editing, completion, archive, and search\n- Projects, contexts, tags, priorities, relationships, and custom fields\n- Recurrence, materialized occurrence notes, reminders, and time tracking\n- Hosted mdbase and end-to-end encrypted relay connections\n- Browser, Android, and iOS packaging from the same application\n\nPlugin-only functionality such as inline Obsidian widgets, the command palette,\nexternal calendar integrations, HTTP APIs, and companion plugins is documented\nunder the [Obsidian plugin](/obsidian/).\n","aliases":[],"toc":[{"level":2,"id":"begin-here","text":"Begin here"},{"level":2,"id":"what-the-app-includes","text":"What the app includes"}],"html":"

The TaskNotes app is currently in beta. It is a web-first client packaged for\nAndroid and iOS, designed for quick capture, daily review, editing, and\ncompletion while keeping task records portable.

\n

The app is compatible with TaskNotes v5 collections, which use the\nmdbase 0.3.0 specification. The same collection can be used by other\ncompatible TaskNotes and mdbase tools.

\n

Every TaskNotes session opens an mdbase collection. You can use a collection\nhosted online or connect to a Markdown collection on your computer through the\nencrypted mdbase relay. TaskNotes reads and writes that collection directly, so\nchanges require a connection.

\n
\n \"TaskNotes\n
The Today workspace in the desktop layout.
\n
\n\n
\n Disposable sample collection\n Try TaskNotes before connecting your own collection.\n Explore Today, Scratchpad, search, and saved views with sample tasks. Your changes disappear when the demo resets.\n Open the interactive demo →\n
\n\n

Begin here#

\n
    \n
  1. Try TaskNotes with sample tasks or open or install TaskNotes.
  2. \n
  3. Learn how mdbase supports TaskNotes.
  4. \n
  5. Choose where your collection lives, then follow the\nconnection walkthrough with video and written steps.
  6. \n
  7. Create a task and open Today.
  8. \n
  9. Turn on reminders only if the collection and platform support delivery.
  10. \n
\n

What the app includes#

\n
    \n
  • Today, Upcoming, Projects, lists, boards, and calendars
  • \n
  • Capture, editing, completion, archive, and search
  • \n
  • Projects, contexts, tags, priorities, relationships, and custom fields
  • \n
  • Recurrence, materialized occurrence notes, reminders, and time tracking
  • \n
  • Hosted mdbase and end-to-end encrypted relay connections
  • \n
  • Browser, Android, and iOS packaging from the same application
  • \n
\n

Plugin-only functionality such as inline Obsidian widgets, the command palette,\nexternal calendar integrations, HTTP APIs, and companion plugins is documented\nunder the Obsidian plugin.

\n","text":"The TaskNotes app is currently in beta. It is a web-first client packaged for Android and iOS, designed for quick capture, daily review, editing, and completion while keeping task records portable. The app is compatible with TaskNotes v5 collections, which use the mdbase 0.3.0 specification. The same collection can be used by other compatible TaskNotes and mdbase tools. Every TaskNotes session opens an mdbase collection. You can use a collection hosted online or connect to a Markdown collection on your computer through the encrypted mdbase relay. TaskNotes reads and writes that collection directly, so changes require a connection. The Today workspace in the desktop layout. Disposable sample collection Try TaskNotes before connecting your own collection. Explore Today, Scratchpad, search, and saved views with sample tasks. Your changes disappear when the demo resets. Open the interactive demo → Begin here# Try TaskNotes with sample tasks or open or install TaskNotes. Learn how mdbase supports TaskNotes. Choose where your collection lives, then follow the connection walkthrough with video and written steps. Create a task and open Today. Turn on reminders only if the collection and platform support delivery. What the app includes# Today, Upcoming, Projects, lists, boards, and calendars Capture, editing, completion, archive, and search Projects, contexts, tags, priorities, relationships, and custom fields Recurrence, materialized occurrence notes, reminders, and time tracking Hosted mdbase and end-to-end encrypted relay connections Browser, Android, and iOS packaging from the same application Plugin-only functionality such as inline Obsidian widgets, the command palette, external calendar integrations, HTTP APIs, and companion plugins is documented under the Obsidian plugin."},{"route":"/app/collections/","title":"Choose a collection","description":"Compare hosted mdbase with a collection connected from your own computer.","product":"app","platforms":["web","android","ios"],"version":"1.0.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/app/collections.md","namespace":"app","relativePath":"collections.md","raw":"---\ntitle: Choose a collection\ndescription: Compare hosted mdbase with a collection connected from your own computer.\nroute: /app/collections/\nproduct: app\nplatforms: [web, android, ios]\n---\n\n# Choose a collection\n\nTaskNotes opens every collection through mdbase. The choice is where the main\ncopy of your Markdown lives: hosted online or on your own computer.\n\nIf mdbase is new to you, start with [mdbase and TaskNotes](/app/mdbase/) for a\nplain-language explanation of the format, Connect desktop app, and hosting\nchoices. For a video and written setup steps, follow\n[Connect TaskNotes to mdbase](/app/connect-mdbase/).\n\n## Hosted mdbase\n\nHosted mdbase is the recommended choice for convenient access across the web,\nAndroid, and iOS. The provider keeps the main collection online, so it is\navailable from any TaskNotes device with a network connection and can deliver\nreminders while TaskNotes is closed.\n\nTaskNotes reads and writes the hosted collection directly. It does not keep a\nseparate offline copy, so you need a network connection to open the collection\nor make changes.\n\n## Connect to a computer\n\nmdbase Connect can make a Markdown collection on your computer available to\nTaskNotes. Requests and responses travel through an end-to-end encrypted relay;\nthe relay cannot read your task contents and you do not need to open a port on\nyour router.\n\nThe computer holds the main copy, so it must be awake, online, and running the\nmdbase Connect background service whenever you use TaskNotes. See how to\n[install mdbase Connect and use a computer collection](/app/mdbase/#use-a-collection-on-your-computer).\n\n## Change collections later\n\nOpen **Settings** and choose **Change collection**. Opening another collection does\nnot copy or move records from the collection you were using.\n","aliases":[],"toc":[{"level":2,"id":"hosted-mdbase","text":"Hosted mdbase"},{"level":2,"id":"connect-to-a-computer","text":"Connect to a computer"},{"level":2,"id":"change-collections-later","text":"Change collections later"}],"html":"

TaskNotes opens every collection through mdbase. The choice is where the main\ncopy of your Markdown lives: hosted online or on your own computer.

\n

If mdbase is new to you, start with mdbase and TaskNotes for a\nplain-language explanation of the format, Connect desktop app, and hosting\nchoices. For a video and written setup steps, follow\nConnect TaskNotes to mdbase.

\n

Hosted mdbase#

\n

Hosted mdbase is the recommended choice for convenient access across the web,\nAndroid, and iOS. The provider keeps the main collection online, so it is\navailable from any TaskNotes device with a network connection and can deliver\nreminders while TaskNotes is closed.

\n

TaskNotes reads and writes the hosted collection directly. It does not keep a\nseparate offline copy, so you need a network connection to open the collection\nor make changes.

\n

Connect to a computer#

\n

mdbase Connect can make a Markdown collection on your computer available to\nTaskNotes. Requests and responses travel through an end-to-end encrypted relay;\nthe relay cannot read your task contents and you do not need to open a port on\nyour router.

\n

The computer holds the main copy, so it must be awake, online, and running the\nmdbase Connect background service whenever you use TaskNotes. See how to\ninstall mdbase Connect and use a computer collection.

\n

Change collections later#

\n

Open Settings and choose Change collection. Opening another collection does\nnot copy or move records from the collection you were using.

\n","text":"TaskNotes opens every collection through mdbase. The choice is where the main copy of your Markdown lives: hosted online or on your own computer. If mdbase is new to you, start with mdbase and TaskNotes for a plain-language explanation of the format, Connect desktop app, and hosting choices. For a video and written setup steps, follow Connect TaskNotes to mdbase. Hosted mdbase# Hosted mdbase is the recommended choice for convenient access across the web, Android, and iOS. The provider keeps the main collection online, so it is available from any TaskNotes device with a network connection and can deliver reminders while TaskNotes is closed. TaskNotes reads and writes the hosted collection directly. It does not keep a separate offline copy, so you need a network connection to open the collection or make changes. Connect to a computer# mdbase Connect can make a Markdown collection on your computer available to TaskNotes. Requests and responses travel through an end-to-end encrypted relay; the relay cannot read your task contents and you do not need to open a port on your router. The computer holds the main copy, so it must be awake, online, and running the mdbase Connect background service whenever you use TaskNotes. See how to install mdbase Connect and use a computer collection. Change collections later# Open Settings and choose Change collection. Opening another collection does not copy or move records from the collection you were using."},{"route":"/app/connect-mdbase/","title":"Connect TaskNotes to mdbase","description":"Watch how to connect hosted mdbase collections and existing local folders to the TaskNotes app, with written steps and a transcript.","product":"app","platforms":["web","android","ios"],"version":"1.0.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/app/connect-mdbase.md","namespace":"app","relativePath":"connect-mdbase.md","raw":"---\ntitle: Connect TaskNotes to mdbase\ndescription: Watch how to connect hosted mdbase collections and existing local folders to the TaskNotes app, with written steps and a transcript.\nroute: /app/connect-mdbase/\nproduct: app\nplatforms: [web, android, ios]\n---\n\n# Connect TaskNotes to mdbase\n\n
\n \n
3 minutes 53 seconds · Silent walkthrough with on-screen instructions and visible cursors. Use the player’s fullscreen control for a closer view.
\n
\n\nDownload the video\n· [Read the transcript](#transcript)\n\nThese instructions are for the web, Android, and iOS app, not the\n[Obsidian plugin](/obsidian/).\n\nThe recording uses disposable demo data in the LAB test environment. Account\nsign-in and OS-specific installer dialogs are omitted. The folder chooser and\nMarkdown editor shown are Linux examples; the connection steps apply across\nplatforms. TaskNotes is in beta, so some labels may change.\n\n## Choose where your collection lives\n\n- **Hosted by mdbase:** available online even when your computer is off. You\n need an internet connection, but not the desktop Connector to use TaskNotes.\n- **On your computer:** files stay in a local folder. Keep that computer\n reachable and mdbase Connect running while other devices use the collection.\n\nHosted collections can also be mirrored to your computer, so you can work\nwith local Markdown files. Mirror setup is outside this walkthrough.\n\nThe same TaskNotes app works with either. Read [What is mdbase?](/app/mdbase/)\nfor more background or [Choose a collection](/app/collections/) for a fuller\ncomparison.\n\n## Connect a hosted collection\n\n1. Open [TaskNotes](https://app.tasknotes.dev/) or its Android or iOS app and\n choose a collection. Sign in to mdbase if asked.\n2. Select a collection labelled **Hosted by mdbase**, then choose **Review\n access**.\n3. Review the named application, collection, requested actions, and setup\n changes. Approve only if you agree. For a collection needing TaskNotes\n definitions, the button reads **Set up and allow access**.\n4. Return to TaskNotes and add a task. It is saved in the hosted collection.\n\nIf you do not have a hosted collection, expand **Add or connect another\ncollection → Create hosted collection** in mdbase. Creating a collection and\napproving TaskNotes access are separate steps.\n\n## Connect an existing local folder\n\n1. Visit the [mdbase Connect download page](https://mdbase.dev/downloads/) and\n choose the **desktop app** for your operating system and processor. Follow\n the current platform installation and beta security guidance, then open\n mdbase Connect. The standalone CLI download does not include the desktop\n interface.\n2. Name your computer and choose **Continue in browser**. Sign in if asked,\n approve the computer, then return to the desktop app and wait for it to\n connect.\n3. Open **Collections → Add existing**. Select the collection root containing\n `mdbase.yaml`, not just its `tasks` subfolder. Adding the folder validates it\n in place; it does not move or upload its files.\n4. Open the collection chooser in TaskNotes and select the collection listed\n under your connected computer. If TaskNotes already has a collection open,\n use **Settings → Change collection → Connect another collection**.\n5. Review and approve the requested access and setup changes if you agree.\n If TaskNotes subsequently asks, review **Apply reviewed setup** as well.\n6. Add a task and inspect its Markdown file in the collection. Completing the\n task updates that file’s status to `done`. You can use any Markdown editor;\n the video uses VS Code.\n\nTaskNotes does not open the folder directly or maintain a durable offline copy.\nYour computer remains the main copy and must be reachable for remote access.\nSee [Connection and availability](/app/connection/) if the collection cannot\nbe reached.\n\n## Switch an existing connection\n\nOpen **Settings → Change collection** and select a collection you have already\napproved. **Connect another collection** returns to mdbase to approve access\nto another one. Switching collections does not copy or move their records.\n\n## Transcript\n\n
\nRead the full video transcript\n\n**00:00** — This video shows how to connect mdbase collections to the TaskNotes app. We’ll start with a hosted collection, then connect an existing folder on your computer.\n\n**00:08** — Hosted by mdbase: available online, even when your computer is off. No desktop Connector needed for TaskNotes.\n\n**00:14** — Hosted collections can also be mirrored to your computer, so you can work with local Markdown files.\n\n**00:21** — On your computer: files stay in an existing folder. Keep mdbase Connect running and the computer reachable. The same TaskNotes app works with either.\n\n**00:29** — Start with hosted: open app.tasknotes.dev and choose a collection.\n\n**00:37** — Select a collection labelled Hosted by mdbase, then review access.\n\n**00:50** — Review the permissions, then approve access if you agree.\n\n**01:00** — Add a task. It is saved in your hosted collection; no local computer is needed.\n\n**01:14** — Already have an mdbase collection on your computer? Connect that folder to TaskNotes without moving its files.\n\n**01:22** — For a local folder, first get the desktop app at mdbase.dev/downloads.\n\n**01:35** — Install and open mdbase Connect.\n\n**01:39** — Name this computer, then choose Continue in browser.\n\n**01:49** — Sign in if asked, then approve this computer.\n\n**02:00** — In Collections, choose Add existing and select your collection folder.\n\n**02:09** — Choose the folder containing mdbase.yaml. Its files stay where they are.\n\n**02:15** — Back in TaskNotes, open the mdbase collection chooser.\n\n**02:21** — Select the collection listed under your connected computer.\n\n**02:35** — Review the requested access and setup changes, then approve if you agree.\n\n**02:44** — Add a task to the local collection.\n\n**02:59** — Each task is a Markdown file. Changes you make in TaskNotes are saved back to the collection.\n\n**03:06** — The task is now a Markdown file in your existing folder.\n\n**03:11** — Keep mdbase Connect running while other devices use this folder.\n\n**03:15** — Once both are connected, switch collections in Settings → Change collection.\n\n**03:24** — Choose a collection you have already approved.\n\n**03:37** — In the local collection, complete the task.\n\n**03:46** — The same Markdown file now says status: done.\n\n
\n","aliases":[],"toc":[{"level":2,"id":"choose-where-your-collection-lives","text":"Choose where your collection lives"},{"level":2,"id":"connect-a-hosted-collection","text":"Connect a hosted collection"},{"level":2,"id":"connect-an-existing-local-folder","text":"Connect an existing local folder"},{"level":2,"id":"switch-an-existing-connection","text":"Switch an existing connection"},{"level":2,"id":"transcript","text":"Transcript"}],"html":"
\n \n
3 minutes 53 seconds · Silent walkthrough with on-screen instructions and visible cursors. Use the player’s fullscreen control for a closer view.
\n
\n\n

Download the video\n· Read the transcript

\n

These instructions are for the web, Android, and iOS app, not the\nObsidian plugin.

\n

The recording uses disposable demo data in the LAB test environment. Account\nsign-in and OS-specific installer dialogs are omitted. The folder chooser and\nMarkdown editor shown are Linux examples; the connection steps apply across\nplatforms. TaskNotes is in beta, so some labels may change.

\n

Choose where your collection lives#

\n
    \n
  • Hosted by mdbase: available online even when your computer is off. You\nneed an internet connection, but not the desktop Connector to use TaskNotes.
  • \n
  • On your computer: files stay in a local folder. Keep that computer\nreachable and mdbase Connect running while other devices use the collection.
  • \n
\n

Hosted collections can also be mirrored to your computer, so you can work\nwith local Markdown files. Mirror setup is outside this walkthrough.

\n

The same TaskNotes app works with either. Read What is mdbase?\nfor more background or Choose a collection for a fuller\ncomparison.

\n

Connect a hosted collection#

\n
    \n
  1. Open TaskNotes or its Android or iOS app and\nchoose a collection. Sign in to mdbase if asked.
  2. \n
  3. Select a collection labelled Hosted by mdbase, then choose Review\naccess.
  4. \n
  5. Review the named application, collection, requested actions, and setup\nchanges. Approve only if you agree. For a collection needing TaskNotes\ndefinitions, the button reads Set up and allow access.
  6. \n
  7. Return to TaskNotes and add a task. It is saved in the hosted collection.
  8. \n
\n

If you do not have a hosted collection, expand Add or connect another\ncollection → Create hosted collection in mdbase. Creating a collection and\napproving TaskNotes access are separate steps.

\n

Connect an existing local folder#

\n
    \n
  1. Visit the mdbase Connect download page and\nchoose the desktop app for your operating system and processor. Follow\nthe current platform installation and beta security guidance, then open\nmdbase Connect. The standalone CLI download does not include the desktop\ninterface.
  2. \n
  3. Name your computer and choose Continue in browser. Sign in if asked,\napprove the computer, then return to the desktop app and wait for it to\nconnect.
  4. \n
  5. Open Collections → Add existing. Select the collection root containing\nmdbase.yaml, not just its tasks subfolder. Adding the folder validates it\nin place; it does not move or upload its files.
  6. \n
  7. Open the collection chooser in TaskNotes and select the collection listed\nunder your connected computer. If TaskNotes already has a collection open,\nuse Settings → Change collection → Connect another collection.
  8. \n
  9. Review and approve the requested access and setup changes if you agree.\nIf TaskNotes subsequently asks, review Apply reviewed setup as well.
  10. \n
  11. Add a task and inspect its Markdown file in the collection. Completing the\ntask updates that file’s status to done. You can use any Markdown editor;\nthe video uses VS Code.
  12. \n
\n

TaskNotes does not open the folder directly or maintain a durable offline copy.\nYour computer remains the main copy and must be reachable for remote access.\nSee Connection and availability if the collection cannot\nbe reached.

\n

Switch an existing connection#

\n

Open Settings → Change collection and select a collection you have already\napproved. Connect another collection returns to mdbase to approve access\nto another one. Switching collections does not copy or move their records.

\n

Transcript#

\n
\nRead the full video transcript\n\n

00:00 — This video shows how to connect mdbase collections to the TaskNotes app. We’ll start with a hosted collection, then connect an existing folder on your computer.

\n

00:08 — Hosted by mdbase: available online, even when your computer is off. No desktop Connector needed for TaskNotes.

\n

00:14 — Hosted collections can also be mirrored to your computer, so you can work with local Markdown files.

\n

00:21 — On your computer: files stay in an existing folder. Keep mdbase Connect running and the computer reachable. The same TaskNotes app works with either.

\n

00:29 — Start with hosted: open app.tasknotes.dev and choose a collection.

\n

00:37 — Select a collection labelled Hosted by mdbase, then review access.

\n

00:50 — Review the permissions, then approve access if you agree.

\n

01:00 — Add a task. It is saved in your hosted collection; no local computer is needed.

\n

01:14 — Already have an mdbase collection on your computer? Connect that folder to TaskNotes without moving its files.

\n

01:22 — For a local folder, first get the desktop app at mdbase.dev/downloads.

\n

01:35 — Install and open mdbase Connect.

\n

01:39 — Name this computer, then choose Continue in browser.

\n

01:49 — Sign in if asked, then approve this computer.

\n

02:00 — In Collections, choose Add existing and select your collection folder.

\n

02:09 — Choose the folder containing mdbase.yaml. Its files stay where they are.

\n

02:15 — Back in TaskNotes, open the mdbase collection chooser.

\n

02:21 — Select the collection listed under your connected computer.

\n

02:35 — Review the requested access and setup changes, then approve if you agree.

\n

02:44 — Add a task to the local collection.

\n

02:59 — Each task is a Markdown file. Changes you make in TaskNotes are saved back to the collection.

\n

03:06 — The task is now a Markdown file in your existing folder.

\n

03:11 — Keep mdbase Connect running while other devices use this folder.

\n

03:15 — Once both are connected, switch collections in Settings → Change collection.

\n

03:24 — Choose a collection you have already approved.

\n

03:37 — In the local collection, complete the task.

\n

03:46 — The same Markdown file now says status: done.

\n
\n","text":"Your browser cannot play this video. Download the MP4 or read the written steps and transcript below. 3 minutes 53 seconds · Silent walkthrough with on-screen instructions and visible cursors. Use the player’s fullscreen control for a closer view. Download the video · Read the transcript These instructions are for the web, Android, and iOS app, not the Obsidian plugin. The recording uses disposable demo data in the LAB test environment. Account sign-in and OS-specific installer dialogs are omitted. The folder chooser and Markdown editor shown are Linux examples; the connection steps apply across platforms. TaskNotes is in beta, so some labels may change. Choose where your collection lives# Hosted by mdbase: available online even when your computer is off. You need an internet connection, but not the desktop Connector to use TaskNotes. On your computer: files stay in a local folder. Keep that computer reachable and mdbase Connect running while other devices use the collection. Hosted collections can also be mirrored to your computer, so you can work with local Markdown files. Mirror setup is outside this walkthrough. The same TaskNotes app works with either. Read What is mdbase? for more background or Choose a collection for a fuller comparison. Connect a hosted collection# Open TaskNotes or its Android or iOS app and choose a collection. Sign in to mdbase if asked. Select a collection labelled Hosted by mdbase, then choose Review access. Review the named application, collection, requested actions, and setup changes. Approve only if you agree. For a collection needing TaskNotes definitions, the button reads Set up and allow access. Return to TaskNotes and add a task. It is saved in the hosted collection. If you do not have a hosted collection, expand Add or connect another collection → Create hosted collection in mdbase. Creating a collection and approving TaskNotes access are separate steps. Connect an existing local folder# Visit the mdbase Connect download page and choose the desktop app for your operating system and processor. Follow the current platform installation and beta security guidance, then open mdbase Connect. The standalone CLI download does not include the desktop interface. Name your computer and choose Continue in browser. Sign in if asked, approve the computer, then return to the desktop app and wait for it to connect. Open Collections → Add existing. Select the collection root containing mdbase.yaml, not just its tasks subfolder. Adding the folder validates it in place; it does not move or upload its files. Open the collection chooser in TaskNotes and select the collection listed under your connected computer. If TaskNotes already has a collection open, use Settings → Change collection → Connect another collection. Review and approve the requested access and setup changes if you agree. If TaskNotes subsequently asks, review Apply reviewed setup as well. Add a task and inspect its Markdown file in the collection. Completing the task updates that file’s status to done. You can use any Markdown editor; the video uses VS Code. TaskNotes does not open the folder directly or maintain a durable offline copy. Your computer remains the main copy and must be reachable for remote access. See Connection and availability if the collection cannot be reached. Switch an existing connection# Open Settings → Change collection and select a collection you have already approved. Connect another collection returns to mdbase to approve access to another one. Switching collections does not copy or move their records. Transcript# Read the full video transcript 00:00 — This video shows how to connect mdbase collections to the TaskNotes app. We’ll start with a hosted collection, then connect an existing folder on your computer. 00:08 — Hosted by mdbase: available online, even when your computer is off. No desktop Connector needed for TaskNotes. 00:14 — Hosted collections can also be mirrored to your computer, so you can work with local Markdown files. 00:21 — On your computer: files stay in an existing folder. Keep mdbase Connect running and the computer reachable. The same TaskNotes app works with either. 00:29 — Start with hosted: open app.tasknotes.dev and choose a collection. 00:37 — Select a collection labelled Hosted by mdbase, then review access. 00:50 — Review the permissions, then approve access if you agree. 01:00 — Add a task. It is saved in your hosted collection; no local computer is needed. 01:14 — Already have an mdbase collection on your computer? Connect that folder to TaskNotes without moving its files. 01:22 — For a local folder, first get the desktop app at mdbase.dev/downloads. 01:35 — Install and open mdbase Connect. 01:39 — Name this computer, then choose Continue in browser. 01:49 — Sign in if asked, then approve this computer. 02:00 — In Collections, choose Add existing and select your collection folder. 02:09 — Choose the folder containing mdbase.yaml. Its files stay where they are. 02:15 — Back in TaskNotes, open the mdbase collection chooser. 02:21 — Select the collection listed under your connected computer. 02:35 — Review the requested access and setup changes, then approve if you agree. 02:44 — Add a task to the local collection. 02:59 — Each task is a Markdown file. Changes you make in TaskNotes are saved back to the collection. 03:06 — The task is now a Markdown file in your existing folder. 03:11 — Keep mdbase Connect running while other devices use this folder. 03:15 — Once both are connected, switch collections in Settings → Change collection. 03:24 — Choose a collection you have already approved. 03:37 — In the local collection, complete the task. 03:46 — The same Markdown file now says status: done."},{"route":"/app/connection/","title":"Connection and availability","description":"Understand when TaskNotes can reach hosted and computer-connected mdbase collections.","product":"app","platforms":["web","android","ios"],"version":"1.0.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/app/connection.md","namespace":"app","relativePath":"connection.md","raw":"---\ntitle: Connection and availability\ndescription: Understand when TaskNotes can reach hosted and computer-connected mdbase collections.\nroute: /app/connection/\nproduct: app\nplatforms: [web, android, ios]\n---\n\n# Connection and availability\n\nTaskNotes reads and writes the selected mdbase collection directly. It does not\nkeep a separate offline collection or a queue of changes waiting to sync.\n\n## What each status means\n\n| Status | Meaning |\n| --- | --- |\n| Connected | TaskNotes can read and change the selected collection |\n| Connecting | TaskNotes is checking the collection connection |\n| Collection unavailable | The hosted service or connected computer cannot be reached |\n\nOpen **More** to see the current status and use **Refresh now** to read the\nlatest collection state.\n\n## Hosted collections\n\nA hosted collection needs a network connection and an available hosted mdbase\nservice. If either is unavailable, TaskNotes cannot open the collection or save\nchanges. Reconnect the collection if its authorization has expired.\n\n## Collections on your computer\n\nA computer collection also needs the computer holding the Markdown to be\nawake, online, and running the mdbase Connect background service. TaskNotes\nreaches it through the end-to-end encrypted relay. If the computer becomes\nunavailable, access returns when the computer and connector return.\n\n## During a connection problem\n\nTasks already visible in the current session may remain on screen during a\nshort interruption, but TaskNotes cannot safely save new changes until mdbase\nis reachable. A failed action is not silently queued for later.\n\nIf the problem continues, open **More** and choose **Change collection** to use\nanother mdbase collection.\n","aliases":[],"toc":[{"level":2,"id":"what-each-status-means","text":"What each status means"},{"level":2,"id":"hosted-collections","text":"Hosted collections"},{"level":2,"id":"collections-on-your-computer","text":"Collections on your computer"},{"level":2,"id":"during-a-connection-problem","text":"During a connection problem"}],"html":"

TaskNotes reads and writes the selected mdbase collection directly. It does not\nkeep a separate offline collection or a queue of changes waiting to sync.

\n

What each status means#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StatusMeaning
ConnectedTaskNotes can read and change the selected collection
ConnectingTaskNotes is checking the collection connection
Collection unavailableThe hosted service or connected computer cannot be reached
\n

Open More to see the current status and use Refresh now to read the\nlatest collection state.

\n

Hosted collections#

\n

A hosted collection needs a network connection and an available hosted mdbase\nservice. If either is unavailable, TaskNotes cannot open the collection or save\nchanges. Reconnect the collection if its authorization has expired.

\n

Collections on your computer#

\n

A computer collection also needs the computer holding the Markdown to be\nawake, online, and running the mdbase Connect background service. TaskNotes\nreaches it through the end-to-end encrypted relay. If the computer becomes\nunavailable, access returns when the computer and connector return.

\n

During a connection problem#

\n

Tasks already visible in the current session may remain on screen during a\nshort interruption, but TaskNotes cannot safely save new changes until mdbase\nis reachable. A failed action is not silently queued for later.

\n

If the problem continues, open More and choose Change collection to use\nanother mdbase collection.

\n","text":"TaskNotes reads and writes the selected mdbase collection directly. It does not keep a separate offline collection or a queue of changes waiting to sync. What each status means# Status Meaning Connected TaskNotes can read and change the selected collection Connecting TaskNotes is checking the collection connection Collection unavailable The hosted service or connected computer cannot be reached Open More to see the current status and use Refresh now to read the latest collection state. Hosted collections# A hosted collection needs a network connection and an available hosted mdbase service. If either is unavailable, TaskNotes cannot open the collection or save changes. Reconnect the collection if its authorization has expired. Collections on your computer# A computer collection also needs the computer holding the Markdown to be awake, online, and running the mdbase Connect background service. TaskNotes reaches it through the end-to-end encrypted relay. If the computer becomes unavailable, access returns when the computer and connector return. During a connection problem# Tasks already visible in the current session may remain on screen during a short interruption, but TaskNotes cannot safely save new changes until mdbase is reachable. A failed action is not silently queued for later. If the problem continues, open More and choose Change collection to use another mdbase collection."},{"route":"/app/demo/","title":"Interactive demo","description":"Explore the TaskNotes app with disposable sample tasks before connecting a collection.","product":"app","platforms":["web"],"version":"1.0.3","generated":false,"noIndex":false,"hideToc":true,"source":"tasknotes.dev:content/app/demo.md","namespace":"app","relativePath":"demo.md","raw":"---\ntitle: Interactive demo\ndescription: Explore the TaskNotes app with disposable sample tasks before connecting a collection.\nroute: /app/demo/\nproduct: app\nplatforms: [web]\nhide_toc: true\n---\n\n# Interactive demo\n\nExplore the TaskNotes app using a disposable collection of sample tasks. You\ncan complete and edit tasks, use Scratchpad, search, and move between views\nwithout signing in or connecting a collection.\n\nThe demo keeps changes only for the current session. Reloading or resetting it\nstarts again with the original sample data.\n","aliases":[],"toc":[],"html":"

Explore the TaskNotes app using a disposable collection of sample tasks. You\ncan complete and edit tasks, use Scratchpad, search, and move between views\nwithout signing in or connecting a collection.

\n

The demo keeps changes only for the current session. Reloading or resetting it\nstarts again with the original sample data.

\n","text":"Explore the TaskNotes app using a disposable collection of sample tasks. You can complete and edit tasks, use Scratchpad, search, and move between views without signing in or connecting a collection. The demo keeps changes only for the current session. Reloading or resetting it starts again with the original sample data."},{"route":"/app/getting-started/","title":"Get started with the TaskNotes app","description":"Open TaskNotes, connect an mdbase collection, create a task, and find your way around the app.","product":"app","platforms":["web","android","ios"],"version":"1.0.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/app/getting-started.md","namespace":"app","relativePath":"getting-started.md","raw":"---\ntitle: Get started with the TaskNotes app\ndescription: Open TaskNotes, connect an mdbase collection, create a task, and find your way around the app.\nroute: /app/getting-started/\nproduct: app\nplatforms: [web, android, ios]\n---\n\n# Get started with the TaskNotes app\n\nTaskNotes app is currently in beta. Features, availability, and setup steps may\nchange before the stable release.\n\nThe app supports TaskNotes v5 collections based on the mdbase 0.3.0\nspecification.\n\n## 1. Open TaskNotes\n\nUse [app.tasknotes.dev](https://app.tasknotes.dev/) in a supported browser or\ninstall the Android or iOS application when it is available through its store.\nThe web and native applications use the same task interface.\n\n## 2. Choose a collection\n\nTaskNotes opens every collection through mdbase. In the collection chooser,\nselect one labelled **Hosted by mdbase** or one listed under your connected\ncomputer. Read [What is mdbase?](/app/mdbase/) if this is new to you, then\n[Choose a collection](/app/collections/) to compare the two options.\n\nFollow [Connect TaskNotes to mdbase](/app/connect-mdbase/) for a short video,\nwritten steps, and a transcript covering hosted collections first, then\nexisting local folders.\n\n## 3. Create a task\n\nUse **Add task**, enter a title, and save. Capture understands the collection's\nconfigured status, priority, project, context, and tag values.\n\n## 4. Review the starter views\n\nOpen **Today** for current work, **Upcoming** for scheduled tasks, and **Views**\nfor the complete collection of lists, boards, calendars, and project views.\nNavigation belongs to the current collection and can be reordered from Views.\n\n## 5. Check collection status\n\nOpen **Settings** to see the collection location, connection state, last refresh,\nnotification access, task model settings, and appearance preference.\n","aliases":[],"toc":[{"level":2,"id":"1-open-tasknotes","text":"1. Open TaskNotes"},{"level":2,"id":"2-choose-a-collection","text":"2. Choose a collection"},{"level":2,"id":"3-create-a-task","text":"3. Create a task"},{"level":2,"id":"4-review-the-starter-views","text":"4. Review the starter views"},{"level":2,"id":"5-check-collection-status","text":"5. Check collection status"}],"html":"

TaskNotes app is currently in beta. Features, availability, and setup steps may\nchange before the stable release.

\n

The app supports TaskNotes v5 collections based on the mdbase 0.3.0\nspecification.

\n

1. Open TaskNotes#

\n

Use app.tasknotes.dev in a supported browser or\ninstall the Android or iOS application when it is available through its store.\nThe web and native applications use the same task interface.

\n

2. Choose a collection#

\n

TaskNotes opens every collection through mdbase. In the collection chooser,\nselect one labelled Hosted by mdbase or one listed under your connected\ncomputer. Read What is mdbase? if this is new to you, then\nChoose a collection to compare the two options.

\n

Follow Connect TaskNotes to mdbase for a short video,\nwritten steps, and a transcript covering hosted collections first, then\nexisting local folders.

\n

3. Create a task#

\n

Use Add task, enter a title, and save. Capture understands the collection's\nconfigured status, priority, project, context, and tag values.

\n

4. Review the starter views#

\n

Open Today for current work, Upcoming for scheduled tasks, and Views\nfor the complete collection of lists, boards, calendars, and project views.\nNavigation belongs to the current collection and can be reordered from Views.

\n

5. Check collection status#

\n

Open Settings to see the collection location, connection state, last refresh,\nnotification access, task model settings, and appearance preference.

\n","text":"TaskNotes app is currently in beta. Features, availability, and setup steps may change before the stable release. The app supports TaskNotes v5 collections based on the mdbase 0.3.0 specification. 1. Open TaskNotes# Use app.tasknotes.dev in a supported browser or install the Android or iOS application when it is available through its store. The web and native applications use the same task interface. 2. Choose a collection# TaskNotes opens every collection through mdbase. In the collection chooser, select one labelled Hosted by mdbase or one listed under your connected computer. Read What is mdbase? if this is new to you, then Choose a collection to compare the two options. Follow Connect TaskNotes to mdbase for a short video, written steps, and a transcript covering hosted collections first, then existing local folders. 3. Create a task# Use Add task, enter a title, and save. Capture understands the collection's configured status, priority, project, context, and tag values. 4. Review the starter views# Open Today for current work, Upcoming for scheduled tasks, and Views for the complete collection of lists, boards, calendars, and project views. Navigation belongs to the current collection and can be reordered from Views. 5. Check collection status# Open Settings to see the collection location, connection state, last refresh, notification access, task model settings, and appearance preference."},{"route":"/app/mdbase/","title":"mdbase and TaskNotes","description":"Understand how TaskNotes uses hosted mdbase or the encrypted relay to reach a collection on your computer.","product":"app","platforms":["web","android","ios"],"version":"1.0.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/app/mdbase.md","namespace":"app","relativePath":"mdbase.md","raw":"---\ntitle: mdbase and TaskNotes\ndescription: Understand how TaskNotes uses hosted mdbase or the encrypted relay to reach a collection on your computer.\nroute: /app/mdbase/\nproduct: app\nplatforms: [web, android, ios]\n---\n\n# mdbase and TaskNotes\n\nmdbase lets TaskNotes work with a portable Markdown collection instead of\nhiding your tasks in a TaskNotes-only database. Every TaskNotes session opens\none mdbase collection: either a collection hosted online or one kept on your\ncomputer and reached through the encrypted relay.\n\n## What is mdbase?\n\nTwo related names appear in TaskNotes:\n\n- **mdbase** is the open collection format and specification. A collection is\n a folder of Markdown files plus a small description of what those files mean.\n- **mdbase Connect** is the access service TaskNotes uses to ask for permission\n and connect to a hosted collection or a collection on your computer.\n\nRead the [mdbase introduction](https://mdbase.dev/) for a visual explanation of\nthe wider ecosystem.\n\n## What it gives TaskNotes\n\nTaskNotes understands what a task looks like inside an mdbase collection. That\ncompatibility is defined by the TaskNotes v5 collection format and its mdbase\n0.3.0 binding. That means TaskNotes can:\n\n- use the same task fields, projects, tags, saved views, and settings on the\n web, Android, and iOS;\n- ask for access to one collection without seeing your other folders; and\n- keep reminders running while TaskNotes is closed when your collection\n supports them.\n\nBehind the scenes, mdbase checks that each change is valid and writes it to the\nmain collection. You still own readable Markdown files rather than a database\nthat only TaskNotes can open.\n\n## How the connection works\n\nThe mdbase collection is the source of truth. TaskNotes reads and writes it\ndirectly and does not keep a separate offline collection, so opening tasks and\nsaving changes require a connection.\n\n| Choice | Where the Markdown lives | What must be available |\n| --- | --- | --- |\n| Hosted mdbase | With the hosted provider | Your device must have a network connection |\n| Connect to your computer | In a folder on your computer | Both devices must be online, and your computer must be running mdbase Connect |\n\n[Choose a collection](/app/collections/) compares the TaskNotes behavior of\nthese options in more detail. [Connect TaskNotes to mdbase](/app/connect-mdbase/)\nshows both connection flows in a short video, with written steps and a transcript.\n\n## Use a collection on your computer\n\nInstall the Electron-based mdbase Connect desktop app to make a folder on your\ncomputer available to TaskNotes. It runs a small background service that keeps\nTaskNotes connected to the Markdown folder. The download also includes command\nline tools. The mdbase editor is online and is not part of the desktop app.\n\n1. Open the [mdbase Connect download page](https://mdbase.dev/downloads/) and\n choose the package for macOS, Windows, or Linux.\n2. Install and open mdbase Connect. Follow any platform-specific beta\n installation notes shown on the download page.\n3. Add an existing mdbase folder on the computer, or create a collection.\n4. In TaskNotes, choose **Connect to a computer** and select that collection.\n5. Review the requested actions and approve the connection.\n\nTaskNotes requests and responses travel through an end-to-end encrypted relay.\nThe relay passes the encrypted data along but cannot read your task contents.\nYou do not need to open an inbound port on your router.\n\nThe background service on your computer checks that TaskNotes has permission,\nthen reads or changes the Markdown files. It does not create another hosted or\noffline copy of the collection.\n\n## Do I need to leave my computer on?\n\nYes. Your computer holds the main copy, so it is part of the connection:\n\n- It must be awake, connected to the internet, and running the mdbase Connect\n background service whenever TaskNotes needs remote access.\n- Sleep, shutdown, a network outage, or a stopped connector makes the\n collection unavailable until the computer returns.\n- Reminder delivery also depends on the computer remaining available.\n- You are responsible for the computer's security, disk health, and backups.\n\nThis works well for an always-on desktop or home server. It is less convenient\nfor a laptop that sleeps or travels regularly. Hosted mdbase removes the\nalways-on-computer requirement, but it moves the main copy to a provider you\nmust trust. Both choices require a network connection while you use TaskNotes.\n\nFor more detail about how Connect protects and routes your data, read\n[How mdbase Connect works](https://mdbase.dev/connect/).\n\n## A practical recommendation\n\nChoose **Hosted mdbase** if dependable access across several devices and\nreminder delivery matter most. Choose **Connect to a computer** if keeping the\nmain Markdown folder on your own machine matters more and that machine can\nremain available.\n","aliases":[],"toc":[{"level":2,"id":"what-is-mdbase","text":"What is mdbase?"},{"level":2,"id":"what-it-gives-tasknotes","text":"What it gives TaskNotes"},{"level":2,"id":"how-the-connection-works","text":"How the connection works"},{"level":2,"id":"use-a-collection-on-your-computer","text":"Use a collection on your computer"},{"level":2,"id":"do-i-need-to-leave-my-computer-on","text":"Do I need to leave my computer on?"},{"level":2,"id":"a-practical-recommendation","text":"A practical recommendation"}],"html":"

mdbase lets TaskNotes work with a portable Markdown collection instead of\nhiding your tasks in a TaskNotes-only database. Every TaskNotes session opens\none mdbase collection: either a collection hosted online or one kept on your\ncomputer and reached through the encrypted relay.

\n

What is mdbase?#

\n

Two related names appear in TaskNotes:

\n
    \n
  • mdbase is the open collection format and specification. A collection is\na folder of Markdown files plus a small description of what those files mean.
  • \n
  • mdbase Connect is the access service TaskNotes uses to ask for permission\nand connect to a hosted collection or a collection on your computer.
  • \n
\n

Read the mdbase introduction for a visual explanation of\nthe wider ecosystem.

\n

What it gives TaskNotes#

\n

TaskNotes understands what a task looks like inside an mdbase collection. That\ncompatibility is defined by the TaskNotes v5 collection format and its mdbase\n0.3.0 binding. That means TaskNotes can:

\n
    \n
  • use the same task fields, projects, tags, saved views, and settings on the\nweb, Android, and iOS;
  • \n
  • ask for access to one collection without seeing your other folders; and
  • \n
  • keep reminders running while TaskNotes is closed when your collection\nsupports them.
  • \n
\n

Behind the scenes, mdbase checks that each change is valid and writes it to the\nmain collection. You still own readable Markdown files rather than a database\nthat only TaskNotes can open.

\n

How the connection works#

\n

The mdbase collection is the source of truth. TaskNotes reads and writes it\ndirectly and does not keep a separate offline collection, so opening tasks and\nsaving changes require a connection.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
ChoiceWhere the Markdown livesWhat must be available
Hosted mdbaseWith the hosted providerYour device must have a network connection
Connect to your computerIn a folder on your computerBoth devices must be online, and your computer must be running mdbase Connect
\n

Choose a collection compares the TaskNotes behavior of\nthese options in more detail. Connect TaskNotes to mdbase\nshows both connection flows in a short video, with written steps and a transcript.

\n

Use a collection on your computer#

\n

Install the Electron-based mdbase Connect desktop app to make a folder on your\ncomputer available to TaskNotes. It runs a small background service that keeps\nTaskNotes connected to the Markdown folder. The download also includes command\nline tools. The mdbase editor is online and is not part of the desktop app.

\n
    \n
  1. Open the mdbase Connect download page and\nchoose the package for macOS, Windows, or Linux.
  2. \n
  3. Install and open mdbase Connect. Follow any platform-specific beta\ninstallation notes shown on the download page.
  4. \n
  5. Add an existing mdbase folder on the computer, or create a collection.
  6. \n
  7. In TaskNotes, choose Connect to a computer and select that collection.
  8. \n
  9. Review the requested actions and approve the connection.
  10. \n
\n

TaskNotes requests and responses travel through an end-to-end encrypted relay.\nThe relay passes the encrypted data along but cannot read your task contents.\nYou do not need to open an inbound port on your router.

\n

The background service on your computer checks that TaskNotes has permission,\nthen reads or changes the Markdown files. It does not create another hosted or\noffline copy of the collection.

\n

Do I need to leave my computer on?#

\n

Yes. Your computer holds the main copy, so it is part of the connection:

\n
    \n
  • It must be awake, connected to the internet, and running the mdbase Connect\nbackground service whenever TaskNotes needs remote access.
  • \n
  • Sleep, shutdown, a network outage, or a stopped connector makes the\ncollection unavailable until the computer returns.
  • \n
  • Reminder delivery also depends on the computer remaining available.
  • \n
  • You are responsible for the computer's security, disk health, and backups.
  • \n
\n

This works well for an always-on desktop or home server. It is less convenient\nfor a laptop that sleeps or travels regularly. Hosted mdbase removes the\nalways-on-computer requirement, but it moves the main copy to a provider you\nmust trust. Both choices require a network connection while you use TaskNotes.

\n

For more detail about how Connect protects and routes your data, read\nHow mdbase Connect works.

\n

A practical recommendation#

\n

Choose Hosted mdbase if dependable access across several devices and\nreminder delivery matter most. Choose Connect to a computer if keeping the\nmain Markdown folder on your own machine matters more and that machine can\nremain available.

\n","text":"mdbase lets TaskNotes work with a portable Markdown collection instead of hiding your tasks in a TaskNotes-only database. Every TaskNotes session opens one mdbase collection: either a collection hosted online or one kept on your computer and reached through the encrypted relay. What is mdbase?# Two related names appear in TaskNotes: mdbase is the open collection format and specification. A collection is a folder of Markdown files plus a small description of what those files mean. mdbase Connect is the access service TaskNotes uses to ask for permission and connect to a hosted collection or a collection on your computer. Read the mdbase introduction for a visual explanation of the wider ecosystem. What it gives TaskNotes# TaskNotes understands what a task looks like inside an mdbase collection. That compatibility is defined by the TaskNotes v5 collection format and its mdbase 0.3.0 binding. That means TaskNotes can: use the same task fields, projects, tags, saved views, and settings on the web, Android, and iOS; ask for access to one collection without seeing your other folders; and keep reminders running while TaskNotes is closed when your collection supports them. Behind the scenes, mdbase checks that each change is valid and writes it to the main collection. You still own readable Markdown files rather than a database that only TaskNotes can open. How the connection works# The mdbase collection is the source of truth. TaskNotes reads and writes it directly and does not keep a separate offline collection, so opening tasks and saving changes require a connection. Choice Where the Markdown lives What must be available Hosted mdbase With the hosted provider Your device must have a network connection Connect to your computer In a folder on your computer Both devices must be online, and your computer must be running mdbase Connect Choose a collection compares the TaskNotes behavior of these options in more detail. Connect TaskNotes to mdbase shows both connection flows in a short video, with written steps and a transcript. Use a collection on your computer# Install the Electron-based mdbase Connect desktop app to make a folder on your computer available to TaskNotes. It runs a small background service that keeps TaskNotes connected to the Markdown folder. The download also includes command line tools. The mdbase editor is online and is not part of the desktop app. Open the mdbase Connect download page and choose the package for macOS, Windows, or Linux. Install and open mdbase Connect. Follow any platform-specific beta installation notes shown on the download page. Add an existing mdbase folder on the computer, or create a collection. In TaskNotes, choose Connect to a computer and select that collection. Review the requested actions and approve the connection. TaskNotes requests and responses travel through an end-to-end encrypted relay. The relay passes the encrypted data along but cannot read your task contents. You do not need to open an inbound port on your router. The background service on your computer checks that TaskNotes has permission, then reads or changes the Markdown files. It does not create another hosted or offline copy of the collection. Do I need to leave my computer on?# Yes. Your computer holds the main copy, so it is part of the connection: It must be awake, connected to the internet, and running the mdbase Connect background service whenever TaskNotes needs remote access. Sleep, shutdown, a network outage, or a stopped connector makes the collection unavailable until the computer returns. Reminder delivery also depends on the computer remaining available. You are responsible for the computer's security, disk health, and backups. This works well for an always-on desktop or home server. It is less convenient for a laptop that sleeps or travels regularly. Hosted mdbase removes the always-on-computer requirement, but it moves the main copy to a provider you must trust. Both choices require a network connection while you use TaskNotes. For more detail about how Connect protects and routes your data, read How mdbase Connect works. A practical recommendation# Choose Hosted mdbase if dependable access across several devices and reminder delivery matter most. Choose Connect to a computer if keeping the main Markdown folder on your own machine matters more and that machine can remain available."},{"route":"/app/reference/manifest/","title":"App integration manifest","description":"Generated reference for the TaskNotes app's mdbase integration requirements and capabilities.","product":"app","platforms":[],"version":"1.0.3","generated":true,"noIndex":false,"hideToc":false,"source":"tasknotes-app:src/generated/mdbase-app.json","namespace":"app","relativePath":"reference/manifest.md","raw":"---\ntitle: App integration manifest\ndescription: Generated reference for the TaskNotes app's mdbase integration requirements and capabilities.\n---\n\n# App integration manifest\n\nThis page is generated from the integration manifest shipped by TaskNotes app 1.0.3.\n\n| Field | Value |\n| --- | --- |\n| Application ID | `dev.tasknotes.app` |\n| Manifest version | `1` |\n| Homepage | [http://127.0.0.1:4173/](http://127.0.0.1:4173/) |\n| Collection access | `full_collection` |\n\n## Required contracts\n\n- `tasknotes.task` version `0.3.0-rc.3`\n\n## File capabilities\n\n- `list`\n- `read`\n- `add`\n- `replace`\n- `move`\n- `delete`\n\n## Notification criteria\n\n- `task.reminder` listens for `mdbase.runtime.timer.fired` version `1.0.0`.\n","aliases":[],"toc":[{"level":2,"id":"required-contracts","text":"Required contracts"},{"level":2,"id":"file-capabilities","text":"File capabilities"},{"level":2,"id":"notification-criteria","text":"Notification criteria"}],"html":"

This page is generated from the integration manifest shipped by TaskNotes app 1.0.3.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
FieldValue
Application IDdev.tasknotes.app
Manifest version1
Homepagehttp://127.0.0.1:4173/
Collection accessfull_collection
\n

Required contracts#

\n
    \n
  • tasknotes.task version 0.3.0-rc.3
  • \n
\n

File capabilities#

\n
    \n
  • list
  • \n
  • read
  • \n
  • add
  • \n
  • replace
  • \n
  • move
  • \n
  • delete
  • \n
\n

Notification criteria#

\n
    \n
  • task.reminder listens for mdbase.runtime.timer.fired version 1.0.0.
  • \n
\n","text":"This page is generated from the integration manifest shipped by TaskNotes app 1.0.3. Field Value Application ID dev.tasknotes.app Manifest version 1 Homepage http://127.0.0.1:4173/ Collection access full_collection Required contracts# tasknotes.task version 0.3.0-rc.3 File capabilities# list read add replace move delete Notification criteria# task.reminder listens for mdbase.runtime.timer.fired version 1.0.0."},{"route":"/app/reminders/","title":"Reminders in the TaskNotes app","description":"Understand reminder data, notification delivery, permissions, and collection requirements.","product":"app","platforms":["web","android","ios"],"version":"1.0.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/app/reminders.md","namespace":"app","relativePath":"reminders.md","raw":"---\ntitle: Reminders in the TaskNotes app\ndescription: Understand reminder data, notification delivery, permissions, and collection requirements.\nroute: /app/reminders/\nproduct: app\nplatforms: [web, android, ios]\n---\n\n# Reminders in the TaskNotes app\n\nTask records can contain relative reminders anchored to scheduled or due dates,\nor absolute reminders fixed to a particular time. Saving reminder data does not\nby itself guarantee notification delivery.\n\n## Delivery by collection\n\n| Collection | Reminder data | Notification delivery |\n| --- | --- | --- |\n| Hosted mdbase | Saved in the collection | Available after opt-in |\n| Computer through the relay | Saved in the collection | Available while the computer and connector remain available |\n\nFor mdbase collections, the authority schedules reminder events so delivery\ndoes not depend on one TaskNotes screen remaining open. Notification payloads\nare content-free; selecting one refreshes authorized collection state in the\napp.\n\n## Turn on reminders\n\nOpen **More**, select **Turn on reminders**, and approve the browser or operating\nsystem permission. Some existing mdbase grants require **Review notification\naccess** before the channel can be enabled.\n\nAn unsupported or insecure browser reports that notification delivery is not\navailable. The reminder definitions remain in the task record.\n","aliases":[],"toc":[{"level":2,"id":"delivery-by-collection","text":"Delivery by collection"},{"level":2,"id":"turn-on-reminders","text":"Turn on reminders"}],"html":"

Task records can contain relative reminders anchored to scheduled or due dates,\nor absolute reminders fixed to a particular time. Saving reminder data does not\nby itself guarantee notification delivery.

\n

Delivery by collection#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
CollectionReminder dataNotification delivery
Hosted mdbaseSaved in the collectionAvailable after opt-in
Computer through the relaySaved in the collectionAvailable while the computer and connector remain available
\n

For mdbase collections, the authority schedules reminder events so delivery\ndoes not depend on one TaskNotes screen remaining open. Notification payloads\nare content-free; selecting one refreshes authorized collection state in the\napp.

\n

Turn on reminders#

\n

Open More, select Turn on reminders, and approve the browser or operating\nsystem permission. Some existing mdbase grants require Review notification\naccess before the channel can be enabled.

\n

An unsupported or insecure browser reports that notification delivery is not\navailable. The reminder definitions remain in the task record.

\n","text":"Task records can contain relative reminders anchored to scheduled or due dates, or absolute reminders fixed to a particular time. Saving reminder data does not by itself guarantee notification delivery. Delivery by collection# Collection Reminder data Notification delivery Hosted mdbase Saved in the collection Available after opt-in Computer through the relay Saved in the collection Available while the computer and connector remain available For mdbase collections, the authority schedules reminder events so delivery does not depend on one TaskNotes screen remaining open. Notification payloads are content-free; selecting one refreshes authorized collection state in the app. Turn on reminders# Open More, select Turn on reminders, and approve the browser or operating system permission. Some existing mdbase grants require Review notification access before the channel can be enabled. An unsupported or insecure browser reports that notification delivery is not available. The reminder definitions remain in the task record."},{"route":"/app/tasks/","title":"Work with tasks","description":"Capture, edit, organize, complete, archive, and search tasks in the TaskNotes app.","product":"app","platforms":["web","android","ios"],"version":"1.0.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/app/tasks.md","namespace":"app","relativePath":"tasks.md","raw":"---\ntitle: Work with tasks\ndescription: Capture, edit, organize, complete, archive, and search tasks in the TaskNotes app.\nroute: /app/tasks/\nproduct: app\nplatforms: [web, android, ios]\n---\n\n# Work with tasks\n\n
\n \"TaskNotes\n
A task opens beside its source view on wider screens.
\n
\n\n## Capture\n\nUse **Add task** from navigation or from a saved view. When a view has safe\ncreation defaults, TaskNotes applies them automatically so the new task remains\nin that view.\n\n## Edit\n\nA task can contain:\n\n- Status and priority\n- Scheduled and due dates\n- Markdown notes\n- Projects, contexts, and tags\n- Dependencies and subtasks\n- Collection-defined custom properties\n- Time estimates and tracked sessions\n- Recurrence and occurrence-note policies\n- Relative and absolute reminder definitions\n\nBackground saves remain ordered if you navigate away while a write is still in\nprogress.\n\n## Complete, archive, and delete\n\nComplete a task from its row or detail screen. Archive retains the record and\nmay move its Markdown file according to collection settings. Delete offers a\nshort undo period before committing the removal.\n\n## Search\n\nSearch runs across the current collection and matches titles, notes, projects,\ncontexts, and tags. Use **Refresh now** under **More** if a change made by\nanother tool does not appear yet.\n","aliases":[],"toc":[{"level":2,"id":"capture","text":"Capture"},{"level":2,"id":"edit","text":"Edit"},{"level":2,"id":"complete-archive-and-delete","text":"Complete, archive, and delete"},{"level":2,"id":"search","text":"Search"}],"html":"
\n \"TaskNotes\n
A task opens beside its source view on wider screens.
\n
\n\n

Capture#

\n

Use Add task from navigation or from a saved view. When a view has safe\ncreation defaults, TaskNotes applies them automatically so the new task remains\nin that view.

\n

Edit#

\n

A task can contain:

\n
    \n
  • Status and priority
  • \n
  • Scheduled and due dates
  • \n
  • Markdown notes
  • \n
  • Projects, contexts, and tags
  • \n
  • Dependencies and subtasks
  • \n
  • Collection-defined custom properties
  • \n
  • Time estimates and tracked sessions
  • \n
  • Recurrence and occurrence-note policies
  • \n
  • Relative and absolute reminder definitions
  • \n
\n

Background saves remain ordered if you navigate away while a write is still in\nprogress.

\n

Complete, archive, and delete#

\n

Complete a task from its row or detail screen. Archive retains the record and\nmay move its Markdown file according to collection settings. Delete offers a\nshort undo period before committing the removal.

\n

Search#

\n

Search runs across the current collection and matches titles, notes, projects,\ncontexts, and tags. Use Refresh now under More if a change made by\nanother tool does not appear yet.

\n","text":"A task opens beside its source view on wider screens. Capture# Use Add task from navigation or from a saved view. When a view has safe creation defaults, TaskNotes applies them automatically so the new task remains in that view. Edit# A task can contain: Status and priority Scheduled and due dates Markdown notes Projects, contexts, and tags Dependencies and subtasks Collection-defined custom properties Time estimates and tracked sessions Recurrence and occurrence-note policies Relative and absolute reminder definitions Background saves remain ordered if you navigate away while a write is still in progress. Complete, archive, and delete# Complete a task from its row or detail screen. Archive retains the record and may move its Markdown file according to collection settings. Delete offers a short undo period before committing the removal. Search# Search runs across the current collection and matches titles, notes, projects, contexts, and tags. Use Refresh now under More if a change made by another tool does not appear yet."},{"route":"/app/troubleshooting/","title":"Troubleshoot the TaskNotes app","description":"Diagnose mdbase connection, authorization, refresh, and notification problems in the app.","product":"app","platforms":["web","android","ios"],"version":"1.0.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/app/troubleshooting.md","namespace":"app","relativePath":"troubleshooting.md","raw":"---\ntitle: Troubleshoot the TaskNotes app\ndescription: Diagnose mdbase connection, authorization, refresh, and notification problems in the app.\nroute: /app/troubleshooting/\nproduct: app\nplatforms: [web, android, ios]\n---\n\n# Troubleshoot the TaskNotes app\n\nStart by recording the app version, platform, collection type, collection\nstatus shown under **More**, and the smallest sequence that reproduces the\nproblem.\n\n## The collection is unavailable\n\nFor a hosted collection, confirm that the device is online and try **Reconnect\nthis collection**. For a computer collection, also confirm that the computer\nholding the Markdown is awake, online, and running mdbase Connect.\n\n## An authorization error appears\n\nUse the reconnect action for the current collection and review the access that\nmdbase requests. If you no longer want to use that collection, open **More** and\nchoose **Change collection**.\n\n## A change did not save\n\nTaskNotes writes directly to mdbase and does not queue failed changes for later.\nRestore the connection, then retry the action. Capture and editing screens keep\nrecoverable input visible when they can do so safely.\n\n## A change from another tool is missing\n\nOpen **More** and choose **Refresh now**. If the record still does not appear,\nconfirm that the other tool wrote to the same mdbase collection and that the\nrecord uses a compatible TaskNotes task definition.\n\n## Notifications do not arrive\n\nConfirm that the current collection is an mdbase collection, reminders are\nenabled in **More**, the browser or operating system permission is granted, and\nthe task contains a valid future reminder. For a computer collection, the\ncomputer and mdbase Connect must remain available.\n","aliases":[],"toc":[{"level":2,"id":"the-collection-is-unavailable","text":"The collection is unavailable"},{"level":2,"id":"an-authorization-error-appears","text":"An authorization error appears"},{"level":2,"id":"a-change-did-not-save","text":"A change did not save"},{"level":2,"id":"a-change-from-another-tool-is-missing","text":"A change from another tool is missing"},{"level":2,"id":"notifications-do-not-arrive","text":"Notifications do not arrive"}],"html":"

Start by recording the app version, platform, collection type, collection\nstatus shown under More, and the smallest sequence that reproduces the\nproblem.

\n

The collection is unavailable#

\n

For a hosted collection, confirm that the device is online and try Reconnect\nthis collection. For a computer collection, also confirm that the computer\nholding the Markdown is awake, online, and running mdbase Connect.

\n

An authorization error appears#

\n

Use the reconnect action for the current collection and review the access that\nmdbase requests. If you no longer want to use that collection, open More and\nchoose Change collection.

\n

A change did not save#

\n

TaskNotes writes directly to mdbase and does not queue failed changes for later.\nRestore the connection, then retry the action. Capture and editing screens keep\nrecoverable input visible when they can do so safely.

\n

A change from another tool is missing#

\n

Open More and choose Refresh now. If the record still does not appear,\nconfirm that the other tool wrote to the same mdbase collection and that the\nrecord uses a compatible TaskNotes task definition.

\n

Notifications do not arrive#

\n

Confirm that the current collection is an mdbase collection, reminders are\nenabled in More, the browser or operating system permission is granted, and\nthe task contains a valid future reminder. For a computer collection, the\ncomputer and mdbase Connect must remain available.

\n","text":"Start by recording the app version, platform, collection type, collection status shown under More, and the smallest sequence that reproduces the problem. The collection is unavailable# For a hosted collection, confirm that the device is online and try Reconnect this collection. For a computer collection, also confirm that the computer holding the Markdown is awake, online, and running mdbase Connect. An authorization error appears# Use the reconnect action for the current collection and review the access that mdbase requests. If you no longer want to use that collection, open More and choose Change collection. A change did not save# TaskNotes writes directly to mdbase and does not queue failed changes for later. Restore the connection, then retry the action. Capture and editing screens keep recoverable input visible when they can do so safely. A change from another tool is missing# Open More and choose Refresh now. If the record still does not appear, confirm that the other tool wrote to the same mdbase collection and that the record uses a compatible TaskNotes task definition. Notifications do not arrive# Confirm that the current collection is an mdbase collection, reminders are enabled in More, the browser or operating system permission is granted, and the task contains a valid future reminder. For a computer collection, the computer and mdbase Connect must remain available."},{"route":"/app/views/","title":"Views and navigation","description":"Use and arrange lists, boards, calendars, projects, and saved views in the TaskNotes app.","product":"app","platforms":["web","android","ios"],"version":"1.0.3","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/app/views.md","namespace":"app","relativePath":"views.md","raw":"---\ntitle: Views and navigation\ndescription: Use and arrange lists, boards, calendars, projects, and saved views in the TaskNotes app.\nroute: /app/views/\nproduct: app\nplatforms: [web, android, ios]\n---\n\n# Views and navigation\n\nViews are saved ways of selecting, sorting, grouping, and presenting records in\na collection. They travel with the collection; the set pinned to navigation is\na preference on each device.\n\n
\n \"TaskNotes\n
The Views manager controls navigation order and saved view definitions.
\n
\n\n## Starter views\n\nTaskNotes creates managed starter views such as Today, Upcoming, Calendar, and\nProjects. They use the same saved-view catalog as user-created views while\nproviding focused presentations for common work.\n\n## Presentations\n\n- **Task list** supports grouping, visible properties, section moves, and manual ordering.\n- **Kanban** groups tasks into columns and can update the grouped property when a task moves.\n- **Calendar** shows task dates in month, week, day, and list layouts.\n- **Mini calendar** combines a month picker with tasks for the selected day.\n- **Projects** finds project records referenced by active tasks.\n\n## Navigation\n\nOpen **Views** to add or remove a view from navigation and to change its order.\nThe first navigation item is the collection's home. Mobile displays the first\nthree views directly and keeps the rest in the Views destination.\n\n## Create and edit views\n\nThe view editor controls the name, presentation, query, grouping, sort order,\nvisible properties, and safe defaults for tasks created from the view. View\ndocuments remain ordinary collection resources rather than being stored only\ninside the TaskNotes app.\n","aliases":[],"toc":[{"level":2,"id":"starter-views","text":"Starter views"},{"level":2,"id":"presentations","text":"Presentations"},{"level":2,"id":"navigation","text":"Navigation"},{"level":2,"id":"create-and-edit-views","text":"Create and edit views"}],"html":"

Views are saved ways of selecting, sorting, grouping, and presenting records in\na collection. They travel with the collection; the set pinned to navigation is\na preference on each device.

\n
\n \"TaskNotes\n
The Views manager controls navigation order and saved view definitions.
\n
\n\n

Starter views#

\n

TaskNotes creates managed starter views such as Today, Upcoming, Calendar, and\nProjects. They use the same saved-view catalog as user-created views while\nproviding focused presentations for common work.

\n

Presentations#

\n
    \n
  • Task list supports grouping, visible properties, section moves, and manual ordering.
  • \n
  • Kanban groups tasks into columns and can update the grouped property when a task moves.
  • \n
  • Calendar shows task dates in month, week, day, and list layouts.
  • \n
  • Mini calendar combines a month picker with tasks for the selected day.
  • \n
  • Projects finds project records referenced by active tasks.
  • \n
\n

Navigation#

\n

Open Views to add or remove a view from navigation and to change its order.\nThe first navigation item is the collection's home. Mobile displays the first\nthree views directly and keeps the rest in the Views destination.

\n

Create and edit views#

\n

The view editor controls the name, presentation, query, grouping, sort order,\nvisible properties, and safe defaults for tasks created from the view. View\ndocuments remain ordinary collection resources rather than being stored only\ninside the TaskNotes app.

\n","text":"Views are saved ways of selecting, sorting, grouping, and presenting records in a collection. They travel with the collection; the set pinned to navigation is a preference on each device. The Views manager controls navigation order and saved view definitions. Starter views# TaskNotes creates managed starter views such as Today, Upcoming, Calendar, and Projects. They use the same saved-view catalog as user-created views while providing focused presentations for common work. Presentations# Task list supports grouping, visible properties, section moves, and manual ordering. Kanban groups tasks into columns and can update the grouped property when a task moves. Calendar shows task dates in month, week, day, and list layouts. Mini calendar combines a month picker with tasks for the selected day. Projects finds project records referenced by active tasks. Navigation# Open Views to add or remove a view from navigation and to change its order. The first navigation item is the collection's home. Mobile displays the first three views directly and keeps the rest in the Views destination. Create and edit views# The view editor controls the name, presentation, query, grouping, sort order, visible properties, and safe defaults for tasks created from the view. View documents remain ordinary collection resources rather than being stored only inside the TaskNotes app."},{"route":"/concepts/task-records/","title":"Portable task records","description":"The Markdown records, collection configuration, and task concepts shared by TaskNotes clients.","product":"shared","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/shared/task-records.md","namespace":"shared","relativePath":"task-records.md","raw":"---\ntitle: Portable task records\ndescription: The Markdown records, collection configuration, and task concepts shared by TaskNotes clients.\nroute: /concepts/task-records/\nproduct: shared\n---\n\n# Portable task records\n\nA TaskNotes task is an ordinary Markdown record with structured properties.\nThose properties describe the task; the Markdown body remains available for\nnotes, checklists, links, and supporting detail.\n\n## Collections\n\nA collection is a group of records plus the configuration that explains how to\ninterpret them. The configuration defines field names, statuses, priorities,\ncustom properties, record locations, and saved views.\n\nThe TaskNotes app uses **collection** throughout. The Obsidian plugin usually\ndescribes the containing folder as a **vault** and presents saved views through\nObsidian Bases.\n\n## Source of truth\n\nWhere the authoritative copy lives depends on the client and connection:\n\n| Client and collection | Source of truth | Availability |\n| --- | --- | --- |\n| TaskNotes app · hosted mdbase | Hosted collection | Requires a network connection |\n| TaskNotes app · computer through relay | Collection on that computer | Requires the network, computer, and connector |\n| Obsidian vault | Markdown files in the vault | Controlled by Obsidian and your sync choice |\n\n## Portability and compatibility\n\nPortable does not mean every client exposes every feature. Inline task widgets,\nObsidian commands, external calendar integrations, and companion plugins belong\nto the Obsidian client. mdbase collection access and background reminder\ndelivery belong to the TaskNotes app.\n\nUse the client-specific guide for interface instructions and the\n[specification](/developers/specification/) for normative data semantics.\n","aliases":[],"toc":[{"level":2,"id":"collections","text":"Collections"},{"level":2,"id":"source-of-truth","text":"Source of truth"},{"level":2,"id":"portability-and-compatibility","text":"Portability and compatibility"}],"html":"

A TaskNotes task is an ordinary Markdown record with structured properties.\nThose properties describe the task; the Markdown body remains available for\nnotes, checklists, links, and supporting detail.

\n

Collections#

\n

A collection is a group of records plus the configuration that explains how to\ninterpret them. The configuration defines field names, statuses, priorities,\ncustom properties, record locations, and saved views.

\n

The TaskNotes app uses collection throughout. The Obsidian plugin usually\ndescribes the containing folder as a vault and presents saved views through\nObsidian Bases.

\n

Source of truth#

\n

Where the authoritative copy lives depends on the client and connection:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Client and collectionSource of truthAvailability
TaskNotes app · hosted mdbaseHosted collectionRequires a network connection
TaskNotes app · computer through relayCollection on that computerRequires the network, computer, and connector
Obsidian vaultMarkdown files in the vaultControlled by Obsidian and your sync choice
\n

Portability and compatibility#

\n

Portable does not mean every client exposes every feature. Inline task widgets,\nObsidian commands, external calendar integrations, and companion plugins belong\nto the Obsidian client. mdbase collection access and background reminder\ndelivery belong to the TaskNotes app.

\n

Use the client-specific guide for interface instructions and the\nspecification for normative data semantics.

\n","text":"A TaskNotes task is an ordinary Markdown record with structured properties. Those properties describe the task; the Markdown body remains available for notes, checklists, links, and supporting detail. Collections# A collection is a group of records plus the configuration that explains how to interpret them. The configuration defines field names, statuses, priorities, custom properties, record locations, and saved views. The TaskNotes app uses collection throughout. The Obsidian plugin usually describes the containing folder as a vault and presents saved views through Obsidian Bases. Source of truth# Where the authoritative copy lives depends on the client and connection: Client and collection Source of truth Availability TaskNotes app · hosted mdbase Hosted collection Requires a network connection TaskNotes app · computer through relay Collection on that computer Requires the network, computer, and connector Obsidian vault Markdown files in the vault Controlled by Obsidian and your sync choice Portability and compatibility# Portable does not mean every client exposes every feature. Inline task widgets, Obsidian commands, external calendar integrations, and companion plugins belong to the Obsidian client. mdbase collection access and background reminder delivery belong to the TaskNotes app. Use the client-specific guide for interface instructions and the specification for normative data semantics."},{"route":"/developers/specification/","title":"0. Overview","description":"TaskNotes is an Obsidian plugin that stores tasks as individual markdown files with YAML frontmatter in a user's vault. Each task is a first-class file: readable and editabl...","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:00-overview.md","namespace":"specification","relativePath":"00-overview.md","raw":"# 0. Overview\n\n## 0.0 About tasknotes\n\n**TaskNotes** is an [Obsidian](https://obsidian.md) plugin that stores tasks as individual markdown files with YAML frontmatter in a user's vault. Each task is a first-class file: readable and editable with any text editor, version-controllable, and searchable without special tooling.\n\nA minimal task file looks like this:\n\n```markdown\n---\ntitle: Buy groceries\nstatus: open\npriority: normal\ndue: 2026-02-21\ntags: [task]\ndateCreated: 2026-02-20T11:15:00Z\ndateModified: 2026-02-20T11:15:00Z\n---\n\nBuy fruit and cleaning supplies.\n```\n\nTasks are identified within the vault by a configurable detection method — by default, by the presence of a specific tag (e.g. `#task` in body or frontmatter). The plugin stores its configuration in `.obsidian/plugins/tasknotes/data.json` within the vault root.\n\n**This specification** was derived from the behavior of the tasknotes plugin and is intended to serve as a stable, testable contract for:\n\n- CLI tools and scripts that process task files outside Obsidian,\n- any application that wants to interoperate with a tasknotes vault.\n\nThe spec is deliberately language-agnostic. It does not require any particular runtime, and the executable conformance suite (in `conformance/`) can be driven by an adapter written in any language.\n\nThe tasknotes plugin is the primary reference for how this spec was derived, but **the specification is normative** — where the spec and the plugin behavior differ, the spec defines the intended behavior. Known deviations are disclosed via conformance claims (§7.5).\n\n## 0.1 Status and authority\n\nThis document is part of `tasknotes-spec` version `0.3.0-rc.3`.\n\nThis specification is normative for implementations that claim conformance.\nNo single implementation is normative; implementations are expected to conform to the specification.\n\n## 0.2 Motivation\n\nTaskNotes-style systems store tasks as markdown files with YAML frontmatter. This model has practical advantages:\n\n- Task records are plain files that can be inspected and edited without proprietary tooling.\n- Data remains portable across environments.\n- Files are suitable for version control and collaboration workflows.\n\nAs soon as more than one tool reads and writes the same task files, implicit assumptions become an interoperability risk. In practice, these risks appear in three areas:\n\n1. Field semantics and naming drift.\n2. Date and timezone interpretation differences.\n3. Recurring-task state transitions that are handled differently by different clients.\n\nWhen these rules are not explicit, users can get inconsistent results from equivalent operations. A shared specification reduces that risk by making behavior testable and versioned.\n\n## 0.3 Objectives\n\nThis specification defines a stable contract for:\n\n- Representing task records in markdown frontmatter.\n- Mapping storage keys to canonical semantic roles.\n- Defining effective collection configuration via provider model (for example `tasknotes.yaml` and/or TaskNotes `data.json`).\n- Interpreting date and datetime values consistently.\n- Applying recurrence, per-instance completion/skip behavior, and optional materialized occurrence notes.\n- Managing time tracking sessions and `time_entries` lifecycle behavior.\n- Parsing and resolving links consistently across task fields.\n- Defining dependency and reminder behavior.\n- Optionally applying deterministic create-time templating behavior.\n- Executing write operations with predictable side-effects.\n- Validating task records and reporting issues.\n\n## 0.4 Non-objectives\n\nThis specification does not standardize:\n\n- UI layout, styling, command palettes, or interaction design.\n- Internal caching architecture or rendering pipelines.\n- Transport protocols (HTTP, IPC, etc.) except where they affect persisted task semantics.\n- Rich template-language features beyond the portable create-time templating contract in §5/§7/§9.\n\n## 0.5 Scope\n\nThis specification is standalone. It does not require conformance to any other specification.\n\nImplementations MAY internally reuse other libraries or specifications, but conformance claims under `tasknotes-spec` are evaluated only against this document.\nTemplating is optional and profile-gated; implementations that do not claim the templating profile remain conformant without template support.\nReferences to TaskNotes plugin behavior, Obsidian behavior, or external specifications are informative context only unless this specification explicitly marks a requirement as normative.\n\n## 0.6 Design principles\n\n### 0.6.1 File-first persistence\n\nTask state is represented in user-visible files. Derived indexes and caches are non-canonical.\n\n### 0.6.2 Deterministic semantics\n\nEquivalent inputs MUST produce equivalent persisted outputs under the same configuration and active runtime timezone.\n\n### 0.6.3 Explicit mapping\n\nSemantic roles are canonical. Storage key names are configurable and therefore must be mapped explicitly.\n\n### 0.6.4 Backward evolution\n\nThe specification supports migration from legacy keys and historical behaviors through explicit compatibility rules.\n\n## 0.7 Conformance\n\nConformance is profile-based (see §7). A minimal implementation can conform to a narrow profile while remaining interoperable for core operations.\n\n## 0.8 Normative language\n\nThe key words **MUST**, **MUST NOT**, **SHOULD**, **SHOULD NOT**, and **MAY** are to be interpreted as described in RFC 2119.\n\n## 0.9 Example collection\n\nA default tasknotes vault looks like this:\n\n```text\nMyVault/\n├── TaskNotes/\n│ ├── Tasks/\n│ │ ├── buy-groceries.md ← task file (title-derived filename by default)\n│ │ └── weekly-review.md\n│ └── Archive/ ← archive folder (if moveArchivedTasks=true)\n├── .obsidian/\n│ └── plugins/\n│ └── tasknotes/\n│ └── data.json ← plugin settings (primary config provider)\n└── tasknotes.yaml ← optional spec-level config (secondary provider)\n```\n\nTask files are identified by the `#task` tag by default (configurable). The full default collection state is described in §9.21.\n\nConfiguration provider semantics and effective configuration rules are defined in §9. An implementation MAY use either provider, both, or additional providers, based on its documented precedence policy.\n\nA task file example (using default field mapping):\n\n```markdown\n---\ntitle: Buy groceries\nstatus: open\npriority: normal\ndue: 2026-02-21\ntags: [task, errands]\ncontexts: [\"town\"]\ndateCreated: 2026-02-20T11:15:00Z\ndateModified: 2026-02-20T11:15:00Z\n---\n\nBuy fruit and cleaning supplies.\n```\n\n## 0.10 Versioning policy\n\nThis specification uses semantic versioning.\n\n- A **major** version introduces breaking semantic changes.\n- A **minor** version introduces additive behavior or optional features.\n- A **patch** version clarifies wording or fixes non-breaking defects.\n\nImplementations MUST reject unsupported major versions when strict mode is enabled.\n\n## 0.11 Change governance\n\nSpecification changes SHOULD be accompanied by:\n\n- a motivation statement,\n- precise normative edits,\n- migration notes when behavior changes,\n- updated examples.\n","aliases":["/spec/00-overview/"],"toc":[{"level":2,"id":"00-about-tasknotes","text":"0.0 About tasknotes"},{"level":2,"id":"01-status-and-authority","text":"0.1 Status and authority"},{"level":2,"id":"02-motivation","text":"0.2 Motivation"},{"level":2,"id":"03-objectives","text":"0.3 Objectives"},{"level":2,"id":"04-non-objectives","text":"0.4 Non-objectives"},{"level":2,"id":"05-scope","text":"0.5 Scope"},{"level":2,"id":"06-design-principles","text":"0.6 Design principles"},{"level":3,"id":"061-file-first-persistence","text":"0.6.1 File-first persistence"},{"level":3,"id":"062-deterministic-semantics","text":"0.6.2 Deterministic semantics"},{"level":3,"id":"063-explicit-mapping","text":"0.6.3 Explicit mapping"},{"level":3,"id":"064-backward-evolution","text":"0.6.4 Backward evolution"},{"level":2,"id":"07-conformance","text":"0.7 Conformance"},{"level":2,"id":"08-normative-language","text":"0.8 Normative language"},{"level":2,"id":"09-example-collection","text":"0.9 Example collection"},{"level":2,"id":"010-versioning-policy","text":"0.10 Versioning policy"},{"level":2,"id":"011-change-governance","text":"0.11 Change governance"}],"html":"

0.0 About tasknotes#

\n

TaskNotes is an Obsidian plugin that stores tasks as individual markdown files with YAML frontmatter in a user's vault. Each task is a first-class file: readable and editable with any text editor, version-controllable, and searchable without special tooling.

\n

A minimal task file looks like this:

\n
---\ntitle: Buy groceries\nstatus: open\npriority: normal\ndue: 2026-02-21\ntags: [task]\ndateCreated: 2026-02-20T11:15:00Z\ndateModified: 2026-02-20T11:15:00Z\n---\n\nBuy fruit and cleaning supplies.\n

Tasks are identified within the vault by a configurable detection method — by default, by the presence of a specific tag (e.g. #task in body or frontmatter). The plugin stores its configuration in .obsidian/plugins/tasknotes/data.json within the vault root.

\n

This specification was derived from the behavior of the tasknotes plugin and is intended to serve as a stable, testable contract for:

\n
    \n
  • CLI tools and scripts that process task files outside Obsidian,
  • \n
  • any application that wants to interoperate with a tasknotes vault.
  • \n
\n

The spec is deliberately language-agnostic. It does not require any particular runtime, and the executable conformance suite (in conformance/) can be driven by an adapter written in any language.

\n

The tasknotes plugin is the primary reference for how this spec was derived, but the specification is normative — where the spec and the plugin behavior differ, the spec defines the intended behavior. Known deviations are disclosed via conformance claims (§7.5).

\n

0.1 Status and authority#

\n

This document is part of tasknotes-spec version 0.3.0-rc.3.

\n

This specification is normative for implementations that claim conformance.\nNo single implementation is normative; implementations are expected to conform to the specification.

\n

0.2 Motivation#

\n

TaskNotes-style systems store tasks as markdown files with YAML frontmatter. This model has practical advantages:

\n
    \n
  • Task records are plain files that can be inspected and edited without proprietary tooling.
  • \n
  • Data remains portable across environments.
  • \n
  • Files are suitable for version control and collaboration workflows.
  • \n
\n

As soon as more than one tool reads and writes the same task files, implicit assumptions become an interoperability risk. In practice, these risks appear in three areas:

\n
    \n
  1. Field semantics and naming drift.
  2. \n
  3. Date and timezone interpretation differences.
  4. \n
  5. Recurring-task state transitions that are handled differently by different clients.
  6. \n
\n

When these rules are not explicit, users can get inconsistent results from equivalent operations. A shared specification reduces that risk by making behavior testable and versioned.

\n

0.3 Objectives#

\n

This specification defines a stable contract for:

\n
    \n
  • Representing task records in markdown frontmatter.
  • \n
  • Mapping storage keys to canonical semantic roles.
  • \n
  • Defining effective collection configuration via provider model (for example tasknotes.yaml and/or TaskNotes data.json).
  • \n
  • Interpreting date and datetime values consistently.
  • \n
  • Applying recurrence, per-instance completion/skip behavior, and optional materialized occurrence notes.
  • \n
  • Managing time tracking sessions and time_entries lifecycle behavior.
  • \n
  • Parsing and resolving links consistently across task fields.
  • \n
  • Defining dependency and reminder behavior.
  • \n
  • Optionally applying deterministic create-time templating behavior.
  • \n
  • Executing write operations with predictable side-effects.
  • \n
  • Validating task records and reporting issues.
  • \n
\n

0.4 Non-objectives#

\n

This specification does not standardize:

\n
    \n
  • UI layout, styling, command palettes, or interaction design.
  • \n
  • Internal caching architecture or rendering pipelines.
  • \n
  • Transport protocols (HTTP, IPC, etc.) except where they affect persisted task semantics.
  • \n
  • Rich template-language features beyond the portable create-time templating contract in §5/§7/§9.
  • \n
\n

0.5 Scope#

\n

This specification is standalone. It does not require conformance to any other specification.

\n

Implementations MAY internally reuse other libraries or specifications, but conformance claims under tasknotes-spec are evaluated only against this document.\nTemplating is optional and profile-gated; implementations that do not claim the templating profile remain conformant without template support.\nReferences to TaskNotes plugin behavior, Obsidian behavior, or external specifications are informative context only unless this specification explicitly marks a requirement as normative.

\n

0.6 Design principles#

\n

0.6.1 File-first persistence#

\n

Task state is represented in user-visible files. Derived indexes and caches are non-canonical.

\n

0.6.2 Deterministic semantics#

\n

Equivalent inputs MUST produce equivalent persisted outputs under the same configuration and active runtime timezone.

\n

0.6.3 Explicit mapping#

\n

Semantic roles are canonical. Storage key names are configurable and therefore must be mapped explicitly.

\n

0.6.4 Backward evolution#

\n

The specification supports migration from legacy keys and historical behaviors through explicit compatibility rules.

\n

0.7 Conformance#

\n

Conformance is profile-based (see §7). A minimal implementation can conform to a narrow profile while remaining interoperable for core operations.

\n

0.8 Normative language#

\n

The key words MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY are to be interpreted as described in RFC 2119.

\n

0.9 Example collection#

\n

A default tasknotes vault looks like this:

\n
MyVault/\n├── TaskNotes/\n│   ├── Tasks/\n│   │   ├── buy-groceries.md    ← task file (title-derived filename by default)\n│   │   └── weekly-review.md\n│   └── Archive/                ← archive folder (if moveArchivedTasks=true)\n├── .obsidian/\n│   └── plugins/\n│       └── tasknotes/\n│           └── data.json       ← plugin settings (primary config provider)\n└── tasknotes.yaml              ← optional spec-level config (secondary provider)\n

Task files are identified by the #task tag by default (configurable). The full default collection state is described in §9.21.

\n

Configuration provider semantics and effective configuration rules are defined in §9. An implementation MAY use either provider, both, or additional providers, based on its documented precedence policy.

\n

A task file example (using default field mapping):

\n
---\ntitle: Buy groceries\nstatus: open\npriority: normal\ndue: 2026-02-21\ntags: [task, errands]\ncontexts: ["town"]\ndateCreated: 2026-02-20T11:15:00Z\ndateModified: 2026-02-20T11:15:00Z\n---\n\nBuy fruit and cleaning supplies.\n

0.10 Versioning policy#

\n

This specification uses semantic versioning.

\n
    \n
  • A major version introduces breaking semantic changes.
  • \n
  • A minor version introduces additive behavior or optional features.
  • \n
  • A patch version clarifies wording or fixes non-breaking defects.
  • \n
\n

Implementations MUST reject unsupported major versions when strict mode is enabled.

\n

0.11 Change governance#

\n

Specification changes SHOULD be accompanied by:

\n
    \n
  • a motivation statement,
  • \n
  • precise normative edits,
  • \n
  • migration notes when behavior changes,
  • \n
  • updated examples.
  • \n
\n","text":"0.0 About tasknotes# TaskNotes is an Obsidian plugin that stores tasks as individual markdown files with YAML frontmatter in a user's vault. Each task is a first-class file: readable and editable with any text editor, version-controllable, and searchable without special tooling. A minimal task file looks like this: --- title: Buy groceries status: open priority: normal due: 2026-02-21 tags: [task] dateCreated: 2026-02-20T11:15:00Z dateModified: 2026-02-20T11:15:00Z --- Buy fruit and cleaning supplies. Tasks are identified within the vault by a configurable detection method — by default, by the presence of a specific tag (e.g. #task in body or frontmatter). The plugin stores its configuration in .obsidian/plugins/tasknotes/data.json within the vault root. This specification was derived from the behavior of the tasknotes plugin and is intended to serve as a stable, testable contract for: CLI tools and scripts that process task files outside Obsidian, any application that wants to interoperate with a tasknotes vault. The spec is deliberately language-agnostic. It does not require any particular runtime, and the executable conformance suite (in conformance/) can be driven by an adapter written in any language. The tasknotes plugin is the primary reference for how this spec was derived, but the specification is normative — where the spec and the plugin behavior differ, the spec defines the intended behavior. Known deviations are disclosed via conformance claims (§7.5). 0.1 Status and authority# This document is part of tasknotes-spec version 0.3.0-rc.3. This specification is normative for implementations that claim conformance. No single implementation is normative; implementations are expected to conform to the specification. 0.2 Motivation# TaskNotes-style systems store tasks as markdown files with YAML frontmatter. This model has practical advantages: Task records are plain files that can be inspected and edited without proprietary tooling. Data remains portable across environments. Files are suitable for version control and collaboration workflows. As soon as more than one tool reads and writes the same task files, implicit assumptions become an interoperability risk. In practice, these risks appear in three areas: Field semantics and naming drift. Date and timezone interpretation differences. Recurring-task state transitions that are handled differently by different clients. When these rules are not explicit, users can get inconsistent results from equivalent operations. A shared specification reduces that risk by making behavior testable and versioned. 0.3 Objectives# This specification defines a stable contract for: Representing task records in markdown frontmatter. Mapping storage keys to canonical semantic roles. Defining effective collection configuration via provider model (for example tasknotes.yaml and/or TaskNotes data.json). Interpreting date and datetime values consistently. Applying recurrence, per-instance completion/skip behavior, and optional materialized occurrence notes. Managing time tracking sessions and time_entries lifecycle behavior. Parsing and resolving links consistently across task fields. Defining dependency and reminder behavior. Optionally applying deterministic create-time templating behavior. Executing write operations with predictable side-effects. Validating task records and reporting issues. 0.4 Non-objectives# This specification does not standardize: UI layout, styling, command palettes, or interaction design. Internal caching architecture or rendering pipelines. Transport protocols (HTTP, IPC, etc.) except where they affect persisted task semantics. Rich template-language features beyond the portable create-time templating contract in §5/§7/§9. 0.5 Scope# This specification is standalone. It does not require conformance to any other specification. Implementations MAY internally reuse other libraries or specifications, but conformance claims under tasknotes-spec are evaluated only against this document. Templating is optional and profile-gated; implementations that do not claim the templating profile remain conformant without template support. References to TaskNotes plugin behavior, Obsidian behavior, or external specifications are informative context only unless this specification explicitly marks a requirement as normative. 0.6 Design principles# 0.6.1 File-first persistence# Task state is represented in user-visible files. Derived indexes and caches are non-canonical. 0.6.2 Deterministic semantics# Equivalent inputs MUST produce equivalent persisted outputs under the same configuration and active runtime timezone. 0.6.3 Explicit mapping# Semantic roles are canonical. Storage key names are configurable and therefore must be mapped explicitly. 0.6.4 Backward evolution# The specification supports migration from legacy keys and historical behaviors through explicit compatibility rules. 0.7 Conformance# Conformance is profile-based (see §7). A minimal implementation can conform to a narrow profile while remaining interoperable for core operations. 0.8 Normative language# The key words MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY are to be interpreted as described in RFC 2119. 0.9 Example collection# A default tasknotes vault looks like this: MyVault/ ├── TaskNotes/ │ ├── Tasks/ │ │ ├── buy-groceries.md ← task file (title-derived filename by default) │ │ └── weekly-review.md │ └── Archive/ ← archive folder (if moveArchivedTasks=true) ├── .obsidian/ │ └── plugins/ │ └── tasknotes/ │ └── data.json ← plugin settings (primary config provider) └── tasknotes.yaml ← optional spec-level config (secondary provider) Task files are identified by the #task tag by default (configurable). The full default collection state is described in §9.21. Configuration provider semantics and effective configuration rules are defined in §9. An implementation MAY use either provider, both, or additional providers, based on its documented precedence policy. A task file example (using default field mapping): --- title: Buy groceries status: open priority: normal due: 2026-02-21 tags: [task, errands] contexts: [\"town\"] dateCreated: 2026-02-20T11:15:00Z dateModified: 2026-02-20T11:15:00Z --- Buy fruit and cleaning supplies. 0.10 Versioning policy# This specification uses semantic versioning. A major version introduces breaking semantic changes. A minor version introduces additive behavior or optional features. A patch version clarifies wording or fixes non-breaking defects. Implementations MUST reject unsupported major versions when strict mode is enabled. 0.11 Change governance# Specification changes SHOULD be accompanied by: a motivation statement, precise normative edits, migration notes when behavior changes, updated examples."},{"route":"/developers/specification/01-terminology/","title":"1. Terminology","description":"This section defines terms used normatively in this specification.","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:01-terminology.md","namespace":"specification","relativePath":"01-terminology.md","raw":"# 1. Terminology\n\nThis section defines terms used normatively in this specification.\n\n## 1.1 Collection\n\nA **collection** is a filesystem scope within which task files are discovered and managed under a single TaskNotes configuration.\n\n## 1.2 Task file\n\nA **task file** is a markdown file identified as a task record by collection rules.\n\n## 1.3 Frontmatter\n\n**Frontmatter** is the YAML block at the start of a markdown file delimited by `---` markers.\n\n## 1.4 Task record\n\nA **task record** is the semantic task object obtained from parsing a task file frontmatter (plus optional derived metadata).\n\n## 1.5 Semantic role\n\nA **semantic role** is a canonical meaning defined by this specification, independent of storage key names.\n\nExamples: `title`, `status`, `date_created`, `complete_instances`.\n\n## 1.6 Storage key\n\nA **storage key** is the YAML property name used in frontmatter.\n\nExamples: `dateCreated`, `date_created`, `completedDate`.\n\n## 1.7 Field mapping\n\n**Field mapping** is the configuration that maps semantic roles to storage keys for reads and writes.\n\n## 1.8 Alias\n\nAn **alias** is a non-canonical storage key accepted for compatibility during reads.\n\n## 1.9 Canonical write key\n\nThe **canonical write key** is the configured storage key that conforming writers use for persisted output.\n\n## 1.10 Date value\n\nA **date value** represents a calendar day with no time-of-day and no timezone.\n\nCanonical form: `YYYY-MM-DD`.\n\n## 1.11 Datetime value\n\nA **datetime value** represents an instant in time.\n\nCanonical form: ISO 8601 UTC with trailing `Z`.\n\n## 1.12 Target date\n\nA **target date** is the calendar date to which a recurrence instance operation applies (for example complete instance on 2026-02-20).\n\n## 1.13 Recurrence rule\n\nA **recurrence rule** is a tasknotes recurrence string stored in the recurrence semantic role.\nIt uses RFC 5545 RRULE-style parameters inside a single semicolon-delimited field value and MAY include an explicit inline `DTSTART` prefix segment as defined in §4.3.\n\n## 1.14 Recurrence anchor\n\n**Recurrence anchor** defines how next-instance progression is computed. Allowed values:\n\n- `scheduled`\n- `completion`\n\n## 1.15 Complete instances\n\n**Complete instances** is the set/list of target dates marked completed for a recurring task.\n\n## 1.16 Skipped instances\n\n**Skipped instances** is the set/list of target dates marked skipped for a recurring task.\n\n## 1.17 Materialized occurrence note\n\nA **materialized occurrence note** is a task file created for one target date of a recurring parent task.\nIt stores user-authored per-occurrence content and, when supported by the implementation, owns the authoritative task state for that occurrence date.\n\n## 1.18 Recurrence parent\n\nA **recurrence parent** is the recurring task record referenced by a materialized occurrence note.\nThe reference is stored in semantic role `recurrence_parent` and resolved as a link according to §11.\n\n## 1.19 Occurrence materialization\n\n**Occurrence materialization** is the creation and reconciliation of materialized occurrence notes from a recurring parent task according to §4.18 and §5.20.\n\n## 1.20 Effective status\n\n**Effective status** is the status presented for a given date context after applying recurrence instance state.\n\n## 1.21 Completed-status list\n\nThe **completed-status list** is the configured ordered list of status values treated as completed for non-recurring completion semantics.\nWhen a single value must be chosen deterministically, the first list entry is used unless explicit operation input overrides it.\n\n## 1.22 Idempotent operation\n\nAn operation is **idempotent** if applying it multiple times with the same input produces the same persisted state as applying it once.\n\n## 1.23 Unknown field\n\nAn **unknown field** is a frontmatter property not mapped to a semantic role in current configuration.\n\n## 1.24 Validation issue\n\nA **validation issue** is a structured report containing at least:\n\n- machine-readable code,\n- severity,\n- optional path/field context,\n- human-readable message.\n\n## 1.25 Strict validation mode\n\n**Strict validation mode** is a mode where invalid required semantics are treated as hard errors and write operations fail.\n\n## 1.26 Legacy compatibility mode\n\n**Legacy compatibility mode** is a mode where specific historical behaviors or aliases are accepted for migration but are not canonical for new writes.\n\n## 1.27 Configuration provider\n\nA **configuration provider** is an adapter that loads configuration from a source (for example `tasknotes.yaml` or `.obsidian/plugins/tasknotes/data.json`) and normalizes it to the schema in §9.\n\n## 1.28 Effective configuration\n\nThe **effective configuration** is the final resolved configuration after applying provider precedence and fallback rules.\n\n## 1.29 Template file\n\nA **template file** is a markdown document used at create time to generate frontmatter and/or body content through variable expansion.\nWhen templating is enabled, template behavior is defined by §5.3.5 and §9.14.\n\n## 1.30 Template expansion\n\n**Template expansion** is deterministic replacement of template variables with create-time task data and runtime date/time values, followed by template merge rules.\n\n## 1.31 Time entry\n\nA **time entry** is a structured record in `time_entries` containing `startTime`, optional `endTime`, and optional `description`.\n\n## 1.32 Active time entry\n\nAn **active time entry** is a time entry with `startTime` present and `endTime` absent.\n\n## 1.33 Time tracking management\n\n**Time tracking management** is the set of operations that start, stop, edit, and remove `time_entries`, including completion-triggered auto-stop behavior when configured.\n","aliases":["/spec/01-terminology/"],"toc":[{"level":2,"id":"11-collection","text":"1.1 Collection"},{"level":2,"id":"12-task-file","text":"1.2 Task file"},{"level":2,"id":"13-frontmatter","text":"1.3 Frontmatter"},{"level":2,"id":"14-task-record","text":"1.4 Task record"},{"level":2,"id":"15-semantic-role","text":"1.5 Semantic role"},{"level":2,"id":"16-storage-key","text":"1.6 Storage key"},{"level":2,"id":"17-field-mapping","text":"1.7 Field mapping"},{"level":2,"id":"18-alias","text":"1.8 Alias"},{"level":2,"id":"19-canonical-write-key","text":"1.9 Canonical write key"},{"level":2,"id":"110-date-value","text":"1.10 Date value"},{"level":2,"id":"111-datetime-value","text":"1.11 Datetime value"},{"level":2,"id":"112-target-date","text":"1.12 Target date"},{"level":2,"id":"113-recurrence-rule","text":"1.13 Recurrence rule"},{"level":2,"id":"114-recurrence-anchor","text":"1.14 Recurrence anchor"},{"level":2,"id":"115-complete-instances","text":"1.15 Complete instances"},{"level":2,"id":"116-skipped-instances","text":"1.16 Skipped instances"},{"level":2,"id":"117-materialized-occurrence-note","text":"1.17 Materialized occurrence note"},{"level":2,"id":"118-recurrence-parent","text":"1.18 Recurrence parent"},{"level":2,"id":"119-occurrence-materialization","text":"1.19 Occurrence materialization"},{"level":2,"id":"120-effective-status","text":"1.20 Effective status"},{"level":2,"id":"121-completed-status-list","text":"1.21 Completed-status list"},{"level":2,"id":"122-idempotent-operation","text":"1.22 Idempotent operation"},{"level":2,"id":"123-unknown-field","text":"1.23 Unknown field"},{"level":2,"id":"124-validation-issue","text":"1.24 Validation issue"},{"level":2,"id":"125-strict-validation-mode","text":"1.25 Strict validation mode"},{"level":2,"id":"126-legacy-compatibility-mode","text":"1.26 Legacy compatibility mode"},{"level":2,"id":"127-configuration-provider","text":"1.27 Configuration provider"},{"level":2,"id":"128-effective-configuration","text":"1.28 Effective configuration"},{"level":2,"id":"129-template-file","text":"1.29 Template file"},{"level":2,"id":"130-template-expansion","text":"1.30 Template expansion"},{"level":2,"id":"131-time-entry","text":"1.31 Time entry"},{"level":2,"id":"132-active-time-entry","text":"1.32 Active time entry"},{"level":2,"id":"133-time-tracking-management","text":"1.33 Time tracking management"}],"html":"

This section defines terms used normatively in this specification.

\n

1.1 Collection#

\n

A collection is a filesystem scope within which task files are discovered and managed under a single TaskNotes configuration.

\n

1.2 Task file#

\n

A task file is a markdown file identified as a task record by collection rules.

\n

1.3 Frontmatter#

\n

Frontmatter is the YAML block at the start of a markdown file delimited by --- markers.

\n

1.4 Task record#

\n

A task record is the semantic task object obtained from parsing a task file frontmatter (plus optional derived metadata).

\n

1.5 Semantic role#

\n

A semantic role is a canonical meaning defined by this specification, independent of storage key names.

\n

Examples: title, status, date_created, complete_instances.

\n

1.6 Storage key#

\n

A storage key is the YAML property name used in frontmatter.

\n

Examples: dateCreated, date_created, completedDate.

\n

1.7 Field mapping#

\n

Field mapping is the configuration that maps semantic roles to storage keys for reads and writes.

\n

1.8 Alias#

\n

An alias is a non-canonical storage key accepted for compatibility during reads.

\n

1.9 Canonical write key#

\n

The canonical write key is the configured storage key that conforming writers use for persisted output.

\n

1.10 Date value#

\n

A date value represents a calendar day with no time-of-day and no timezone.

\n

Canonical form: YYYY-MM-DD.

\n

1.11 Datetime value#

\n

A datetime value represents an instant in time.

\n

Canonical form: ISO 8601 UTC with trailing Z.

\n

1.12 Target date#

\n

A target date is the calendar date to which a recurrence instance operation applies (for example complete instance on 2026-02-20).

\n

1.13 Recurrence rule#

\n

A recurrence rule is a tasknotes recurrence string stored in the recurrence semantic role.\nIt uses RFC 5545 RRULE-style parameters inside a single semicolon-delimited field value and MAY include an explicit inline DTSTART prefix segment as defined in §4.3.

\n

1.14 Recurrence anchor#

\n

Recurrence anchor defines how next-instance progression is computed. Allowed values:

\n
    \n
  • scheduled
  • \n
  • completion
  • \n
\n

1.15 Complete instances#

\n

Complete instances is the set/list of target dates marked completed for a recurring task.

\n

1.16 Skipped instances#

\n

Skipped instances is the set/list of target dates marked skipped for a recurring task.

\n

1.17 Materialized occurrence note#

\n

A materialized occurrence note is a task file created for one target date of a recurring parent task.\nIt stores user-authored per-occurrence content and, when supported by the implementation, owns the authoritative task state for that occurrence date.

\n

1.18 Recurrence parent#

\n

A recurrence parent is the recurring task record referenced by a materialized occurrence note.\nThe reference is stored in semantic role recurrence_parent and resolved as a link according to §11.

\n

1.19 Occurrence materialization#

\n

Occurrence materialization is the creation and reconciliation of materialized occurrence notes from a recurring parent task according to §4.18 and §5.20.

\n

1.20 Effective status#

\n

Effective status is the status presented for a given date context after applying recurrence instance state.

\n

1.21 Completed-status list#

\n

The completed-status list is the configured ordered list of status values treated as completed for non-recurring completion semantics.\nWhen a single value must be chosen deterministically, the first list entry is used unless explicit operation input overrides it.

\n

1.22 Idempotent operation#

\n

An operation is idempotent if applying it multiple times with the same input produces the same persisted state as applying it once.

\n

1.23 Unknown field#

\n

An unknown field is a frontmatter property not mapped to a semantic role in current configuration.

\n

1.24 Validation issue#

\n

A validation issue is a structured report containing at least:

\n
    \n
  • machine-readable code,
  • \n
  • severity,
  • \n
  • optional path/field context,
  • \n
  • human-readable message.
  • \n
\n

1.25 Strict validation mode#

\n

Strict validation mode is a mode where invalid required semantics are treated as hard errors and write operations fail.

\n

1.26 Legacy compatibility mode#

\n

Legacy compatibility mode is a mode where specific historical behaviors or aliases are accepted for migration but are not canonical for new writes.

\n

1.27 Configuration provider#

\n

A configuration provider is an adapter that loads configuration from a source (for example tasknotes.yaml or .obsidian/plugins/tasknotes/data.json) and normalizes it to the schema in §9.

\n

1.28 Effective configuration#

\n

The effective configuration is the final resolved configuration after applying provider precedence and fallback rules.

\n

1.29 Template file#

\n

A template file is a markdown document used at create time to generate frontmatter and/or body content through variable expansion.\nWhen templating is enabled, template behavior is defined by §5.3.5 and §9.14.

\n

1.30 Template expansion#

\n

Template expansion is deterministic replacement of template variables with create-time task data and runtime date/time values, followed by template merge rules.

\n

1.31 Time entry#

\n

A time entry is a structured record in time_entries containing startTime, optional endTime, and optional description.

\n

1.32 Active time entry#

\n

An active time entry is a time entry with startTime present and endTime absent.

\n

1.33 Time tracking management#

\n

Time tracking management is the set of operations that start, stop, edit, and remove time_entries, including completion-triggered auto-stop behavior when configured.

\n","text":"This section defines terms used normatively in this specification. 1.1 Collection# A collection is a filesystem scope within which task files are discovered and managed under a single TaskNotes configuration. 1.2 Task file# A task file is a markdown file identified as a task record by collection rules. 1.3 Frontmatter# Frontmatter is the YAML block at the start of a markdown file delimited by --- markers. 1.4 Task record# A task record is the semantic task object obtained from parsing a task file frontmatter (plus optional derived metadata). 1.5 Semantic role# A semantic role is a canonical meaning defined by this specification, independent of storage key names. Examples: title, status, date_created, complete_instances. 1.6 Storage key# A storage key is the YAML property name used in frontmatter. Examples: dateCreated, date_created, completedDate. 1.7 Field mapping# Field mapping is the configuration that maps semantic roles to storage keys for reads and writes. 1.8 Alias# An alias is a non-canonical storage key accepted for compatibility during reads. 1.9 Canonical write key# The canonical write key is the configured storage key that conforming writers use for persisted output. 1.10 Date value# A date value represents a calendar day with no time-of-day and no timezone. Canonical form: YYYY-MM-DD. 1.11 Datetime value# A datetime value represents an instant in time. Canonical form: ISO 8601 UTC with trailing Z. 1.12 Target date# A target date is the calendar date to which a recurrence instance operation applies (for example complete instance on 2026-02-20). 1.13 Recurrence rule# A recurrence rule is a tasknotes recurrence string stored in the recurrence semantic role. It uses RFC 5545 RRULE-style parameters inside a single semicolon-delimited field value and MAY include an explicit inline DTSTART prefix segment as defined in §4.3. 1.14 Recurrence anchor# Recurrence anchor defines how next-instance progression is computed. Allowed values: scheduled completion 1.15 Complete instances# Complete instances is the set/list of target dates marked completed for a recurring task. 1.16 Skipped instances# Skipped instances is the set/list of target dates marked skipped for a recurring task. 1.17 Materialized occurrence note# A materialized occurrence note is a task file created for one target date of a recurring parent task. It stores user-authored per-occurrence content and, when supported by the implementation, owns the authoritative task state for that occurrence date. 1.18 Recurrence parent# A recurrence parent is the recurring task record referenced by a materialized occurrence note. The reference is stored in semantic role recurrence_parent and resolved as a link according to §11. 1.19 Occurrence materialization# Occurrence materialization is the creation and reconciliation of materialized occurrence notes from a recurring parent task according to §4.18 and §5.20. 1.20 Effective status# Effective status is the status presented for a given date context after applying recurrence instance state. 1.21 Completed-status list# The completed-status list is the configured ordered list of status values treated as completed for non-recurring completion semantics. When a single value must be chosen deterministically, the first list entry is used unless explicit operation input overrides it. 1.22 Idempotent operation# An operation is idempotent if applying it multiple times with the same input produces the same persisted state as applying it once. 1.23 Unknown field# An unknown field is a frontmatter property not mapped to a semantic role in current configuration. 1.24 Validation issue# A validation issue is a structured report containing at least: machine-readable code, severity, optional path/field context, human-readable message. 1.25 Strict validation mode# Strict validation mode is a mode where invalid required semantics are treated as hard errors and write operations fail. 1.26 Legacy compatibility mode# Legacy compatibility mode is a mode where specific historical behaviors or aliases are accepted for migration but are not canonical for new writes. 1.27 Configuration provider# A configuration provider is an adapter that loads configuration from a source (for example tasknotes.yaml or .obsidian/plugins/tasknotes/data.json) and normalizes it to the schema in §9. 1.28 Effective configuration# The effective configuration is the final resolved configuration after applying provider precedence and fallback rules. 1.29 Template file# A template file is a markdown document used at create time to generate frontmatter and/or body content through variable expansion. When templating is enabled, template behavior is defined by §5.3.5 and §9.14. 1.30 Template expansion# Template expansion is deterministic replacement of template variables with create-time task data and runtime date/time values, followed by template merge rules. 1.31 Time entry# A time entry is a structured record in time_entries containing startTime, optional endTime, and optional description. 1.32 Active time entry# An active time entry is a time entry with startTime present and endTime absent. 1.33 Time tracking management# Time tracking management is the set of operations that start, stop, edit, and remove time_entries, including completion-triggered auto-stop behavior when configured."},{"route":"/developers/specification/02-model-and-mapping/","title":"2. Model and Field Mapping","description":"A task record consists of:","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:02-model-and-mapping.md","namespace":"specification","relativePath":"02-model-and-mapping.md","raw":"# 2. Model and Field Mapping\n\n## 2.1 Task record model\n\nA task record consists of:\n\n- frontmatter object (structured fields),\n- markdown body (freeform text),\n- file metadata (path, created/modified time) where available.\n\nFrontmatter is normative for task semantics. Body content is non-normative except where an implementation exposes body search or body-derived features.\n\n## 2.2 Required semantic roles\n\nConforming implementations MUST support these semantic roles:\n\n| Semantic role | Type | Required |\n|---|---|---|\n| `title` | string | support required (value required via configured title source, see §2.2.2) |\n| `status` | string/enum | yes |\n| `completed_date` | date | support required (conditionally required, see §2.2.1) |\n| `date_created` | datetime | yes |\n| `date_modified` | datetime | yes |\n\nIf storage omits a role marked `yes`, validation MUST report an error (see §6).\nFor operation-required roles, validation and operation rules in §5 and §6 apply.\n\n### 2.2.1 Conditional requiredness (`completed_date`)\n\n`completed_date` support is mandatory, but presence is conditional:\n\n- For non-recurring tasks with `status` in configured `status.completed_values`, `completed_date` MUST be present.\n- For non-recurring tasks with non-completed status, `completed_date` MAY be absent.\n- For recurring tasks, `completed_date` is not required by recurrence completion semantics and MAY be absent.\n\nValidators MUST apply this conditional rule and MUST NOT treat `completed_date` as unconditionally required.\n\n### 2.2.2 Conditional requiredness (`title`)\n\nSemantic `title` is always required, with deterministic read resolution and storage-mode-dependent read/write behavior:\n\n- Readers MUST resolve semantic title using storage-mode-aware precedence (§9.13):\n 1. when `title.storage=frontmatter`: mapped `title` key when present and non-empty, then file basename fallback;\n 2. when `title.storage=filename`: file basename first, then mapped `title` fallback when basename is unavailable.\n- If mapped title and filename-derived title both exist and differ, the source authoritative for active `title.storage` MUST win and implementations SHOULD emit `title_source_conflict`.\n- When `title.storage=filename`, implementations MAY keep mapped `title` as a synchronized compatibility mirror, but filename-derived title remains authoritative.\n- Title storage mode controls canonical writes (§9.13): `frontmatter` favors mapped-key writes; `filename` favors filename-derived title with rename-on-title-change behavior.\n\nValidators MUST enforce semantic title presence using the active title-resolution policy (§9.13), not frontmatter key presence alone.\n\n## 2.3 Common semantic roles\n\nImplementations conforming beyond minimal scope SHOULD support:\n\n| Semantic role | Type | Notes |\n|---|---|---|\n| `id` | string | stable task identity token; see §2.6.5 |\n| `priority` | string/enum | configurable values |\n| `due` | date or datetime | see §3 |\n| `scheduled` | date or datetime | see §3 |\n| `tags` | list | free tags |\n| `contexts` | list | commonly prefixed with `@` |\n| `projects` | list | project references, see §11 |\n| `attachments` | list | ordered file references owned by the task, see §2.6.7 and §11.8.3 |\n| `time_estimate` | integer >= 0 | minutes |\n| `time_entries` | list | see §2.6 |\n| `recurrence` | string | tasknotes recurrence string; see §4 |\n| `recurrence_anchor` | enum | `scheduled` or `completion` |\n| `complete_instances` | list | recurring completion state |\n| `skipped_instances` | list | recurring skip state |\n| `recurrence_parent` | link-or-string | parent recurring task reference for materialized occurrence notes; see §4.18 |\n| `occurrence_date` | date | target date represented by a materialized occurrence note |\n| `occurrence_materialization` | enum | parent task materialization mode: `manual`, `on_completion`, or `rolling` |\n| `occurrence_next_trigger` | enum | parent task next-note trigger: `completion` or `completion_or_skip` |\n| `occurrence_template` | link-or-string | optional template used when creating materialized occurrence notes |\n| `occurrence_past_horizon` | duration | optional rolling materialization lookbehind bound |\n| `occurrence_future_horizon` | duration | optional rolling materialization lookahead bound |\n| `blocked_by` | list | dependency records, see §10 and §11 |\n| `reminders` | list | reminder records, see §10 |\n\nOptional extended roles are defined in §7 profiles.\n\n## 2.4 Field mapping requirements\n\n### 2.4.1 Mapping presence\n\nAn implementation MUST have an effective mapping from each supported semantic role to a canonical write key.\nMapping configuration is defined in §9.\nIf semantic role `id` is supported, it MUST also have a canonical write key.\n\n### 2.4.2 Read behavior\n\nReaders MUST:\n\n1. Read the canonical mapped key if present.\n2. Support configured aliases where enabled.\n3. Resolve conflicts deterministically when canonical and alias keys coexist.\n4. When canonical and alias keys both exist for the same semantic role, canonical key value MUST win.\n5. When canonical key wins over alias, validator/loader SHOULD emit warning `alias_conflict_ignored`.\n\n### 2.4.3 Write behavior\n\nWriters MUST:\n\n- write only canonical keys,\n- avoid introducing alias keys in new writes,\n- preserve unknown fields unless the operation explicitly opts into normalization.\n\n## 2.5 Legacy alias compatibility\n\nImplementations SHOULD accept these aliases on read for interoperability:\n\n| Semantic role | Canonical example | Alias examples |\n|---|---|---|\n| `recurrence_anchor` | `recurrence_anchor` | `recurrenceAnchor` |\n| `complete_instances` | `complete_instances` | `completeInstances` |\n| `skipped_instances` | `skipped_instances` | `skippedInstances` |\n| `recurrence_parent` | `recurrence_parent` | `recurrenceParent` |\n| `occurrence_date` | `occurrence_date` | `occurrenceDate` |\n| `occurrence_materialization` | `occurrence_materialization` | `occurrenceMaterialization` |\n| `occurrence_next_trigger` | `occurrence_next_trigger` | `occurrenceNextTrigger` |\n| `occurrence_template` | `occurrence_template` | `occurrenceTemplate` |\n| `occurrence_past_horizon` | `occurrence_past_horizon` | `occurrencePastHorizon` |\n| `occurrence_future_horizon` | `occurrence_future_horizon` | `occurrenceFutureHorizon` |\n| `date_created` | `dateCreated` | `date_created` |\n| `date_modified` | `dateModified` | `date_modified` |\n| `completed_date` | `completedDate` | `completed_date` |\n| `time_entries` | `timeEntries` | `time_entries` |\n| `time_estimate` | `timeEstimate` | `time_estimate` |\n| `blocked_by` | `blockedBy` | `blocked_by` |\n| `attachments` | `attachments` | — |\n\nThis table is compatibility guidance, not a requirement to choose camelCase or snake_case as canonical.\n\n## 2.6 Structured role schemas\n\n### 2.6.1 time_entries\n\n`time_entries` items MUST be objects with:\n\n- `startTime` datetime (required)\n- `endTime` datetime (optional)\n- `description` string (optional)\n\nAdditional constraints:\n\n- a task MUST NOT contain more than one active time entry (entry with `startTime` and no `endTime`) at commit time.\n- an entry with missing `endTime` is interpreted as an active/running session.\n- an implementation MAY accept `duration` on read for backward compatibility, but canonical duration is derived from start/end and SHOULD NOT be persisted on canonical writes.\n\nNested key names in `time_entries` are fixed by this specification and are not independently configurable in `mapping`.\n\n### 2.6.2 projects\n\n`projects` SHOULD be represented as links when link semantics are supported, but plain strings MAY be accepted.\nWhen interpreted as links, parsing and resolution MUST follow §11.\n\n### 2.6.3 blocked_by\n\n`blocked_by` items MUST be objects with:\n\n- `uid` link-or-string task reference (required)\n- `reltype` enum (required; default allowed by §10 when omitted)\n- `gap` ISO 8601 duration string (optional)\n\nDetailed semantics are defined in §10. `uid` parsing and resolution MUST follow §11.\n\n### 2.6.4 reminders\n\n`reminders` items MUST be objects with:\n\n- `id` string (required)\n- `type` enum `absolute|relative` (required)\n- relative-only fields: `relatedTo`, `offset`\n- absolute-only fields: `absoluteTime`\n- `description` string (optional)\n\nDetailed semantics are defined in §10.\n\n### 2.6.5 id (stable task identity)\n\nWhen semantic role `id` is present:\n\n- value MUST be a non-empty string.\n- value MUST be treated as stable identity metadata and MUST NOT be rewritten by rename, move, or title-change operations.\n- readers and link resolution MAY use it as an identity lookup key (see §11.4 Step 3).\n- implementations SHOULD keep `id` unique within a collection; duplicate IDs SHOULD produce a validation issue.\n\n### 2.6.6 Materialized occurrence roles\n\nThe roles in this subsection are required only for implementations claiming profile `materialized-occurrences` (§7.3.4).\n\nParent recurring task roles:\n\n- `occurrence_materialization`: enum `manual|on_completion|rolling`; controls when occurrence notes are created (§4.18.5).\n- `occurrence_next_trigger`: enum `completion|completion_or_skip`; controls whether skip/cancel transitions advance creation of the next occurrence note (§4.18.6).\n- `occurrence_template`: link-or-string reference to a template file used when creating occurrence notes. Link parsing/resolution follows §11 when supported.\n- `occurrence_past_horizon` and `occurrence_future_horizon`: ISO 8601 durations used by rolling materialization (§4.18.7).\n\nMaterialized occurrence note roles:\n\n- `recurrence_parent`: link-or-string reference to the parent recurring task. Wikilinks are the default interoperable representation in Obsidian-oriented collections.\n- `occurrence_date`: date value identifying the target date this occurrence note represents.\n\nImplementations claiming `materialized-occurrences` MUST treat `recurrence_parent` and `occurrence_date` together as the occurrence identity key.\nWithin a resolved parent task, at most one materialized occurrence note SHOULD exist for each `occurrence_date`; duplicate notes MUST be reported when detected (§6.4).\n\nMaterialized occurrence notes MAY also use normal task roles such as `status`, `completed_date`, `scheduled`, `due`, `time_entries`, `reminders`, `contexts`, `projects`, and body content.\nFor dates where a materialized occurrence note exists, its own task state is authoritative as defined in §4.18.3.\n\n### 2.6.7 attachments\n\n`attachments` is the authoritative task-membership list for files associated\nwith a task. It MUST be represented as an ordered list of non-empty\nlink-or-string values. Each value MUST identify one collection file and MUST\nfollow the parsing, resolution, and canonical-write rules in §11.8.3.\n\nThe list itself intentionally contains references only. MIME type, byte size,\ncontent digest, storage revision, timestamps, and other binary metadata belong\nto the collection's file descriptor or filesystem metadata and MUST NOT be\nduplicated into canonical task frontmatter.\n\nThe Markdown body MAY embed or link an attached file for inline presentation,\nbut body links and embeds do not add or remove task membership. A file is a task\nattachment if and only if it appears in the mapped `attachments` list.\n\nReaders MAY accept a single scalar reference as compatibility input and\nnormalize it to a one-item list. Canonical writes MUST use a list, preserve its\norder, and MUST NOT contain empty or duplicate normalized targets.\n\n## 2.7 Unknown fields\n\nUnknown frontmatter keys MUST be preserved by default during updates, complete/uncomplete, skip/unskip, dependency mutations, reminder mutations, and archive operations.\n\nUnknown fields MAY be removed only when:\n\n- explicit normalization/migration is requested, or\n- strict schema replacement is explicitly requested.\n\n## 2.8 Example mapping\n\nExample effective mapping:\n\n```yaml\nmapping:\n id: id\n title: title\n status: status\n date_created: dateCreated\n date_modified: dateModified\n completed_date: completedDate\n recurrence: recurrence\n recurrence_anchor: recurrence_anchor\n complete_instances: complete_instances\n skipped_instances: skipped_instances\n recurrence_parent: recurrence_parent\n occurrence_date: occurrence_date\n occurrence_materialization: occurrence_materialization\n occurrence_next_trigger: occurrence_next_trigger\n occurrence_template: occurrence_template\n occurrence_past_horizon: occurrence_past_horizon\n occurrence_future_horizon: occurrence_future_horizon\n time_estimate: timeEstimate\n time_entries: timeEntries\n blocked_by: blockedBy\n reminders: reminders\n```\n\n## 2.9 Example task record\n\n```markdown\n---\nid: task-2026-01-10-weekly-review\ntitle: Weekly review\nstatus: open\npriority: high\nscheduled: 2026-02-20\nrecurrence: FREQ=WEEKLY;BYDAY=FR\nrecurrence_anchor: scheduled\ncomplete_instances: [2026-02-13]\nskipped_instances: []\nblockedBy:\n - uid: \"[[prepare-metrics]]\"\n reltype: FINISHTOSTART\n gap: P1D\nreminders:\n - id: rem_day_before\n type: relative\n relatedTo: due\n offset: -P1D\n - id: rem_start\n type: absolute\n absoluteTime: 2026-02-20T09:00:00Z\ndateCreated: 2026-01-10T09:30:00Z\ndateModified: 2026-02-20T08:02:11Z\n---\n\nReview completed work and plan next week.\n```\n\n## 2.10 Deterministic load example\n\nGiven frontmatter:\n\n```yaml\nrecurrence_anchor: scheduled\nrecurrenceAnchor: completion\n```\n\nIf canonical key is `recurrence_anchor`, a conforming loader using canonical-precedence policy MUST resolve semantic `recurrence_anchor` as `scheduled` and SHOULD emit a compatibility warning.\n","aliases":["/spec/02-model-and-mapping/"],"toc":[{"level":2,"id":"21-task-record-model","text":"2.1 Task record model"},{"level":2,"id":"22-required-semantic-roles","text":"2.2 Required semantic roles"},{"level":3,"id":"221-conditional-requiredness-completeddate","text":"2.2.1 Conditional requiredness (completed_date)"},{"level":3,"id":"222-conditional-requiredness-title","text":"2.2.2 Conditional requiredness (title)"},{"level":2,"id":"23-common-semantic-roles","text":"2.3 Common semantic roles"},{"level":2,"id":"24-field-mapping-requirements","text":"2.4 Field mapping requirements"},{"level":3,"id":"241-mapping-presence","text":"2.4.1 Mapping presence"},{"level":3,"id":"242-read-behavior","text":"2.4.2 Read behavior"},{"level":3,"id":"243-write-behavior","text":"2.4.3 Write behavior"},{"level":2,"id":"25-legacy-alias-compatibility","text":"2.5 Legacy alias compatibility"},{"level":2,"id":"26-structured-role-schemas","text":"2.6 Structured role schemas"},{"level":3,"id":"261-timeentries","text":"2.6.1 time_entries"},{"level":3,"id":"262-projects","text":"2.6.2 projects"},{"level":3,"id":"263-blockedby","text":"2.6.3 blocked_by"},{"level":3,"id":"264-reminders","text":"2.6.4 reminders"},{"level":3,"id":"265-id-stable-task-identity","text":"2.6.5 id (stable task identity)"},{"level":3,"id":"266-materialized-occurrence-roles","text":"2.6.6 Materialized occurrence roles"},{"level":3,"id":"267-attachments","text":"2.6.7 attachments"},{"level":2,"id":"27-unknown-fields","text":"2.7 Unknown fields"},{"level":2,"id":"28-example-mapping","text":"2.8 Example mapping"},{"level":2,"id":"29-example-task-record","text":"2.9 Example task record"},{"level":2,"id":"210-deterministic-load-example","text":"2.10 Deterministic load example"}],"html":"

2.1 Task record model#

\n

A task record consists of:

\n
    \n
  • frontmatter object (structured fields),
  • \n
  • markdown body (freeform text),
  • \n
  • file metadata (path, created/modified time) where available.
  • \n
\n

Frontmatter is normative for task semantics. Body content is non-normative except where an implementation exposes body search or body-derived features.

\n

2.2 Required semantic roles#

\n

Conforming implementations MUST support these semantic roles:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Semantic roleTypeRequired
titlestringsupport required (value required via configured title source, see §2.2.2)
statusstring/enumyes
completed_datedatesupport required (conditionally required, see §2.2.1)
date_createddatetimeyes
date_modifieddatetimeyes
\n

If storage omits a role marked yes, validation MUST report an error (see §6).\nFor operation-required roles, validation and operation rules in §5 and §6 apply.

\n

2.2.1 Conditional requiredness (completed_date)#

\n

completed_date support is mandatory, but presence is conditional:

\n
    \n
  • For non-recurring tasks with status in configured status.completed_values, completed_date MUST be present.
  • \n
  • For non-recurring tasks with non-completed status, completed_date MAY be absent.
  • \n
  • For recurring tasks, completed_date is not required by recurrence completion semantics and MAY be absent.
  • \n
\n

Validators MUST apply this conditional rule and MUST NOT treat completed_date as unconditionally required.

\n

2.2.2 Conditional requiredness (title)#

\n

Semantic title is always required, with deterministic read resolution and storage-mode-dependent read/write behavior:

\n
    \n
  • Readers MUST resolve semantic title using storage-mode-aware precedence (§9.13):
      \n
    1. when title.storage=frontmatter: mapped title key when present and non-empty, then file basename fallback;
    2. \n
    3. when title.storage=filename: file basename first, then mapped title fallback when basename is unavailable.
    4. \n
    \n
  • \n
  • If mapped title and filename-derived title both exist and differ, the source authoritative for active title.storage MUST win and implementations SHOULD emit title_source_conflict.
  • \n
  • When title.storage=filename, implementations MAY keep mapped title as a synchronized compatibility mirror, but filename-derived title remains authoritative.
  • \n
  • Title storage mode controls canonical writes (§9.13): frontmatter favors mapped-key writes; filename favors filename-derived title with rename-on-title-change behavior.
  • \n
\n

Validators MUST enforce semantic title presence using the active title-resolution policy (§9.13), not frontmatter key presence alone.

\n

2.3 Common semantic roles#

\n

Implementations conforming beyond minimal scope SHOULD support:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Semantic roleTypeNotes
idstringstable task identity token; see §2.6.5
prioritystring/enumconfigurable values
duedate or datetimesee §3
scheduleddate or datetimesee §3
tagslistfree tags
contextslistcommonly prefixed with @
projectslistproject references, see §11
attachmentslistordered file references owned by the task, see §2.6.7 and §11.8.3
time_estimateinteger >= 0minutes
time_entrieslistsee §2.6
recurrencestringtasknotes recurrence string; see §4
recurrence_anchorenumscheduled or completion
complete_instanceslistrecurring completion state
skipped_instanceslistrecurring skip state
recurrence_parentlink-or-stringparent recurring task reference for materialized occurrence notes; see §4.18
occurrence_datedatetarget date represented by a materialized occurrence note
occurrence_materializationenumparent task materialization mode: manual, on_completion, or rolling
occurrence_next_triggerenumparent task next-note trigger: completion or completion_or_skip
occurrence_templatelink-or-stringoptional template used when creating materialized occurrence notes
occurrence_past_horizondurationoptional rolling materialization lookbehind bound
occurrence_future_horizondurationoptional rolling materialization lookahead bound
blocked_bylistdependency records, see §10 and §11
reminderslistreminder records, see §10
\n

Optional extended roles are defined in §7 profiles.

\n

2.4 Field mapping requirements#

\n

2.4.1 Mapping presence#

\n

An implementation MUST have an effective mapping from each supported semantic role to a canonical write key.\nMapping configuration is defined in §9.\nIf semantic role id is supported, it MUST also have a canonical write key.

\n

2.4.2 Read behavior#

\n

Readers MUST:

\n
    \n
  1. Read the canonical mapped key if present.
  2. \n
  3. Support configured aliases where enabled.
  4. \n
  5. Resolve conflicts deterministically when canonical and alias keys coexist.
  6. \n
  7. When canonical and alias keys both exist for the same semantic role, canonical key value MUST win.
  8. \n
  9. When canonical key wins over alias, validator/loader SHOULD emit warning alias_conflict_ignored.
  10. \n
\n

2.4.3 Write behavior#

\n

Writers MUST:

\n
    \n
  • write only canonical keys,
  • \n
  • avoid introducing alias keys in new writes,
  • \n
  • preserve unknown fields unless the operation explicitly opts into normalization.
  • \n
\n

2.5 Legacy alias compatibility#

\n

Implementations SHOULD accept these aliases on read for interoperability:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Semantic roleCanonical exampleAlias examples
recurrence_anchorrecurrence_anchorrecurrenceAnchor
complete_instancescomplete_instancescompleteInstances
skipped_instancesskipped_instancesskippedInstances
recurrence_parentrecurrence_parentrecurrenceParent
occurrence_dateoccurrence_dateoccurrenceDate
occurrence_materializationoccurrence_materializationoccurrenceMaterialization
occurrence_next_triggeroccurrence_next_triggeroccurrenceNextTrigger
occurrence_templateoccurrence_templateoccurrenceTemplate
occurrence_past_horizonoccurrence_past_horizonoccurrencePastHorizon
occurrence_future_horizonoccurrence_future_horizonoccurrenceFutureHorizon
date_createddateCreateddate_created
date_modifieddateModifieddate_modified
completed_datecompletedDatecompleted_date
time_entriestimeEntriestime_entries
time_estimatetimeEstimatetime_estimate
blocked_byblockedByblocked_by
attachmentsattachments—
\n

This table is compatibility guidance, not a requirement to choose camelCase or snake_case as canonical.

\n

2.6 Structured role schemas#

\n

2.6.1 time_entries#

\n

time_entries items MUST be objects with:

\n
    \n
  • startTime datetime (required)
  • \n
  • endTime datetime (optional)
  • \n
  • description string (optional)
  • \n
\n

Additional constraints:

\n
    \n
  • a task MUST NOT contain more than one active time entry (entry with startTime and no endTime) at commit time.
  • \n
  • an entry with missing endTime is interpreted as an active/running session.
  • \n
  • an implementation MAY accept duration on read for backward compatibility, but canonical duration is derived from start/end and SHOULD NOT be persisted on canonical writes.
  • \n
\n

Nested key names in time_entries are fixed by this specification and are not independently configurable in mapping.

\n

2.6.2 projects#

\n

projects SHOULD be represented as links when link semantics are supported, but plain strings MAY be accepted.\nWhen interpreted as links, parsing and resolution MUST follow §11.

\n

2.6.3 blocked_by#

\n

blocked_by items MUST be objects with:

\n
    \n
  • uid link-or-string task reference (required)
  • \n
  • reltype enum (required; default allowed by §10 when omitted)
  • \n
  • gap ISO 8601 duration string (optional)
  • \n
\n

Detailed semantics are defined in §10. uid parsing and resolution MUST follow §11.

\n

2.6.4 reminders#

\n

reminders items MUST be objects with:

\n
    \n
  • id string (required)
  • \n
  • type enum absolute|relative (required)
  • \n
  • relative-only fields: relatedTo, offset
  • \n
  • absolute-only fields: absoluteTime
  • \n
  • description string (optional)
  • \n
\n

Detailed semantics are defined in §10.

\n

2.6.5 id (stable task identity)#

\n

When semantic role id is present:

\n
    \n
  • value MUST be a non-empty string.
  • \n
  • value MUST be treated as stable identity metadata and MUST NOT be rewritten by rename, move, or title-change operations.
  • \n
  • readers and link resolution MAY use it as an identity lookup key (see §11.4 Step 3).
  • \n
  • implementations SHOULD keep id unique within a collection; duplicate IDs SHOULD produce a validation issue.
  • \n
\n

2.6.6 Materialized occurrence roles#

\n

The roles in this subsection are required only for implementations claiming profile materialized-occurrences (§7.3.4).

\n

Parent recurring task roles:

\n
    \n
  • occurrence_materialization: enum manual|on_completion|rolling; controls when occurrence notes are created (§4.18.5).
  • \n
  • occurrence_next_trigger: enum completion|completion_or_skip; controls whether skip/cancel transitions advance creation of the next occurrence note (§4.18.6).
  • \n
  • occurrence_template: link-or-string reference to a template file used when creating occurrence notes. Link parsing/resolution follows §11 when supported.
  • \n
  • occurrence_past_horizon and occurrence_future_horizon: ISO 8601 durations used by rolling materialization (§4.18.7).
  • \n
\n

Materialized occurrence note roles:

\n
    \n
  • recurrence_parent: link-or-string reference to the parent recurring task. Wikilinks are the default interoperable representation in Obsidian-oriented collections.
  • \n
  • occurrence_date: date value identifying the target date this occurrence note represents.
  • \n
\n

Implementations claiming materialized-occurrences MUST treat recurrence_parent and occurrence_date together as the occurrence identity key.\nWithin a resolved parent task, at most one materialized occurrence note SHOULD exist for each occurrence_date; duplicate notes MUST be reported when detected (§6.4).

\n

Materialized occurrence notes MAY also use normal task roles such as status, completed_date, scheduled, due, time_entries, reminders, contexts, projects, and body content.\nFor dates where a materialized occurrence note exists, its own task state is authoritative as defined in §4.18.3.

\n

2.6.7 attachments#

\n

attachments is the authoritative task-membership list for files associated\nwith a task. It MUST be represented as an ordered list of non-empty\nlink-or-string values. Each value MUST identify one collection file and MUST\nfollow the parsing, resolution, and canonical-write rules in §11.8.3.

\n

The list itself intentionally contains references only. MIME type, byte size,\ncontent digest, storage revision, timestamps, and other binary metadata belong\nto the collection's file descriptor or filesystem metadata and MUST NOT be\nduplicated into canonical task frontmatter.

\n

The Markdown body MAY embed or link an attached file for inline presentation,\nbut body links and embeds do not add or remove task membership. A file is a task\nattachment if and only if it appears in the mapped attachments list.

\n

Readers MAY accept a single scalar reference as compatibility input and\nnormalize it to a one-item list. Canonical writes MUST use a list, preserve its\norder, and MUST NOT contain empty or duplicate normalized targets.

\n

2.7 Unknown fields#

\n

Unknown frontmatter keys MUST be preserved by default during updates, complete/uncomplete, skip/unskip, dependency mutations, reminder mutations, and archive operations.

\n

Unknown fields MAY be removed only when:

\n
    \n
  • explicit normalization/migration is requested, or
  • \n
  • strict schema replacement is explicitly requested.
  • \n
\n

2.8 Example mapping#

\n

Example effective mapping:

\n
mapping:\n  id: id\n  title: title\n  status: status\n  date_created: dateCreated\n  date_modified: dateModified\n  completed_date: completedDate\n  recurrence: recurrence\n  recurrence_anchor: recurrence_anchor\n  complete_instances: complete_instances\n  skipped_instances: skipped_instances\n  recurrence_parent: recurrence_parent\n  occurrence_date: occurrence_date\n  occurrence_materialization: occurrence_materialization\n  occurrence_next_trigger: occurrence_next_trigger\n  occurrence_template: occurrence_template\n  occurrence_past_horizon: occurrence_past_horizon\n  occurrence_future_horizon: occurrence_future_horizon\n  time_estimate: timeEstimate\n  time_entries: timeEntries\n  blocked_by: blockedBy\n  reminders: reminders\n

2.9 Example task record#

\n
---\nid: task-2026-01-10-weekly-review\ntitle: Weekly review\nstatus: open\npriority: high\nscheduled: 2026-02-20\nrecurrence: FREQ=WEEKLY;BYDAY=FR\nrecurrence_anchor: scheduled\ncomplete_instances: [2026-02-13]\nskipped_instances: []\nblockedBy:\n  - uid: "[[prepare-metrics]]"\n    reltype: FINISHTOSTART\n    gap: P1D\nreminders:\n  - id: rem_day_before\n    type: relative\n    relatedTo: due\n    offset: -P1D\n  - id: rem_start\n    type: absolute\n    absoluteTime: 2026-02-20T09:00:00Z\ndateCreated: 2026-01-10T09:30:00Z\ndateModified: 2026-02-20T08:02:11Z\n---\n\nReview completed work and plan next week.\n

2.10 Deterministic load example#

\n

Given frontmatter:

\n
recurrence_anchor: scheduled\nrecurrenceAnchor: completion\n

If canonical key is recurrence_anchor, a conforming loader using canonical-precedence policy MUST resolve semantic recurrence_anchor as scheduled and SHOULD emit a compatibility warning.

\n","text":"2.1 Task record model# A task record consists of: frontmatter object (structured fields), markdown body (freeform text), file metadata (path, created/modified time) where available. Frontmatter is normative for task semantics. Body content is non-normative except where an implementation exposes body search or body-derived features. 2.2 Required semantic roles# Conforming implementations MUST support these semantic roles: Semantic role Type Required title string support required (value required via configured title source, see §2.2.2) status string/enum yes completed_date date support required (conditionally required, see §2.2.1) date_created datetime yes date_modified datetime yes If storage omits a role marked yes, validation MUST report an error (see §6). For operation-required roles, validation and operation rules in §5 and §6 apply. 2.2.1 Conditional requiredness (completed_date)# completed_date support is mandatory, but presence is conditional: For non-recurring tasks with status in configured status.completed_values, completed_date MUST be present. For non-recurring tasks with non-completed status, completed_date MAY be absent. For recurring tasks, completed_date is not required by recurrence completion semantics and MAY be absent. Validators MUST apply this conditional rule and MUST NOT treat completed_date as unconditionally required. 2.2.2 Conditional requiredness (title)# Semantic title is always required, with deterministic read resolution and storage-mode-dependent read/write behavior: Readers MUST resolve semantic title using storage-mode-aware precedence (§9.13): when title.storage=frontmatter: mapped title key when present and non-empty, then file basename fallback; when title.storage=filename: file basename first, then mapped title fallback when basename is unavailable. If mapped title and filename-derived title both exist and differ, the source authoritative for active title.storage MUST win and implementations SHOULD emit title_source_conflict. When title.storage=filename, implementations MAY keep mapped title as a synchronized compatibility mirror, but filename-derived title remains authoritative. Title storage mode controls canonical writes (§9.13): frontmatter favors mapped-key writes; filename favors filename-derived title with rename-on-title-change behavior. Validators MUST enforce semantic title presence using the active title-resolution policy (§9.13), not frontmatter key presence alone. 2.3 Common semantic roles# Implementations conforming beyond minimal scope SHOULD support: Semantic role Type Notes id string stable task identity token; see §2.6.5 priority string/enum configurable values due date or datetime see §3 scheduled date or datetime see §3 tags list free tags contexts list commonly prefixed with @ projects list project references, see §11 attachments list ordered file references owned by the task, see §2.6.7 and §11.8.3 time_estimate integer >= 0 minutes time_entries list see §2.6 recurrence string tasknotes recurrence string; see §4 recurrence_anchor enum scheduled or completion complete_instances list recurring completion state skipped_instances list recurring skip state recurrence_parent link-or-string parent recurring task reference for materialized occurrence notes; see §4.18 occurrence_date date target date represented by a materialized occurrence note occurrence_materialization enum parent task materialization mode: manual, on_completion, or rolling occurrence_next_trigger enum parent task next-note trigger: completion or completion_or_skip occurrence_template link-or-string optional template used when creating materialized occurrence notes occurrence_past_horizon duration optional rolling materialization lookbehind bound occurrence_future_horizon duration optional rolling materialization lookahead bound blocked_by list dependency records, see §10 and §11 reminders list reminder records, see §10 Optional extended roles are defined in §7 profiles. 2.4 Field mapping requirements# 2.4.1 Mapping presence# An implementation MUST have an effective mapping from each supported semantic role to a canonical write key. Mapping configuration is defined in §9. If semantic role id is supported, it MUST also have a canonical write key. 2.4.2 Read behavior# Readers MUST: Read the canonical mapped key if present. Support configured aliases where enabled. Resolve conflicts deterministically when canonical and alias keys coexist. When canonical and alias keys both exist for the same semantic role, canonical key value MUST win. When canonical key wins over alias, validator/loader SHOULD emit warning alias_conflict_ignored. 2.4.3 Write behavior# Writers MUST: write only canonical keys, avoid introducing alias keys in new writes, preserve unknown fields unless the operation explicitly opts into normalization. 2.5 Legacy alias compatibility# Implementations SHOULD accept these aliases on read for interoperability: Semantic role Canonical example Alias examples recurrence_anchor recurrence_anchor recurrenceAnchor complete_instances complete_instances completeInstances skipped_instances skipped_instances skippedInstances recurrence_parent recurrence_parent recurrenceParent occurrence_date occurrence_date occurrenceDate occurrence_materialization occurrence_materialization occurrenceMaterialization occurrence_next_trigger occurrence_next_trigger occurrenceNextTrigger occurrence_template occurrence_template occurrenceTemplate occurrence_past_horizon occurrence_past_horizon occurrencePastHorizon occurrence_future_horizon occurrence_future_horizon occurrenceFutureHorizon date_created dateCreated date_created date_modified dateModified date_modified completed_date completedDate completed_date time_entries timeEntries time_entries time_estimate timeEstimate time_estimate blocked_by blockedBy blocked_by attachments attachments — This table is compatibility guidance, not a requirement to choose camelCase or snake_case as canonical. 2.6 Structured role schemas# 2.6.1 time_entries# time_entries items MUST be objects with: startTime datetime (required) endTime datetime (optional) description string (optional) Additional constraints: a task MUST NOT contain more than one active time entry (entry with startTime and no endTime) at commit time. an entry with missing endTime is interpreted as an active/running session. an implementation MAY accept duration on read for backward compatibility, but canonical duration is derived from start/end and SHOULD NOT be persisted on canonical writes. Nested key names in time_entries are fixed by this specification and are not independently configurable in mapping. 2.6.2 projects# projects SHOULD be represented as links when link semantics are supported, but plain strings MAY be accepted. When interpreted as links, parsing and resolution MUST follow §11. 2.6.3 blocked_by# blocked_by items MUST be objects with: uid link-or-string task reference (required) reltype enum (required; default allowed by §10 when omitted) gap ISO 8601 duration string (optional) Detailed semantics are defined in §10. uid parsing and resolution MUST follow §11. 2.6.4 reminders# reminders items MUST be objects with: id string (required) type enum absolute|relative (required) relative-only fields: relatedTo, offset absolute-only fields: absoluteTime description string (optional) Detailed semantics are defined in §10. 2.6.5 id (stable task identity)# When semantic role id is present: value MUST be a non-empty string. value MUST be treated as stable identity metadata and MUST NOT be rewritten by rename, move, or title-change operations. readers and link resolution MAY use it as an identity lookup key (see §11.4 Step 3). implementations SHOULD keep id unique within a collection; duplicate IDs SHOULD produce a validation issue. 2.6.6 Materialized occurrence roles# The roles in this subsection are required only for implementations claiming profile materialized-occurrences (§7.3.4). Parent recurring task roles: occurrence_materialization: enum manual|on_completion|rolling; controls when occurrence notes are created (§4.18.5). occurrence_next_trigger: enum completion|completion_or_skip; controls whether skip/cancel transitions advance creation of the next occurrence note (§4.18.6). occurrence_template: link-or-string reference to a template file used when creating occurrence notes. Link parsing/resolution follows §11 when supported. occurrence_past_horizon and occurrence_future_horizon: ISO 8601 durations used by rolling materialization (§4.18.7). Materialized occurrence note roles: recurrence_parent: link-or-string reference to the parent recurring task. Wikilinks are the default interoperable representation in Obsidian-oriented collections. occurrence_date: date value identifying the target date this occurrence note represents. Implementations claiming materialized-occurrences MUST treat recurrence_parent and occurrence_date together as the occurrence identity key. Within a resolved parent task, at most one materialized occurrence note SHOULD exist for each occurrence_date; duplicate notes MUST be reported when detected (§6.4). Materialized occurrence notes MAY also use normal task roles such as status, completed_date, scheduled, due, time_entries, reminders, contexts, projects, and body content. For dates where a materialized occurrence note exists, its own task state is authoritative as defined in §4.18.3. 2.6.7 attachments# attachments is the authoritative task-membership list for files associated with a task. It MUST be represented as an ordered list of non-empty link-or-string values. Each value MUST identify one collection file and MUST follow the parsing, resolution, and canonical-write rules in §11.8.3. The list itself intentionally contains references only. MIME type, byte size, content digest, storage revision, timestamps, and other binary metadata belong to the collection's file descriptor or filesystem metadata and MUST NOT be duplicated into canonical task frontmatter. The Markdown body MAY embed or link an attached file for inline presentation, but body links and embeds do not add or remove task membership. A file is a task attachment if and only if it appears in the mapped attachments list. Readers MAY accept a single scalar reference as compatibility input and normalize it to a one-item list. Canonical writes MUST use a list, preserve its order, and MUST NOT contain empty or duplicate normalized targets. 2.7 Unknown fields# Unknown frontmatter keys MUST be preserved by default during updates, complete/uncomplete, skip/unskip, dependency mutations, reminder mutations, and archive operations. Unknown fields MAY be removed only when: explicit normalization/migration is requested, or strict schema replacement is explicitly requested. 2.8 Example mapping# Example effective mapping: mapping: id: id title: title status: status date_created: dateCreated date_modified: dateModified completed_date: completedDate recurrence: recurrence recurrence_anchor: recurrence_anchor complete_instances: complete_instances skipped_instances: skipped_instances recurrence_parent: recurrence_parent occurrence_date: occurrence_date occurrence_materialization: occurrence_materialization occurrence_next_trigger: occurrence_next_trigger occurrence_template: occurrence_template occurrence_past_horizon: occurrence_past_horizon occurrence_future_horizon: occurrence_future_horizon time_estimate: timeEstimate time_entries: timeEntries blocked_by: blockedBy reminders: reminders 2.9 Example task record# --- id: task-2026-01-10-weekly-review title: Weekly review status: open priority: high scheduled: 2026-02-20 recurrence: FREQ=WEEKLY;BYDAY=FR recurrence_anchor: scheduled complete_instances: [2026-02-13] skipped_instances: [] blockedBy: - uid: \"[[prepare-metrics]]\" reltype: FINISHTOSTART gap: P1D reminders: - id: rem_day_before type: relative relatedTo: due offset: -P1D - id: rem_start type: absolute absoluteTime: 2026-02-20T09:00:00Z dateCreated: 2026-01-10T09:30:00Z dateModified: 2026-02-20T08:02:11Z --- Review completed work and plan next week. 2.10 Deterministic load example# Given frontmatter: recurrence_anchor: scheduled recurrenceAnchor: completion If canonical key is recurrence_anchor, a conforming loader using canonical-precedence policy MUST resolve semantic recurrence_anchor as scheduled and SHOULD emit a compatibility warning."},{"route":"/developers/specification/03-temporal-semantics/","title":"3. Temporal Semantics","description":"This section defines how implementations MUST interpret, compare, and serialize task-related date and datetime values.","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:03-temporal-semantics.md","namespace":"specification","relativePath":"03-temporal-semantics.md","raw":"# 3. Temporal Semantics\n\n## 3.1 Purpose\n\nThis section defines how implementations MUST interpret, compare, and serialize task-related date and datetime values.\n\n## 3.2 Supported temporal value classes\n\nImplementations MUST support:\n\n1. **Date values**: calendar day without time or timezone.\n2. **Datetime values**: instant in time.\n\n## 3.3 Canonical serialization\n\n### 3.3.1 Date\n\nCanonical date serialization is:\n\n```text\nYYYY-MM-DD\n```\n\n### 3.3.2 Datetime\n\nCanonical datetime serialization is UTC ISO 8601 with `Z`, for example:\n\n```text\n2026-02-20T13:45:00Z\n```\n\nCanonical datetime writes MUST use second precision (`YYYY-MM-DDTHH:MM:SSZ`) and MUST NOT include fractional seconds.\nImplementations MAY accept alternative inbound datetime forms but MUST normalize outbound canonical writes.\nIf an accepted inbound datetime includes fractional seconds, writers MUST normalize deterministically by truncating fractional precision to whole seconds.\n\n## 3.4 Parsing requirements\n\n### 3.4.1 Date parsing\n\nDate parsing MUST reject invalid calendar dates.\n\n- valid: `2026-02-28`\n- invalid: `2026-02-30`\n\n### 3.4.2 Datetime parsing\n\nDatetime parsing MUST reject malformed values.\nIn strict mode, datetime parsing MUST reject ambiguous local datetimes without offset (for example `2026-02-20T09:00:00` with no timezone offset).\nIn permissive mode, implementations MAY accept such values only under an explicitly documented compatibility policy and SHOULD emit a warning.\n\n### 3.4.3 Mixed input tolerance\n\nImplementations MAY accept both date and datetime values for roles like `due` and `scheduled` if configured to do so. The accepted form MUST be documented.\n\n### 3.4.4 Inbound acceptance matrix\n\nTo avoid ambiguity, conforming parsers MUST follow this matrix.\n\nDate forms:\n\n| Form | Example | Strict | Permissive |\n|---|---|---|---|\n| Canonical date | `2026-02-20` | accept | accept |\n| Basic date (no separators) | `20260220` | reject (`invalid_date_value`) | MAY accept only under documented compatibility policy; SHOULD emit warning |\n\nDatetime forms:\n\n| Form | Example | Strict | Permissive |\n|---|---|---|---|\n| Canonical UTC | `2026-02-20T09:00:00Z` | accept | accept |\n| ISO with explicit offset | `2026-02-20T09:00:00+10:00` | accept | accept |\n| ISO with fractional seconds | `2026-02-20T09:00:00.250Z` | accept (normalize to second precision on write) | accept (normalize to second precision on write) |\n| Offset-less local datetime | `2026-02-20T09:00:00` | reject (`invalid_datetime_value`) | MAY accept only under documented compatibility policy; SHOULD emit warning |\n| Space-separated datetime | `2026-02-20 09:00:00` | reject (`invalid_datetime_value`) | MAY accept only under documented compatibility policy; SHOULD emit warning |\n| Basic datetime (no separators) | `20260220T090000Z` | reject (`invalid_datetime_value`) | MAY accept only under documented compatibility policy; SHOULD emit warning |\n\nWhen permissive-mode compatibility accepts a non-canonical form, canonical writes MUST still follow §3.3.\n\n## 3.5 Day semantics vs instant semantics\n\n### 3.5.1 Date roles\n\nDate roles represent days, not instants, and MUST NOT be timezone-shifted.\n\n### 3.5.2 Datetime roles\n\nDatetime roles represent instants and MUST preserve instant equality through normalization.\n\nExample:\n\n- input `2026-02-20T08:00:00-05:00`\n- canonical write `2026-02-20T13:00:00Z`\n\n### 3.5.3 Implementation guidance: UTC-anchor strategy (non-normative)\n\nBecause date-only fields are human-readable (`YYYY-MM-DD`) while implementations often compute using datetime objects, a common strategy is to use a UTC-midnight anchor for date-only internals.\n\nRecommended approach:\n\n1. Parse date-only values to a UTC-midnight anchor instant for internal computations.\n2. Format date-only values from UTC calendar components when writing `YYYY-MM-DD`.\n3. Keep date-only roles as date-only on write unless an explicit conversion operation is requested.\n4. Evaluate user-facing day semantics (today, overdue, day grouping) using local calendar-day boundaries per §3.6.\n\nImplementations MAY use different internal representations as long as all normative requirements in this section are preserved.\n\n## 3.6 Local calendar-day evaluation\n\n### 3.6.1 Active runtime timezone\n\nFor day-level semantics, the active runtime timezone is:\n\n1. the caller-provided temporal execution context, when present\n2. the collection authority's configured timezone\n3. the process/system local timezone.\n\nThe timezone is runtime context, not TaskNotes type-binding configuration. A\nremote caller SHOULD send its current IANA timezone for interactive operations;\na headless authority SHOULD use its durable collection timezone. Every\noperation MUST resolve this precedence once and use one effective timezone for\nall day-level semantics in that operation.\n\nImplementations MUST make the effective timezone discoverable.\n\n### 3.6.2 Local calendar-day rules\n\nWhen calculating day-level concepts (for example overdue/day grouping/calendar day cells), implementations MUST evaluate against local calendar-day boundaries of the active runtime timezone.\n\nThis requirement prevents off-by-one day drift in positive and negative UTC offsets.\n\n## 3.7 Comparison rules\n\n### 3.7.1 Date-to-date\n\nCompare by calendar day ordering.\n\n### 3.7.2 Datetime-to-datetime\n\nCompare by instant ordering.\n\n### 3.7.3 Date-to-datetime\n\nIf compared, implementations MUST document coercion policy. Recommended policy:\n\n- convert date to local start-of-day for day-level comparisons,\n- avoid implicit coercion for instant-level comparisons.\n\n## 3.8 due and scheduled semantics\n\n`due` and `scheduled` MAY be either date or datetime by configuration.\n\nImplementations MUST:\n\n- preserve stored granularity unless explicit conversion is requested,\n- avoid silently converting date to datetime during unrelated writes,\n- require documented explicit policy for date-to-datetime conversion operations,\n- apply consistent coercion policy in filters and status calculations.\n\n## 3.9 Completion date semantics\n\n`completed_date` is a date role.\n\nFor non-recurring completion, writers MUST set `completed_date` using §5 semantics:\n\n- explicit completion-day input when provided,\n- otherwise current local day in active runtime timezone.\n\n## 3.10 Created/modified timestamps\n\n`date_created` and `date_modified` are datetime roles.\n\nWriters MUST:\n\n- set both on create,\n- update `date_modified` on successful mutating operations that change persisted state,\n- preserve `date_created` unless explicit migration/edit operation changes it.\n\n## 3.11 time_entries semantics\n\n### 3.11.1 Timestamp format\n\n`time_entries.startTime` and `time_entries.endTime` MUST be datetime instants in canonical form on write.\n\n### 3.11.2 Range validity\n\nIf both times exist, `endTime` MUST be greater than or equal to `startTime`.\n\n### 3.11.3 Duration handling\n\nIf duration is present, implementations SHOULD treat it as derived and MAY rewrite or remove stale duration values during normalization.\n\n### 3.11.4 Active session semantics\n\nAn entry with `startTime` and no `endTime` represents an active/running session.\n\nImplementations that support time-tracking management operations (§5.19) MUST enforce at most one active session per task at commit time.\n\n### 3.11.5 Derived time calculations\n\nFor interoperability, implementations SHOULD expose both derived views when reporting tracked time:\n\n- `closed_minutes`: sum of entries where both `startTime` and `endTime` exist.\n- `live_minutes`: `closed_minutes` plus elapsed minutes of active entries (if any).\n\nImplementations MUST document which derived view is used by each reporting surface (for example task cards, stats, APIs).\n\n## 3.12 reminder temporal semantics\n\nReminder time fields are governed by §10.3 and MUST follow canonical datetime and duration formats from this section.\n\nRules:\n\n- `reminders[].absoluteTime` MUST be a canonical datetime on write.\n- `reminders[].offset` MUST be a valid ISO 8601 duration string.\n- relative reminder base conversion for date-only values MUST use `reminders.date_only_anchor_time` from §9, or `00:00` local time if unset.\n\n## 3.13 Example: local-day overdue evaluation\n\nAssume local timezone `America/Los_Angeles` and local date `2026-02-20`.\n\nTask A:\n\n```yaml\ndue: 2026-02-19\nstatus: open\n```\n\nTask A is overdue.\n\nTask B:\n\n```yaml\ndue: 2026-02-20\nstatus: open\n```\n\nTask B is not overdue at start of day; it becomes overdue on `2026-02-21` local day.\n\n## 3.14 Example: preserving granularity\n\nBefore update:\n\n```yaml\ndue: 2026-02-20\npriority: normal\n```\n\nOperation: update priority only.\n\nAfter update (conforming):\n\n```yaml\ndue: 2026-02-20\npriority: high\n```\n\nNon-conforming behavior would silently rewrite `due` to a datetime.\n\n## 3.15 Example: canonical datetime write\n\nInput:\n\n```yaml\ntimeEntries:\n - startTime: 2026-02-20T09:30:00+01:00\n endTime: 2026-02-20T10:00:00+01:00\n```\n\nCanonical write:\n\n```yaml\ntimeEntries:\n - startTime: 2026-02-20T08:30:00Z\n endTime: 2026-02-20T09:00:00Z\n```\n\n## 3.16 Example: UTC-anchor roundtrip for date-only field\n\nInput:\n\n```yaml\ndue: 2026-02-20\n```\n\nInternal computation anchor:\n\n```text\n2026-02-20T00:00:00Z\n```\n\nAfter unrelated update, conforming write:\n\n```yaml\ndue: 2026-02-20\n```\n\nNon-conforming behavior would rewrite `due` as a datetime or shift it to another day based on local offset.\n","aliases":["/spec/03-temporal-semantics/"],"toc":[{"level":2,"id":"31-purpose","text":"3.1 Purpose"},{"level":2,"id":"32-supported-temporal-value-classes","text":"3.2 Supported temporal value classes"},{"level":2,"id":"33-canonical-serialization","text":"3.3 Canonical serialization"},{"level":3,"id":"331-date","text":"3.3.1 Date"},{"level":3,"id":"332-datetime","text":"3.3.2 Datetime"},{"level":2,"id":"34-parsing-requirements","text":"3.4 Parsing requirements"},{"level":3,"id":"341-date-parsing","text":"3.4.1 Date parsing"},{"level":3,"id":"342-datetime-parsing","text":"3.4.2 Datetime parsing"},{"level":3,"id":"343-mixed-input-tolerance","text":"3.4.3 Mixed input tolerance"},{"level":3,"id":"344-inbound-acceptance-matrix","text":"3.4.4 Inbound acceptance matrix"},{"level":2,"id":"35-day-semantics-vs-instant-semantics","text":"3.5 Day semantics vs instant semantics"},{"level":3,"id":"351-date-roles","text":"3.5.1 Date roles"},{"level":3,"id":"352-datetime-roles","text":"3.5.2 Datetime roles"},{"level":3,"id":"353-implementation-guidance-utc-anchor-strategy-non-normative","text":"3.5.3 Implementation guidance: UTC-anchor strategy (non-normative)"},{"level":2,"id":"36-local-calendar-day-evaluation","text":"3.6 Local calendar-day evaluation"},{"level":3,"id":"361-active-runtime-timezone","text":"3.6.1 Active runtime timezone"},{"level":3,"id":"362-local-calendar-day-rules","text":"3.6.2 Local calendar-day rules"},{"level":2,"id":"37-comparison-rules","text":"3.7 Comparison rules"},{"level":3,"id":"371-date-to-date","text":"3.7.1 Date-to-date"},{"level":3,"id":"372-datetime-to-datetime","text":"3.7.2 Datetime-to-datetime"},{"level":3,"id":"373-date-to-datetime","text":"3.7.3 Date-to-datetime"},{"level":2,"id":"38-due-and-scheduled-semantics","text":"3.8 due and scheduled semantics"},{"level":2,"id":"39-completion-date-semantics","text":"3.9 Completion date semantics"},{"level":2,"id":"310-createdmodified-timestamps","text":"3.10 Created/modified timestamps"},{"level":2,"id":"311-timeentries-semantics","text":"3.11 time_entries semantics"},{"level":3,"id":"3111-timestamp-format","text":"3.11.1 Timestamp format"},{"level":3,"id":"3112-range-validity","text":"3.11.2 Range validity"},{"level":3,"id":"3113-duration-handling","text":"3.11.3 Duration handling"},{"level":3,"id":"3114-active-session-semantics","text":"3.11.4 Active session semantics"},{"level":3,"id":"3115-derived-time-calculations","text":"3.11.5 Derived time calculations"},{"level":2,"id":"312-reminder-temporal-semantics","text":"3.12 reminder temporal semantics"},{"level":2,"id":"313-example-local-day-overdue-evaluation","text":"3.13 Example: local-day overdue evaluation"},{"level":2,"id":"314-example-preserving-granularity","text":"3.14 Example: preserving granularity"},{"level":2,"id":"315-example-canonical-datetime-write","text":"3.15 Example: canonical datetime write"},{"level":2,"id":"316-example-utc-anchor-roundtrip-for-date-only-field","text":"3.16 Example: UTC-anchor roundtrip for date-only field"}],"html":"

3.1 Purpose#

\n

This section defines how implementations MUST interpret, compare, and serialize task-related date and datetime values.

\n

3.2 Supported temporal value classes#

\n

Implementations MUST support:

\n
    \n
  1. Date values: calendar day without time or timezone.
  2. \n
  3. Datetime values: instant in time.
  4. \n
\n

3.3 Canonical serialization#

\n

3.3.1 Date#

\n

Canonical date serialization is:

\n
YYYY-MM-DD\n

3.3.2 Datetime#

\n

Canonical datetime serialization is UTC ISO 8601 with Z, for example:

\n
2026-02-20T13:45:00Z\n

Canonical datetime writes MUST use second precision (YYYY-MM-DDTHH:MM:SSZ) and MUST NOT include fractional seconds.\nImplementations MAY accept alternative inbound datetime forms but MUST normalize outbound canonical writes.\nIf an accepted inbound datetime includes fractional seconds, writers MUST normalize deterministically by truncating fractional precision to whole seconds.

\n

3.4 Parsing requirements#

\n

3.4.1 Date parsing#

\n

Date parsing MUST reject invalid calendar dates.

\n
    \n
  • valid: 2026-02-28
  • \n
  • invalid: 2026-02-30
  • \n
\n

3.4.2 Datetime parsing#

\n

Datetime parsing MUST reject malformed values.\nIn strict mode, datetime parsing MUST reject ambiguous local datetimes without offset (for example 2026-02-20T09:00:00 with no timezone offset).\nIn permissive mode, implementations MAY accept such values only under an explicitly documented compatibility policy and SHOULD emit a warning.

\n

3.4.3 Mixed input tolerance#

\n

Implementations MAY accept both date and datetime values for roles like due and scheduled if configured to do so. The accepted form MUST be documented.

\n

3.4.4 Inbound acceptance matrix#

\n

To avoid ambiguity, conforming parsers MUST follow this matrix.

\n

Date forms:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
FormExampleStrictPermissive
Canonical date2026-02-20acceptaccept
Basic date (no separators)20260220reject (invalid_date_value)MAY accept only under documented compatibility policy; SHOULD emit warning
\n

Datetime forms:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
FormExampleStrictPermissive
Canonical UTC2026-02-20T09:00:00Zacceptaccept
ISO with explicit offset2026-02-20T09:00:00+10:00acceptaccept
ISO with fractional seconds2026-02-20T09:00:00.250Zaccept (normalize to second precision on write)accept (normalize to second precision on write)
Offset-less local datetime2026-02-20T09:00:00reject (invalid_datetime_value)MAY accept only under documented compatibility policy; SHOULD emit warning
Space-separated datetime2026-02-20 09:00:00reject (invalid_datetime_value)MAY accept only under documented compatibility policy; SHOULD emit warning
Basic datetime (no separators)20260220T090000Zreject (invalid_datetime_value)MAY accept only under documented compatibility policy; SHOULD emit warning
\n

When permissive-mode compatibility accepts a non-canonical form, canonical writes MUST still follow §3.3.

\n

3.5 Day semantics vs instant semantics#

\n

3.5.1 Date roles#

\n

Date roles represent days, not instants, and MUST NOT be timezone-shifted.

\n

3.5.2 Datetime roles#

\n

Datetime roles represent instants and MUST preserve instant equality through normalization.

\n

Example:

\n
    \n
  • input 2026-02-20T08:00:00-05:00
  • \n
  • canonical write 2026-02-20T13:00:00Z
  • \n
\n

3.5.3 Implementation guidance: UTC-anchor strategy (non-normative)#

\n

Because date-only fields are human-readable (YYYY-MM-DD) while implementations often compute using datetime objects, a common strategy is to use a UTC-midnight anchor for date-only internals.

\n

Recommended approach:

\n
    \n
  1. Parse date-only values to a UTC-midnight anchor instant for internal computations.
  2. \n
  3. Format date-only values from UTC calendar components when writing YYYY-MM-DD.
  4. \n
  5. Keep date-only roles as date-only on write unless an explicit conversion operation is requested.
  6. \n
  7. Evaluate user-facing day semantics (today, overdue, day grouping) using local calendar-day boundaries per §3.6.
  8. \n
\n

Implementations MAY use different internal representations as long as all normative requirements in this section are preserved.

\n

3.6 Local calendar-day evaluation#

\n

3.6.1 Active runtime timezone#

\n

For day-level semantics, the active runtime timezone is:

\n
    \n
  1. the caller-provided temporal execution context, when present
  2. \n
  3. the collection authority's configured timezone
  4. \n
  5. the process/system local timezone.
  6. \n
\n

The timezone is runtime context, not TaskNotes type-binding configuration. A\nremote caller SHOULD send its current IANA timezone for interactive operations;\na headless authority SHOULD use its durable collection timezone. Every\noperation MUST resolve this precedence once and use one effective timezone for\nall day-level semantics in that operation.

\n

Implementations MUST make the effective timezone discoverable.

\n

3.6.2 Local calendar-day rules#

\n

When calculating day-level concepts (for example overdue/day grouping/calendar day cells), implementations MUST evaluate against local calendar-day boundaries of the active runtime timezone.

\n

This requirement prevents off-by-one day drift in positive and negative UTC offsets.

\n

3.7 Comparison rules#

\n

3.7.1 Date-to-date#

\n

Compare by calendar day ordering.

\n

3.7.2 Datetime-to-datetime#

\n

Compare by instant ordering.

\n

3.7.3 Date-to-datetime#

\n

If compared, implementations MUST document coercion policy. Recommended policy:

\n
    \n
  • convert date to local start-of-day for day-level comparisons,
  • \n
  • avoid implicit coercion for instant-level comparisons.
  • \n
\n

3.8 due and scheduled semantics#

\n

due and scheduled MAY be either date or datetime by configuration.

\n

Implementations MUST:

\n
    \n
  • preserve stored granularity unless explicit conversion is requested,
  • \n
  • avoid silently converting date to datetime during unrelated writes,
  • \n
  • require documented explicit policy for date-to-datetime conversion operations,
  • \n
  • apply consistent coercion policy in filters and status calculations.
  • \n
\n

3.9 Completion date semantics#

\n

completed_date is a date role.

\n

For non-recurring completion, writers MUST set completed_date using §5 semantics:

\n
    \n
  • explicit completion-day input when provided,
  • \n
  • otherwise current local day in active runtime timezone.
  • \n
\n

3.10 Created/modified timestamps#

\n

date_created and date_modified are datetime roles.

\n

Writers MUST:

\n
    \n
  • set both on create,
  • \n
  • update date_modified on successful mutating operations that change persisted state,
  • \n
  • preserve date_created unless explicit migration/edit operation changes it.
  • \n
\n

3.11 time_entries semantics#

\n

3.11.1 Timestamp format#

\n

time_entries.startTime and time_entries.endTime MUST be datetime instants in canonical form on write.

\n

3.11.2 Range validity#

\n

If both times exist, endTime MUST be greater than or equal to startTime.

\n

3.11.3 Duration handling#

\n

If duration is present, implementations SHOULD treat it as derived and MAY rewrite or remove stale duration values during normalization.

\n

3.11.4 Active session semantics#

\n

An entry with startTime and no endTime represents an active/running session.

\n

Implementations that support time-tracking management operations (§5.19) MUST enforce at most one active session per task at commit time.

\n

3.11.5 Derived time calculations#

\n

For interoperability, implementations SHOULD expose both derived views when reporting tracked time:

\n
    \n
  • closed_minutes: sum of entries where both startTime and endTime exist.
  • \n
  • live_minutes: closed_minutes plus elapsed minutes of active entries (if any).
  • \n
\n

Implementations MUST document which derived view is used by each reporting surface (for example task cards, stats, APIs).

\n

3.12 reminder temporal semantics#

\n

Reminder time fields are governed by §10.3 and MUST follow canonical datetime and duration formats from this section.

\n

Rules:

\n
    \n
  • reminders[].absoluteTime MUST be a canonical datetime on write.
  • \n
  • reminders[].offset MUST be a valid ISO 8601 duration string.
  • \n
  • relative reminder base conversion for date-only values MUST use reminders.date_only_anchor_time from §9, or 00:00 local time if unset.
  • \n
\n

3.13 Example: local-day overdue evaluation#

\n

Assume local timezone America/Los_Angeles and local date 2026-02-20.

\n

Task A:

\n
due: 2026-02-19\nstatus: open\n

Task A is overdue.

\n

Task B:

\n
due: 2026-02-20\nstatus: open\n

Task B is not overdue at start of day; it becomes overdue on 2026-02-21 local day.

\n

3.14 Example: preserving granularity#

\n

Before update:

\n
due: 2026-02-20\npriority: normal\n

Operation: update priority only.

\n

After update (conforming):

\n
due: 2026-02-20\npriority: high\n

Non-conforming behavior would silently rewrite due to a datetime.

\n

3.15 Example: canonical datetime write#

\n

Input:

\n
timeEntries:\n  - startTime: 2026-02-20T09:30:00+01:00\n    endTime: 2026-02-20T10:00:00+01:00\n

Canonical write:

\n
timeEntries:\n  - startTime: 2026-02-20T08:30:00Z\n    endTime: 2026-02-20T09:00:00Z\n

3.16 Example: UTC-anchor roundtrip for date-only field#

\n

Input:

\n
due: 2026-02-20\n

Internal computation anchor:

\n
2026-02-20T00:00:00Z\n

After unrelated update, conforming write:

\n
due: 2026-02-20\n

Non-conforming behavior would rewrite due as a datetime or shift it to another day based on local offset.

\n","text":"3.1 Purpose# This section defines how implementations MUST interpret, compare, and serialize task-related date and datetime values. 3.2 Supported temporal value classes# Implementations MUST support: Date values: calendar day without time or timezone. Datetime values: instant in time. 3.3 Canonical serialization# 3.3.1 Date# Canonical date serialization is: YYYY-MM-DD 3.3.2 Datetime# Canonical datetime serialization is UTC ISO 8601 with Z, for example: 2026-02-20T13:45:00Z Canonical datetime writes MUST use second precision (YYYY-MM-DDTHH:MM:SSZ) and MUST NOT include fractional seconds. Implementations MAY accept alternative inbound datetime forms but MUST normalize outbound canonical writes. If an accepted inbound datetime includes fractional seconds, writers MUST normalize deterministically by truncating fractional precision to whole seconds. 3.4 Parsing requirements# 3.4.1 Date parsing# Date parsing MUST reject invalid calendar dates. valid: 2026-02-28 invalid: 2026-02-30 3.4.2 Datetime parsing# Datetime parsing MUST reject malformed values. In strict mode, datetime parsing MUST reject ambiguous local datetimes without offset (for example 2026-02-20T09:00:00 with no timezone offset). In permissive mode, implementations MAY accept such values only under an explicitly documented compatibility policy and SHOULD emit a warning. 3.4.3 Mixed input tolerance# Implementations MAY accept both date and datetime values for roles like due and scheduled if configured to do so. The accepted form MUST be documented. 3.4.4 Inbound acceptance matrix# To avoid ambiguity, conforming parsers MUST follow this matrix. Date forms: Form Example Strict Permissive Canonical date 2026-02-20 accept accept Basic date (no separators) 20260220 reject (invalid_date_value) MAY accept only under documented compatibility policy; SHOULD emit warning Datetime forms: Form Example Strict Permissive Canonical UTC 2026-02-20T09:00:00Z accept accept ISO with explicit offset 2026-02-20T09:00:00+10:00 accept accept ISO with fractional seconds 2026-02-20T09:00:00.250Z accept (normalize to second precision on write) accept (normalize to second precision on write) Offset-less local datetime 2026-02-20T09:00:00 reject (invalid_datetime_value) MAY accept only under documented compatibility policy; SHOULD emit warning Space-separated datetime 2026-02-20 09:00:00 reject (invalid_datetime_value) MAY accept only under documented compatibility policy; SHOULD emit warning Basic datetime (no separators) 20260220T090000Z reject (invalid_datetime_value) MAY accept only under documented compatibility policy; SHOULD emit warning When permissive-mode compatibility accepts a non-canonical form, canonical writes MUST still follow §3.3. 3.5 Day semantics vs instant semantics# 3.5.1 Date roles# Date roles represent days, not instants, and MUST NOT be timezone-shifted. 3.5.2 Datetime roles# Datetime roles represent instants and MUST preserve instant equality through normalization. Example: input 2026-02-20T08:00:00-05:00 canonical write 2026-02-20T13:00:00Z 3.5.3 Implementation guidance: UTC-anchor strategy (non-normative)# Because date-only fields are human-readable (YYYY-MM-DD) while implementations often compute using datetime objects, a common strategy is to use a UTC-midnight anchor for date-only internals. Recommended approach: Parse date-only values to a UTC-midnight anchor instant for internal computations. Format date-only values from UTC calendar components when writing YYYY-MM-DD. Keep date-only roles as date-only on write unless an explicit conversion operation is requested. Evaluate user-facing day semantics (today, overdue, day grouping) using local calendar-day boundaries per §3.6. Implementations MAY use different internal representations as long as all normative requirements in this section are preserved. 3.6 Local calendar-day evaluation# 3.6.1 Active runtime timezone# For day-level semantics, the active runtime timezone is: the caller-provided temporal execution context, when present the collection authority's configured timezone the process/system local timezone. The timezone is runtime context, not TaskNotes type-binding configuration. A remote caller SHOULD send its current IANA timezone for interactive operations; a headless authority SHOULD use its durable collection timezone. Every operation MUST resolve this precedence once and use one effective timezone for all day-level semantics in that operation. Implementations MUST make the effective timezone discoverable. 3.6.2 Local calendar-day rules# When calculating day-level concepts (for example overdue/day grouping/calendar day cells), implementations MUST evaluate against local calendar-day boundaries of the active runtime timezone. This requirement prevents off-by-one day drift in positive and negative UTC offsets. 3.7 Comparison rules# 3.7.1 Date-to-date# Compare by calendar day ordering. 3.7.2 Datetime-to-datetime# Compare by instant ordering. 3.7.3 Date-to-datetime# If compared, implementations MUST document coercion policy. Recommended policy: convert date to local start-of-day for day-level comparisons, avoid implicit coercion for instant-level comparisons. 3.8 due and scheduled semantics# due and scheduled MAY be either date or datetime by configuration. Implementations MUST: preserve stored granularity unless explicit conversion is requested, avoid silently converting date to datetime during unrelated writes, require documented explicit policy for date-to-datetime conversion operations, apply consistent coercion policy in filters and status calculations. 3.9 Completion date semantics# completed_date is a date role. For non-recurring completion, writers MUST set completed_date using §5 semantics: explicit completion-day input when provided, otherwise current local day in active runtime timezone. 3.10 Created/modified timestamps# date_created and date_modified are datetime roles. Writers MUST: set both on create, update date_modified on successful mutating operations that change persisted state, preserve date_created unless explicit migration/edit operation changes it. 3.11 time_entries semantics# 3.11.1 Timestamp format# time_entries.startTime and time_entries.endTime MUST be datetime instants in canonical form on write. 3.11.2 Range validity# If both times exist, endTime MUST be greater than or equal to startTime. 3.11.3 Duration handling# If duration is present, implementations SHOULD treat it as derived and MAY rewrite or remove stale duration values during normalization. 3.11.4 Active session semantics# An entry with startTime and no endTime represents an active/running session. Implementations that support time-tracking management operations (§5.19) MUST enforce at most one active session per task at commit time. 3.11.5 Derived time calculations# For interoperability, implementations SHOULD expose both derived views when reporting tracked time: closed_minutes: sum of entries where both startTime and endTime exist. live_minutes: closed_minutes plus elapsed minutes of active entries (if any). Implementations MUST document which derived view is used by each reporting surface (for example task cards, stats, APIs). 3.12 reminder temporal semantics# Reminder time fields are governed by §10.3 and MUST follow canonical datetime and duration formats from this section. Rules: reminders[].absoluteTime MUST be a canonical datetime on write. reminders[].offset MUST be a valid ISO 8601 duration string. relative reminder base conversion for date-only values MUST use reminders.date_only_anchor_time from §9, or 00:00 local time if unset. 3.13 Example: local-day overdue evaluation# Assume local timezone America/Los_Angeles and local date 2026-02-20. Task A: due: 2026-02-19 status: open Task A is overdue. Task B: due: 2026-02-20 status: open Task B is not overdue at start of day; it becomes overdue on 2026-02-21 local day. 3.14 Example: preserving granularity# Before update: due: 2026-02-20 priority: normal Operation: update priority only. After update (conforming): due: 2026-02-20 priority: high Non-conforming behavior would silently rewrite due to a datetime. 3.15 Example: canonical datetime write# Input: timeEntries: - startTime: 2026-02-20T09:30:00+01:00 endTime: 2026-02-20T10:00:00+01:00 Canonical write: timeEntries: - startTime: 2026-02-20T08:30:00Z endTime: 2026-02-20T09:00:00Z 3.16 Example: UTC-anchor roundtrip for date-only field# Input: due: 2026-02-20 Internal computation anchor: 2026-02-20T00:00:00Z After unrelated update, conforming write: due: 2026-02-20 Non-conforming behavior would rewrite due as a datetime or shift it to another day based on local offset."},{"route":"/developers/specification/04-recurrence/","title":"4. Recurrence","description":"This section defines recurrence semantics, including rule representation, anchor behavior, and per-instance completion/skip state.","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:04-recurrence.md","namespace":"specification","relativePath":"04-recurrence.md","raw":"# 4. Recurrence\n\n## 4.1 Purpose\n\nThis section defines recurrence semantics, including rule representation, anchor behavior, and per-instance completion/skip state.\n\n## 4.2 Recurrence applicability\n\nA task is recurring when semantic role `recurrence` contains a valid tasknotes recurrence string.\n\nIf `recurrence` is absent or empty, the task is non-recurring.\n\n## 4.3 Rule format\n\n### 4.3.1 Required format\n\n`recurrence` MUST be a tasknotes recurrence string.\nThis syntax is RRULE-derived but is not a full RFC 5545 content line or multi-line iCalendar fragment.\nThe RRULE parameter portion MUST use RFC 5545 RRULE property syntax.\nIt MAY include a leading inline `DTSTART` segment.\n\nIf `DTSTART` is present, it MUST use one of:\n\n- `DTSTART:YYYYMMDD` (date-only)\n- `DTSTART:YYYYMMDDTHHMMSSZ` (UTC datetime)\n\nCanonical combined form is:\n\n- `DTSTART:...;FREQ=...`\n\nImplementations MAY accept inbound `RRULE:` prefixes or multi-line iCalendar-like inputs for compatibility, but canonical writes SHOULD use the combined single-field form above.\n\nExamples:\n\n- `FREQ=DAILY`\n- `FREQ=WEEKLY;BYDAY=MO,WE,FR`\n- `FREQ=MONTHLY;BYMONTHDAY=1`\n- `DTSTART:20260220;FREQ=WEEKLY;BYDAY=FR`\n\n### 4.3.2 Invalid rule handling\n\nInvalid recurrence rules MUST produce a validation error in strict mode and SHOULD produce at least a warning in permissive mode.\n\n## 4.4 Recurrence anchor\n\n`recurrence_anchor` controls progression semantics and MUST be one of:\n\n- `scheduled`\n- `completion`\n\nIf missing, implementations SHOULD default to `scheduled` unless collection configuration defines another default.\n\n### 4.4.1 Recurrence seed precedence\n\nWhen recurrence generation requires a seed/start date, implementations MUST resolve it in this order:\n\n1. `DTSTART` embedded in `recurrence`,\n2. semantic `scheduled`,\n3. semantic `date_created`.\n\nIf no seed can be resolved, recurrence materialization MUST fail deterministically and validation MUST report an error.\n\n### 4.4.2 Anchor progression behavior\n\nFor `recurrence_anchor=scheduled`, progression is based on the scheduled chain and `DTSTART` MUST remain fixed after it is set.\n\nFor `recurrence_anchor=completion`, complete-instance operations MUST advance progression by updating `DTSTART` to the completion target (date or datetime per §4.4.3).\n\n### 4.4.3 `DTSTART` update semantics\n\nWhen `recurrence_anchor=completion` and instance completion succeeds for resolved target day `D`:\n\n1. Instance-list state (`complete_instances`, `skipped_instances`) MUST always use day `D`.\n2. If the caller provided an explicit datetime target, `DTSTART` MUST be rewritten as `DTSTART:YYYYMMDDTHHMMSSZ` using that target instant normalized to UTC.\n3. Otherwise, `DTSTART` MUST be rewritten as `DTSTART:YYYYMMDD` for day `D`.\n4. RRULE components other than `DTSTART` MUST be preserved unless an explicit recurrence-edit operation changes them.\n5. If `DTSTART` is absent, completion-anchor progression MUST insert it before RRULE parameters.\n\n### 4.4.4 Recalculation semantics for `recurrence_anchor=completion`\n\nWhen calculating the next candidate occurrence for `recurrence_anchor=completion`:\n\n1. Implementations MUST treat `DTSTART` progression as the consumed-history mechanism.\n2. `complete_instances` MUST NOT be used as an exclusion set for future occurrence selection in this mode.\n3. `skipped_instances` MUST still exclude matching candidate dates.\n4. Candidate selection MUST choose the first RRULE occurrence strictly after the current `DTSTART` anchor (or resolved seed if `DTSTART` is absent).\n\nThis matches the completion-anchor progression model where each completion advances the chain by rewriting `DTSTART`.\nThis model is intentionally not fully reversible via ordinary `uncomplete instance`; progression history lives in `DTSTART`, not only in `complete_instances`.\n\n### 4.4.5 `DTSTART` canonicalization on recurring writes\n\nTo ensure stable recurrence materialization across implementations, writers that persist recurring tasks MUST ensure `DTSTART` is present after create or successful recurring-instance completion.\n\nRules:\n\n1. If persisted `recurrence` already contains `DTSTART`, keep it unless an explicit operation updates it per §4.4.3.\n2. If persisted `recurrence` omits `DTSTART`, writers MUST resolve a seed using §4.4.1 and insert `DTSTART` before RRULE parameters.\n3. For `recurrence_anchor=scheduled`, inserted `DTSTART` becomes the fixed progression baseline and MUST NOT be rewritten by later scheduled-anchor completions.\n4. If seed resolution fails, operation MUST fail deterministically and emit `missing_recurrence_seed`.\n\n## 4.5 Instance state fields\n\nPer-instance state is represented by:\n\n- `complete_instances`: list of date values\n- `skipped_instances`: list of date values\n\nThese lists represent day-level instance outcomes.\n\n## 4.6 Invariants\n\nImplementations MUST enforce:\n\n1. Items in instance lists are valid date values.\n2. No date appears in both lists simultaneously.\n3. Duplicate dates are normalized (set semantics) or rejected deterministically.\n4. Validators MUST NOT reject an instance date solely because it is not an RRULE-generated occurrence.\n\n## 4.7 Instance completion semantics\n\nOperation: `complete instance` for target date `D`.\n\nConforming behavior:\n\n1. Add `D` to `complete_instances`.\n2. Remove `D` from `skipped_instances` if present.\n3. Leave base task status unchanged unless explicit policy states otherwise.\n4. Update `date_modified` when state changes.\n\nOperation MUST be idempotent.\n\n## 4.8 Instance uncompletion semantics\n\nOperation: `uncomplete instance` for target date `D`.\n\nConforming behavior:\n\n1. Remove `D` from `complete_instances` if present.\n2. Do not add `D` to `skipped_instances` implicitly.\n3. For `recurrence_anchor=completion`, uncomplete MUST NOT rewrite or roll back `DTSTART`; restoring prior progression requires an explicit recurrence edit or implementation-specific rewind operation.\n4. Update `date_modified` when state changes.\n\nOperation MUST be idempotent.\n\n## 4.9 Instance skip semantics\n\nOperation: `skip instance` for target date `D`.\n\nConforming behavior:\n\n1. Add `D` to `skipped_instances`.\n2. Remove `D` from `complete_instances` if present.\n3. Update `date_modified` when state changes.\n\nOperation MUST be idempotent.\n\n## 4.10 Instance unskip semantics\n\nOperation: `unskip instance` for target date `D`.\n\nConforming behavior:\n\n1. Remove `D` from `skipped_instances` if present.\n2. Do not add to `complete_instances` implicitly.\n3. Update `date_modified` when state changes.\n\nOperation MUST be idempotent.\n\n## 4.11 Effective instance state\n\nFor target date `D`, effective state MUST be resolved in this order:\n\n1. If `D` in `complete_instances`: state is `completed`.\n2. Else if `D` in `skipped_instances`: state is `skipped`.\n3. Else: state is unresolved/default for that instance.\n\nBecause overlap is invalid, this ordering is deterministic.\n\n## 4.12 Interaction with base status\n\nFor recurring tasks:\n\n- Base `status` is task-level metadata and MUST NOT be forcibly rewritten to a completed status on instance completion unless explicitly configured.\n- Instance state determines completion for recurrence-aware views and operations.\n- Dependency blocked/unblocked evaluation for v0.1 follows §10.2.5 and is not recurrence-instance-aware unless explicitly extended by implementation policy.\n\nFor non-recurring tasks, completion uses base status semantics (§5).\n\n## 4.13 Completed-status configuration\n\nImplementations MUST define which status values are treated as complete for non-recurring tasks.\n\nThe completed-status list MUST be configurable or schema-driven and MUST NOT rely on a hardcoded single literal.\n\n## 4.14 Example: complete then skip same day\n\nInitial:\n\n```yaml\nrecurrence: FREQ=DAILY\ncompleteInstances: [2026-02-20]\nskippedInstances: []\n```\n\nSkip target date `2026-02-20`:\n\n```yaml\nrecurrence: FREQ=DAILY\ncompleteInstances: []\nskippedInstances: [2026-02-20]\n```\n\n## 4.15 Example: idempotent complete\n\nInitial:\n\n```yaml\ncompleteInstances: [2026-02-20]\nskippedInstances: []\n```\n\nComplete `2026-02-20` again:\n\n- persisted instance lists remain unchanged,\n- operation succeeds without duplicate entries.\n\n## 4.16 Example: anchor semantics\n\nTask:\n\n```yaml\nrecurrence: FREQ=WEEKLY;BYDAY=FR\nrecurrenceAnchor: completion\n```\n\nIf implementation supports next-occurrence materialization, it MUST compute next occurrence relative to completion progression when anchor is `completion`, not solely by scheduled chain.\nImplementations using `DTSTART` progression MUST update `DTSTART` to the completion date for this mode.\n\nWorked example (`recurrence_anchor=completion`):\n\n```yaml\nrecurrence: DTSTART:20260220;FREQ=DAILY\nrecurrence_anchor: completion\ncomplete_instances: [2026-02-20, 2026-02-21]\nskipped_instances: [2026-02-23]\n```\n\nConforming recalculation:\n\n- does **not** exclude `2026-02-22` because it is absent from `skipped_instances`,\n- does exclude `2026-02-23` because it is skipped,\n- ignores `complete_instances` for future exclusion in this mode (§4.4.4).\n\n## 4.17 Validation examples\n\nInvalid overlap:\n\n```yaml\ncompleteInstances: [2026-02-20]\nskippedInstances: [2026-02-20]\n```\n\nResult: validation error `instance_state_overlap`.\n\nInvalid date in list:\n\n```yaml\ncompleteInstances: [2026-02-30]\n```\n\nResult: validation error `invalid_date_value`.\n\n## 4.18 Recurrence materialization\n\nThis subsection is required only for implementations claiming profile `materialized-occurrences` (§7.3.4).\n\nRecurrence materialization creates ordinary task files for specific target dates of a recurring parent task.\nIt is additive behavior: implementations that do not claim `materialized-occurrences` continue to use the instance-list model in §4.5-§4.12.\nMaterialized occurrence notes MUST be task files according to the collection's task-detection rules (§9.7).\n\n### 4.18.1 Parent and occurrence ownership\n\nThe parent recurring task owns series-level semantics:\n\n- `recurrence`\n- `recurrence_anchor`\n- recurrence generation and `DTSTART` progression\n- parent instance-list compatibility state (`complete_instances`, `skipped_instances`)\n- materialization policy fields (`occurrence_materialization`, `occurrence_next_trigger`, `occurrence_template`, `occurrence_past_horizon`, `occurrence_future_horizon`)\n\nA materialized occurrence note owns per-date task semantics for its `occurrence_date`, including:\n\n- `status`\n- `completed_date`\n- body content and checklists\n- `time_entries`\n- per-occurrence `due`, `scheduled`, `reminders`, `contexts`, `projects`, and unknown fields\n\n### 4.18.2 Occurrence identity and parent reference\n\nA materialized occurrence note MUST store:\n\n- `recurrence_parent`: a link-or-string reference to the parent recurring task\n- `occurrence_date`: the target date represented by the occurrence note\n\nThe preferred Obsidian-compatible representation for `recurrence_parent` is a wikilink, for example:\n\n```yaml\nrecurrence_parent: \"[[Weekly Review]]\"\noccurrence_date: 2026-02-27\n```\n\nImplementations claiming `materialized-occurrences` MUST resolve `recurrence_parent` using §11 link semantics for this role, even if they do not claim full `extended`.\nIf the parent cannot be resolved, validation SHOULD report `invalid_recurrence_parent`.\n\nFor one resolved parent, there SHOULD be at most one materialized occurrence note per `occurrence_date`.\nDuplicate detected occurrence notes SHOULD report `duplicate_occurrence_note` and MUST NOT be chosen nondeterministically for writes.\n\n### 4.18.3 Effective state precedence\n\nFor target date `D`, recurrence-aware effective state MUST be resolved in this order:\n\n1. If a materialized occurrence note exists for `(parent, D)`, derive state from that note's own task state:\n - `completed` when its `status` is in `status.completed_values`;\n - `skipped` when its `status` is in `status.skipped_values`;\n - otherwise unresolved/default for that instance.\n2. Else if `D` is in parent `complete_instances`: state is `completed`.\n3. Else if `D` is in parent `skipped_instances`: state is `skipped`.\n4. Else: state is unresolved/default for that instance.\n\nIf a materialized occurrence note disagrees with the parent instance lists, the materialized occurrence note wins for `D`.\nValidators SHOULD report `occurrence_state_conflict`, and repair/normalization operations MAY update parent lists to match occurrence notes.\n\n### 4.18.4 Parent instance lists as compatibility state\n\nWhen materialized occurrence notes are supported, parent `complete_instances` and `skipped_instances` remain part of canonical persisted state.\nThey serve as interoperability state for unmaterialized occurrences and as a compatibility index for clients that do not read occurrence notes.\n\nConforming writers SHOULD reconcile parent lists after materialized occurrence completion, skip, uncompletion, or unskip:\n\n- completed child state: add `D` to `complete_instances`, remove `D` from `skipped_instances`;\n- skipped child state: add `D` to `skipped_instances`, remove `D` from `complete_instances`;\n- active/unresolved child state after uncompletion/unskip: remove `D` from the relevant parent list.\n\nReconciliation failure MUST NOT silently change the occurrence note state.\nImplementations SHOULD surface a recoverable error or warning.\n\n### 4.18.5 Materialization modes\n\n`occurrence_materialization` controls when materialized occurrence notes are created.\nAllowed values:\n\n- `manual`: occurrence notes are created only by explicit user or API action.\n- `on_completion`: completing a materialized occurrence note creates the next occurrence note.\n- `rolling`: the implementation maintains a bounded materialized window, such as today through the next 14 days.\n\nIf absent, `occurrence_materialization` MUST default to `manual`.\n\n`on_completion` does not by itself create the first occurrence note in a series.\nThe first materialized occurrence MUST be created by explicit materialization, rolling materialization, or a documented create-time option.\n\nConforming implementations MUST NOT create occurrence notes merely as a side effect of read-only browsing.\n\n### 4.18.6 Next-occurrence trigger\n\n`occurrence_next_trigger` controls whether skip/cancel transitions also create the next occurrence note when `occurrence_materialization=on_completion`.\nAllowed values:\n\n- `completion`: only completion creates the next occurrence note.\n- `completion_or_skip`: completion and skip/cancel create the next occurrence note.\n\nIf absent, `occurrence_next_trigger` MUST default to `completion`.\n\nThe next occurrence MUST be computed from the parent recurring task after applying the triggering state transition and §4.4 anchor semantics.\nMaterializing the next occurrence MUST be idempotent: if the next occurrence note already exists, the operation MUST return or reuse it rather than creating a duplicate.\n\n### 4.18.7 Rolling materialization bounds\n\nFor `occurrence_materialization=rolling`, implementations MUST enforce finite bounds.\nUnbounded future materialization is non-conformant.\n\nBounds SHOULD be expressed with ISO 8601 durations such as:\n\n```yaml\noccurrence_past_horizon: P0D\noccurrence_future_horizon: P14D\n```\n\nIf bounds are absent and rolling mode is enabled, implementations MUST use documented finite defaults.\n\n### 4.18.8 Recurrence edits and historical notes\n\nMaterialized occurrence notes are durable task files.\nEditing the parent recurrence rule MUST NOT silently delete, rewrite, or move existing materialized occurrence notes.\n\nIf an existing occurrence note's `occurrence_date` is no longer generated by the current parent recurrence rule, validators MAY report `materialization_target_not_generated` as a warning.\nThis condition MUST NOT be treated as an error by default because recurrence edits can make historical notes intentionally non-generated.\n","aliases":["/spec/04-recurrence/"],"toc":[{"level":2,"id":"41-purpose","text":"4.1 Purpose"},{"level":2,"id":"42-recurrence-applicability","text":"4.2 Recurrence applicability"},{"level":2,"id":"43-rule-format","text":"4.3 Rule format"},{"level":3,"id":"431-required-format","text":"4.3.1 Required format"},{"level":3,"id":"432-invalid-rule-handling","text":"4.3.2 Invalid rule handling"},{"level":2,"id":"44-recurrence-anchor","text":"4.4 Recurrence anchor"},{"level":3,"id":"441-recurrence-seed-precedence","text":"4.4.1 Recurrence seed precedence"},{"level":3,"id":"442-anchor-progression-behavior","text":"4.4.2 Anchor progression behavior"},{"level":3,"id":"443-dtstart-update-semantics","text":"4.4.3 DTSTART update semantics"},{"level":3,"id":"444-recalculation-semantics-for-recurrenceanchorcompletion","text":"4.4.4 Recalculation semantics for recurrence_anchor=completion"},{"level":3,"id":"445-dtstart-canonicalization-on-recurring-writes","text":"4.4.5 DTSTART canonicalization on recurring writes"},{"level":2,"id":"45-instance-state-fields","text":"4.5 Instance state fields"},{"level":2,"id":"46-invariants","text":"4.6 Invariants"},{"level":2,"id":"47-instance-completion-semantics","text":"4.7 Instance completion semantics"},{"level":2,"id":"48-instance-uncompletion-semantics","text":"4.8 Instance uncompletion semantics"},{"level":2,"id":"49-instance-skip-semantics","text":"4.9 Instance skip semantics"},{"level":2,"id":"410-instance-unskip-semantics","text":"4.10 Instance unskip semantics"},{"level":2,"id":"411-effective-instance-state","text":"4.11 Effective instance state"},{"level":2,"id":"412-interaction-with-base-status","text":"4.12 Interaction with base status"},{"level":2,"id":"413-completed-status-configuration","text":"4.13 Completed-status configuration"},{"level":2,"id":"414-example-complete-then-skip-same-day","text":"4.14 Example: complete then skip same day"},{"level":2,"id":"415-example-idempotent-complete","text":"4.15 Example: idempotent complete"},{"level":2,"id":"416-example-anchor-semantics","text":"4.16 Example: anchor semantics"},{"level":2,"id":"417-validation-examples","text":"4.17 Validation examples"},{"level":2,"id":"418-recurrence-materialization","text":"4.18 Recurrence materialization"},{"level":3,"id":"4181-parent-and-occurrence-ownership","text":"4.18.1 Parent and occurrence ownership"},{"level":3,"id":"4182-occurrence-identity-and-parent-reference","text":"4.18.2 Occurrence identity and parent reference"},{"level":3,"id":"4183-effective-state-precedence","text":"4.18.3 Effective state precedence"},{"level":3,"id":"4184-parent-instance-lists-as-compatibility-state","text":"4.18.4 Parent instance lists as compatibility state"},{"level":3,"id":"4185-materialization-modes","text":"4.18.5 Materialization modes"},{"level":3,"id":"4186-next-occurrence-trigger","text":"4.18.6 Next-occurrence trigger"},{"level":3,"id":"4187-rolling-materialization-bounds","text":"4.18.7 Rolling materialization bounds"},{"level":3,"id":"4188-recurrence-edits-and-historical-notes","text":"4.18.8 Recurrence edits and historical notes"}],"html":"

4.1 Purpose#

\n

This section defines recurrence semantics, including rule representation, anchor behavior, and per-instance completion/skip state.

\n

4.2 Recurrence applicability#

\n

A task is recurring when semantic role recurrence contains a valid tasknotes recurrence string.

\n

If recurrence is absent or empty, the task is non-recurring.

\n

4.3 Rule format#

\n

4.3.1 Required format#

\n

recurrence MUST be a tasknotes recurrence string.\nThis syntax is RRULE-derived but is not a full RFC 5545 content line or multi-line iCalendar fragment.\nThe RRULE parameter portion MUST use RFC 5545 RRULE property syntax.\nIt MAY include a leading inline DTSTART segment.

\n

If DTSTART is present, it MUST use one of:

\n
    \n
  • DTSTART:YYYYMMDD (date-only)
  • \n
  • DTSTART:YYYYMMDDTHHMMSSZ (UTC datetime)
  • \n
\n

Canonical combined form is:

\n
    \n
  • DTSTART:...;FREQ=...
  • \n
\n

Implementations MAY accept inbound RRULE: prefixes or multi-line iCalendar-like inputs for compatibility, but canonical writes SHOULD use the combined single-field form above.

\n

Examples:

\n
    \n
  • FREQ=DAILY
  • \n
  • FREQ=WEEKLY;BYDAY=MO,WE,FR
  • \n
  • FREQ=MONTHLY;BYMONTHDAY=1
  • \n
  • DTSTART:20260220;FREQ=WEEKLY;BYDAY=FR
  • \n
\n

4.3.2 Invalid rule handling#

\n

Invalid recurrence rules MUST produce a validation error in strict mode and SHOULD produce at least a warning in permissive mode.

\n

4.4 Recurrence anchor#

\n

recurrence_anchor controls progression semantics and MUST be one of:

\n
    \n
  • scheduled
  • \n
  • completion
  • \n
\n

If missing, implementations SHOULD default to scheduled unless collection configuration defines another default.

\n

4.4.1 Recurrence seed precedence#

\n

When recurrence generation requires a seed/start date, implementations MUST resolve it in this order:

\n
    \n
  1. DTSTART embedded in recurrence,
  2. \n
  3. semantic scheduled,
  4. \n
  5. semantic date_created.
  6. \n
\n

If no seed can be resolved, recurrence materialization MUST fail deterministically and validation MUST report an error.

\n

4.4.2 Anchor progression behavior#

\n

For recurrence_anchor=scheduled, progression is based on the scheduled chain and DTSTART MUST remain fixed after it is set.

\n

For recurrence_anchor=completion, complete-instance operations MUST advance progression by updating DTSTART to the completion target (date or datetime per §4.4.3).

\n

4.4.3 DTSTART update semantics#

\n

When recurrence_anchor=completion and instance completion succeeds for resolved target day D:

\n
    \n
  1. Instance-list state (complete_instances, skipped_instances) MUST always use day D.
  2. \n
  3. If the caller provided an explicit datetime target, DTSTART MUST be rewritten as DTSTART:YYYYMMDDTHHMMSSZ using that target instant normalized to UTC.
  4. \n
  5. Otherwise, DTSTART MUST be rewritten as DTSTART:YYYYMMDD for day D.
  6. \n
  7. RRULE components other than DTSTART MUST be preserved unless an explicit recurrence-edit operation changes them.
  8. \n
  9. If DTSTART is absent, completion-anchor progression MUST insert it before RRULE parameters.
  10. \n
\n

4.4.4 Recalculation semantics for recurrence_anchor=completion#

\n

When calculating the next candidate occurrence for recurrence_anchor=completion:

\n
    \n
  1. Implementations MUST treat DTSTART progression as the consumed-history mechanism.
  2. \n
  3. complete_instances MUST NOT be used as an exclusion set for future occurrence selection in this mode.
  4. \n
  5. skipped_instances MUST still exclude matching candidate dates.
  6. \n
  7. Candidate selection MUST choose the first RRULE occurrence strictly after the current DTSTART anchor (or resolved seed if DTSTART is absent).
  8. \n
\n

This matches the completion-anchor progression model where each completion advances the chain by rewriting DTSTART.\nThis model is intentionally not fully reversible via ordinary uncomplete instance; progression history lives in DTSTART, not only in complete_instances.

\n

4.4.5 DTSTART canonicalization on recurring writes#

\n

To ensure stable recurrence materialization across implementations, writers that persist recurring tasks MUST ensure DTSTART is present after create or successful recurring-instance completion.

\n

Rules:

\n
    \n
  1. If persisted recurrence already contains DTSTART, keep it unless an explicit operation updates it per §4.4.3.
  2. \n
  3. If persisted recurrence omits DTSTART, writers MUST resolve a seed using §4.4.1 and insert DTSTART before RRULE parameters.
  4. \n
  5. For recurrence_anchor=scheduled, inserted DTSTART becomes the fixed progression baseline and MUST NOT be rewritten by later scheduled-anchor completions.
  6. \n
  7. If seed resolution fails, operation MUST fail deterministically and emit missing_recurrence_seed.
  8. \n
\n

4.5 Instance state fields#

\n

Per-instance state is represented by:

\n
    \n
  • complete_instances: list of date values
  • \n
  • skipped_instances: list of date values
  • \n
\n

These lists represent day-level instance outcomes.

\n

4.6 Invariants#

\n

Implementations MUST enforce:

\n
    \n
  1. Items in instance lists are valid date values.
  2. \n
  3. No date appears in both lists simultaneously.
  4. \n
  5. Duplicate dates are normalized (set semantics) or rejected deterministically.
  6. \n
  7. Validators MUST NOT reject an instance date solely because it is not an RRULE-generated occurrence.
  8. \n
\n

4.7 Instance completion semantics#

\n

Operation: complete instance for target date D.

\n

Conforming behavior:

\n
    \n
  1. Add D to complete_instances.
  2. \n
  3. Remove D from skipped_instances if present.
  4. \n
  5. Leave base task status unchanged unless explicit policy states otherwise.
  6. \n
  7. Update date_modified when state changes.
  8. \n
\n

Operation MUST be idempotent.

\n

4.8 Instance uncompletion semantics#

\n

Operation: uncomplete instance for target date D.

\n

Conforming behavior:

\n
    \n
  1. Remove D from complete_instances if present.
  2. \n
  3. Do not add D to skipped_instances implicitly.
  4. \n
  5. For recurrence_anchor=completion, uncomplete MUST NOT rewrite or roll back DTSTART; restoring prior progression requires an explicit recurrence edit or implementation-specific rewind operation.
  6. \n
  7. Update date_modified when state changes.
  8. \n
\n

Operation MUST be idempotent.

\n

4.9 Instance skip semantics#

\n

Operation: skip instance for target date D.

\n

Conforming behavior:

\n
    \n
  1. Add D to skipped_instances.
  2. \n
  3. Remove D from complete_instances if present.
  4. \n
  5. Update date_modified when state changes.
  6. \n
\n

Operation MUST be idempotent.

\n

4.10 Instance unskip semantics#

\n

Operation: unskip instance for target date D.

\n

Conforming behavior:

\n
    \n
  1. Remove D from skipped_instances if present.
  2. \n
  3. Do not add to complete_instances implicitly.
  4. \n
  5. Update date_modified when state changes.
  6. \n
\n

Operation MUST be idempotent.

\n

4.11 Effective instance state#

\n

For target date D, effective state MUST be resolved in this order:

\n
    \n
  1. If D in complete_instances: state is completed.
  2. \n
  3. Else if D in skipped_instances: state is skipped.
  4. \n
  5. Else: state is unresolved/default for that instance.
  6. \n
\n

Because overlap is invalid, this ordering is deterministic.

\n

4.12 Interaction with base status#

\n

For recurring tasks:

\n
    \n
  • Base status is task-level metadata and MUST NOT be forcibly rewritten to a completed status on instance completion unless explicitly configured.
  • \n
  • Instance state determines completion for recurrence-aware views and operations.
  • \n
  • Dependency blocked/unblocked evaluation for v0.1 follows §10.2.5 and is not recurrence-instance-aware unless explicitly extended by implementation policy.
  • \n
\n

For non-recurring tasks, completion uses base status semantics (§5).

\n

4.13 Completed-status configuration#

\n

Implementations MUST define which status values are treated as complete for non-recurring tasks.

\n

The completed-status list MUST be configurable or schema-driven and MUST NOT rely on a hardcoded single literal.

\n

4.14 Example: complete then skip same day#

\n

Initial:

\n
recurrence: FREQ=DAILY\ncompleteInstances: [2026-02-20]\nskippedInstances: []\n

Skip target date 2026-02-20:

\n
recurrence: FREQ=DAILY\ncompleteInstances: []\nskippedInstances: [2026-02-20]\n

4.15 Example: idempotent complete#

\n

Initial:

\n
completeInstances: [2026-02-20]\nskippedInstances: []\n

Complete 2026-02-20 again:

\n
    \n
  • persisted instance lists remain unchanged,
  • \n
  • operation succeeds without duplicate entries.
  • \n
\n

4.16 Example: anchor semantics#

\n

Task:

\n
recurrence: FREQ=WEEKLY;BYDAY=FR\nrecurrenceAnchor: completion\n

If implementation supports next-occurrence materialization, it MUST compute next occurrence relative to completion progression when anchor is completion, not solely by scheduled chain.\nImplementations using DTSTART progression MUST update DTSTART to the completion date for this mode.

\n

Worked example (recurrence_anchor=completion):

\n
recurrence: DTSTART:20260220;FREQ=DAILY\nrecurrence_anchor: completion\ncomplete_instances: [2026-02-20, 2026-02-21]\nskipped_instances: [2026-02-23]\n

Conforming recalculation:

\n
    \n
  • does not exclude 2026-02-22 because it is absent from skipped_instances,
  • \n
  • does exclude 2026-02-23 because it is skipped,
  • \n
  • ignores complete_instances for future exclusion in this mode (§4.4.4).
  • \n
\n

4.17 Validation examples#

\n

Invalid overlap:

\n
completeInstances: [2026-02-20]\nskippedInstances: [2026-02-20]\n

Result: validation error instance_state_overlap.

\n

Invalid date in list:

\n
completeInstances: [2026-02-30]\n

Result: validation error invalid_date_value.

\n

4.18 Recurrence materialization#

\n

This subsection is required only for implementations claiming profile materialized-occurrences (§7.3.4).

\n

Recurrence materialization creates ordinary task files for specific target dates of a recurring parent task.\nIt is additive behavior: implementations that do not claim materialized-occurrences continue to use the instance-list model in §4.5-§4.12.\nMaterialized occurrence notes MUST be task files according to the collection's task-detection rules (§9.7).

\n

4.18.1 Parent and occurrence ownership#

\n

The parent recurring task owns series-level semantics:

\n
    \n
  • recurrence
  • \n
  • recurrence_anchor
  • \n
  • recurrence generation and DTSTART progression
  • \n
  • parent instance-list compatibility state (complete_instances, skipped_instances)
  • \n
  • materialization policy fields (occurrence_materialization, occurrence_next_trigger, occurrence_template, occurrence_past_horizon, occurrence_future_horizon)
  • \n
\n

A materialized occurrence note owns per-date task semantics for its occurrence_date, including:

\n
    \n
  • status
  • \n
  • completed_date
  • \n
  • body content and checklists
  • \n
  • time_entries
  • \n
  • per-occurrence due, scheduled, reminders, contexts, projects, and unknown fields
  • \n
\n

4.18.2 Occurrence identity and parent reference#

\n

A materialized occurrence note MUST store:

\n
    \n
  • recurrence_parent: a link-or-string reference to the parent recurring task
  • \n
  • occurrence_date: the target date represented by the occurrence note
  • \n
\n

The preferred Obsidian-compatible representation for recurrence_parent is a wikilink, for example:

\n
recurrence_parent: "[[Weekly Review]]"\noccurrence_date: 2026-02-27\n

Implementations claiming materialized-occurrences MUST resolve recurrence_parent using §11 link semantics for this role, even if they do not claim full extended.\nIf the parent cannot be resolved, validation SHOULD report invalid_recurrence_parent.

\n

For one resolved parent, there SHOULD be at most one materialized occurrence note per occurrence_date.\nDuplicate detected occurrence notes SHOULD report duplicate_occurrence_note and MUST NOT be chosen nondeterministically for writes.

\n

4.18.3 Effective state precedence#

\n

For target date D, recurrence-aware effective state MUST be resolved in this order:

\n
    \n
  1. If a materialized occurrence note exists for (parent, D), derive state from that note's own task state:
      \n
    • completed when its status is in status.completed_values;
    • \n
    • skipped when its status is in status.skipped_values;
    • \n
    • otherwise unresolved/default for that instance.
    • \n
    \n
  2. \n
  3. Else if D is in parent complete_instances: state is completed.
  4. \n
  5. Else if D is in parent skipped_instances: state is skipped.
  6. \n
  7. Else: state is unresolved/default for that instance.
  8. \n
\n

If a materialized occurrence note disagrees with the parent instance lists, the materialized occurrence note wins for D.\nValidators SHOULD report occurrence_state_conflict, and repair/normalization operations MAY update parent lists to match occurrence notes.

\n

4.18.4 Parent instance lists as compatibility state#

\n

When materialized occurrence notes are supported, parent complete_instances and skipped_instances remain part of canonical persisted state.\nThey serve as interoperability state for unmaterialized occurrences and as a compatibility index for clients that do not read occurrence notes.

\n

Conforming writers SHOULD reconcile parent lists after materialized occurrence completion, skip, uncompletion, or unskip:

\n
    \n
  • completed child state: add D to complete_instances, remove D from skipped_instances;
  • \n
  • skipped child state: add D to skipped_instances, remove D from complete_instances;
  • \n
  • active/unresolved child state after uncompletion/unskip: remove D from the relevant parent list.
  • \n
\n

Reconciliation failure MUST NOT silently change the occurrence note state.\nImplementations SHOULD surface a recoverable error or warning.

\n

4.18.5 Materialization modes#

\n

occurrence_materialization controls when materialized occurrence notes are created.\nAllowed values:

\n
    \n
  • manual: occurrence notes are created only by explicit user or API action.
  • \n
  • on_completion: completing a materialized occurrence note creates the next occurrence note.
  • \n
  • rolling: the implementation maintains a bounded materialized window, such as today through the next 14 days.
  • \n
\n

If absent, occurrence_materialization MUST default to manual.

\n

on_completion does not by itself create the first occurrence note in a series.\nThe first materialized occurrence MUST be created by explicit materialization, rolling materialization, or a documented create-time option.

\n

Conforming implementations MUST NOT create occurrence notes merely as a side effect of read-only browsing.

\n

4.18.6 Next-occurrence trigger#

\n

occurrence_next_trigger controls whether skip/cancel transitions also create the next occurrence note when occurrence_materialization=on_completion.\nAllowed values:

\n
    \n
  • completion: only completion creates the next occurrence note.
  • \n
  • completion_or_skip: completion and skip/cancel create the next occurrence note.
  • \n
\n

If absent, occurrence_next_trigger MUST default to completion.

\n

The next occurrence MUST be computed from the parent recurring task after applying the triggering state transition and §4.4 anchor semantics.\nMaterializing the next occurrence MUST be idempotent: if the next occurrence note already exists, the operation MUST return or reuse it rather than creating a duplicate.

\n

4.18.7 Rolling materialization bounds#

\n

For occurrence_materialization=rolling, implementations MUST enforce finite bounds.\nUnbounded future materialization is non-conformant.

\n

Bounds SHOULD be expressed with ISO 8601 durations such as:

\n
occurrence_past_horizon: P0D\noccurrence_future_horizon: P14D\n

If bounds are absent and rolling mode is enabled, implementations MUST use documented finite defaults.

\n

4.18.8 Recurrence edits and historical notes#

\n

Materialized occurrence notes are durable task files.\nEditing the parent recurrence rule MUST NOT silently delete, rewrite, or move existing materialized occurrence notes.

\n

If an existing occurrence note's occurrence_date is no longer generated by the current parent recurrence rule, validators MAY report materialization_target_not_generated as a warning.\nThis condition MUST NOT be treated as an error by default because recurrence edits can make historical notes intentionally non-generated.

\n","text":"4.1 Purpose# This section defines recurrence semantics, including rule representation, anchor behavior, and per-instance completion/skip state. 4.2 Recurrence applicability# A task is recurring when semantic role recurrence contains a valid tasknotes recurrence string. If recurrence is absent or empty, the task is non-recurring. 4.3 Rule format# 4.3.1 Required format# recurrence MUST be a tasknotes recurrence string. This syntax is RRULE-derived but is not a full RFC 5545 content line or multi-line iCalendar fragment. The RRULE parameter portion MUST use RFC 5545 RRULE property syntax. It MAY include a leading inline DTSTART segment. If DTSTART is present, it MUST use one of: DTSTART:YYYYMMDD (date-only) DTSTART:YYYYMMDDTHHMMSSZ (UTC datetime) Canonical combined form is: DTSTART:...;FREQ=... Implementations MAY accept inbound RRULE: prefixes or multi-line iCalendar-like inputs for compatibility, but canonical writes SHOULD use the combined single-field form above. Examples: FREQ=DAILY FREQ=WEEKLY;BYDAY=MO,WE,FR FREQ=MONTHLY;BYMONTHDAY=1 DTSTART:20260220;FREQ=WEEKLY;BYDAY=FR 4.3.2 Invalid rule handling# Invalid recurrence rules MUST produce a validation error in strict mode and SHOULD produce at least a warning in permissive mode. 4.4 Recurrence anchor# recurrence_anchor controls progression semantics and MUST be one of: scheduled completion If missing, implementations SHOULD default to scheduled unless collection configuration defines another default. 4.4.1 Recurrence seed precedence# When recurrence generation requires a seed/start date, implementations MUST resolve it in this order: DTSTART embedded in recurrence, semantic scheduled, semantic date_created. If no seed can be resolved, recurrence materialization MUST fail deterministically and validation MUST report an error. 4.4.2 Anchor progression behavior# For recurrence_anchor=scheduled, progression is based on the scheduled chain and DTSTART MUST remain fixed after it is set. For recurrence_anchor=completion, complete-instance operations MUST advance progression by updating DTSTART to the completion target (date or datetime per §4.4.3). 4.4.3 DTSTART update semantics# When recurrence_anchor=completion and instance completion succeeds for resolved target day D: Instance-list state (complete_instances, skipped_instances) MUST always use day D. If the caller provided an explicit datetime target, DTSTART MUST be rewritten as DTSTART:YYYYMMDDTHHMMSSZ using that target instant normalized to UTC. Otherwise, DTSTART MUST be rewritten as DTSTART:YYYYMMDD for day D. RRULE components other than DTSTART MUST be preserved unless an explicit recurrence-edit operation changes them. If DTSTART is absent, completion-anchor progression MUST insert it before RRULE parameters. 4.4.4 Recalculation semantics for recurrence_anchor=completion# When calculating the next candidate occurrence for recurrence_anchor=completion: Implementations MUST treat DTSTART progression as the consumed-history mechanism. complete_instances MUST NOT be used as an exclusion set for future occurrence selection in this mode. skipped_instances MUST still exclude matching candidate dates. Candidate selection MUST choose the first RRULE occurrence strictly after the current DTSTART anchor (or resolved seed if DTSTART is absent). This matches the completion-anchor progression model where each completion advances the chain by rewriting DTSTART. This model is intentionally not fully reversible via ordinary uncomplete instance; progression history lives in DTSTART, not only in complete_instances. 4.4.5 DTSTART canonicalization on recurring writes# To ensure stable recurrence materialization across implementations, writers that persist recurring tasks MUST ensure DTSTART is present after create or successful recurring-instance completion. Rules: If persisted recurrence already contains DTSTART, keep it unless an explicit operation updates it per §4.4.3. If persisted recurrence omits DTSTART, writers MUST resolve a seed using §4.4.1 and insert DTSTART before RRULE parameters. For recurrence_anchor=scheduled, inserted DTSTART becomes the fixed progression baseline and MUST NOT be rewritten by later scheduled-anchor completions. If seed resolution fails, operation MUST fail deterministically and emit missing_recurrence_seed. 4.5 Instance state fields# Per-instance state is represented by: complete_instances: list of date values skipped_instances: list of date values These lists represent day-level instance outcomes. 4.6 Invariants# Implementations MUST enforce: Items in instance lists are valid date values. No date appears in both lists simultaneously. Duplicate dates are normalized (set semantics) or rejected deterministically. Validators MUST NOT reject an instance date solely because it is not an RRULE-generated occurrence. 4.7 Instance completion semantics# Operation: complete instance for target date D. Conforming behavior: Add D to complete_instances. Remove D from skipped_instances if present. Leave base task status unchanged unless explicit policy states otherwise. Update date_modified when state changes. Operation MUST be idempotent. 4.8 Instance uncompletion semantics# Operation: uncomplete instance for target date D. Conforming behavior: Remove D from complete_instances if present. Do not add D to skipped_instances implicitly. For recurrence_anchor=completion, uncomplete MUST NOT rewrite or roll back DTSTART; restoring prior progression requires an explicit recurrence edit or implementation-specific rewind operation. Update date_modified when state changes. Operation MUST be idempotent. 4.9 Instance skip semantics# Operation: skip instance for target date D. Conforming behavior: Add D to skipped_instances. Remove D from complete_instances if present. Update date_modified when state changes. Operation MUST be idempotent. 4.10 Instance unskip semantics# Operation: unskip instance for target date D. Conforming behavior: Remove D from skipped_instances if present. Do not add to complete_instances implicitly. Update date_modified when state changes. Operation MUST be idempotent. 4.11 Effective instance state# For target date D, effective state MUST be resolved in this order: If D in complete_instances: state is completed. Else if D in skipped_instances: state is skipped. Else: state is unresolved/default for that instance. Because overlap is invalid, this ordering is deterministic. 4.12 Interaction with base status# For recurring tasks: Base status is task-level metadata and MUST NOT be forcibly rewritten to a completed status on instance completion unless explicitly configured. Instance state determines completion for recurrence-aware views and operations. Dependency blocked/unblocked evaluation for v0.1 follows §10.2.5 and is not recurrence-instance-aware unless explicitly extended by implementation policy. For non-recurring tasks, completion uses base status semantics (§5). 4.13 Completed-status configuration# Implementations MUST define which status values are treated as complete for non-recurring tasks. The completed-status list MUST be configurable or schema-driven and MUST NOT rely on a hardcoded single literal. 4.14 Example: complete then skip same day# Initial: recurrence: FREQ=DAILY completeInstances: [2026-02-20] skippedInstances: [] Skip target date 2026-02-20: recurrence: FREQ=DAILY completeInstances: [] skippedInstances: [2026-02-20] 4.15 Example: idempotent complete# Initial: completeInstances: [2026-02-20] skippedInstances: [] Complete 2026-02-20 again: persisted instance lists remain unchanged, operation succeeds without duplicate entries. 4.16 Example: anchor semantics# Task: recurrence: FREQ=WEEKLY;BYDAY=FR recurrenceAnchor: completion If implementation supports next-occurrence materialization, it MUST compute next occurrence relative to completion progression when anchor is completion, not solely by scheduled chain. Implementations using DTSTART progression MUST update DTSTART to the completion date for this mode. Worked example (recurrence_anchor=completion): recurrence: DTSTART:20260220;FREQ=DAILY recurrence_anchor: completion complete_instances: [2026-02-20, 2026-02-21] skipped_instances: [2026-02-23] Conforming recalculation: does not exclude 2026-02-22 because it is absent from skipped_instances, does exclude 2026-02-23 because it is skipped, ignores complete_instances for future exclusion in this mode (§4.4.4). 4.17 Validation examples# Invalid overlap: completeInstances: [2026-02-20] skippedInstances: [2026-02-20] Result: validation error instance_state_overlap. Invalid date in list: completeInstances: [2026-02-30] Result: validation error invalid_date_value. 4.18 Recurrence materialization# This subsection is required only for implementations claiming profile materialized-occurrences (§7.3.4). Recurrence materialization creates ordinary task files for specific target dates of a recurring parent task. It is additive behavior: implementations that do not claim materialized-occurrences continue to use the instance-list model in §4.5-§4.12. Materialized occurrence notes MUST be task files according to the collection's task-detection rules (§9.7). 4.18.1 Parent and occurrence ownership# The parent recurring task owns series-level semantics: recurrence recurrence_anchor recurrence generation and DTSTART progression parent instance-list compatibility state (complete_instances, skipped_instances) materialization policy fields (occurrence_materialization, occurrence_next_trigger, occurrence_template, occurrence_past_horizon, occurrence_future_horizon) A materialized occurrence note owns per-date task semantics for its occurrence_date, including: status completed_date body content and checklists time_entries per-occurrence due, scheduled, reminders, contexts, projects, and unknown fields 4.18.2 Occurrence identity and parent reference# A materialized occurrence note MUST store: recurrence_parent: a link-or-string reference to the parent recurring task occurrence_date: the target date represented by the occurrence note The preferred Obsidian-compatible representation for recurrence_parent is a wikilink, for example: recurrence_parent: \"[[Weekly Review]]\" occurrence_date: 2026-02-27 Implementations claiming materialized-occurrences MUST resolve recurrence_parent using §11 link semantics for this role, even if they do not claim full extended. If the parent cannot be resolved, validation SHOULD report invalid_recurrence_parent. For one resolved parent, there SHOULD be at most one materialized occurrence note per occurrence_date. Duplicate detected occurrence notes SHOULD report duplicate_occurrence_note and MUST NOT be chosen nondeterministically for writes. 4.18.3 Effective state precedence# For target date D, recurrence-aware effective state MUST be resolved in this order: If a materialized occurrence note exists for (parent, D), derive state from that note's own task state: completed when its status is in status.completed_values; skipped when its status is in status.skipped_values; otherwise unresolved/default for that instance. Else if D is in parent complete_instances: state is completed. Else if D is in parent skipped_instances: state is skipped. Else: state is unresolved/default for that instance. If a materialized occurrence note disagrees with the parent instance lists, the materialized occurrence note wins for D. Validators SHOULD report occurrence_state_conflict, and repair/normalization operations MAY update parent lists to match occurrence notes. 4.18.4 Parent instance lists as compatibility state# When materialized occurrence notes are supported, parent complete_instances and skipped_instances remain part of canonical persisted state. They serve as interoperability state for unmaterialized occurrences and as a compatibility index for clients that do not read occurrence notes. Conforming writers SHOULD reconcile parent lists after materialized occurrence completion, skip, uncompletion, or unskip: completed child state: add D to complete_instances, remove D from skipped_instances; skipped child state: add D to skipped_instances, remove D from complete_instances; active/unresolved child state after uncompletion/unskip: remove D from the relevant parent list. Reconciliation failure MUST NOT silently change the occurrence note state. Implementations SHOULD surface a recoverable error or warning. 4.18.5 Materialization modes# occurrence_materialization controls when materialized occurrence notes are created. Allowed values: manual: occurrence notes are created only by explicit user or API action. on_completion: completing a materialized occurrence note creates the next occurrence note. rolling: the implementation maintains a bounded materialized window, such as today through the next 14 days. If absent, occurrence_materialization MUST default to manual. on_completion does not by itself create the first occurrence note in a series. The first materialized occurrence MUST be created by explicit materialization, rolling materialization, or a documented create-time option. Conforming implementations MUST NOT create occurrence notes merely as a side effect of read-only browsing. 4.18.6 Next-occurrence trigger# occurrence_next_trigger controls whether skip/cancel transitions also create the next occurrence note when occurrence_materialization=on_completion. Allowed values: completion: only completion creates the next occurrence note. completion_or_skip: completion and skip/cancel create the next occurrence note. If absent, occurrence_next_trigger MUST default to completion. The next occurrence MUST be computed from the parent recurring task after applying the triggering state transition and §4.4 anchor semantics. Materializing the next occurrence MUST be idempotent: if the next occurrence note already exists, the operation MUST return or reuse it rather than creating a duplicate. 4.18.7 Rolling materialization bounds# For occurrence_materialization=rolling, implementations MUST enforce finite bounds. Unbounded future materialization is non-conformant. Bounds SHOULD be expressed with ISO 8601 durations such as: occurrence_past_horizon: P0D occurrence_future_horizon: P14D If bounds are absent and rolling mode is enabled, implementations MUST use documented finite defaults. 4.18.8 Recurrence edits and historical notes# Materialized occurrence notes are durable task files. Editing the parent recurrence rule MUST NOT silently delete, rewrite, or move existing materialized occurrence notes. If an existing occurrence note's occurrence_date is no longer generated by the current parent recurrence rule, validators MAY report materialization_target_not_generated as a warning. This condition MUST NOT be treated as an error by default because recurrence edits can make historical notes intentionally non-generated."},{"route":"/developers/specification/05-operations/","title":"5. Operations","description":"This section defines normative behavior for task mutations and read-facing resolution concerns that affect persisted state.","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:05-operations.md","namespace":"specification","relativePath":"05-operations.md","raw":"# 5. Operations\n\n## 5.1 Purpose\n\nThis section defines normative behavior for task mutations and read-facing resolution concerns that affect persisted state.\n\n## 5.2 General operation rules\n\nFor all mutating operations:\n\n1. Validation MUST run before commit in strict mode.\n2. Writes MUST be atomic at file level (all-or-nothing per file).\n3. `date_modified` MUST be updated on successful state change.\n4. Unknown fields MUST be preserved unless explicit normalization is requested. This applies to every operation in this section: create, update, complete, uncomplete, skip, unskip, dependency mutations, reminder mutations, archive, and time-tracking operations.\n5. Operations identified as idempotent MUST remain safe under repetition.\n\n### 5.2.1 Target day/date resolution\n\nRecurring instance operations act on a target day/date (`complete instance`, `uncomplete instance`, `skip`, `unskip`).\nNon-recurring `complete` uses completion-day semantics for `completed_date`.\n\nResolution MUST be deterministic:\n\n1. If caller provides an explicit target date/datetime, that value is authoritative.\n2. If caller omits target for recurring instance operations, implementations MUST resolve in this order:\n - task `scheduled`, if present and target-day-resolvable,\n - else task `due`, if present and target-day-resolvable,\n - else current local day in active runtime timezone (§3.6).\n3. Target-day resolution for fallback task fields (`scheduled` / `due`) MUST use this extraction policy:\n - if stored value is canonical date (`YYYY-MM-DD`), use it as-is;\n - if stored value is datetime, use the literal date token before `T` (`YYYY-MM-DD`) without timezone shifting;\n - if stored value is non-canonical but accepted by compatibility policy, implementations MAY normalize to a date token and SHOULD emit a warning;\n - if a candidate value is unusable, continue to the next fallback source.\n4. For non-recurring complete, if caller omits explicit completion-day input, implementations MUST use current local day in active runtime timezone.\n\nWhen an explicit target is datetime:\n\n- operations that require day semantics MUST use its calendar date part in active runtime timezone,\n- for recurring `complete instance` with `recurrence_anchor=completion`, the same explicit datetime target MUST also drive `DTSTART` rewrite semantics in §4.4.3.\n\nThis explicit-target datetime rule is intentionally distinct from persisted-field fallback extraction above.\n\n### 5.2.2 Idempotency and `date_modified`\n\nFor operations marked idempotent:\n\n- first application MAY change state and `date_modified`,\n- repeated application with semantically equivalent input MUST leave persisted state unchanged.\n\nWhen a repeated idempotent operation is a no-op, `date_modified` MUST remain unchanged.\n\n## 5.3 Create\n\n### 5.3.1 Input requirements\n\nCreate MUST provide at minimum semantic roles required by §2, directly or via defaults.\n\n### 5.3.2 Required behavior\n\nCreate MUST:\n\n- apply default values,\n- generate `date_created` and `date_modified` when absent,\n- resolve semantic `title` and filename/path behavior according to §9.13,\n- apply create-time templating when enabled and supported (§5.3.5, §9.14, §7),\n- serialize canonical keys and canonical temporal formats,\n- when `recurrence` is present, canonicalize `DTSTART` per §4.4.5,\n- preserve caller-provided semantic `id` when present,\n- fail with validation errors if required constraints are unmet,\n- apply default reminders according to §10.3.9 when configured.\n\n### 5.3.3 Title and filename resolution on create\n\nCreate MUST produce a deterministic initial filename/path.\n\nRules:\n\n- Generated filenames MUST use filename-safe sanitization and MUST avoid invalid/empty basenames.\n- If `title.storage=filename`:\n - basename MUST derive from semantic title,\n - title changes after create are handled by update semantics (§5.4.4),\n - implementations MAY also persist mapped `title` as a synchronized compatibility mirror,\n - `title.filename_format` and `title.custom_filename_template` MUST be ignored.\n- If `title.storage=frontmatter`, create-time basename MUST follow `title.filename_format`:\n - `title`: sanitized semantic title,\n - `zettel`: implementation-defined zettel pattern (MUST be documented),\n - `timestamp`: implementation-defined timestamp pattern (MUST be documented),\n - `custom`: `title.custom_filename_template` expansion.\n- If generated path already exists, implementation MUST resolve collision deterministically (for example numeric suffixing).\n\n### 5.3.4 Example\n\nInput intent:\n\n```yaml\ntitle: \"Pay electricity bill\"\n```\n\nAssume defaults:\n\n- status default `open`\n- priority default `normal`\n\nPersisted frontmatter (example):\n\n```yaml\ntitle: Pay electricity bill\nstatus: open\npriority: normal\ndateCreated: 2026-02-20T14:00:00Z\ndateModified: 2026-02-20T14:00:00Z\n```\n\n### 5.3.5 Optional create-time templating\n\nThis subsection is required only for implementations claiming profile `templating` (§7.3.3).\n\nCreate-time templating pipeline MUST be deterministic:\n\n1. Compute base create payload from explicit input, defaults (§9.8), and generated/system values (`date_created`, `date_modified`, resolved title policy).\n2. Expand template variables using that base payload and active runtime date/time context.\n3. Merge template frontmatter into base frontmatter with base payload precedence (base keys MUST win on conflict).\n4. Resolve body output:\n - if expanded template body is non-empty, use it;\n - otherwise use caller-provided body/details (if any).\n\nTemplate parse rules:\n\n- If template content begins with `---`, implementations MUST treat the first `--- ... ---` block as template frontmatter and the remainder as template body.\n- Frontmatter variable expansion MUST run before YAML parsing of template frontmatter.\n\nPortable variable support:\n\nImplementations claiming `templating` MUST support all variables in the **Required** column of the table below. Implementations MAY support any variable in the **Extended** column.\n\n**Required task-data variables:**\n\n| Variable | Value | Format / separator |\n|---|---|---|\n| `{{title}}` | Semantic title | string; YAML-quoted if needed |\n| `{{status}}` | Task status value | string |\n| `{{priority}}` | Task priority value | string |\n| `{{dueDate}}` | Due date if set | `YYYY-MM-DD` or empty |\n| `{{scheduledDate}}` | Scheduled date if set | `YYYY-MM-DD` or empty |\n| `{{details}}` | Caller-provided body/description | string |\n| `{{contexts}}` | Contexts list | comma-separated, e.g. `\"work, home\"` |\n| `{{tags}}` | Tags list | comma-separated, e.g. `\"task, errands\"` |\n| `{{hashtags}}` | Tags list as hashtags | space-separated, e.g. `\"#task #errands\"` |\n| `{{timeEstimate}}` | Time estimate in minutes | integer string or empty |\n| `{{parentNote}}` | Parent note name/path | string; YAML-quoted if needed |\n\n**Required date/time variables (expansion time):**\n\n| Variable | Value | Format |\n|---|---|---|\n| `{{date}}` | Current date | `yyyy-MM-dd` |\n| `{{time}}` | Current time (24h) | `HH:mm` |\n| `{{year}}` | Full year | `yyyy` |\n| `{{month}}` | Month number | `MM` |\n| `{{day}}` | Day of month | `dd` |\n\n**Extended variables (optional):**\n\n| Variable | Value | Format |\n|---|---|---|\n| `{{dateTime}}` | Date + time | `yyyy-MM-dd-HHmm` |\n| `{{timestamp}}` | Full timestamp | `yyyy-MM-dd-HHmmss` |\n| `{{shortDate}}` | Short date | `yyMMdd` |\n| `{{shortYear}}` | Two-digit year | `yy` |\n| `{{monthName}}` | Month full name | e.g. `February` |\n| `{{monthNameShort}}` | Month short name | e.g. `Feb` |\n| `{{dayName}}` | Weekday full name | e.g. `Monday` |\n| `{{dayNameShort}}` | Weekday short name | e.g. `Mon` |\n| `{{week}}` | ISO week number | `ww` |\n| `{{quarter}}` | Quarter number | `1`–`4` |\n| `{{hour}}` | Hour (24h) | `HH` |\n| `{{minute}}` | Minute | `mm` |\n| `{{second}}` | Second | `ss` |\n| `{{time12}}` | Time with AM/PM | `hh:mm a` |\n| `{{time24}}` | Time (24h) | `HH:mm` |\n| `{{timezone}}` | UTC offset long | e.g. `+05:30` |\n| `{{utcOffset}}` | UTC offset long | e.g. `+05:30` |\n| `{{unix}}` | Unix timestamp (seconds) | integer string |\n| `{{unixMs}}` | Unix timestamp (ms) | integer string |\n| `{{zettel}}` | Zettelkasten ID | date + seconds-since-midnight base-36 |\n| `{{titleLower}}` | Title lowercase | string |\n| `{{titleUpper}}` | Title uppercase | string |\n| `{{titleSnake}}` | Title snake_case | string |\n| `{{titleKebab}}` | Title kebab-case | string |\n| `{{titleCamel}}` | Title camelCase | string |\n| `{{titlePascal}}` | Title PascalCase | string |\n| `{{priorityShort}}` | First letter of priority | uppercase char |\n| `{{statusShort}}` | First letter of status | uppercase char |\n\nUnknown variables (not in the above lists) MUST be handled per `templating.unknown_variable_policy` (§9.14):\n- `preserve`: leave the `{{...}}` placeholder as-is.\n- `empty`: replace with an empty string.\n\nDeterministic expansion context:\n\n- date/time variable expansion MUST use the active runtime timezone from §3.6.\n- locale-sensitive variables (`monthName`, `monthNameShort`, `dayName`, `dayNameShort`, `time12`) MUST use English locale outputs for portability (`January`, `Jan`, `Monday`, `Mon`, `AM`/`PM`).\n- template-generated datetime-like outputs used in frontmatter MUST normalize to second precision when written as canonical datetime roles (§3.3.2).\n\nFailure behavior:\n\n- `templating.failure_mode=error`: template read/parse failures MUST abort create.\n- `templating.failure_mode=warning_fallback`: template read/parse failures MUST continue create using non-templated behavior (base frontmatter + caller body/details) and SHOULD emit warnings (`template_missing` or `template_parse_failed`).\n\n### 5.3.6 Identity handling on create\n\nIf semantic `id` is provided on create, writers MUST preserve it.\nIf implementation supports auto-generation of semantic `id`, generation policy MUST be documented and resulting `id` MUST remain stable after create.\n\n## 5.4 Update\n\n### 5.4.1 Patch semantics\n\nUpdate MUST be patch-by-default: only targeted semantic roles are changed.\n\n### 5.4.2 Preservation rules\n\nUpdate MUST preserve:\n\n- unrelated known roles,\n- unknown fields,\n- original date/datetime granularity for untouched fields.\n\n### 5.4.3 Example\n\nBefore:\n\n```yaml\ntitle: Weekly review\nscheduled: 2026-02-20\npriority: normal\ncustomClient: ACME\n```\n\nOperation: set priority to `high`.\n\nAfter:\n\n```yaml\ntitle: Weekly review\nscheduled: 2026-02-20\npriority: high\ncustomClient: ACME\n```\n\n### 5.4.4 Title updates and filename updates\n\nIf an update changes semantic `title`, behavior MUST follow `title.storage`:\n\n- `title.storage=filename`: implementation MUST rename file basename to match updated title (with sanitization and deterministic collision handling), preserving parent folder unless caller requested a move.\n- `title.storage=frontmatter`: implementation MUST update mapped title field and MUST NOT rename file unless an explicit rename operation is requested.\n\nIf implementation keeps frontmatter title for compatibility while `title.storage=filename`, it MUST keep stored title synchronized with effective filename-derived title.\n\n## 5.5 Complete (non-recurring)\n\nFor non-recurring tasks, complete MUST:\n\n1. Set `status` to a configured completed value, unless already completed.\n If multiple completed values are configured, implementation MUST choose deterministically (default: first entry in `status.completed_values`).\n2. Set `completed_date` to completion day:\n - explicit completion-day input when provided,\n - otherwise current local day in active runtime timezone (§5.2.1).\n3. Apply overwrite policy deterministically (`overwrite` or `preserve_if_present`).\n4. Update `date_modified` on state change.\n\nImplementations MUST document completion-day input handling and `completed_date` overwrite policy.\n\nOperation MUST be idempotent.\n\n## 5.6 Uncomplete (non-recurring)\n\nFor non-recurring tasks, uncomplete MUST:\n\n1. Set `status` to configured active/default status according to policy (default: `status.default`).\n2. Clear or retain `completed_date` according to policy.\n3. Update `date_modified` on state change.\n\nPolicy MUST be documented and deterministic.\n\nOperation MUST be idempotent.\n\n## 5.7 Complete instance (recurring)\n\nFor recurring tasks, complete with resolved target date `D` (§5.2.1) MUST follow §4.7.\n\nWriters MUST NOT convert recurring completion into a base status rewrite unless explicit configuration requires it.\nWhen `recurrence_anchor=completion` and caller supplies an explicit datetime target, implementations MUST apply §4.4.3 datetime `DTSTART` rewrite behavior.\nWhen `recurrence_anchor=scheduled` and `DTSTART` is absent, implementations MUST insert `DTSTART` deterministically per §4.4.5.\nNext-occurrence recalculation in this mode MUST follow §4.4.4.\n\n## 5.8 Uncomplete instance (recurring)\n\nFor recurring tasks, uncomplete with resolved target date `D` (§5.2.1) MUST follow §4.8.\nFor `recurrence_anchor=completion`, ordinary uncomplete is intentionally non-reversible and MUST NOT roll back `DTSTART`.\n\n## 5.9 Skip and unskip instance\n\nSkip/unskip for recurring tasks with resolved target date `D` (§5.2.1) MUST follow §4.9 and §4.10.\n\n## 5.10 Dependency operations\n\nDependency operations MUST follow §10.2.\n\n### 5.10.1 Add dependency\n\nAdd dependency MUST:\n\n- validate dependency entry schema,\n- parse and resolve `uid` per §11,\n- enforce duplicate and self-reference rules,\n- preserve existing non-target dependency entries,\n- update `date_modified` on change.\n\n### 5.10.2 Remove dependency\n\nRemove dependency by `uid` MUST be idempotent.\n\n### 5.10.3 Replace dependency list\n\nReplace dependency list MUST be explicit (not default patch behavior).\n\n## 5.11 Reminder operations\n\nReminder operations MUST follow §10.3.\n\n### 5.11.1 Add reminder\n\nAdd reminder MUST:\n\n- validate reminder schema,\n- enforce unique `id` within task,\n- update `date_modified` on change.\n\n### 5.11.2 Update reminder\n\nUpdate reminder MUST target a reminder by `id` and be patch-by-default.\n\n### 5.11.3 Remove reminder\n\nRemove reminder by `id` MUST be idempotent.\n\n## 5.12 Archive\n\nImplementations MAY support archive semantics through:\n\n- archive tag,\n- archive status,\n- dedicated boolean/archive field.\n\nArchive behavior MUST be documented.\n\nArchive MUST NOT implicitly delete the task.\n\n## 5.13 Delete\n\nDelete MUST remove the task file.\n\nDelete MUST NOT implicitly delete files referenced by `attachments`. An\nimplementation MAY offer a separate, explicit cleanup action subject to\n§5.21.4.\n\nOptional safety behavior:\n\n- Implementations MAY perform backlink/dependency checks.\n- If checks are enabled, implementation MUST provide a bypass option for explicit force delete.\n\n## 5.14 Rename\n\nRename operation changes file path/filename while preserving semantic record identity.\n\n### 5.14.1 Rename interaction with title storage mode\n\n- If `title.storage=filename`, basename changes from rename MUST update effective semantic title.\n- If `title.storage=frontmatter`, rename MUST NOT implicitly rewrite mapped `title` unless explicitly requested.\n- Implementations that persist frontmatter title in `title.storage=filename` mode MUST either update that field on rename or remove it to prevent divergence.\n- If semantic `id` is present, rename/move MUST preserve its value unchanged.\n\nIf implementation supports link/reference updating, it MUST:\n\n- update resolvable references deterministically,\n- report unresolved or ambiguous updates,\n- update dependency `uid` and `projects` references consistently with normal links.\n\nIf implementation does not support reference updates, this limitation MUST be disclosed in conformance claim.\n\n## 5.15 Batch operations\n\nBatch operations MAY be supported.\n\nIf supported, implementation MUST report per-item outcomes and summary counts:\n\n- total\n- succeeded\n- failed\n\nPartial success behavior MUST be documented.\n\n## 5.16 Concurrency\n\nImplementations SHOULD provide write-conflict detection (for example based on modified timestamp or file hash).\n\nWhen conflict is detected, operation MUST fail safely unless explicit overwrite is requested.\n\n## 5.17 Dry run\n\nIf dry run mode is supported, operation MUST:\n\n- execute validation and transformation logic,\n- report intended changes,\n- perform no file write.\n\n## 5.18 Error model\n\nImplementation-native operation failures MUST provide structured error information with:\n\n- operation name,\n- error code,\n- message,\n- optional field/path context.\n\nFor conformance adapter envelopes (§5.23), failures MAY be represented as a compact `error` string for transport compatibility, but implementations SHOULD also expose the structured fields (for example via `error_details`).\n\n## 5.19 Time tracking management\n\nThis subsection applies to implementations that support `time_entries`.\n\n### 5.19.1 Start time tracking\n\nStart on task `T` MUST:\n\n- fail when `T` already has an active time entry,\n- append a new entry with canonical `startTime` and no `endTime`,\n- MAY set a default `description`,\n- update `date_modified`,\n- persist canonical `time_entries` shape (including removal of legacy/stale `duration` fields when normalizing).\n\nRecommended error code when already active: `time_tracking_already_active`.\n\n### 5.19.2 Stop time tracking\n\nStop on task `T` MUST:\n\n- fail when `T` has no active time entry,\n- set `endTime` on the active entry to canonical current datetime,\n- update `date_modified`,\n- preserve non-target entries and unknown frontmatter fields.\n\nRecommended error code when no active session exists: `no_active_time_entry`.\n\n### 5.19.3 Edit or replace time entries\n\nWhen replacing/editing `time_entries` explicitly, implementations MUST:\n\n- validate each entry per §2.6.1 and §3.11,\n- persist canonical datetime formats,\n- treat `duration` as derived compatibility input and SHOULD remove it from canonical writes,\n- update `date_modified` when persisted state changes.\n\n### 5.19.4 Remove a time entry\n\nRemove MUST target one deterministic entry (for example by index or stable selector) and update `date_modified` on change.\nSelector semantics MUST be documented.\n\n### 5.19.5 Completion-triggered auto-stop\n\nIf `time_tracking.auto_stop_on_complete=true` (§9.16), completion transitions MUST trigger stop behavior for the same task only.\n\nRules:\n\n- non-recurring tasks: trigger when status transitions from non-completed to completed status.\n- recurring tasks: trigger when `complete_instances` grows.\n- materialized occurrence notes: trigger on the occurrence note's own status transition to completed; parent reconciliation SHOULD NOT trigger a second stop on the parent unless the parent itself has an active time entry and the implementation documents that policy.\n- implementations MUST NOT stop active sessions on unrelated tasks.\n- if `time_tracking.auto_stop_notification=true`, implementations MAY emit a user-visible notice.\n\n### 5.19.6 Reporting tracked time\n\nFor reporting surfaces (for example task summaries or stats), implementations MUST document whether totals use `closed_minutes` or `live_minutes` semantics from §3.11.5.\n\n## 5.20 Recurrence materialization operations\n\nThis subsection is required only for implementations claiming profile `materialized-occurrences` (§7.3.4).\n\n### 5.20.1 Materialize occurrence\n\nOperation: `materialize occurrence` for parent recurring task `P` and target date `D`.\n\nConforming behavior:\n\n1. Resolve `P` and confirm it is recurring.\n2. If an occurrence note for `(P, D)` already exists, return that note without creating a duplicate.\n3. Create a task note using `occurrence_template` when configured, otherwise using normal create behavior.\n4. Persist `recurrence_parent` as a link to `P` and `occurrence_date` as `D`.\n5. Set `scheduled` to `D` unless caller input or template output explicitly supplies another per-occurrence scheduled value.\n6. Set initial `status` using normal create defaults unless caller input or template output explicitly supplies a status.\n7. Preserve template/body output as occurrence-owned content after creation.\n8. Update `date_created` and `date_modified` according to create semantics.\n\nThe operation MUST be idempotent for `(P, D)`.\n\nIf `D` is not generated by the current recurrence rule, implementations MAY allow materialization as an explicit user action but SHOULD report `materialization_target_not_generated`.\n\n### 5.20.2 Complete materialized occurrence\n\nCompleting a materialized occurrence note MUST:\n\n1. Complete the occurrence note using normal non-recurring completion semantics (§5.5).\n2. Reconcile the parent by adding `D` to `complete_instances` and removing `D` from `skipped_instances`.\n3. If the parent has `recurrence_anchor=completion`, advance parent progression according to §4.4.3 and §4.4.4.\n4. If `occurrence_materialization=on_completion`, compute the next occurrence from the parent after the completion transition and materialize that next occurrence note idempotently.\n\nThe occurrence note's successful completion MUST NOT be rolled back solely because next-occurrence materialization fails.\nWhen the next note cannot be created, implementations SHOULD report `next_occurrence_materialization_failed`.\n\n### 5.20.3 Skip materialized occurrence\n\nSkipping a materialized occurrence note MUST preserve the note.\nSkip is a state transition, not deletion.\n\nConforming behavior:\n\n1. Set the occurrence note to the configured skipped status (`status.default_skipped`, or the first `status.skipped_values` entry when `default_skipped` is absent).\n2. Clear or retain `completed_date` according to the same documented policy used for uncompletion unless the implementation documents a skip-specific policy.\n3. Reconcile the parent by adding `D` to `skipped_instances` and removing `D` from `complete_instances`.\n4. If `occurrence_materialization=on_completion` and `occurrence_next_trigger=completion_or_skip`, compute and materialize the next occurrence note idempotently.\n\nIf no skipped status is configured, skip of a materialized occurrence MUST fail deterministically in strict mode and SHOULD report `missing_skipped_status`.\n\n### 5.20.4 Uncomplete and unskip materialized occurrence\n\nUncomplete of a materialized occurrence note MUST:\n\n1. Reopen the occurrence note using normal uncomplete semantics (§5.6).\n2. Remove `D` from parent `complete_instances`.\n3. For `recurrence_anchor=completion`, MUST NOT roll back parent `DTSTART`, matching §4.8.\n4. MUST NOT delete any later materialized occurrence note.\n\nUnskip of a materialized occurrence note MUST:\n\n1. Reopen the occurrence note to configured active/default status.\n2. Remove `D` from parent `skipped_instances`.\n3. MUST NOT add `D` to parent `complete_instances` implicitly.\n4. MUST NOT delete any later materialized occurrence note.\n\n### 5.20.5 Delete and unmaterialize occurrence\n\nDeleting a materialized occurrence note removes the task file and MUST NOT be interpreted as skip.\n\nImplementations MAY provide an explicit `unmaterialize occurrence` operation.\nIf supported, it MUST document whether parent state is preserved, cleared, or reconciled.\nIn all cases, deleting or unmaterializing an occurrence MUST NOT silently delete the parent recurring task.\n\nIf parent instance lists still refer to a deleted occurrence note's date, validators MAY report an orphan/cache warning such as `orphan_occurrence_note`.\n\n## 5.21 Attachment operations\n\nThese rules apply to implementations that support the `attachments`\ncapability.\n\n### 5.21.1 Attach a file\n\nAttach MUST:\n\n1. durably write the binary to a collection path before publishing its task\n reference;\n2. add one canonical reference to the mapped `attachments` list;\n3. preserve the existing list order and append new references by default;\n4. avoid duplicate normalized targets; and\n5. update `date_modified` only when membership changes.\n\nBinary write and task-frontmatter update are not assumed to be one atomic\nstorage transaction. Implementations MUST make interrupted operations\nrecoverable or idempotently retryable. If the binary write succeeds but the\ntask update does not, the implementation MUST retain enough durable intent to\nretry or identify the unreferenced file for explicit cleanup.\n\n### 5.21.2 Detach a file\n\nDetach removes the matching reference from `attachments` and is idempotent.\nDetach MUST NOT delete the underlying file. It MUST preserve the relative order\nof all other references.\n\n### 5.21.3 Insert an attached file inline\n\nAn implementation MAY offer an inline-insert operation. It MUST first satisfy\nattach semantics, then insert a Markdown link or embed into the task body.\nRemoving that body markup MUST NOT detach the file; detaching MUST NOT silently\nrewrite body content unless the user explicitly requests both changes.\n\n### 5.21.4 Delete an attachment file\n\nPhysical deletion MUST be a distinct, explicit action. Before deleting, an\nimplementation MUST check authoritative, current task `attachments` lists and\nSHOULD check body links/embeds and other collection backlinks. A stale or\noffline replica is not sufficient evidence that a file is unreferenced. If the\nbinary authority and record authority can change independently, the check and\ndelete MUST use an authority-provided transaction or equivalent precondition\nthat closes the race. An implementation MUST NOT offer physical deletion when\nit cannot establish that guarantee; detach remains available and leaves a safe\norphan. If another reference exists, deletion MUST be rejected unless the\ncaller explicitly chooses a force action whose affected references are\ndisclosed.\n\nAfter a successful non-forced deletion, implementations MUST remove the\ncurrent task's matching attachment reference. Failed deletion MUST leave\nfrontmatter unchanged. An accepted local outbox entry is not a successful\nphysical deletion until the binary authority acknowledges it.\n\n### 5.21.5 Materialized occurrences\n\nWhen an occurrence note is materialized, it SHOULD inherit the parent task's\nattachment references in the same order. This copies references, not file\nbytes. Subsequent edits to either task's membership list are independent, and\nphysical deletion remains governed by §5.21.4.\n\n## 5.22 Operation examples\n\n### 5.22.1 Non-recurring complete\n\nBefore:\n\n```yaml\ntitle: Buy groceries\nstatus: open\ncompletedDate:\ndateModified: 2026-02-20T09:00:00Z\n```\n\nAfter complete on `2026-02-20`:\n\n```yaml\ntitle: Buy groceries\nstatus: done\ncompletedDate: 2026-02-20\ndateModified: 2026-02-20T09:05:00Z\n```\n\n### 5.22.2 Recurring complete instance\n\nBefore:\n\n```yaml\ntitle: Weekly review\nstatus: open\nscheduled: 2026-02-20\nrecurrence: FREQ=WEEKLY;BYDAY=FR\ncompleteInstances: []\nskippedInstances: []\ndateModified: 2026-02-20T08:00:00Z\n```\n\nAfter complete instance on `2026-02-20`:\n\n```yaml\ntitle: Weekly review\nstatus: open\nscheduled: 2026-02-20\nrecurrence: DTSTART:20260220;FREQ=WEEKLY;BYDAY=FR\ncompleteInstances: [2026-02-20]\nskippedInstances: []\ndateModified: 2026-02-20T08:10:00Z\n```\n\n### 5.22.3 Recurring skip instance overriding completion\n\nBefore:\n\n```yaml\ncompleteInstances: [2026-02-20]\nskippedInstances: []\n```\n\nAfter skip `2026-02-20`:\n\n```yaml\ncompleteInstances: []\nskippedInstances: [2026-02-20]\n```\n\n### 5.22.4 Preserve unknown fields on update\n\nBefore:\n\n```yaml\ntitle: Plan Q2\nstatus: open\nvendorTicket: ZX-42\n```\n\nUpdate status to `in-progress`.\n\nAfter:\n\n```yaml\ntitle: Plan Q2\nstatus: in-progress\nvendorTicket: ZX-42\n```\n\n### 5.22.5 Add dependency\n\nBefore:\n\n```yaml\nblockedBy: []\n```\n\nAdd dependency:\n\n```yaml\nuid: \"[[prepare-metrics]]\"\nreltype: FINISHTOSTART\n```\n\nAfter:\n\n```yaml\nblockedBy:\n - uid: \"[[prepare-metrics]]\"\n reltype: FINISHTOSTART\n```\n\n### 5.22.6 Add reminder\n\nBefore:\n\n```yaml\nreminders: []\n```\n\nAdd reminder:\n\n```yaml\nid: due_minus_1h\ntype: relative\nrelatedTo: due\noffset: -PT1H\n```\n\nAfter:\n\n```yaml\nreminders:\n - id: due_minus_1h\n type: relative\n relatedTo: due\n offset: -PT1H\n```\n\n## 5.23 Conformance operation interface\n\nThe conformance suite exercises operations via the `execute(operation, input) → envelope` interface defined in the adapter contract. This section specifies the input/output contracts for each conformance-testable operation name.\n\nUnless otherwise noted, all operations return `{ ok: true, result: {...} }` on success and `{ ok: false, error: \"...\" }` on failure. Adapters MAY additionally return `error_details` with structured fields from §5.18.\n\n### General operations\n\n#### `op.mutate_with_validation`\n\nTests §5.2 rule 1: validation runs before commit.\n\nInput:\n```json\n{ \"strict\": true, \"frontmatter\": { ... } }\n```\n\nBehavior: validate `frontmatter` as a task record. In strict mode (`strict=true`), any validation error MUST produce `ok=false`.\n\nOutput on validation error:\n```json\n{ \"ok\": false, \"error\": \"validation|invalid_type|...\" }\n```\n\n---\n\n#### `op.atomic_write`\n\nTests §5.2 rule 2: writes are all-or-nothing.\n\nInput:\n```json\n{\n \"original\": { ... },\n \"patch\": { ... },\n \"simulateFailureAfterWrite\": true\n}\n```\n\nBehavior: apply `patch` to `original`, then simulate a post-write failure. The adapter MUST report whether the write was committed and what state the record is in after recovery.\n\nOutput:\n```json\n{\n \"ok\": true,\n \"result\": {\n \"committed\": false,\n \"persisted\": { ... }\n }\n}\n```\n\n`committed=false` means the write was rolled back. `persisted` reflects the actual frontmatter after recovery — it MUST match `original` (not the patched version) when `simulateFailureAfterWrite=true`.\n\n---\n\n#### `op.idempotency_check`\n\nTests §5.2 rule 5: operations are safe under repetition.\n\nInput:\n```json\n{\n \"operation\": \"complete_nonrecurring\",\n \"first\": { \"status\": \"open\", \"completedDate\": null },\n \"second\": { \"status\": \"done\", \"completedDate\": \"2026-02-20\" }\n}\n```\n\nBehavior: applying the named operation to `first` state and then again to `second` state MUST produce identical persisted results (including unchanged `dateModified` on the second no-op application). The adapter checks whether this holds.\n\nOutput:\n```json\n{ \"ok\": true, \"result\": { \"idempotent\": true } }\n```\n\n---\n\n#### `op.update_patch`\n\nTests §5.4 patch semantics and unknown-field preservation.\n\nInput:\n```json\n{\n \"original\": { \"title\": \"...\", \"vendorTicket\": \"ZX-42\", ... },\n \"patch\": { \"priority\": \"high\" },\n \"changed\": true\n}\n```\n\nBehavior: apply `patch` to `original`. Return the merged frontmatter.\n\nOutput:\n```json\n{\n \"ok\": true,\n \"result\": {\n \"changed\": true,\n \"frontmatter\": { \"title\": \"...\", \"priority\": \"high\", \"vendorTicket\": \"ZX-42\", ... }\n }\n}\n```\n\n- `changed` indicates whether any field actually changed value.\n- `frontmatter` MUST include all unknown fields from `original` unchanged.\n\n---\n\n#### `op.complete_nonrecurring`\n\nTests §5.5 non-recurring completion.\n\nInput:\n```json\n{\n \"frontmatter\": { \"title\": \"...\", \"status\": \"open\" },\n \"completedValues\": [\"done\", \"cancelled\"],\n \"explicitDate\": \"2026-02-20\"\n}\n```\n\nBehavior: apply a complete operation to `frontmatter` using `completedValues` (ordered list) and `explicitDate` as the completion day (omit to use current local day).\n\nOutput:\n```json\n{ \"ok\": true, \"result\": { \"status\": \"done\", \"completedDate\": \"2026-02-20\" } }\n```\n\n- `status` MUST be the first entry in `completedValues`.\n- `completedDate` MUST be `explicitDate` if provided; otherwise a valid `YYYY-MM-DD` date.\n- If `frontmatter.status` is already a completed value, the operation MUST still succeed (idempotent).\n\n---\n\n#### `op.uncomplete_nonrecurring`\n\nTests §5.6 non-recurring uncompletion.\n\nInput:\n```json\n{\n \"frontmatter\": { \"title\": \"...\", \"status\": \"done\", \"completedDate\": \"2026-02-20\" },\n \"defaultStatus\": \"open\",\n \"clearCompletedDate\": true\n}\n```\n\nOutput:\n```json\n{ \"ok\": true, \"result\": { \"status\": \"open\", \"completedDate\": null } }\n```\n\n- `status` MUST be `defaultStatus`.\n- If `clearCompletedDate=true`, `completedDate` MUST be `null` in the result.\n- If `clearCompletedDate=false`, `completedDate` MUST be preserved.\n\n---\n\n#### `op.error_shape`\n\nTests §5.18 error model.\n\nInput:\n```json\n{ \"operation\": \"update\", \"code\": \"invalid_type\", \"message\": \"bad value\", \"field\": \"status\" }\n```\n\nBehavior: construct and return a structured error object.\n\nOutput:\n```json\n{\n \"ok\": true,\n \"result\": {\n \"operation\": \"update\",\n \"code\": \"invalid_type\",\n \"message\": \"...\"\n }\n}\n```\n\nThe `message` field MUST be a non-empty string. The `operation` and `code` fields MUST match the input.\n\n---\n\n#### `op.detect_conflict`\n\nTests §5.16 write-conflict detection.\n\nInput:\n```json\n{ \"expectedVersion\": \"a\", \"actualVersion\": \"b\", \"overwrite\": false }\n```\n\nBehavior: when `expectedVersion != actualVersion` and `overwrite=false`, the operation MUST fail.\n\nOutput on conflict:\n```json\n{ \"ok\": false, \"error\": \"conflict|write_conflict|...\" }\n```\n\n---\n\n#### `op.dry_run`\n\nTests §5.17 dry-run mode.\n\nInput:\n```json\n{ \"operation\": \"update\", \"patch\": { \"status\": \"done\" } }\n```\n\nOutput:\n```json\n{\n \"ok\": true,\n \"result\": {\n \"wrote\": false,\n \"plannedChanges\": [\"status\", ...]\n }\n}\n```\n\n`wrote` MUST be `false`. `plannedChanges` MUST list the field names that would have changed.\n\n---\n\n### Recurrence operations\n\nFor `recurrence.complete`, `recurrence.uncomplete_instance`, `recurrence.skip_instance`, `recurrence.unskip_instance`, and `recurrence.effective_state`, the input and output contracts are defined by the respective sections of §4 and §5.7–5.9.\n\nCommon input fields for recurrence operations:\n- `targetDate` or `completionDate`: `YYYY-MM-DD` target day\n- `completeInstances`: current list of completed dates\n- `skippedInstances`: current list of skipped dates\n\n`recurrence.effective_state` output:\n```json\n{ \"ok\": true, \"result\": { \"value\": \"completed|skipped|open\" } }\n```\n\n---\n\n### Materialized occurrence operations\n\nFor `occurrence.materialize`, `occurrence.complete`, `occurrence.skip`, `occurrence.uncomplete`, `occurrence.unskip`, and `occurrence.unmaterialize`, input and output contracts are defined by §4.18 and §5.20.\n\nCommon input fields for materialized occurrence operations:\n- `parent`: frontmatter/path/link object for the recurring parent task\n- `occurrence`: frontmatter/path/link object for an existing occurrence note when applicable\n- `targetDate`: `YYYY-MM-DD` target day\n- `config`: effective occurrence/status configuration needed by the operation\n\n`occurrence.materialize` output:\n```json\n{ \"ok\": true, \"result\": { \"created\": true, \"occurrence\": { \"...\": \"...\" } } }\n```\n\n`created` MUST be `false` when the operation returns an already-existing occurrence note for the same parent/date.\n\n---\n\n### Time-tracking operations\n\nFor `time.start`, `time.stop`, `time.replace_entries`, `time.remove_entry`, `time.auto_stop_on_complete`, and `time.report_totals`, the contracts are defined by §5.19.\n\nCommon input patterns:\n- `entries`: current `time_entries` array\n- `now`: ISO 8601 datetime representing current instant\n- `dateModified`: current `date_modified` value\n\n`time.report_totals` output:\n```json\n{ \"ok\": true, \"result\": { \"closed_minutes\": N, \"live_minutes\": M } }\n```\n\n`live_minutes` is only present when an active (no `endTime`) entry exists.\n","aliases":["/spec/05-operations/"],"toc":[{"level":2,"id":"51-purpose","text":"5.1 Purpose"},{"level":2,"id":"52-general-operation-rules","text":"5.2 General operation rules"},{"level":3,"id":"521-target-daydate-resolution","text":"5.2.1 Target day/date resolution"},{"level":3,"id":"522-idempotency-and-datemodified","text":"5.2.2 Idempotency and date_modified"},{"level":2,"id":"53-create","text":"5.3 Create"},{"level":3,"id":"531-input-requirements","text":"5.3.1 Input requirements"},{"level":3,"id":"532-required-behavior","text":"5.3.2 Required behavior"},{"level":3,"id":"533-title-and-filename-resolution-on-create","text":"5.3.3 Title and filename resolution on create"},{"level":3,"id":"534-example","text":"5.3.4 Example"},{"level":3,"id":"535-optional-create-time-templating","text":"5.3.5 Optional create-time templating"},{"level":3,"id":"536-identity-handling-on-create","text":"5.3.6 Identity handling on create"},{"level":2,"id":"54-update","text":"5.4 Update"},{"level":3,"id":"541-patch-semantics","text":"5.4.1 Patch semantics"},{"level":3,"id":"542-preservation-rules","text":"5.4.2 Preservation rules"},{"level":3,"id":"543-example","text":"5.4.3 Example"},{"level":3,"id":"544-title-updates-and-filename-updates","text":"5.4.4 Title updates and filename updates"},{"level":2,"id":"55-complete-non-recurring","text":"5.5 Complete (non-recurring)"},{"level":2,"id":"56-uncomplete-non-recurring","text":"5.6 Uncomplete (non-recurring)"},{"level":2,"id":"57-complete-instance-recurring","text":"5.7 Complete instance (recurring)"},{"level":2,"id":"58-uncomplete-instance-recurring","text":"5.8 Uncomplete instance (recurring)"},{"level":2,"id":"59-skip-and-unskip-instance","text":"5.9 Skip and unskip instance"},{"level":2,"id":"510-dependency-operations","text":"5.10 Dependency operations"},{"level":3,"id":"5101-add-dependency","text":"5.10.1 Add dependency"},{"level":3,"id":"5102-remove-dependency","text":"5.10.2 Remove dependency"},{"level":3,"id":"5103-replace-dependency-list","text":"5.10.3 Replace dependency list"},{"level":2,"id":"511-reminder-operations","text":"5.11 Reminder operations"},{"level":3,"id":"5111-add-reminder","text":"5.11.1 Add reminder"},{"level":3,"id":"5112-update-reminder","text":"5.11.2 Update reminder"},{"level":3,"id":"5113-remove-reminder","text":"5.11.3 Remove reminder"},{"level":2,"id":"512-archive","text":"5.12 Archive"},{"level":2,"id":"513-delete","text":"5.13 Delete"},{"level":2,"id":"514-rename","text":"5.14 Rename"},{"level":3,"id":"5141-rename-interaction-with-title-storage-mode","text":"5.14.1 Rename interaction with title storage mode"},{"level":2,"id":"515-batch-operations","text":"5.15 Batch operations"},{"level":2,"id":"516-concurrency","text":"5.16 Concurrency"},{"level":2,"id":"517-dry-run","text":"5.17 Dry run"},{"level":2,"id":"518-error-model","text":"5.18 Error model"},{"level":2,"id":"519-time-tracking-management","text":"5.19 Time tracking management"},{"level":3,"id":"5191-start-time-tracking","text":"5.19.1 Start time tracking"},{"level":3,"id":"5192-stop-time-tracking","text":"5.19.2 Stop time tracking"},{"level":3,"id":"5193-edit-or-replace-time-entries","text":"5.19.3 Edit or replace time entries"},{"level":3,"id":"5194-remove-a-time-entry","text":"5.19.4 Remove a time entry"},{"level":3,"id":"5195-completion-triggered-auto-stop","text":"5.19.5 Completion-triggered auto-stop"},{"level":3,"id":"5196-reporting-tracked-time","text":"5.19.6 Reporting tracked time"},{"level":2,"id":"520-recurrence-materialization-operations","text":"5.20 Recurrence materialization operations"},{"level":3,"id":"5201-materialize-occurrence","text":"5.20.1 Materialize occurrence"},{"level":3,"id":"5202-complete-materialized-occurrence","text":"5.20.2 Complete materialized occurrence"},{"level":3,"id":"5203-skip-materialized-occurrence","text":"5.20.3 Skip materialized occurrence"},{"level":3,"id":"5204-uncomplete-and-unskip-materialized-occurrence","text":"5.20.4 Uncomplete and unskip materialized occurrence"},{"level":3,"id":"5205-delete-and-unmaterialize-occurrence","text":"5.20.5 Delete and unmaterialize occurrence"},{"level":2,"id":"521-attachment-operations","text":"5.21 Attachment operations"},{"level":3,"id":"5211-attach-a-file","text":"5.21.1 Attach a file"},{"level":3,"id":"5212-detach-a-file","text":"5.21.2 Detach a file"},{"level":3,"id":"5213-insert-an-attached-file-inline","text":"5.21.3 Insert an attached file inline"},{"level":3,"id":"5214-delete-an-attachment-file","text":"5.21.4 Delete an attachment file"},{"level":3,"id":"5215-materialized-occurrences","text":"5.21.5 Materialized occurrences"},{"level":2,"id":"522-operation-examples","text":"5.22 Operation examples"},{"level":3,"id":"5221-non-recurring-complete","text":"5.22.1 Non-recurring complete"},{"level":3,"id":"5222-recurring-complete-instance","text":"5.22.2 Recurring complete instance"},{"level":3,"id":"5223-recurring-skip-instance-overriding-completion","text":"5.22.3 Recurring skip instance overriding completion"},{"level":3,"id":"5224-preserve-unknown-fields-on-update","text":"5.22.4 Preserve unknown fields on update"},{"level":3,"id":"5225-add-dependency","text":"5.22.5 Add dependency"},{"level":3,"id":"5226-add-reminder","text":"5.22.6 Add reminder"},{"level":2,"id":"523-conformance-operation-interface","text":"5.23 Conformance operation interface"},{"level":3,"id":"general-operations","text":"General operations"},{"level":3,"id":"recurrence-operations","text":"Recurrence operations"},{"level":3,"id":"materialized-occurrence-operations","text":"Materialized occurrence operations"},{"level":3,"id":"time-tracking-operations","text":"Time-tracking operations"}],"html":"

5.1 Purpose#

\n

This section defines normative behavior for task mutations and read-facing resolution concerns that affect persisted state.

\n

5.2 General operation rules#

\n

For all mutating operations:

\n
    \n
  1. Validation MUST run before commit in strict mode.
  2. \n
  3. Writes MUST be atomic at file level (all-or-nothing per file).
  4. \n
  5. date_modified MUST be updated on successful state change.
  6. \n
  7. Unknown fields MUST be preserved unless explicit normalization is requested. This applies to every operation in this section: create, update, complete, uncomplete, skip, unskip, dependency mutations, reminder mutations, archive, and time-tracking operations.
  8. \n
  9. Operations identified as idempotent MUST remain safe under repetition.
  10. \n
\n

5.2.1 Target day/date resolution#

\n

Recurring instance operations act on a target day/date (complete instance, uncomplete instance, skip, unskip).\nNon-recurring complete uses completion-day semantics for completed_date.

\n

Resolution MUST be deterministic:

\n
    \n
  1. If caller provides an explicit target date/datetime, that value is authoritative.
  2. \n
  3. If caller omits target for recurring instance operations, implementations MUST resolve in this order:
      \n
    • task scheduled, if present and target-day-resolvable,
    • \n
    • else task due, if present and target-day-resolvable,
    • \n
    • else current local day in active runtime timezone (§3.6).
    • \n
    \n
  4. \n
  5. Target-day resolution for fallback task fields (scheduled / due) MUST use this extraction policy:
      \n
    • if stored value is canonical date (YYYY-MM-DD), use it as-is;
    • \n
    • if stored value is datetime, use the literal date token before T (YYYY-MM-DD) without timezone shifting;
    • \n
    • if stored value is non-canonical but accepted by compatibility policy, implementations MAY normalize to a date token and SHOULD emit a warning;
    • \n
    • if a candidate value is unusable, continue to the next fallback source.
    • \n
    \n
  6. \n
  7. For non-recurring complete, if caller omits explicit completion-day input, implementations MUST use current local day in active runtime timezone.
  8. \n
\n

When an explicit target is datetime:

\n
    \n
  • operations that require day semantics MUST use its calendar date part in active runtime timezone,
  • \n
  • for recurring complete instance with recurrence_anchor=completion, the same explicit datetime target MUST also drive DTSTART rewrite semantics in §4.4.3.
  • \n
\n

This explicit-target datetime rule is intentionally distinct from persisted-field fallback extraction above.

\n

5.2.2 Idempotency and date_modified#

\n

For operations marked idempotent:

\n
    \n
  • first application MAY change state and date_modified,
  • \n
  • repeated application with semantically equivalent input MUST leave persisted state unchanged.
  • \n
\n

When a repeated idempotent operation is a no-op, date_modified MUST remain unchanged.

\n

5.3 Create#

\n

5.3.1 Input requirements#

\n

Create MUST provide at minimum semantic roles required by §2, directly or via defaults.

\n

5.3.2 Required behavior#

\n

Create MUST:

\n
    \n
  • apply default values,
  • \n
  • generate date_created and date_modified when absent,
  • \n
  • resolve semantic title and filename/path behavior according to §9.13,
  • \n
  • apply create-time templating when enabled and supported (§5.3.5, §9.14, §7),
  • \n
  • serialize canonical keys and canonical temporal formats,
  • \n
  • when recurrence is present, canonicalize DTSTART per §4.4.5,
  • \n
  • preserve caller-provided semantic id when present,
  • \n
  • fail with validation errors if required constraints are unmet,
  • \n
  • apply default reminders according to §10.3.9 when configured.
  • \n
\n

5.3.3 Title and filename resolution on create#

\n

Create MUST produce a deterministic initial filename/path.

\n

Rules:

\n
    \n
  • Generated filenames MUST use filename-safe sanitization and MUST avoid invalid/empty basenames.
  • \n
  • If title.storage=filename:
      \n
    • basename MUST derive from semantic title,
    • \n
    • title changes after create are handled by update semantics (§5.4.4),
    • \n
    • implementations MAY also persist mapped title as a synchronized compatibility mirror,
    • \n
    • title.filename_format and title.custom_filename_template MUST be ignored.
    • \n
    \n
  • \n
  • If title.storage=frontmatter, create-time basename MUST follow title.filename_format:
      \n
    • title: sanitized semantic title,
    • \n
    • zettel: implementation-defined zettel pattern (MUST be documented),
    • \n
    • timestamp: implementation-defined timestamp pattern (MUST be documented),
    • \n
    • custom: title.custom_filename_template expansion.
    • \n
    \n
  • \n
  • If generated path already exists, implementation MUST resolve collision deterministically (for example numeric suffixing).
  • \n
\n

5.3.4 Example#

\n

Input intent:

\n
title: "Pay electricity bill"\n

Assume defaults:

\n
    \n
  • status default open
  • \n
  • priority default normal
  • \n
\n

Persisted frontmatter (example):

\n
title: Pay electricity bill\nstatus: open\npriority: normal\ndateCreated: 2026-02-20T14:00:00Z\ndateModified: 2026-02-20T14:00:00Z\n

5.3.5 Optional create-time templating#

\n

This subsection is required only for implementations claiming profile templating (§7.3.3).

\n

Create-time templating pipeline MUST be deterministic:

\n
    \n
  1. Compute base create payload from explicit input, defaults (§9.8), and generated/system values (date_created, date_modified, resolved title policy).
  2. \n
  3. Expand template variables using that base payload and active runtime date/time context.
  4. \n
  5. Merge template frontmatter into base frontmatter with base payload precedence (base keys MUST win on conflict).
  6. \n
  7. Resolve body output:
      \n
    • if expanded template body is non-empty, use it;
    • \n
    • otherwise use caller-provided body/details (if any).
    • \n
    \n
  8. \n
\n

Template parse rules:

\n
    \n
  • If template content begins with ---, implementations MUST treat the first --- ... --- block as template frontmatter and the remainder as template body.
  • \n
  • Frontmatter variable expansion MUST run before YAML parsing of template frontmatter.
  • \n
\n

Portable variable support:

\n

Implementations claiming templating MUST support all variables in the Required column of the table below. Implementations MAY support any variable in the Extended column.

\n

Required task-data variables:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableValueFormat / separator
{{title}}Semantic titlestring; YAML-quoted if needed
{{status}}Task status valuestring
{{priority}}Task priority valuestring
{{dueDate}}Due date if setYYYY-MM-DD or empty
{{scheduledDate}}Scheduled date if setYYYY-MM-DD or empty
{{details}}Caller-provided body/descriptionstring
{{contexts}}Contexts listcomma-separated, e.g. "work, home"
{{tags}}Tags listcomma-separated, e.g. "task, errands"
{{hashtags}}Tags list as hashtagsspace-separated, e.g. "#task #errands"
{{timeEstimate}}Time estimate in minutesinteger string or empty
{{parentNote}}Parent note name/pathstring; YAML-quoted if needed
\n

Required date/time variables (expansion time):

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableValueFormat
{{date}}Current dateyyyy-MM-dd
{{time}}Current time (24h)HH:mm
{{year}}Full yearyyyy
{{month}}Month numberMM
{{day}}Day of monthdd
\n

Extended variables (optional):

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableValueFormat
{{dateTime}}Date + timeyyyy-MM-dd-HHmm
{{timestamp}}Full timestampyyyy-MM-dd-HHmmss
{{shortDate}}Short dateyyMMdd
{{shortYear}}Two-digit yearyy
{{monthName}}Month full namee.g. February
{{monthNameShort}}Month short namee.g. Feb
{{dayName}}Weekday full namee.g. Monday
{{dayNameShort}}Weekday short namee.g. Mon
{{week}}ISO week numberww
{{quarter}}Quarter number1–4
{{hour}}Hour (24h)HH
{{minute}}Minutemm
{{second}}Secondss
{{time12}}Time with AM/PMhh:mm a
{{time24}}Time (24h)HH:mm
{{timezone}}UTC offset longe.g. +05:30
{{utcOffset}}UTC offset longe.g. +05:30
{{unix}}Unix timestamp (seconds)integer string
{{unixMs}}Unix timestamp (ms)integer string
{{zettel}}Zettelkasten IDdate + seconds-since-midnight base-36
{{titleLower}}Title lowercasestring
{{titleUpper}}Title uppercasestring
{{titleSnake}}Title snake_casestring
{{titleKebab}}Title kebab-casestring
{{titleCamel}}Title camelCasestring
{{titlePascal}}Title PascalCasestring
{{priorityShort}}First letter of priorityuppercase char
{{statusShort}}First letter of statusuppercase char
\n

Unknown variables (not in the above lists) MUST be handled per templating.unknown_variable_policy (§9.14):

\n
    \n
  • preserve: leave the {{...}} placeholder as-is.
  • \n
  • empty: replace with an empty string.
  • \n
\n

Deterministic expansion context:

\n
    \n
  • date/time variable expansion MUST use the active runtime timezone from §3.6.
  • \n
  • locale-sensitive variables (monthName, monthNameShort, dayName, dayNameShort, time12) MUST use English locale outputs for portability (January, Jan, Monday, Mon, AM/PM).
  • \n
  • template-generated datetime-like outputs used in frontmatter MUST normalize to second precision when written as canonical datetime roles (§3.3.2).
  • \n
\n

Failure behavior:

\n
    \n
  • templating.failure_mode=error: template read/parse failures MUST abort create.
  • \n
  • templating.failure_mode=warning_fallback: template read/parse failures MUST continue create using non-templated behavior (base frontmatter + caller body/details) and SHOULD emit warnings (template_missing or template_parse_failed).
  • \n
\n

5.3.6 Identity handling on create#

\n

If semantic id is provided on create, writers MUST preserve it.\nIf implementation supports auto-generation of semantic id, generation policy MUST be documented and resulting id MUST remain stable after create.

\n

5.4 Update#

\n

5.4.1 Patch semantics#

\n

Update MUST be patch-by-default: only targeted semantic roles are changed.

\n

5.4.2 Preservation rules#

\n

Update MUST preserve:

\n
    \n
  • unrelated known roles,
  • \n
  • unknown fields,
  • \n
  • original date/datetime granularity for untouched fields.
  • \n
\n

5.4.3 Example#

\n

Before:

\n
title: Weekly review\nscheduled: 2026-02-20\npriority: normal\ncustomClient: ACME\n

Operation: set priority to high.

\n

After:

\n
title: Weekly review\nscheduled: 2026-02-20\npriority: high\ncustomClient: ACME\n

5.4.4 Title updates and filename updates#

\n

If an update changes semantic title, behavior MUST follow title.storage:

\n
    \n
  • title.storage=filename: implementation MUST rename file basename to match updated title (with sanitization and deterministic collision handling), preserving parent folder unless caller requested a move.
  • \n
  • title.storage=frontmatter: implementation MUST update mapped title field and MUST NOT rename file unless an explicit rename operation is requested.
  • \n
\n

If implementation keeps frontmatter title for compatibility while title.storage=filename, it MUST keep stored title synchronized with effective filename-derived title.

\n

5.5 Complete (non-recurring)#

\n

For non-recurring tasks, complete MUST:

\n
    \n
  1. Set status to a configured completed value, unless already completed.\nIf multiple completed values are configured, implementation MUST choose deterministically (default: first entry in status.completed_values).
  2. \n
  3. Set completed_date to completion day:
      \n
    • explicit completion-day input when provided,
    • \n
    • otherwise current local day in active runtime timezone (§5.2.1).
    • \n
    \n
  4. \n
  5. Apply overwrite policy deterministically (overwrite or preserve_if_present).
  6. \n
  7. Update date_modified on state change.
  8. \n
\n

Implementations MUST document completion-day input handling and completed_date overwrite policy.

\n

Operation MUST be idempotent.

\n

5.6 Uncomplete (non-recurring)#

\n

For non-recurring tasks, uncomplete MUST:

\n
    \n
  1. Set status to configured active/default status according to policy (default: status.default).
  2. \n
  3. Clear or retain completed_date according to policy.
  4. \n
  5. Update date_modified on state change.
  6. \n
\n

Policy MUST be documented and deterministic.

\n

Operation MUST be idempotent.

\n

5.7 Complete instance (recurring)#

\n

For recurring tasks, complete with resolved target date D (§5.2.1) MUST follow §4.7.

\n

Writers MUST NOT convert recurring completion into a base status rewrite unless explicit configuration requires it.\nWhen recurrence_anchor=completion and caller supplies an explicit datetime target, implementations MUST apply §4.4.3 datetime DTSTART rewrite behavior.\nWhen recurrence_anchor=scheduled and DTSTART is absent, implementations MUST insert DTSTART deterministically per §4.4.5.\nNext-occurrence recalculation in this mode MUST follow §4.4.4.

\n

5.8 Uncomplete instance (recurring)#

\n

For recurring tasks, uncomplete with resolved target date D (§5.2.1) MUST follow §4.8.\nFor recurrence_anchor=completion, ordinary uncomplete is intentionally non-reversible and MUST NOT roll back DTSTART.

\n

5.9 Skip and unskip instance#

\n

Skip/unskip for recurring tasks with resolved target date D (§5.2.1) MUST follow §4.9 and §4.10.

\n

5.10 Dependency operations#

\n

Dependency operations MUST follow §10.2.

\n

5.10.1 Add dependency#

\n

Add dependency MUST:

\n
    \n
  • validate dependency entry schema,
  • \n
  • parse and resolve uid per §11,
  • \n
  • enforce duplicate and self-reference rules,
  • \n
  • preserve existing non-target dependency entries,
  • \n
  • update date_modified on change.
  • \n
\n

5.10.2 Remove dependency#

\n

Remove dependency by uid MUST be idempotent.

\n

5.10.3 Replace dependency list#

\n

Replace dependency list MUST be explicit (not default patch behavior).

\n

5.11 Reminder operations#

\n

Reminder operations MUST follow §10.3.

\n

5.11.1 Add reminder#

\n

Add reminder MUST:

\n
    \n
  • validate reminder schema,
  • \n
  • enforce unique id within task,
  • \n
  • update date_modified on change.
  • \n
\n

5.11.2 Update reminder#

\n

Update reminder MUST target a reminder by id and be patch-by-default.

\n

5.11.3 Remove reminder#

\n

Remove reminder by id MUST be idempotent.

\n

5.12 Archive#

\n

Implementations MAY support archive semantics through:

\n
    \n
  • archive tag,
  • \n
  • archive status,
  • \n
  • dedicated boolean/archive field.
  • \n
\n

Archive behavior MUST be documented.

\n

Archive MUST NOT implicitly delete the task.

\n

5.13 Delete#

\n

Delete MUST remove the task file.

\n

Delete MUST NOT implicitly delete files referenced by attachments. An\nimplementation MAY offer a separate, explicit cleanup action subject to\n§5.21.4.

\n

Optional safety behavior:

\n
    \n
  • Implementations MAY perform backlink/dependency checks.
  • \n
  • If checks are enabled, implementation MUST provide a bypass option for explicit force delete.
  • \n
\n

5.14 Rename#

\n

Rename operation changes file path/filename while preserving semantic record identity.

\n

5.14.1 Rename interaction with title storage mode#

\n
    \n
  • If title.storage=filename, basename changes from rename MUST update effective semantic title.
  • \n
  • If title.storage=frontmatter, rename MUST NOT implicitly rewrite mapped title unless explicitly requested.
  • \n
  • Implementations that persist frontmatter title in title.storage=filename mode MUST either update that field on rename or remove it to prevent divergence.
  • \n
  • If semantic id is present, rename/move MUST preserve its value unchanged.
  • \n
\n

If implementation supports link/reference updating, it MUST:

\n
    \n
  • update resolvable references deterministically,
  • \n
  • report unresolved or ambiguous updates,
  • \n
  • update dependency uid and projects references consistently with normal links.
  • \n
\n

If implementation does not support reference updates, this limitation MUST be disclosed in conformance claim.

\n

5.15 Batch operations#

\n

Batch operations MAY be supported.

\n

If supported, implementation MUST report per-item outcomes and summary counts:

\n
    \n
  • total
  • \n
  • succeeded
  • \n
  • failed
  • \n
\n

Partial success behavior MUST be documented.

\n

5.16 Concurrency#

\n

Implementations SHOULD provide write-conflict detection (for example based on modified timestamp or file hash).

\n

When conflict is detected, operation MUST fail safely unless explicit overwrite is requested.

\n

5.17 Dry run#

\n

If dry run mode is supported, operation MUST:

\n
    \n
  • execute validation and transformation logic,
  • \n
  • report intended changes,
  • \n
  • perform no file write.
  • \n
\n

5.18 Error model#

\n

Implementation-native operation failures MUST provide structured error information with:

\n
    \n
  • operation name,
  • \n
  • error code,
  • \n
  • message,
  • \n
  • optional field/path context.
  • \n
\n

For conformance adapter envelopes (§5.23), failures MAY be represented as a compact error string for transport compatibility, but implementations SHOULD also expose the structured fields (for example via error_details).

\n

5.19 Time tracking management#

\n

This subsection applies to implementations that support time_entries.

\n

5.19.1 Start time tracking#

\n

Start on task T MUST:

\n
    \n
  • fail when T already has an active time entry,
  • \n
  • append a new entry with canonical startTime and no endTime,
  • \n
  • MAY set a default description,
  • \n
  • update date_modified,
  • \n
  • persist canonical time_entries shape (including removal of legacy/stale duration fields when normalizing).
  • \n
\n

Recommended error code when already active: time_tracking_already_active.

\n

5.19.2 Stop time tracking#

\n

Stop on task T MUST:

\n
    \n
  • fail when T has no active time entry,
  • \n
  • set endTime on the active entry to canonical current datetime,
  • \n
  • update date_modified,
  • \n
  • preserve non-target entries and unknown frontmatter fields.
  • \n
\n

Recommended error code when no active session exists: no_active_time_entry.

\n

5.19.3 Edit or replace time entries#

\n

When replacing/editing time_entries explicitly, implementations MUST:

\n
    \n
  • validate each entry per §2.6.1 and §3.11,
  • \n
  • persist canonical datetime formats,
  • \n
  • treat duration as derived compatibility input and SHOULD remove it from canonical writes,
  • \n
  • update date_modified when persisted state changes.
  • \n
\n

5.19.4 Remove a time entry#

\n

Remove MUST target one deterministic entry (for example by index or stable selector) and update date_modified on change.\nSelector semantics MUST be documented.

\n

5.19.5 Completion-triggered auto-stop#

\n

If time_tracking.auto_stop_on_complete=true (§9.16), completion transitions MUST trigger stop behavior for the same task only.

\n

Rules:

\n
    \n
  • non-recurring tasks: trigger when status transitions from non-completed to completed status.
  • \n
  • recurring tasks: trigger when complete_instances grows.
  • \n
  • materialized occurrence notes: trigger on the occurrence note's own status transition to completed; parent reconciliation SHOULD NOT trigger a second stop on the parent unless the parent itself has an active time entry and the implementation documents that policy.
  • \n
  • implementations MUST NOT stop active sessions on unrelated tasks.
  • \n
  • if time_tracking.auto_stop_notification=true, implementations MAY emit a user-visible notice.
  • \n
\n

5.19.6 Reporting tracked time#

\n

For reporting surfaces (for example task summaries or stats), implementations MUST document whether totals use closed_minutes or live_minutes semantics from §3.11.5.

\n

5.20 Recurrence materialization operations#

\n

This subsection is required only for implementations claiming profile materialized-occurrences (§7.3.4).

\n

5.20.1 Materialize occurrence#

\n

Operation: materialize occurrence for parent recurring task P and target date D.

\n

Conforming behavior:

\n
    \n
  1. Resolve P and confirm it is recurring.
  2. \n
  3. If an occurrence note for (P, D) already exists, return that note without creating a duplicate.
  4. \n
  5. Create a task note using occurrence_template when configured, otherwise using normal create behavior.
  6. \n
  7. Persist recurrence_parent as a link to P and occurrence_date as D.
  8. \n
  9. Set scheduled to D unless caller input or template output explicitly supplies another per-occurrence scheduled value.
  10. \n
  11. Set initial status using normal create defaults unless caller input or template output explicitly supplies a status.
  12. \n
  13. Preserve template/body output as occurrence-owned content after creation.
  14. \n
  15. Update date_created and date_modified according to create semantics.
  16. \n
\n

The operation MUST be idempotent for (P, D).

\n

If D is not generated by the current recurrence rule, implementations MAY allow materialization as an explicit user action but SHOULD report materialization_target_not_generated.

\n

5.20.2 Complete materialized occurrence#

\n

Completing a materialized occurrence note MUST:

\n
    \n
  1. Complete the occurrence note using normal non-recurring completion semantics (§5.5).
  2. \n
  3. Reconcile the parent by adding D to complete_instances and removing D from skipped_instances.
  4. \n
  5. If the parent has recurrence_anchor=completion, advance parent progression according to §4.4.3 and §4.4.4.
  6. \n
  7. If occurrence_materialization=on_completion, compute the next occurrence from the parent after the completion transition and materialize that next occurrence note idempotently.
  8. \n
\n

The occurrence note's successful completion MUST NOT be rolled back solely because next-occurrence materialization fails.\nWhen the next note cannot be created, implementations SHOULD report next_occurrence_materialization_failed.

\n

5.20.3 Skip materialized occurrence#

\n

Skipping a materialized occurrence note MUST preserve the note.\nSkip is a state transition, not deletion.

\n

Conforming behavior:

\n
    \n
  1. Set the occurrence note to the configured skipped status (status.default_skipped, or the first status.skipped_values entry when default_skipped is absent).
  2. \n
  3. Clear or retain completed_date according to the same documented policy used for uncompletion unless the implementation documents a skip-specific policy.
  4. \n
  5. Reconcile the parent by adding D to skipped_instances and removing D from complete_instances.
  6. \n
  7. If occurrence_materialization=on_completion and occurrence_next_trigger=completion_or_skip, compute and materialize the next occurrence note idempotently.
  8. \n
\n

If no skipped status is configured, skip of a materialized occurrence MUST fail deterministically in strict mode and SHOULD report missing_skipped_status.

\n

5.20.4 Uncomplete and unskip materialized occurrence#

\n

Uncomplete of a materialized occurrence note MUST:

\n
    \n
  1. Reopen the occurrence note using normal uncomplete semantics (§5.6).
  2. \n
  3. Remove D from parent complete_instances.
  4. \n
  5. For recurrence_anchor=completion, MUST NOT roll back parent DTSTART, matching §4.8.
  6. \n
  7. MUST NOT delete any later materialized occurrence note.
  8. \n
\n

Unskip of a materialized occurrence note MUST:

\n
    \n
  1. Reopen the occurrence note to configured active/default status.
  2. \n
  3. Remove D from parent skipped_instances.
  4. \n
  5. MUST NOT add D to parent complete_instances implicitly.
  6. \n
  7. MUST NOT delete any later materialized occurrence note.
  8. \n
\n

5.20.5 Delete and unmaterialize occurrence#

\n

Deleting a materialized occurrence note removes the task file and MUST NOT be interpreted as skip.

\n

Implementations MAY provide an explicit unmaterialize occurrence operation.\nIf supported, it MUST document whether parent state is preserved, cleared, or reconciled.\nIn all cases, deleting or unmaterializing an occurrence MUST NOT silently delete the parent recurring task.

\n

If parent instance lists still refer to a deleted occurrence note's date, validators MAY report an orphan/cache warning such as orphan_occurrence_note.

\n

5.21 Attachment operations#

\n

These rules apply to implementations that support the attachments\ncapability.

\n

5.21.1 Attach a file#

\n

Attach MUST:

\n
    \n
  1. durably write the binary to a collection path before publishing its task\nreference;
  2. \n
  3. add one canonical reference to the mapped attachments list;
  4. \n
  5. preserve the existing list order and append new references by default;
  6. \n
  7. avoid duplicate normalized targets; and
  8. \n
  9. update date_modified only when membership changes.
  10. \n
\n

Binary write and task-frontmatter update are not assumed to be one atomic\nstorage transaction. Implementations MUST make interrupted operations\nrecoverable or idempotently retryable. If the binary write succeeds but the\ntask update does not, the implementation MUST retain enough durable intent to\nretry or identify the unreferenced file for explicit cleanup.

\n

5.21.2 Detach a file#

\n

Detach removes the matching reference from attachments and is idempotent.\nDetach MUST NOT delete the underlying file. It MUST preserve the relative order\nof all other references.

\n

5.21.3 Insert an attached file inline#

\n

An implementation MAY offer an inline-insert operation. It MUST first satisfy\nattach semantics, then insert a Markdown link or embed into the task body.\nRemoving that body markup MUST NOT detach the file; detaching MUST NOT silently\nrewrite body content unless the user explicitly requests both changes.

\n

5.21.4 Delete an attachment file#

\n

Physical deletion MUST be a distinct, explicit action. Before deleting, an\nimplementation MUST check authoritative, current task attachments lists and\nSHOULD check body links/embeds and other collection backlinks. A stale or\noffline replica is not sufficient evidence that a file is unreferenced. If the\nbinary authority and record authority can change independently, the check and\ndelete MUST use an authority-provided transaction or equivalent precondition\nthat closes the race. An implementation MUST NOT offer physical deletion when\nit cannot establish that guarantee; detach remains available and leaves a safe\norphan. If another reference exists, deletion MUST be rejected unless the\ncaller explicitly chooses a force action whose affected references are\ndisclosed.

\n

After a successful non-forced deletion, implementations MUST remove the\ncurrent task's matching attachment reference. Failed deletion MUST leave\nfrontmatter unchanged. An accepted local outbox entry is not a successful\nphysical deletion until the binary authority acknowledges it.

\n

5.21.5 Materialized occurrences#

\n

When an occurrence note is materialized, it SHOULD inherit the parent task's\nattachment references in the same order. This copies references, not file\nbytes. Subsequent edits to either task's membership list are independent, and\nphysical deletion remains governed by §5.21.4.

\n

5.22 Operation examples#

\n

5.22.1 Non-recurring complete#

\n

Before:

\n
title: Buy groceries\nstatus: open\ncompletedDate:\ndateModified: 2026-02-20T09:00:00Z\n

After complete on 2026-02-20:

\n
title: Buy groceries\nstatus: done\ncompletedDate: 2026-02-20\ndateModified: 2026-02-20T09:05:00Z\n

5.22.2 Recurring complete instance#

\n

Before:

\n
title: Weekly review\nstatus: open\nscheduled: 2026-02-20\nrecurrence: FREQ=WEEKLY;BYDAY=FR\ncompleteInstances: []\nskippedInstances: []\ndateModified: 2026-02-20T08:00:00Z\n

After complete instance on 2026-02-20:

\n
title: Weekly review\nstatus: open\nscheduled: 2026-02-20\nrecurrence: DTSTART:20260220;FREQ=WEEKLY;BYDAY=FR\ncompleteInstances: [2026-02-20]\nskippedInstances: []\ndateModified: 2026-02-20T08:10:00Z\n

5.22.3 Recurring skip instance overriding completion#

\n

Before:

\n
completeInstances: [2026-02-20]\nskippedInstances: []\n

After skip 2026-02-20:

\n
completeInstances: []\nskippedInstances: [2026-02-20]\n

5.22.4 Preserve unknown fields on update#

\n

Before:

\n
title: Plan Q2\nstatus: open\nvendorTicket: ZX-42\n

Update status to in-progress.

\n

After:

\n
title: Plan Q2\nstatus: in-progress\nvendorTicket: ZX-42\n

5.22.5 Add dependency#

\n

Before:

\n
blockedBy: []\n

Add dependency:

\n
uid: "[[prepare-metrics]]"\nreltype: FINISHTOSTART\n

After:

\n
blockedBy:\n  - uid: "[[prepare-metrics]]"\n    reltype: FINISHTOSTART\n

5.22.6 Add reminder#

\n

Before:

\n
reminders: []\n

Add reminder:

\n
id: due_minus_1h\ntype: relative\nrelatedTo: due\noffset: -PT1H\n

After:

\n
reminders:\n  - id: due_minus_1h\n    type: relative\n    relatedTo: due\n    offset: -PT1H\n

5.23 Conformance operation interface#

\n

The conformance suite exercises operations via the execute(operation, input) → envelope interface defined in the adapter contract. This section specifies the input/output contracts for each conformance-testable operation name.

\n

Unless otherwise noted, all operations return { ok: true, result: {...} } on success and { ok: false, error: "..." } on failure. Adapters MAY additionally return error_details with structured fields from §5.18.

\n

General operations#

\n

op.mutate_with_validation#

\n

Tests §5.2 rule 1: validation runs before commit.

\n

Input:

\n
{ "strict": true, "frontmatter": { ... } }\n

Behavior: validate frontmatter as a task record. In strict mode (strict=true), any validation error MUST produce ok=false.

\n

Output on validation error:

\n
{ "ok": false, "error": "validation|invalid_type|..." }\n

\n

op.atomic_write#

\n

Tests §5.2 rule 2: writes are all-or-nothing.

\n

Input:

\n
{\n  "original": { ... },\n  "patch": { ... },\n  "simulateFailureAfterWrite": true\n}\n

Behavior: apply patch to original, then simulate a post-write failure. The adapter MUST report whether the write was committed and what state the record is in after recovery.

\n

Output:

\n
{\n  "ok": true,\n  "result": {\n    "committed": false,\n    "persisted": { ... }\n  }\n}\n

committed=false means the write was rolled back. persisted reflects the actual frontmatter after recovery — it MUST match original (not the patched version) when simulateFailureAfterWrite=true.

\n
\n

op.idempotency_check#

\n

Tests §5.2 rule 5: operations are safe under repetition.

\n

Input:

\n
{\n  "operation": "complete_nonrecurring",\n  "first": { "status": "open", "completedDate": null },\n  "second": { "status": "done", "completedDate": "2026-02-20" }\n}\n

Behavior: applying the named operation to first state and then again to second state MUST produce identical persisted results (including unchanged dateModified on the second no-op application). The adapter checks whether this holds.

\n

Output:

\n
{ "ok": true, "result": { "idempotent": true } }\n

\n

op.update_patch#

\n

Tests §5.4 patch semantics and unknown-field preservation.

\n

Input:

\n
{\n  "original": { "title": "...", "vendorTicket": "ZX-42", ... },\n  "patch": { "priority": "high" },\n  "changed": true\n}\n

Behavior: apply patch to original. Return the merged frontmatter.

\n

Output:

\n
{\n  "ok": true,\n  "result": {\n    "changed": true,\n    "frontmatter": { "title": "...", "priority": "high", "vendorTicket": "ZX-42", ... }\n  }\n}\n
    \n
  • changed indicates whether any field actually changed value.
  • \n
  • frontmatter MUST include all unknown fields from original unchanged.
  • \n
\n
\n

op.complete_nonrecurring#

\n

Tests §5.5 non-recurring completion.

\n

Input:

\n
{\n  "frontmatter": { "title": "...", "status": "open" },\n  "completedValues": ["done", "cancelled"],\n  "explicitDate": "2026-02-20"\n}\n

Behavior: apply a complete operation to frontmatter using completedValues (ordered list) and explicitDate as the completion day (omit to use current local day).

\n

Output:

\n
{ "ok": true, "result": { "status": "done", "completedDate": "2026-02-20" } }\n
    \n
  • status MUST be the first entry in completedValues.
  • \n
  • completedDate MUST be explicitDate if provided; otherwise a valid YYYY-MM-DD date.
  • \n
  • If frontmatter.status is already a completed value, the operation MUST still succeed (idempotent).
  • \n
\n
\n

op.uncomplete_nonrecurring#

\n

Tests §5.6 non-recurring uncompletion.

\n

Input:

\n
{\n  "frontmatter": { "title": "...", "status": "done", "completedDate": "2026-02-20" },\n  "defaultStatus": "open",\n  "clearCompletedDate": true\n}\n

Output:

\n
{ "ok": true, "result": { "status": "open", "completedDate": null } }\n
    \n
  • status MUST be defaultStatus.
  • \n
  • If clearCompletedDate=true, completedDate MUST be null in the result.
  • \n
  • If clearCompletedDate=false, completedDate MUST be preserved.
  • \n
\n
\n

op.error_shape#

\n

Tests §5.18 error model.

\n

Input:

\n
{ "operation": "update", "code": "invalid_type", "message": "bad value", "field": "status" }\n

Behavior: construct and return a structured error object.

\n

Output:

\n
{\n  "ok": true,\n  "result": {\n    "operation": "update",\n    "code": "invalid_type",\n    "message": "..."\n  }\n}\n

The message field MUST be a non-empty string. The operation and code fields MUST match the input.

\n
\n

op.detect_conflict#

\n

Tests §5.16 write-conflict detection.

\n

Input:

\n
{ "expectedVersion": "a", "actualVersion": "b", "overwrite": false }\n

Behavior: when expectedVersion != actualVersion and overwrite=false, the operation MUST fail.

\n

Output on conflict:

\n
{ "ok": false, "error": "conflict|write_conflict|..." }\n

\n

op.dry_run#

\n

Tests §5.17 dry-run mode.

\n

Input:

\n
{ "operation": "update", "patch": { "status": "done" } }\n

Output:

\n
{\n  "ok": true,\n  "result": {\n    "wrote": false,\n    "plannedChanges": ["status", ...]\n  }\n}\n

wrote MUST be false. plannedChanges MUST list the field names that would have changed.

\n
\n

Recurrence operations#

\n

For recurrence.complete, recurrence.uncomplete_instance, recurrence.skip_instance, recurrence.unskip_instance, and recurrence.effective_state, the input and output contracts are defined by the respective sections of §4 and §5.7–5.9.

\n

Common input fields for recurrence operations:

\n
    \n
  • targetDate or completionDate: YYYY-MM-DD target day
  • \n
  • completeInstances: current list of completed dates
  • \n
  • skippedInstances: current list of skipped dates
  • \n
\n

recurrence.effective_state output:

\n
{ "ok": true, "result": { "value": "completed|skipped|open" } }\n

\n

Materialized occurrence operations#

\n

For occurrence.materialize, occurrence.complete, occurrence.skip, occurrence.uncomplete, occurrence.unskip, and occurrence.unmaterialize, input and output contracts are defined by §4.18 and §5.20.

\n

Common input fields for materialized occurrence operations:

\n
    \n
  • parent: frontmatter/path/link object for the recurring parent task
  • \n
  • occurrence: frontmatter/path/link object for an existing occurrence note when applicable
  • \n
  • targetDate: YYYY-MM-DD target day
  • \n
  • config: effective occurrence/status configuration needed by the operation
  • \n
\n

occurrence.materialize output:

\n
{ "ok": true, "result": { "created": true, "occurrence": { "...": "..." } } }\n

created MUST be false when the operation returns an already-existing occurrence note for the same parent/date.

\n
\n

Time-tracking operations#

\n

For time.start, time.stop, time.replace_entries, time.remove_entry, time.auto_stop_on_complete, and time.report_totals, the contracts are defined by §5.19.

\n

Common input patterns:

\n
    \n
  • entries: current time_entries array
  • \n
  • now: ISO 8601 datetime representing current instant
  • \n
  • dateModified: current date_modified value
  • \n
\n

time.report_totals output:

\n
{ "ok": true, "result": { "closed_minutes": N, "live_minutes": M } }\n

live_minutes is only present when an active (no endTime) entry exists.

\n","text":"5.1 Purpose# This section defines normative behavior for task mutations and read-facing resolution concerns that affect persisted state. 5.2 General operation rules# For all mutating operations: Validation MUST run before commit in strict mode. Writes MUST be atomic at file level (all-or-nothing per file). date_modified MUST be updated on successful state change. Unknown fields MUST be preserved unless explicit normalization is requested. This applies to every operation in this section: create, update, complete, uncomplete, skip, unskip, dependency mutations, reminder mutations, archive, and time-tracking operations. Operations identified as idempotent MUST remain safe under repetition. 5.2.1 Target day/date resolution# Recurring instance operations act on a target day/date (complete instance, uncomplete instance, skip, unskip). Non-recurring complete uses completion-day semantics for completed_date. Resolution MUST be deterministic: If caller provides an explicit target date/datetime, that value is authoritative. If caller omits target for recurring instance operations, implementations MUST resolve in this order: task scheduled, if present and target-day-resolvable, else task due, if present and target-day-resolvable, else current local day in active runtime timezone (§3.6). Target-day resolution for fallback task fields (scheduled / due) MUST use this extraction policy: if stored value is canonical date (YYYY-MM-DD), use it as-is; if stored value is datetime, use the literal date token before T (YYYY-MM-DD) without timezone shifting; if stored value is non-canonical but accepted by compatibility policy, implementations MAY normalize to a date token and SHOULD emit a warning; if a candidate value is unusable, continue to the next fallback source. For non-recurring complete, if caller omits explicit completion-day input, implementations MUST use current local day in active runtime timezone. When an explicit target is datetime: operations that require day semantics MUST use its calendar date part in active runtime timezone, for recurring complete instance with recurrence_anchor=completion, the same explicit datetime target MUST also drive DTSTART rewrite semantics in §4.4.3. This explicit-target datetime rule is intentionally distinct from persisted-field fallback extraction above. 5.2.2 Idempotency and date_modified# For operations marked idempotent: first application MAY change state and date_modified, repeated application with semantically equivalent input MUST leave persisted state unchanged. When a repeated idempotent operation is a no-op, date_modified MUST remain unchanged. 5.3 Create# 5.3.1 Input requirements# Create MUST provide at minimum semantic roles required by §2, directly or via defaults. 5.3.2 Required behavior# Create MUST: apply default values, generate date_created and date_modified when absent, resolve semantic title and filename/path behavior according to §9.13, apply create-time templating when enabled and supported (§5.3.5, §9.14, §7), serialize canonical keys and canonical temporal formats, when recurrence is present, canonicalize DTSTART per §4.4.5, preserve caller-provided semantic id when present, fail with validation errors if required constraints are unmet, apply default reminders according to §10.3.9 when configured. 5.3.3 Title and filename resolution on create# Create MUST produce a deterministic initial filename/path. Rules: Generated filenames MUST use filename-safe sanitization and MUST avoid invalid/empty basenames. If title.storage=filename: basename MUST derive from semantic title, title changes after create are handled by update semantics (§5.4.4), implementations MAY also persist mapped title as a synchronized compatibility mirror, title.filename_format and title.custom_filename_template MUST be ignored. If title.storage=frontmatter, create-time basename MUST follow title.filename_format: title: sanitized semantic title, zettel: implementation-defined zettel pattern (MUST be documented), timestamp: implementation-defined timestamp pattern (MUST be documented), custom: title.custom_filename_template expansion. If generated path already exists, implementation MUST resolve collision deterministically (for example numeric suffixing). 5.3.4 Example# Input intent: title: \"Pay electricity bill\" Assume defaults: status default open priority default normal Persisted frontmatter (example): title: Pay electricity bill status: open priority: normal dateCreated: 2026-02-20T14:00:00Z dateModified: 2026-02-20T14:00:00Z 5.3.5 Optional create-time templating# This subsection is required only for implementations claiming profile templating (§7.3.3). Create-time templating pipeline MUST be deterministic: Compute base create payload from explicit input, defaults (§9.8), and generated/system values (date_created, date_modified, resolved title policy). Expand template variables using that base payload and active runtime date/time context. Merge template frontmatter into base frontmatter with base payload precedence (base keys MUST win on conflict). Resolve body output: if expanded template body is non-empty, use it; otherwise use caller-provided body/details (if any). Template parse rules: If template content begins with ---, implementations MUST treat the first --- ... --- block as template frontmatter and the remainder as template body. Frontmatter variable expansion MUST run before YAML parsing of template frontmatter. Portable variable support: Implementations claiming templating MUST support all variables in the Required column of the table below. Implementations MAY support any variable in the Extended column. Required task-data variables: Variable Value Format / separator {{title}} Semantic title string; YAML-quoted if needed {{status}} Task status value string {{priority}} Task priority value string {{dueDate}} Due date if set YYYY-MM-DD or empty {{scheduledDate}} Scheduled date if set YYYY-MM-DD or empty {{details}} Caller-provided body/description string {{contexts}} Contexts list comma-separated, e.g. \"work, home\" {{tags}} Tags list comma-separated, e.g. \"task, errands\" {{hashtags}} Tags list as hashtags space-separated, e.g. \"#task #errands\" {{timeEstimate}} Time estimate in minutes integer string or empty {{parentNote}} Parent note name/path string; YAML-quoted if needed Required date/time variables (expansion time): Variable Value Format {{date}} Current date yyyy-MM-dd {{time}} Current time (24h) HH:mm {{year}} Full year yyyy {{month}} Month number MM {{day}} Day of month dd Extended variables (optional): Variable Value Format {{dateTime}} Date + time yyyy-MM-dd-HHmm {{timestamp}} Full timestamp yyyy-MM-dd-HHmmss {{shortDate}} Short date yyMMdd {{shortYear}} Two-digit year yy {{monthName}} Month full name e.g. February {{monthNameShort}} Month short name e.g. Feb {{dayName}} Weekday full name e.g. Monday {{dayNameShort}} Weekday short name e.g. Mon {{week}} ISO week number ww {{quarter}} Quarter number 1–4 {{hour}} Hour (24h) HH {{minute}} Minute mm {{second}} Second ss {{time12}} Time with AM/PM hh:mm a {{time24}} Time (24h) HH:mm {{timezone}} UTC offset long e.g. +05:30 {{utcOffset}} UTC offset long e.g. +05:30 {{unix}} Unix timestamp (seconds) integer string {{unixMs}} Unix timestamp (ms) integer string {{zettel}} Zettelkasten ID date + seconds-since-midnight base-36 {{titleLower}} Title lowercase string {{titleUpper}} Title uppercase string {{titleSnake}} Title snake_case string {{titleKebab}} Title kebab-case string {{titleCamel}} Title camelCase string {{titlePascal}} Title PascalCase string {{priorityShort}} First letter of priority uppercase char {{statusShort}} First letter of status uppercase char Unknown variables (not in the above lists) MUST be handled per templating.unknown_variable_policy (§9.14): preserve: leave the {{...}} placeholder as-is. empty: replace with an empty string. Deterministic expansion context: date/time variable expansion MUST use the active runtime timezone from §3.6. locale-sensitive variables (monthName, monthNameShort, dayName, dayNameShort, time12) MUST use English locale outputs for portability (January, Jan, Monday, Mon, AM/PM). template-generated datetime-like outputs used in frontmatter MUST normalize to second precision when written as canonical datetime roles (§3.3.2). Failure behavior: templating.failure_mode=error: template read/parse failures MUST abort create. templating.failure_mode=warning_fallback: template read/parse failures MUST continue create using non-templated behavior (base frontmatter + caller body/details) and SHOULD emit warnings (template_missing or template_parse_failed). 5.3.6 Identity handling on create# If semantic id is provided on create, writers MUST preserve it. If implementation supports auto-generation of semantic id, generation policy MUST be documented and resulting id MUST remain stable after create. 5.4 Update# 5.4.1 Patch semantics# Update MUST be patch-by-default: only targeted semantic roles are changed. 5.4.2 Preservation rules# Update MUST preserve: unrelated known roles, unknown fields, original date/datetime granularity for untouched fields. 5.4.3 Example# Before: title: Weekly review scheduled: 2026-02-20 priority: normal customClient: ACME Operation: set priority to high. After: title: Weekly review scheduled: 2026-02-20 priority: high customClient: ACME 5.4.4 Title updates and filename updates# If an update changes semantic title, behavior MUST follow title.storage: title.storage=filename: implementation MUST rename file basename to match updated title (with sanitization and deterministic collision handling), preserving parent folder unless caller requested a move. title.storage=frontmatter: implementation MUST update mapped title field and MUST NOT rename file unless an explicit rename operation is requested. If implementation keeps frontmatter title for compatibility while title.storage=filename, it MUST keep stored title synchronized with effective filename-derived title. 5.5 Complete (non-recurring)# For non-recurring tasks, complete MUST: Set status to a configured completed value, unless already completed. If multiple completed values are configured, implementation MUST choose deterministically (default: first entry in status.completed_values). Set completed_date to completion day: explicit completion-day input when provided, otherwise current local day in active runtime timezone (§5.2.1). Apply overwrite policy deterministically (overwrite or preserve_if_present). Update date_modified on state change. Implementations MUST document completion-day input handling and completed_date overwrite policy. Operation MUST be idempotent. 5.6 Uncomplete (non-recurring)# For non-recurring tasks, uncomplete MUST: Set status to configured active/default status according to policy (default: status.default). Clear or retain completed_date according to policy. Update date_modified on state change. Policy MUST be documented and deterministic. Operation MUST be idempotent. 5.7 Complete instance (recurring)# For recurring tasks, complete with resolved target date D (§5.2.1) MUST follow §4.7. Writers MUST NOT convert recurring completion into a base status rewrite unless explicit configuration requires it. When recurrence_anchor=completion and caller supplies an explicit datetime target, implementations MUST apply §4.4.3 datetime DTSTART rewrite behavior. When recurrence_anchor=scheduled and DTSTART is absent, implementations MUST insert DTSTART deterministically per §4.4.5. Next-occurrence recalculation in this mode MUST follow §4.4.4. 5.8 Uncomplete instance (recurring)# For recurring tasks, uncomplete with resolved target date D (§5.2.1) MUST follow §4.8. For recurrence_anchor=completion, ordinary uncomplete is intentionally non-reversible and MUST NOT roll back DTSTART. 5.9 Skip and unskip instance# Skip/unskip for recurring tasks with resolved target date D (§5.2.1) MUST follow §4.9 and §4.10. 5.10 Dependency operations# Dependency operations MUST follow §10.2. 5.10.1 Add dependency# Add dependency MUST: validate dependency entry schema, parse and resolve uid per §11, enforce duplicate and self-reference rules, preserve existing non-target dependency entries, update date_modified on change. 5.10.2 Remove dependency# Remove dependency by uid MUST be idempotent. 5.10.3 Replace dependency list# Replace dependency list MUST be explicit (not default patch behavior). 5.11 Reminder operations# Reminder operations MUST follow §10.3. 5.11.1 Add reminder# Add reminder MUST: validate reminder schema, enforce unique id within task, update date_modified on change. 5.11.2 Update reminder# Update reminder MUST target a reminder by id and be patch-by-default. 5.11.3 Remove reminder# Remove reminder by id MUST be idempotent. 5.12 Archive# Implementations MAY support archive semantics through: archive tag, archive status, dedicated boolean/archive field. Archive behavior MUST be documented. Archive MUST NOT implicitly delete the task. 5.13 Delete# Delete MUST remove the task file. Delete MUST NOT implicitly delete files referenced by attachments. An implementation MAY offer a separate, explicit cleanup action subject to §5.21.4. Optional safety behavior: Implementations MAY perform backlink/dependency checks. If checks are enabled, implementation MUST provide a bypass option for explicit force delete. 5.14 Rename# Rename operation changes file path/filename while preserving semantic record identity. 5.14.1 Rename interaction with title storage mode# If title.storage=filename, basename changes from rename MUST update effective semantic title. If title.storage=frontmatter, rename MUST NOT implicitly rewrite mapped title unless explicitly requested. Implementations that persist frontmatter title in title.storage=filename mode MUST either update that field on rename or remove it to prevent divergence. If semantic id is present, rename/move MUST preserve its value unchanged. If implementation supports link/reference updating, it MUST: update resolvable references deterministically, report unresolved or ambiguous updates, update dependency uid and projects references consistently with normal links. If implementation does not support reference updates, this limitation MUST be disclosed in conformance claim. 5.15 Batch operations# Batch operations MAY be supported. If supported, implementation MUST report per-item outcomes and summary counts: total succeeded failed Partial success behavior MUST be documented. 5.16 Concurrency# Implementations SHOULD provide write-conflict detection (for example based on modified timestamp or file hash). When conflict is detected, operation MUST fail safely unless explicit overwrite is requested. 5.17 Dry run# If dry run mode is supported, operation MUST: execute validation and transformation logic, report intended changes, perform no file write. 5.18 Error model# Implementation-native operation failures MUST provide structured error information with: operation name, error code, message, optional field/path context. For conformance adapter envelopes (§5.23), failures MAY be represented as a compact error string for transport compatibility, but implementations SHOULD also expose the structured fields (for example via error_details). 5.19 Time tracking management# This subsection applies to implementations that support time_entries. 5.19.1 Start time tracking# Start on task T MUST: fail when T already has an active time entry, append a new entry with canonical startTime and no endTime, MAY set a default description, update date_modified, persist canonical time_entries shape (including removal of legacy/stale duration fields when normalizing). Recommended error code when already active: time_tracking_already_active. 5.19.2 Stop time tracking# Stop on task T MUST: fail when T has no active time entry, set endTime on the active entry to canonical current datetime, update date_modified, preserve non-target entries and unknown frontmatter fields. Recommended error code when no active"},{"route":"/developers/specification/06-validation/","title":"6. Validation","description":"Validation ensures persisted task records conform to this specification and collection configuration.","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:06-validation.md","namespace":"specification","relativePath":"06-validation.md","raw":"# 6. Validation\n\n## 6.1 Purpose\n\nValidation ensures persisted task records conform to this specification and collection configuration.\n\n## 6.2 Validation phases\n\nImplementations SHOULD validate in these phases:\n\n1. Parse validation (YAML/frontmatter structure)\n2. Schema validation (types and role constraints)\n3. Semantic validation (cross-field invariants)\n\n## 6.3 Validation modes\n\nConforming implementations MUST support:\n\n- `strict`: errors block writes.\n\nImplementations MAY additionally support:\n\n- `permissive`: writes may continue with warnings.\n\nCurrent mode MUST be discoverable.\n\n## 6.4 Required checks\n\nA conforming validator MUST implement checks required by the claimed profile(s):\n\n| Check ID | Requirement | Required for |\n|---|---|---|\n| 1 | Unconditionally required semantic roles are present (`status`, `date_created`, `date_modified`). | `core-lite` and above |\n| 1a | `completed_date` conditional requiredness is enforced per §2.2.1. | `core-lite` and above |\n| 1b | `title` resolves via active title policy (§2.2.2 and §9.13): storage-mode-aware precedence and fallback. | `core-lite` and above |\n| 2 | Field values match role type requirements. | `core-lite` and above |\n| 3 | Temporal values conform to §3. | `core-lite` and above |\n| 4 | Recurrence values conform to §4 (including tasknotes recurrence-string syntax and anchor-seed resolution rules). | `recurrence` and above |\n| 5 | Per-instance lists contain valid dates with no overlap. | `recurrence` and above |\n| 6 | `date_modified` is not earlier than `date_created` when both exist. | `core-lite` and above |\n| 7 | `time_estimate` is non-negative when present. | any profile that supports `time_estimate` |\n| 8 | `time_entries` entries include required `startTime`, ranges are valid when `endTime` exists, and at most one active entry exists per task. | any profile that supports `time_entries` |\n| 9 | `blocked_by` entries conform to §10.2 (shape, enum, duplicates, self-reference). | `extended` |\n| 10 | `reminders` entries conform to §10.3 (shape, type-specific fields, unique ids). | `extended` |\n| 11 | relative reminders have resolvable base fields or produce configured error/warning behavior. | `extended` |\n| 12 | link-bearing fields (`projects`, `blocked_by.uid`, and supported `attachments`) conform to §11 parsing/resolution and traversal safety. | `extended`, or any implementation supporting `attachments` |\n| 13 | templating configuration is valid when provided (`templating` schema and enums). | `templating` |\n| 14 | create-time template failures obey configured failure mode (`error` vs fallback). | `templating` |\n| 15 | semantic `id` (when present) is a non-empty string; duplicate collection-level IDs SHOULD be reported when detectable. | any profile that supports semantic `id` |\n| 16 | materialized occurrence notes contain valid `recurrence_parent` and `occurrence_date` roles. | `materialized-occurrences` |\n| 17 | no duplicate materialized occurrence notes exist for the same resolved `(recurrence_parent, occurrence_date)` pair. | `materialized-occurrences` |\n| 18 | materialization policy values and rolling horizons conform to §4.18 and §9.17. | `materialized-occurrences` |\n| 19 | `attachments` is a list of non-empty, unique normalized file references with explicit extensions. | any implementation supporting `attachments` |\n\n## 6.5 Unknown field policy\n\nUnknown fields:\n\n- MUST NOT fail validation by default unless collection is configured for strict schema closure.\n- SHOULD generate informational warnings when strict schema closure is desired but not enabled.\n\n## 6.6 Issue structure\n\nValidation issues MUST include:\n\n- `code` (machine-readable)\n- `severity` (`error`, `warning`, or `info`)\n- `message` (human-readable)\n\nIssues SHOULD include:\n\n- `field` or path\n- `expected` and `actual` details where useful\n\n## 6.7 Recommended issue codes\n\n| Code | Severity (default) | Meaning |\n|---|---|---|\n| `missing_required` | error | required role missing |\n| `invalid_type` | error | value type mismatch |\n| `invalid_enum_value` | error | value not in configured set |\n| `invalid_date_value` | error | malformed or impossible date |\n| `invalid_datetime_value` | error | malformed datetime |\n| `invalid_recurrence_rule` | error | recurrence not valid tasknotes recurrence syntax |\n| `missing_recurrence_seed` | error | recurrence has no resolvable seed/start date |\n| `invalid_recurrence_anchor` | error | anchor not allowed |\n| `instance_state_overlap` | error | same date in complete and skipped lists |\n| `invalid_time_range` | error | end before start in time entry |\n| `missing_time_entry_start` | error | time entry is missing required startTime |\n| `multiple_active_time_entries` | error | more than one active time entry exists in one task |\n| `invalid_dependency_entry` | error | dependency object missing required fields |\n| `invalid_dependency_reltype` | error | dependency reltype not allowed |\n| `invalid_dependency_gap` | error | dependency gap not valid ISO 8601 duration |\n| `duplicate_dependency_uid` | error in strict mode when `dependencies.enforce_unique_uid=true`; warning otherwise by policy | repeated dependency uid in task |\n| `self_dependency` | error | task depends on itself |\n| `unresolved_dependency_target` | warning | dependency target not resolvable |\n| `invalid_reminder_entry` | error | reminder object missing required fields |\n| `duplicate_reminder_id` | error | repeated reminder id in task |\n| `invalid_reminder_type` | error | reminder type not allowed |\n| `invalid_reminder_offset` | error | relative reminder offset not valid duration |\n| `invalid_reminder_related_to` | error | relatedTo must be due or scheduled |\n| `invalid_reminder_absolute_time` | error | absoluteTime invalid datetime |\n| `unresolvable_reminder_base` | error | relative reminder base field missing/unusable |\n| `invalid_link_format` | error | link value cannot be parsed as supported format |\n| `ambiguous_link` | warning | link resolves to multiple candidates |\n| `path_traversal` | error | resolved path escapes collection root |\n| `unresolved_link_target` | warning | link target cannot be resolved |\n| `invalid_attachment_reference` | error | attachment reference is empty, lacks an explicit extension, or targets a directory |\n| `duplicate_attachment_reference` | error | attachment list repeats the same normalized target |\n| `invalid_task_id` | error | semantic `id` is empty or invalid type |\n| `duplicate_task_id` | warning | duplicate semantic `id` detected in collection scope |\n| `alias_conflict_ignored` | warning | alias key ignored due to canonical conflict |\n| `unresolvable_title` | error | title cannot be resolved from title resolution policy |\n| `title_source_conflict` | warning | mapped title and filename title differ; active title-storage policy selected authoritative source |\n| `template_missing` | warning | configured template file cannot be read/found |\n| `template_parse_failed` | warning | template frontmatter/body parsing or expansion failed |\n| `missing_recurrence_parent` | error | materialized occurrence note omits recurrence_parent |\n| `invalid_recurrence_parent` | warning | occurrence note parent reference cannot be resolved or does not reference a recurring task |\n| `missing_occurrence_date` | error | materialized occurrence note omits occurrence_date |\n| `duplicate_occurrence_note` | warning | more than one materialized occurrence note exists for the same parent/date |\n| `occurrence_state_conflict` | warning | materialized occurrence state disagrees with parent instance lists |\n| `materialization_target_not_generated` | warning | occurrence date is not generated by current parent recurrence rule |\n| `missing_skipped_status` | error | skip of materialized occurrence requires configured skipped status |\n| `next_occurrence_materialization_failed` | warning | triggering operation succeeded but next occurrence note could not be created |\n| `orphan_occurrence_note` | warning | materialized occurrence note has no resolvable recurring parent or parent state references a deleted occurrence note |\n| `unknown_field` | info | unmapped field encountered |\n\nImplementations MAY extend this code set but SHOULD preserve existing meanings.\n\n## 6.8 Write-time validation behavior\n\nIn strict mode, mutating operations MUST fail if any error-severity issue is present after applying intended changes.\n\nWarnings SHOULD NOT block writes unless explicitly configured.\n\nDatetime/date acceptance and rejection in validation MUST follow the normative matrix in §3.4.4.\n\n## 6.9 Validation examples\n\n### 6.9.1 Missing required role\n\nInput:\n\n```yaml\ntitle: Plan workshop\nstatus: open\ndateCreated: 2026-02-20T09:00:00Z\n```\n\nIssue:\n\n```yaml\ncode: missing_required\nseverity: error\nfield: dateModified\nmessage: Required field 'dateModified' is missing.\n```\n\n### 6.9.2 Invalid recurrence anchor\n\nInput:\n\n```yaml\nrecurrence: FREQ=DAILY\nrecurrenceAnchor: due\n```\n\nIssue:\n\n```yaml\ncode: invalid_recurrence_anchor\nseverity: error\nfield: recurrenceAnchor\nmessage: recurrence anchor must be 'scheduled' or 'completion'.\n```\n\n### 6.9.3 Overlap in instance state\n\nInput:\n\n```yaml\ncompleteInstances: [2026-02-20]\nskippedInstances: [2026-02-20]\n```\n\nIssue:\n\n```yaml\ncode: instance_state_overlap\nseverity: error\nmessage: same date exists in complete and skipped instance lists.\n```\n\n### 6.9.4 Invalid dependency reltype\n\nInput:\n\n```yaml\nblockedBy:\n - uid: \"[[task-a]]\"\n reltype: BLOCKS\n```\n\nIssue:\n\n```yaml\ncode: invalid_dependency_reltype\nseverity: error\nfield: blockedBy[0].reltype\nmessage: reltype must be one of FINISHTOSTART, STARTTOSTART, FINISHTOFINISH, STARTTOFINISH.\n```\n\n### 6.9.5 Unresolvable reminder base\n\nInput:\n\n```yaml\nreminders:\n - id: due_minus_1d\n type: relative\n relatedTo: due\n offset: -P1D\n```\n\nIssue when `due` missing:\n\n```yaml\ncode: unresolvable_reminder_base\nseverity: error\nfield: reminders[0]\nmessage: relative reminder references due but no due value exists.\n```\n\n### 6.9.6 Unknown field in permissive mode\n\nInput:\n\n```yaml\ntitle: Plan workshop\nstatus: open\nvendorPriority: p1\n```\n\nIssue example:\n\n```yaml\ncode: unknown_field\nseverity: info\nfield: vendorPriority\nmessage: field is not mapped to a known semantic role.\n```\n\n### 6.9.7 Multiple active time entries\n\nInput:\n\n```yaml\ntimeEntries:\n - startTime: 2026-02-20T10:00:00Z\n - startTime: 2026-02-20T11:00:00Z\n```\n\nIssue:\n\n```yaml\ncode: multiple_active_time_entries\nseverity: error\nfield: timeEntries\nmessage: task contains more than one active time entry.\n```\n","aliases":["/spec/06-validation/"],"toc":[{"level":2,"id":"61-purpose","text":"6.1 Purpose"},{"level":2,"id":"62-validation-phases","text":"6.2 Validation phases"},{"level":2,"id":"63-validation-modes","text":"6.3 Validation modes"},{"level":2,"id":"64-required-checks","text":"6.4 Required checks"},{"level":2,"id":"65-unknown-field-policy","text":"6.5 Unknown field policy"},{"level":2,"id":"66-issue-structure","text":"6.6 Issue structure"},{"level":2,"id":"67-recommended-issue-codes","text":"6.7 Recommended issue codes"},{"level":2,"id":"68-write-time-validation-behavior","text":"6.8 Write-time validation behavior"},{"level":2,"id":"69-validation-examples","text":"6.9 Validation examples"},{"level":3,"id":"691-missing-required-role","text":"6.9.1 Missing required role"},{"level":3,"id":"692-invalid-recurrence-anchor","text":"6.9.2 Invalid recurrence anchor"},{"level":3,"id":"693-overlap-in-instance-state","text":"6.9.3 Overlap in instance state"},{"level":3,"id":"694-invalid-dependency-reltype","text":"6.9.4 Invalid dependency reltype"},{"level":3,"id":"695-unresolvable-reminder-base","text":"6.9.5 Unresolvable reminder base"},{"level":3,"id":"696-unknown-field-in-permissive-mode","text":"6.9.6 Unknown field in permissive mode"},{"level":3,"id":"697-multiple-active-time-entries","text":"6.9.7 Multiple active time entries"}],"html":"

6.1 Purpose#

\n

Validation ensures persisted task records conform to this specification and collection configuration.

\n

6.2 Validation phases#

\n

Implementations SHOULD validate in these phases:

\n
    \n
  1. Parse validation (YAML/frontmatter structure)
  2. \n
  3. Schema validation (types and role constraints)
  4. \n
  5. Semantic validation (cross-field invariants)
  6. \n
\n

6.3 Validation modes#

\n

Conforming implementations MUST support:

\n
    \n
  • strict: errors block writes.
  • \n
\n

Implementations MAY additionally support:

\n
    \n
  • permissive: writes may continue with warnings.
  • \n
\n

Current mode MUST be discoverable.

\n

6.4 Required checks#

\n

A conforming validator MUST implement checks required by the claimed profile(s):

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Check IDRequirementRequired for
1Unconditionally required semantic roles are present (status, date_created, date_modified).core-lite and above
1acompleted_date conditional requiredness is enforced per §2.2.1.core-lite and above
1btitle resolves via active title policy (§2.2.2 and §9.13): storage-mode-aware precedence and fallback.core-lite and above
2Field values match role type requirements.core-lite and above
3Temporal values conform to §3.core-lite and above
4Recurrence values conform to §4 (including tasknotes recurrence-string syntax and anchor-seed resolution rules).recurrence and above
5Per-instance lists contain valid dates with no overlap.recurrence and above
6date_modified is not earlier than date_created when both exist.core-lite and above
7time_estimate is non-negative when present.any profile that supports time_estimate
8time_entries entries include required startTime, ranges are valid when endTime exists, and at most one active entry exists per task.any profile that supports time_entries
9blocked_by entries conform to §10.2 (shape, enum, duplicates, self-reference).extended
10reminders entries conform to §10.3 (shape, type-specific fields, unique ids).extended
11relative reminders have resolvable base fields or produce configured error/warning behavior.extended
12link-bearing fields (projects, blocked_by.uid, and supported attachments) conform to §11 parsing/resolution and traversal safety.extended, or any implementation supporting attachments
13templating configuration is valid when provided (templating schema and enums).templating
14create-time template failures obey configured failure mode (error vs fallback).templating
15semantic id (when present) is a non-empty string; duplicate collection-level IDs SHOULD be reported when detectable.any profile that supports semantic id
16materialized occurrence notes contain valid recurrence_parent and occurrence_date roles.materialized-occurrences
17no duplicate materialized occurrence notes exist for the same resolved (recurrence_parent, occurrence_date) pair.materialized-occurrences
18materialization policy values and rolling horizons conform to §4.18 and §9.17.materialized-occurrences
19attachments is a list of non-empty, unique normalized file references with explicit extensions.any implementation supporting attachments
\n

6.5 Unknown field policy#

\n

Unknown fields:

\n
    \n
  • MUST NOT fail validation by default unless collection is configured for strict schema closure.
  • \n
  • SHOULD generate informational warnings when strict schema closure is desired but not enabled.
  • \n
\n

6.6 Issue structure#

\n

Validation issues MUST include:

\n
    \n
  • code (machine-readable)
  • \n
  • severity (error, warning, or info)
  • \n
  • message (human-readable)
  • \n
\n

Issues SHOULD include:

\n
    \n
  • field or path
  • \n
  • expected and actual details where useful
  • \n
\n\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
CodeSeverity (default)Meaning
missing_requirederrorrequired role missing
invalid_typeerrorvalue type mismatch
invalid_enum_valueerrorvalue not in configured set
invalid_date_valueerrormalformed or impossible date
invalid_datetime_valueerrormalformed datetime
invalid_recurrence_ruleerrorrecurrence not valid tasknotes recurrence syntax
missing_recurrence_seederrorrecurrence has no resolvable seed/start date
invalid_recurrence_anchorerroranchor not allowed
instance_state_overlaperrorsame date in complete and skipped lists
invalid_time_rangeerrorend before start in time entry
missing_time_entry_starterrortime entry is missing required startTime
multiple_active_time_entrieserrormore than one active time entry exists in one task
invalid_dependency_entryerrordependency object missing required fields
invalid_dependency_reltypeerrordependency reltype not allowed
invalid_dependency_gaperrordependency gap not valid ISO 8601 duration
duplicate_dependency_uiderror in strict mode when dependencies.enforce_unique_uid=true; warning otherwise by policyrepeated dependency uid in task
self_dependencyerrortask depends on itself
unresolved_dependency_targetwarningdependency target not resolvable
invalid_reminder_entryerrorreminder object missing required fields
duplicate_reminder_iderrorrepeated reminder id in task
invalid_reminder_typeerrorreminder type not allowed
invalid_reminder_offseterrorrelative reminder offset not valid duration
invalid_reminder_related_toerrorrelatedTo must be due or scheduled
invalid_reminder_absolute_timeerrorabsoluteTime invalid datetime
unresolvable_reminder_baseerrorrelative reminder base field missing/unusable
invalid_link_formaterrorlink value cannot be parsed as supported format
ambiguous_linkwarninglink resolves to multiple candidates
path_traversalerrorresolved path escapes collection root
unresolved_link_targetwarninglink target cannot be resolved
invalid_attachment_referenceerrorattachment reference is empty, lacks an explicit extension, or targets a directory
duplicate_attachment_referenceerrorattachment list repeats the same normalized target
invalid_task_iderrorsemantic id is empty or invalid type
duplicate_task_idwarningduplicate semantic id detected in collection scope
alias_conflict_ignoredwarningalias key ignored due to canonical conflict
unresolvable_titleerrortitle cannot be resolved from title resolution policy
title_source_conflictwarningmapped title and filename title differ; active title-storage policy selected authoritative source
template_missingwarningconfigured template file cannot be read/found
template_parse_failedwarningtemplate frontmatter/body parsing or expansion failed
missing_recurrence_parenterrormaterialized occurrence note omits recurrence_parent
invalid_recurrence_parentwarningoccurrence note parent reference cannot be resolved or does not reference a recurring task
missing_occurrence_dateerrormaterialized occurrence note omits occurrence_date
duplicate_occurrence_notewarningmore than one materialized occurrence note exists for the same parent/date
occurrence_state_conflictwarningmaterialized occurrence state disagrees with parent instance lists
materialization_target_not_generatedwarningoccurrence date is not generated by current parent recurrence rule
missing_skipped_statuserrorskip of materialized occurrence requires configured skipped status
next_occurrence_materialization_failedwarningtriggering operation succeeded but next occurrence note could not be created
orphan_occurrence_notewarningmaterialized occurrence note has no resolvable recurring parent or parent state references a deleted occurrence note
unknown_fieldinfounmapped field encountered
\n

Implementations MAY extend this code set but SHOULD preserve existing meanings.

\n

6.8 Write-time validation behavior#

\n

In strict mode, mutating operations MUST fail if any error-severity issue is present after applying intended changes.

\n

Warnings SHOULD NOT block writes unless explicitly configured.

\n

Datetime/date acceptance and rejection in validation MUST follow the normative matrix in §3.4.4.

\n

6.9 Validation examples#

\n

6.9.1 Missing required role#

\n

Input:

\n
title: Plan workshop\nstatus: open\ndateCreated: 2026-02-20T09:00:00Z\n

Issue:

\n
code: missing_required\nseverity: error\nfield: dateModified\nmessage: Required field 'dateModified' is missing.\n

6.9.2 Invalid recurrence anchor#

\n

Input:

\n
recurrence: FREQ=DAILY\nrecurrenceAnchor: due\n

Issue:

\n
code: invalid_recurrence_anchor\nseverity: error\nfield: recurrenceAnchor\nmessage: recurrence anchor must be 'scheduled' or 'completion'.\n

6.9.3 Overlap in instance state#

\n

Input:

\n
completeInstances: [2026-02-20]\nskippedInstances: [2026-02-20]\n

Issue:

\n
code: instance_state_overlap\nseverity: error\nmessage: same date exists in complete and skipped instance lists.\n

6.9.4 Invalid dependency reltype#

\n

Input:

\n
blockedBy:\n  - uid: "[[task-a]]"\n    reltype: BLOCKS\n

Issue:

\n
code: invalid_dependency_reltype\nseverity: error\nfield: blockedBy[0].reltype\nmessage: reltype must be one of FINISHTOSTART, STARTTOSTART, FINISHTOFINISH, STARTTOFINISH.\n

6.9.5 Unresolvable reminder base#

\n

Input:

\n
reminders:\n  - id: due_minus_1d\n    type: relative\n    relatedTo: due\n    offset: -P1D\n

Issue when due missing:

\n
code: unresolvable_reminder_base\nseverity: error\nfield: reminders[0]\nmessage: relative reminder references due but no due value exists.\n

6.9.6 Unknown field in permissive mode#

\n

Input:

\n
title: Plan workshop\nstatus: open\nvendorPriority: p1\n

Issue example:

\n
code: unknown_field\nseverity: info\nfield: vendorPriority\nmessage: field is not mapped to a known semantic role.\n

6.9.7 Multiple active time entries#

\n

Input:

\n
timeEntries:\n  - startTime: 2026-02-20T10:00:00Z\n  - startTime: 2026-02-20T11:00:00Z\n

Issue:

\n
code: multiple_active_time_entries\nseverity: error\nfield: timeEntries\nmessage: task contains more than one active time entry.\n
","text":"6.1 Purpose# Validation ensures persisted task records conform to this specification and collection configuration. 6.2 Validation phases# Implementations SHOULD validate in these phases: Parse validation (YAML/frontmatter structure) Schema validation (types and role constraints) Semantic validation (cross-field invariants) 6.3 Validation modes# Conforming implementations MUST support: strict: errors block writes. Implementations MAY additionally support: permissive: writes may continue with warnings. Current mode MUST be discoverable. 6.4 Required checks# A conforming validator MUST implement checks required by the claimed profile(s): Check ID Requirement Required for 1 Unconditionally required semantic roles are present (status, date_created, date_modified). core-lite and above 1a completed_date conditional requiredness is enforced per §2.2.1. core-lite and above 1b title resolves via active title policy (§2.2.2 and §9.13): storage-mode-aware precedence and fallback. core-lite and above 2 Field values match role type requirements. core-lite and above 3 Temporal values conform to §3. core-lite and above 4 Recurrence values conform to §4 (including tasknotes recurrence-string syntax and anchor-seed resolution rules). recurrence and above 5 Per-instance lists contain valid dates with no overlap. recurrence and above 6 date_modified is not earlier than date_created when both exist. core-lite and above 7 time_estimate is non-negative when present. any profile that supports time_estimate 8 time_entries entries include required startTime, ranges are valid when endTime exists, and at most one active entry exists per task. any profile that supports time_entries 9 blocked_by entries conform to §10.2 (shape, enum, duplicates, self-reference). extended 10 reminders entries conform to §10.3 (shape, type-specific fields, unique ids). extended 11 relative reminders have resolvable base fields or produce configured error/warning behavior. extended 12 link-bearing fields (projects, blocked_by.uid, and supported attachments) conform to §11 parsing/resolution and traversal safety. extended, or any implementation supporting attachments 13 templating configuration is valid when provided (templating schema and enums). templating 14 create-time template failures obey configured failure mode (error vs fallback). templating 15 semantic id (when present) is a non-empty string; duplicate collection-level IDs SHOULD be reported when detectable. any profile that supports semantic id 16 materialized occurrence notes contain valid recurrence_parent and occurrence_date roles. materialized-occurrences 17 no duplicate materialized occurrence notes exist for the same resolved (recurrence_parent, occurrence_date) pair. materialized-occurrences 18 materialization policy values and rolling horizons conform to §4.18 and §9.17. materialized-occurrences 19 attachments is a list of non-empty, unique normalized file references with explicit extensions. any implementation supporting attachments 6.5 Unknown field policy# Unknown fields: MUST NOT fail validation by default unless collection is configured for strict schema closure. SHOULD generate informational warnings when strict schema closure is desired but not enabled. 6.6 Issue structure# Validation issues MUST include: code (machine-readable) severity (error, warning, or info) message (human-readable) Issues SHOULD include: field or path expected and actual details where useful 6.7 Recommended issue codes# Code Severity (default) Meaning missing_required error required role missing invalid_type error value type mismatch invalid_enum_value error value not in configured set invalid_date_value error malformed or impossible date invalid_datetime_value error malformed datetime invalid_recurrence_rule error recurrence not valid tasknotes recurrence syntax missing_recurrence_seed error recurrence has no resolvable seed/start date invalid_recurrence_anchor error anchor not allowed instance_state_overlap error same date in complete and skipped lists invalid_time_range error end before start in time entry missing_time_entry_start error time entry is missing required startTime multiple_active_time_entries error more than one active time entry exists in one task invalid_dependency_entry error dependency object missing required fields invalid_dependency_reltype error dependency reltype not allowed invalid_dependency_gap error dependency gap not valid ISO 8601 duration duplicate_dependency_uid error in strict mode when dependencies.enforce_unique_uid=true; warning otherwise by policy repeated dependency uid in task self_dependency error task depends on itself unresolved_dependency_target warning dependency target not resolvable invalid_reminder_entry error reminder object missing required fields duplicate_reminder_id error repeated reminder id in task invalid_reminder_type error reminder type not allowed invalid_reminder_offset error relative reminder offset not valid duration invalid_reminder_related_to error relatedTo must be due or scheduled invalid_reminder_absolute_time error absoluteTime invalid datetime unresolvable_reminder_base error relative reminder base field missing/unusable invalid_link_format error link value cannot be parsed as supported format ambiguous_link warning link resolves to multiple candidates path_traversal error resolved path escapes collection root unresolved_link_target warning link target cannot be resolved invalid_attachment_reference error attachment reference is empty, lacks an explicit extension, or targets a directory duplicate_attachment_reference error attachment list repeats the same normalized target invalid_task_id error semantic id is empty or invalid type duplicate_task_id warning duplicate semantic id detected in collection scope alias_conflict_ignored warning alias key ignored due to canonical conflict unresolvable_title error title cannot be resolved from title resolution policy title_source_conflict warning mapped title and filename title differ; active title-storage policy selected authoritative source template_missing warning configured template file cannot be read/found template_parse_failed warning template frontmatter/body parsing or expansion failed missing_recurrence_parent error materialized occurrence note omits recurrence_parent invalid_recurrence_parent warning occurrence note parent reference cannot be resolved or does not reference a recurring task missing_occurrence_date error materialized occurrence note omits occurrence_date duplicate_occurrence_note warning more than one materialized occurrence note exists for the same parent/date occurrence_state_conflict warning materialized occurrence state disagrees with parent instance lists materialization_target_not_generated warning occurrence date is not generated by current parent recurrence rule missing_skipped_status error skip of materialized occurrence requires configured skipped status next_occurrence_materialization_failed warning triggering operation succeeded but next occurrence note could not be created orphan_occurrence_note warning materialized occurrence note has no resolvable recurring parent or parent state references a deleted occurrence note unknown_field info unmapped field encountered Implementations MAY extend this code set but SHOULD preserve existing meanings. 6.8 Write-time validation behavior# In strict mode, mutating operations MUST fail if any error-severity issue is present after applying intended changes. Warnings SHOULD NOT block writes unless explicitly configured. Datetime/date acceptance and rejection in validation MUST follow the normative matrix in §3.4.4. 6.9 Validation examples# 6.9.1 Missing required role# Input: title: Plan workshop status: open dateCreated: 2026-02-20T09:00:00Z Issue: code: missing_required severity: error field: dateModified message: Required field 'dateModified' is missing. 6.9.2 Invalid recurrence anchor# Input: recurrence: FREQ=DAILY recurrenceAnchor: due Issue: code: invalid_recurrence_anchor severity: error field: recurrenceAnchor message: recurrence anchor must be 'scheduled' or 'completion'. 6.9.3 Overlap in instance state# Input: completeInstances: [2026-02-20] skippedInstances: [2026-02-20] Issue: code: instance_state_overlap severity: error message: same date exists in complete and skipped instance lists. 6.9.4 Invalid dependency reltype# Input: blockedBy: - uid: \"[[task-a]]\" reltype: BLOCKS Issue: code: invalid_dependency_reltype severity: error field: blockedBy[0].reltype message: reltype must be one of FINISHTOSTART, STARTTOSTART, FINISHTOFINISH, STARTTOFINISH. 6.9.5 Unresolvable reminder base# Input: reminders: - id: due_minus_1d type: relative relatedTo: due offset: -P1D Issue when due missing: code: unresolvable_reminder_base severity: error field: reminders[0] message: relative reminder references due but no due value exists. 6.9.6 Unknown field in permissive mode# Input: title: Plan workshop status: open vendorPriority: p1 Issue example: code: unknown_field severity: info field: vendorPriority message: field is not mapped to a known semantic role. 6.9.7 Multiple active time entries# Input: timeEntries: - startTime: 2026-02-20T10:00:00Z - startTime: 2026-02-20T11:00:00Z Issue: code: multiple_active_time_entries severity: error field: timeEntries message: task contains more than one active time entry."},{"route":"/developers/specification/07-conformance/","title":"7. Conformance","description":"This section defines conformance profiles and claim requirements for implementations.","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:07-conformance.md","namespace":"specification","relativePath":"07-conformance.md","raw":"# 7. Conformance\n\n## 7.1 Purpose\n\nThis section defines conformance profiles and claim requirements for implementations.\n\n## 7.2 Conformance principles\n\nAn implementation MUST NOT claim conformance to a profile unless all required capabilities of that profile are implemented.\n\nImplementations MAY implement additional behavior beyond a profile, but extra behavior MUST NOT violate profile requirements.\n\n## 7.3 Profile model\n\nProfiles are cumulative unless explicitly marked otherwise.\n\n### 7.3.1 Profile: `core-lite`\n\nRequired capabilities:\n\n- task identification and loading\n- semantic-role mapping and canonical writes (§2)\n- required role support (`title`, `status`, `completed_date`, `date_created`, `date_modified`)\n- create, update, delete operations (§5)\n- non-recurring complete/uncomplete (§5)\n- temporal parsing/canonical serialization basics (§3)\n- strict validation mode support (§6.3)\n- validation core checks (§6.4 items 1,1a,1b,2,3,6)\n\n### 7.3.2 Profile: `recurrence`\n\nAdditional required capabilities:\n\n- tasknotes recurrence-string parsing/validation, including RRULE parameter syntax and inline `DTSTART` handling\n- recurrence anchor semantics, including seed precedence and completion-anchor progression\n- complete/uncomplete instance\n- skip/unskip instance\n- instance-list invariants and effective state resolution\n- validation checks for recurrence and instance overlap\n\n### 7.3.3 Profile: `templating` (non-cumulative extension)\n\nThis profile is not cumulative; it MAY be claimed alongside `core-lite`, `recurrence`, `materialized-occurrences`, and/or `extended`.\n`templating` MUST NOT be claimed alone.\n\nRequired capabilities:\n\n- create-time template processing semantics per §5.3.5\n- `templating` configuration support per §9.14\n- deterministic template/frontmatter/body merge behavior\n- deterministic failure-mode behavior for template read/parse failures\n- support for portable double-brace template variables defined in §5.3.5\n\n### 7.3.4 Profile: `materialized-occurrences` (non-cumulative extension)\n\nThis profile is not cumulative; it MUST be claimed alongside `recurrence`.\nIt MAY be claimed alongside `extended` and/or `templating`, but it does not require either.\n\nRequired capabilities:\n\n- materialized occurrence roles and identity semantics (§2.6.6)\n- recurrence materialization semantics (§4.18)\n- materialize/complete/skip/uncomplete/unskip materialized occurrence operations (§5.20)\n- `occurrences` configuration defaults (§9.17)\n- parent-reference link parsing/resolution for `recurrence_parent` (§11), without requiring full `extended`\n- validation checks for materialized occurrence identity, duplicates, and state conflicts (§6.4 items 16-18)\n\nClaiming `materialized-occurrences` also has required capability-token implications:\n\n- `meta.claim.capabilities` MUST include `materialized-occurrences`.\n- `meta.claim.profiles` MUST also include `recurrence`.\n- Omitting either token while claiming `materialized-occurrences` is a non-conformant claim.\n\n### 7.3.5 Profile: `extended`\n\nAdditional required capabilities:\n\n- dependency schema support (`blocked_by`)\n- reminder schema support (`reminders`)\n- link parsing/resolution semantics for link-bearing fields (§11)\n- time-tracking management semantics for `time_entries` (§5.19), including per-task active-session constraints\n- dependency operations and validation per §10.2\n- reminder operations and validation per §10.3\n\nIf `extended` is claimed, all of the above baseline capabilities MUST conform to documented semantics.\n\nClaiming `extended` also has required capability-token implications:\n\n- `meta.claim.capabilities` MUST include `dependencies`, `reminders`, `links`, and `time-tracking`.\n- Omitting any of these tokens while claiming `extended` is a non-conformant claim (even if capability-gated fixtures are skipped by a runner).\n\nOptional capability extensions within `extended`:\n\n- `rename` capability: reference-aware rename behavior (including dependency UID references)\n- `archive` capability: archive semantics (§5.12)\n- `batch` capability: batch operations with per-item outcomes (§5.15)\n- `concurrency` capability: write-conflict detection semantics (§5.16)\n- `dry-run` capability: dry-run semantics (§5.17)\n\nWhen an optional capability token is claimed, corresponding behavior MUST conform to documented semantics.\n\n## 7.4 Conformance claim format\n\nA conformance claim MUST include:\n\n- implementation name and version,\n- `tasknotes-spec` version,\n- claimed profile list,\n- validation mode support (`strict` required; `permissive` optional),\n- known deviations,\n- compatibility mode status (if any),\n- configuration provider status (active provider chain, precedence policy, and fallback state).\n\nExample:\n\n```text\nImplementation: example-task-cli v1.4.0\nSpec: tasknotes-spec 0.3.0-rc.3\nProfiles: core-lite, recurrence, templating\nValidation modes: strict, permissive\nKnown deviations: none\nCompatibility mode: disabled\nConfiguration providers: tasknotes_plugin_data_json > built_in_defaults\nConfiguration fallback: none\n```\n\n## 7.5 Deviation disclosure\n\nAny known deviation from normative text MUST be explicitly disclosed in conformance output/documentation.\n\nA deviation entry SHOULD include:\n\n- affected section,\n- deviation summary,\n- impact,\n- planned resolution version.\n\n## 7.6 Feature detection\n\nImplementations SHOULD expose machine-readable capability metadata, including:\n\n- profiles\n- effective runtime timezone\n- active configuration providers and precedence chain\n- enabled compatibility modes\n- configurable status sets\n- supported mapping aliases\n- templating support flags and effective templating failure mode\n- dependency and reminder support flags\n- attachment membership, reference normalization, and host-provided binary\n operation flags (including whether physical deletion is available)\n- time-tracking support flags, including active-session policy and auto-stop-on-complete behavior\n- materialized occurrence support flags, including materialization mode, next trigger, and rolling bounds\n- configured natural-language capture triggers when the optional `nlp` block is\n present\n\n## 7.7 Strictness disclosure\n\nConformance requires `strict` validation mode support (§6.3).\n\nConformance claims MUST indicate whether `permissive` mode is also supported.\n\n## 7.8 Example profile matrix\n\n| Capability | core-lite | recurrence | templating | materialized-occurrences | extended |\n|---|---:|---:|---:|---:|---:|\n| create/update/delete | required | required | companion-profile required | companion-profile required | required |\n| non-recurring complete | required | required | companion-profile required | companion-profile required | required |\n| recurring instance complete/skip | - | required | optional | required via companion `recurrence` claim | required |\n| materialize occurrence notes (§4.18, §5.20) | - | - | optional | required | optional |\n| recurrence parent link resolution | - | - | optional | required for `recurrence_parent` only | required |\n| template expansion/merge (§5.3.5) | - | - | required | optional | optional |\n| double-brace portable variable support | - | - | required | optional | optional |\n| recurrence-string validation | - | required | optional | required via companion `recurrence` claim | required |\n| link parsing/resolution (§11) | - | - | optional | required for `recurrence_parent` only | required |\n| attachment membership and ops (§5.21) | optional via `attachments` capability | optional via `attachments` capability | optional via `attachments` capability | optional via `attachments` capability | optional via `attachments` capability |\n| dependency schema and ops | - | - | optional | optional | required |\n| reminder schema and ops | - | - | optional | optional | required |\n| time tracking start/stop/edit semantics (§5.19) | - | - | optional | optional | required |\n| rename updates dependency/project links | - | - | optional | optional | optional via `rename` capability |\n| archive semantics (§5.12) | - | - | optional | optional | optional via `archive` capability |\n| batch per-item outcomes (§5.15) | - | - | optional | optional | optional via `batch` capability |\n| write-conflict detection (§5.16) | - | - | optional | optional | optional via `concurrency` capability |\n| dry-run reporting (§5.17) | - | - | optional | optional | optional via `dry-run` capability |\n\n## 7.9 Executable fixture suite\n\nThis specification includes an executable fixture suite in `conformance/`.\n\n- language-neutral fixtures are stored in `conformance/fixtures/*.json`\n- section/profile/operation coverage is tracked in `conformance/manifest.json`\n- coverage guard tests MUST enforce both section representation and minimum-depth thresholds for key sections/operations.\n- adapters execute fixture operations per `conformance/docs/ADAPTER_CONTRACT.md`\n- runners MUST execute fixtures only when both conditions hold:\n - fixture `profile` is satisfied by claimed adapter profiles under cumulative profile rules (§7.3),\n - all fixture `requires` capability tokens are present.\n\nFixture expectations MUST be profile-modular: they MUST NOT assume capability values or profile memberships beyond what the fixture's own `profile`/`requires` gating guarantees.\nFixtures for optional extension capabilities (`rename`, `archive`, `batch`, `concurrency`, `dry-run`) MUST be capability-gated via `requires` and MUST NOT rely on `extended` profile membership alone.\n\nConformance claims SHOULD report fixture pass/fail results against the claimed profiles.\n\n## 7.10 Meta operations\n\nThe following operations are part of the conformance interface and MUST be supported by any adapter that participates in the conformance suite, regardless of claimed profile. These meta operations MUST be callable without requiring any capability token.\n\n### `meta.claim`\n\nReturns the adapter's self-reported metadata.\n\nInput: `{}` (empty object)\n\nOutput:\n```json\n{\n \"ok\": true,\n \"result\": {\n \"implementation\": \"my-tool\",\n \"version\": \"1.0.0\",\n \"spec_version\": \"0.3.0-rc.3\",\n \"validation_modes\": [\"strict\"],\n \"profiles\": [\"core-lite\", \"recurrence\"],\n \"capabilities\": [\"dependencies\", \"links\"]\n }\n}\n```\n\nFields:\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `implementation` | string | yes | Human-readable implementation name |\n| `version` | string | yes | Implementation version string |\n| `spec_version` | string | yes | `tasknotes-spec` version targeted by this adapter |\n| `validation_modes` | string[] | yes | Supported validation modes; MUST include `strict` |\n| `profiles` | string[] | yes | Claimed conformance profiles; valid values: `core-lite`, `recurrence`, `extended`, `templating`, `materialized-occurrences` |\n| `capabilities` | string[] | yes | Optional capability tokens; known tokens listed in §7.11 |\n\n`profiles` lists explicitly claimed profiles. Cumulative profile expansion is applied by runners for fixture selection (§7.3, §7.9), but does not change literal membership semantics of `meta.has_profile`.\n\nProfile-token consistency rules:\n\n- If `profiles` contains `extended`, `capabilities` MUST include `dependencies`, `reminders`, `links`, and `time-tracking`.\n- If `profiles` contains `templating`, `capabilities` MUST include `templating`.\n- If `profiles` contains `materialized-occurrences`, `profiles` MUST also contain `recurrence` and `capabilities` MUST include `materialized-occurrences`.\n- Runners and fixture suites SHOULD validate these claim-consistency rules directly from `meta.claim`, not only by capability-gating feature fixtures.\n\n### `meta.has_capability`\n\nTests whether the adapter claims a specific capability.\n\nInput:\n```json\n{ \"capability\": \"dependencies\" }\n```\n\nOutput:\n```json\n{ \"ok\": true, \"result\": { \"value\": true } }\n```\n\n`result.value` MUST be `true` if the capability is in the `capabilities` array returned by `meta.claim`, and `false` otherwise.\n\n### `meta.has_profile`\n\nTests whether the adapter claims a specific conformance profile.\n\nInput:\n```json\n{ \"profile\": \"recurrence\" }\n```\n\nOutput:\n```json\n{ \"ok\": true, \"result\": { \"value\": true } }\n```\n\n`result.value` MUST be `true` if the profile is in the `profiles` array returned by `meta.claim`, and `false` otherwise.\n\n## 7.11 Known capability tokens\n\nThe following capability tokens are defined by this specification. Implementations MAY define additional tokens.\n\n| Token | Required by profile | Meaning |\n|---|---|---|\n| `dependencies` | `extended` | Supports `blocked_by`, dependency operations, and dependency validation |\n| `reminders` | `extended` | Supports `reminders`, reminder operations, and reminder validation |\n| `attachments` | optional extension under any profile | Treats the mapped `attachments` list as authoritative membership; validates and normalizes its collection-file references; and implements §5.21 attachment operations using host-owned binary storage. A claim MUST separately disclose which host file actions are available; it does not by itself promise physical deletion where the host cannot perform an authoritative reference check. |\n| `links` | `extended` | Supports link parsing and resolution (§11) |\n| `time-tracking` | `extended` | Supports time-tracking management operations (§5.19) |\n| `materialized-occurrences` | `materialized-occurrences` | Supports recurrence materialization and materialized occurrence operations (§4.18, §5.20) |\n| `rename` | optional extension under `extended` | Supports file rename with reference updates |\n| `archive` | optional extension under `extended` | Supports archive semantics (§5.12) |\n| `batch` | optional extension under `extended` | Supports batch operations with per-item outcomes (§5.15) |\n| `concurrency` | optional extension under `extended` | Supports write-conflict detection (§5.16) |\n| `dry-run` | optional extension under `extended` | Supports dry-run mode (§5.17) |\n| `migration` | — | Supports migration operations (§8) |\n| `templating` | `templating` | Supports create-time templating (§5.3.5) |\n","aliases":["/spec/07-conformance/"],"toc":[{"level":2,"id":"71-purpose","text":"7.1 Purpose"},{"level":2,"id":"72-conformance-principles","text":"7.2 Conformance principles"},{"level":2,"id":"73-profile-model","text":"7.3 Profile model"},{"level":3,"id":"731-profile-core-lite","text":"7.3.1 Profile: core-lite"},{"level":3,"id":"732-profile-recurrence","text":"7.3.2 Profile: recurrence"},{"level":3,"id":"733-profile-templating-non-cumulative-extension","text":"7.3.3 Profile: templating (non-cumulative extension)"},{"level":3,"id":"734-profile-materialized-occurrences-non-cumulative-extension","text":"7.3.4 Profile: materialized-occurrences (non-cumulative extension)"},{"level":3,"id":"735-profile-extended","text":"7.3.5 Profile: extended"},{"level":2,"id":"74-conformance-claim-format","text":"7.4 Conformance claim format"},{"level":2,"id":"75-deviation-disclosure","text":"7.5 Deviation disclosure"},{"level":2,"id":"76-feature-detection","text":"7.6 Feature detection"},{"level":2,"id":"77-strictness-disclosure","text":"7.7 Strictness disclosure"},{"level":2,"id":"78-example-profile-matrix","text":"7.8 Example profile matrix"},{"level":2,"id":"79-executable-fixture-suite","text":"7.9 Executable fixture suite"},{"level":2,"id":"710-meta-operations","text":"7.10 Meta operations"},{"level":3,"id":"metaclaim","text":"meta.claim"},{"level":3,"id":"metahascapability","text":"meta.has_capability"},{"level":3,"id":"metahasprofile","text":"meta.has_profile"},{"level":2,"id":"711-known-capability-tokens","text":"7.11 Known capability tokens"}],"html":"

7.1 Purpose#

\n

This section defines conformance profiles and claim requirements for implementations.

\n

7.2 Conformance principles#

\n

An implementation MUST NOT claim conformance to a profile unless all required capabilities of that profile are implemented.

\n

Implementations MAY implement additional behavior beyond a profile, but extra behavior MUST NOT violate profile requirements.

\n

7.3 Profile model#

\n

Profiles are cumulative unless explicitly marked otherwise.

\n

7.3.1 Profile: core-lite#

\n

Required capabilities:

\n
    \n
  • task identification and loading
  • \n
  • semantic-role mapping and canonical writes (§2)
  • \n
  • required role support (title, status, completed_date, date_created, date_modified)
  • \n
  • create, update, delete operations (§5)
  • \n
  • non-recurring complete/uncomplete (§5)
  • \n
  • temporal parsing/canonical serialization basics (§3)
  • \n
  • strict validation mode support (§6.3)
  • \n
  • validation core checks (§6.4 items 1,1a,1b,2,3,6)
  • \n
\n

7.3.2 Profile: recurrence#

\n

Additional required capabilities:

\n
    \n
  • tasknotes recurrence-string parsing/validation, including RRULE parameter syntax and inline DTSTART handling
  • \n
  • recurrence anchor semantics, including seed precedence and completion-anchor progression
  • \n
  • complete/uncomplete instance
  • \n
  • skip/unskip instance
  • \n
  • instance-list invariants and effective state resolution
  • \n
  • validation checks for recurrence and instance overlap
  • \n
\n

7.3.3 Profile: templating (non-cumulative extension)#

\n

This profile is not cumulative; it MAY be claimed alongside core-lite, recurrence, materialized-occurrences, and/or extended.\ntemplating MUST NOT be claimed alone.

\n

Required capabilities:

\n
    \n
  • create-time template processing semantics per §5.3.5
  • \n
  • templating configuration support per §9.14
  • \n
  • deterministic template/frontmatter/body merge behavior
  • \n
  • deterministic failure-mode behavior for template read/parse failures
  • \n
  • support for portable double-brace template variables defined in §5.3.5
  • \n
\n

7.3.4 Profile: materialized-occurrences (non-cumulative extension)#

\n

This profile is not cumulative; it MUST be claimed alongside recurrence.\nIt MAY be claimed alongside extended and/or templating, but it does not require either.

\n

Required capabilities:

\n
    \n
  • materialized occurrence roles and identity semantics (§2.6.6)
  • \n
  • recurrence materialization semantics (§4.18)
  • \n
  • materialize/complete/skip/uncomplete/unskip materialized occurrence operations (§5.20)
  • \n
  • occurrences configuration defaults (§9.17)
  • \n
  • parent-reference link parsing/resolution for recurrence_parent (§11), without requiring full extended
  • \n
  • validation checks for materialized occurrence identity, duplicates, and state conflicts (§6.4 items 16-18)
  • \n
\n

Claiming materialized-occurrences also has required capability-token implications:

\n
    \n
  • meta.claim.capabilities MUST include materialized-occurrences.
  • \n
  • meta.claim.profiles MUST also include recurrence.
  • \n
  • Omitting either token while claiming materialized-occurrences is a non-conformant claim.
  • \n
\n

7.3.5 Profile: extended#

\n

Additional required capabilities:

\n
    \n
  • dependency schema support (blocked_by)
  • \n
  • reminder schema support (reminders)
  • \n
  • link parsing/resolution semantics for link-bearing fields (§11)
  • \n
  • time-tracking management semantics for time_entries (§5.19), including per-task active-session constraints
  • \n
  • dependency operations and validation per §10.2
  • \n
  • reminder operations and validation per §10.3
  • \n
\n

If extended is claimed, all of the above baseline capabilities MUST conform to documented semantics.

\n

Claiming extended also has required capability-token implications:

\n
    \n
  • meta.claim.capabilities MUST include dependencies, reminders, links, and time-tracking.
  • \n
  • Omitting any of these tokens while claiming extended is a non-conformant claim (even if capability-gated fixtures are skipped by a runner).
  • \n
\n

Optional capability extensions within extended:

\n
    \n
  • rename capability: reference-aware rename behavior (including dependency UID references)
  • \n
  • archive capability: archive semantics (§5.12)
  • \n
  • batch capability: batch operations with per-item outcomes (§5.15)
  • \n
  • concurrency capability: write-conflict detection semantics (§5.16)
  • \n
  • dry-run capability: dry-run semantics (§5.17)
  • \n
\n

When an optional capability token is claimed, corresponding behavior MUST conform to documented semantics.

\n

7.4 Conformance claim format#

\n

A conformance claim MUST include:

\n
    \n
  • implementation name and version,
  • \n
  • tasknotes-spec version,
  • \n
  • claimed profile list,
  • \n
  • validation mode support (strict required; permissive optional),
  • \n
  • known deviations,
  • \n
  • compatibility mode status (if any),
  • \n
  • configuration provider status (active provider chain, precedence policy, and fallback state).
  • \n
\n

Example:

\n
Implementation: example-task-cli v1.4.0\nSpec: tasknotes-spec 0.3.0-rc.3\nProfiles: core-lite, recurrence, templating\nValidation modes: strict, permissive\nKnown deviations: none\nCompatibility mode: disabled\nConfiguration providers: tasknotes_plugin_data_json > built_in_defaults\nConfiguration fallback: none\n

7.5 Deviation disclosure#

\n

Any known deviation from normative text MUST be explicitly disclosed in conformance output/documentation.

\n

A deviation entry SHOULD include:

\n
    \n
  • affected section,
  • \n
  • deviation summary,
  • \n
  • impact,
  • \n
  • planned resolution version.
  • \n
\n

7.6 Feature detection#

\n

Implementations SHOULD expose machine-readable capability metadata, including:

\n
    \n
  • profiles
  • \n
  • effective runtime timezone
  • \n
  • active configuration providers and precedence chain
  • \n
  • enabled compatibility modes
  • \n
  • configurable status sets
  • \n
  • supported mapping aliases
  • \n
  • templating support flags and effective templating failure mode
  • \n
  • dependency and reminder support flags
  • \n
  • attachment membership, reference normalization, and host-provided binary\noperation flags (including whether physical deletion is available)
  • \n
  • time-tracking support flags, including active-session policy and auto-stop-on-complete behavior
  • \n
  • materialized occurrence support flags, including materialization mode, next trigger, and rolling bounds
  • \n
  • configured natural-language capture triggers when the optional nlp block is\npresent
  • \n
\n

7.7 Strictness disclosure#

\n

Conformance requires strict validation mode support (§6.3).

\n

Conformance claims MUST indicate whether permissive mode is also supported.

\n

7.8 Example profile matrix#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Capabilitycore-literecurrencetemplatingmaterialized-occurrencesextended
create/update/deleterequiredrequiredcompanion-profile requiredcompanion-profile requiredrequired
non-recurring completerequiredrequiredcompanion-profile requiredcompanion-profile requiredrequired
recurring instance complete/skip-requiredoptionalrequired via companion recurrence claimrequired
materialize occurrence notes (§4.18, §5.20)--optionalrequiredoptional
recurrence parent link resolution--optionalrequired for recurrence_parent onlyrequired
template expansion/merge (§5.3.5)--requiredoptionaloptional
double-brace portable variable support--requiredoptionaloptional
recurrence-string validation-requiredoptionalrequired via companion recurrence claimrequired
link parsing/resolution (§11)--optionalrequired for recurrence_parent onlyrequired
attachment membership and ops (§5.21)optional via attachments capabilityoptional via attachments capabilityoptional via attachments capabilityoptional via attachments capabilityoptional via attachments capability
dependency schema and ops--optionaloptionalrequired
reminder schema and ops--optionaloptionalrequired
time tracking start/stop/edit semantics (§5.19)--optionaloptionalrequired
rename updates dependency/project links--optionaloptionaloptional via rename capability
archive semantics (§5.12)--optionaloptionaloptional via archive capability
batch per-item outcomes (§5.15)--optionaloptionaloptional via batch capability
write-conflict detection (§5.16)--optionaloptionaloptional via concurrency capability
dry-run reporting (§5.17)--optionaloptionaloptional via dry-run capability
\n

7.9 Executable fixture suite#

\n

This specification includes an executable fixture suite in conformance/.

\n
    \n
  • language-neutral fixtures are stored in conformance/fixtures/*.json
  • \n
  • section/profile/operation coverage is tracked in conformance/manifest.json
  • \n
  • coverage guard tests MUST enforce both section representation and minimum-depth thresholds for key sections/operations.
  • \n
  • adapters execute fixture operations per conformance/docs/ADAPTER_CONTRACT.md
  • \n
  • runners MUST execute fixtures only when both conditions hold:
      \n
    • fixture profile is satisfied by claimed adapter profiles under cumulative profile rules (§7.3),
    • \n
    • all fixture requires capability tokens are present.
    • \n
    \n
  • \n
\n

Fixture expectations MUST be profile-modular: they MUST NOT assume capability values or profile memberships beyond what the fixture's own profile/requires gating guarantees.\nFixtures for optional extension capabilities (rename, archive, batch, concurrency, dry-run) MUST be capability-gated via requires and MUST NOT rely on extended profile membership alone.

\n

Conformance claims SHOULD report fixture pass/fail results against the claimed profiles.

\n

7.10 Meta operations#

\n

The following operations are part of the conformance interface and MUST be supported by any adapter that participates in the conformance suite, regardless of claimed profile. These meta operations MUST be callable without requiring any capability token.

\n

meta.claim#

\n

Returns the adapter's self-reported metadata.

\n

Input: {} (empty object)

\n

Output:

\n
{\n  "ok": true,\n  "result": {\n    "implementation": "my-tool",\n    "version": "1.0.0",\n    "spec_version": "0.3.0-rc.3",\n    "validation_modes": ["strict"],\n    "profiles": ["core-lite", "recurrence"],\n    "capabilities": ["dependencies", "links"]\n  }\n}\n

Fields:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
FieldTypeRequiredDescription
implementationstringyesHuman-readable implementation name
versionstringyesImplementation version string
spec_versionstringyestasknotes-spec version targeted by this adapter
validation_modesstring[]yesSupported validation modes; MUST include strict
profilesstring[]yesClaimed conformance profiles; valid values: core-lite, recurrence, extended, templating, materialized-occurrences
capabilitiesstring[]yesOptional capability tokens; known tokens listed in §7.11
\n

profiles lists explicitly claimed profiles. Cumulative profile expansion is applied by runners for fixture selection (§7.3, §7.9), but does not change literal membership semantics of meta.has_profile.

\n

Profile-token consistency rules:

\n
    \n
  • If profiles contains extended, capabilities MUST include dependencies, reminders, links, and time-tracking.
  • \n
  • If profiles contains templating, capabilities MUST include templating.
  • \n
  • If profiles contains materialized-occurrences, profiles MUST also contain recurrence and capabilities MUST include materialized-occurrences.
  • \n
  • Runners and fixture suites SHOULD validate these claim-consistency rules directly from meta.claim, not only by capability-gating feature fixtures.
  • \n
\n

meta.has_capability#

\n

Tests whether the adapter claims a specific capability.

\n

Input:

\n
{ "capability": "dependencies" }\n

Output:

\n
{ "ok": true, "result": { "value": true } }\n

result.value MUST be true if the capability is in the capabilities array returned by meta.claim, and false otherwise.

\n

meta.has_profile#

\n

Tests whether the adapter claims a specific conformance profile.

\n

Input:

\n
{ "profile": "recurrence" }\n

Output:

\n
{ "ok": true, "result": { "value": true } }\n

result.value MUST be true if the profile is in the profiles array returned by meta.claim, and false otherwise.

\n

7.11 Known capability tokens#

\n

The following capability tokens are defined by this specification. Implementations MAY define additional tokens.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
TokenRequired by profileMeaning
dependenciesextendedSupports blocked_by, dependency operations, and dependency validation
remindersextendedSupports reminders, reminder operations, and reminder validation
attachmentsoptional extension under any profileTreats the mapped attachments list as authoritative membership; validates and normalizes its collection-file references; and implements §5.21 attachment operations using host-owned binary storage. A claim MUST separately disclose which host file actions are available; it does not by itself promise physical deletion where the host cannot perform an authoritative reference check.
linksextendedSupports link parsing and resolution (§11)
time-trackingextendedSupports time-tracking management operations (§5.19)
materialized-occurrencesmaterialized-occurrencesSupports recurrence materialization and materialized occurrence operations (§4.18, §5.20)
renameoptional extension under extendedSupports file rename with reference updates
archiveoptional extension under extendedSupports archive semantics (§5.12)
batchoptional extension under extendedSupports batch operations with per-item outcomes (§5.15)
concurrencyoptional extension under extendedSupports write-conflict detection (§5.16)
dry-runoptional extension under extendedSupports dry-run mode (§5.17)
migration—Supports migration operations (§8)
templatingtemplatingSupports create-time templating (§5.3.5)
\n","text":"7.1 Purpose# This section defines conformance profiles and claim requirements for implementations. 7.2 Conformance principles# An implementation MUST NOT claim conformance to a profile unless all required capabilities of that profile are implemented. Implementations MAY implement additional behavior beyond a profile, but extra behavior MUST NOT violate profile requirements. 7.3 Profile model# Profiles are cumulative unless explicitly marked otherwise. 7.3.1 Profile: core-lite# Required capabilities: task identification and loading semantic-role mapping and canonical writes (§2) required role support (title, status, completed_date, date_created, date_modified) create, update, delete operations (§5) non-recurring complete/uncomplete (§5) temporal parsing/canonical serialization basics (§3) strict validation mode support (§6.3) validation core checks (§6.4 items 1,1a,1b,2,3,6) 7.3.2 Profile: recurrence# Additional required capabilities: tasknotes recurrence-string parsing/validation, including RRULE parameter syntax and inline DTSTART handling recurrence anchor semantics, including seed precedence and completion-anchor progression complete/uncomplete instance skip/unskip instance instance-list invariants and effective state resolution validation checks for recurrence and instance overlap 7.3.3 Profile: templating (non-cumulative extension)# This profile is not cumulative; it MAY be claimed alongside core-lite, recurrence, materialized-occurrences, and/or extended. templating MUST NOT be claimed alone. Required capabilities: create-time template processing semantics per §5.3.5 templating configuration support per §9.14 deterministic template/frontmatter/body merge behavior deterministic failure-mode behavior for template read/parse failures support for portable double-brace template variables defined in §5.3.5 7.3.4 Profile: materialized-occurrences (non-cumulative extension)# This profile is not cumulative; it MUST be claimed alongside recurrence. It MAY be claimed alongside extended and/or templating, but it does not require either. Required capabilities: materialized occurrence roles and identity semantics (§2.6.6) recurrence materialization semantics (§4.18) materialize/complete/skip/uncomplete/unskip materialized occurrence operations (§5.20) occurrences configuration defaults (§9.17) parent-reference link parsing/resolution for recurrence_parent (§11), without requiring full extended validation checks for materialized occurrence identity, duplicates, and state conflicts (§6.4 items 16-18) Claiming materialized-occurrences also has required capability-token implications: meta.claim.capabilities MUST include materialized-occurrences. meta.claim.profiles MUST also include recurrence. Omitting either token while claiming materialized-occurrences is a non-conformant claim. 7.3.5 Profile: extended# Additional required capabilities: dependency schema support (blocked_by) reminder schema support (reminders) link parsing/resolution semantics for link-bearing fields (§11) time-tracking management semantics for time_entries (§5.19), including per-task active-session constraints dependency operations and validation per §10.2 reminder operations and validation per §10.3 If extended is claimed, all of the above baseline capabilities MUST conform to documented semantics. Claiming extended also has required capability-token implications: meta.claim.capabilities MUST include dependencies, reminders, links, and time-tracking. Omitting any of these tokens while claiming extended is a non-conformant claim (even if capability-gated fixtures are skipped by a runner). Optional capability extensions within extended: rename capability: reference-aware rename behavior (including dependency UID references) archive capability: archive semantics (§5.12) batch capability: batch operations with per-item outcomes (§5.15) concurrency capability: write-conflict detection semantics (§5.16) dry-run capability: dry-run semantics (§5.17) When an optional capability token is claimed, corresponding behavior MUST conform to documented semantics. 7.4 Conformance claim format# A conformance claim MUST include: implementation name and version, tasknotes-spec version, claimed profile list, validation mode support (strict required; permissive optional), known deviations, compatibility mode status (if any), configuration provider status (active provider chain, precedence policy, and fallback state). Example: Implementation: example-task-cli v1.4.0 Spec: tasknotes-spec 0.3.0-rc.3 Profiles: core-lite, recurrence, templating Validation modes: strict, permissive Known deviations: none Compatibility mode: disabled Configuration providers: tasknotes_plugin_data_json > built_in_defaults Configuration fallback: none 7.5 Deviation disclosure# Any known deviation from normative text MUST be explicitly disclosed in conformance output/documentation. A deviation entry SHOULD include: affected section, deviation summary, impact, planned resolution version. 7.6 Feature detection# Implementations SHOULD expose machine-readable capability metadata, including: profiles effective runtime timezone active configuration providers and precedence chain enabled compatibility modes configurable status sets supported mapping aliases templating support flags and effective templating failure mode dependency and reminder support flags attachment membership, reference normalization, and host-provided binary operation flags (including whether physical deletion is available) time-tracking support flags, including active-session policy and auto-stop-on-complete behavior materialized occurrence support flags, including materialization mode, next trigger, and rolling bounds configured natural-language capture triggers when the optional nlp block is present 7.7 Strictness disclosure# Conformance requires strict validation mode support (§6.3). Conformance claims MUST indicate whether permissive mode is also supported. 7.8 Example profile matrix# Capability core-lite recurrence templating materialized-occurrences extended create/update/delete required required companion-profile required companion-profile required required non-recurring complete required required companion-profile required companion-profile required required recurring instance complete/skip - required optional required via companion recurrence claim required materialize occurrence notes (§4.18, §5.20) - - optional required optional recurrence parent link resolution - - optional required for recurrence_parent only required template expansion/merge (§5.3.5) - - required optional optional double-brace portable variable support - - required optional optional recurrence-string validation - required optional required via companion recurrence claim required link parsing/resolution (§11) - - optional required for recurrence_parent only required attachment membership and ops (§5.21) optional via attachments capability optional via attachments capability optional via attachments capability optional via attachments capability optional via attachments capability dependency schema and ops - - optional optional required reminder schema and ops - - optional optional required time tracking start/stop/edit semantics (§5.19) - - optional optional required rename updates dependency/project links - - optional optional optional via rename capability archive semantics (§5.12) - - optional optional optional via archive capability batch per-item outcomes (§5.15) - - optional optional optional via batch capability write-conflict detection (§5.16) - - optional optional optional via concurrency capability dry-run reporting (§5.17) - - optional optional optional via dry-run capability 7.9 Executable fixture suite# This specification includes an executable fixture suite in conformance/. language-neutral fixtures are stored in conformance/fixtures/*.json section/profile/operation coverage is tracked in conformance/manifest.json coverage guard tests MUST enforce both section representation and minimum-depth thresholds for key sections/operations. adapters execute fixture operations per conformance/docs/ADAPTER_CONTRACT.md runners MUST execute fixtures only when both conditions hold: fixture profile is satisfied by claimed adapter profiles under cumulative profile rules (§7.3), all fixture requires capability tokens are present. Fixture expectations MUST be profile-modular: they MUST NOT assume capability values or profile memberships beyond what the fixture's own profile/requires gating guarantees. Fixtures for optional extension capabilities (rename, archive, batch, concurrency, dry-run) MUST be capability-gated via requires and MUST NOT rely on extended profile membership alone. Conformance claims SHOULD report fixture pass/fail results against the claimed profiles. 7.10 Meta operations# The following operations are part of the conformance interface and MUST be supported by any adapter that participates in the conformance suite, regardless of claimed profile. These meta operations MUST be callable without requiring any capability token. meta.claim# Returns the adapter's self-reported metadata. Input: {} (empty object) Output: { \"ok\": true, \"result\": { \"implementation\": \"my-tool\", \"version\": \"1.0.0\", \"spec_version\": \"0.3.0-rc.3\", \"validation_modes\": [\"strict\"], \"profiles\": [\"core-lite\", \"recurrence\"], \"capabilities\": [\"dependencies\", \"links\"] } } Fields: Field Type Required Description implementation string yes Human-readable implementation name version string yes Implementation version string spec_version string yes tasknotes-spec version targeted by this adapter validation_modes string[] yes Supported validation modes; MUST include strict profiles string[] yes Claimed conformance profiles; valid values: core-lite, recurrence, extended, templating, materialized-occurrences capabilities string[] yes Optional capability tokens; known tokens listed in §7.11 profiles lists explicitly claimed profiles. Cumulative profile expansion is applied by runners for fixture selection (§7.3, §7.9), but does not change literal membership semantics of meta.has_profile. Profile-token consistency rules: If profiles contains extended, capabilities MUST include dependencies, reminders, links, and time-tracking. If profiles contains templating, capabilities MUST include templating. If profiles contains materialized-occurrences, profiles MUST also contain recurrence and capabilities MUST include materialized-occurrences. Runners and fixture suites SHOULD validate these claim-consistency rules directly from meta.claim, not only by capability-gating feature fixtures. meta.has_capability# Tests whether the adapter claims a specific capability. Input: { \"capability\": \"dependencies\" } Output: { \"ok\": true, \"result\": { \"value\": true } } result.value MUST be true if the capability is in the capabilities array returned by meta.claim, and false otherwise. meta.has_profile# Tests whether the adapter claims a specific conformance profile. Input: { \"profile\": \"recurrence\" } Output: { \"ok\": true, \"result\": { \"value\": true } } result.value MUST be true if the profile is in the profiles array returned by meta.claim, and false otherwise. 7.11 Known capability tokens# The following capability tokens are defined by this specification. Implementations MAY define additional tokens. Token Required by profile Meaning dependencies extended Supports blocked_by, dependency operations, and dependency validation reminders extended Supports reminders, reminder operations, and reminder validation attachments optional extension under any profile Treats the mapped attachments list as authoritative membership; validates and normalizes its collection-file references; and implements §5.21 attachment operations using host-owned binary storage. A claim MUST separately disclose which host file actions are available; it does not by itself promise physical deletion where the host cannot perform an authoritative reference check. links extended Supports link parsing and resolution (§11) time-tracking extended Supports time-tracking management operations (§5.19) materialized-occurrences materialized-occurrences Supports recurrence materialization and materialized occurrence operations (§4.18, §5.20) rename optional extension under extended Supports file rename with reference updates archive optional extension under extended Supports archive semantics (§5.12) batch optional extension under extended Supports batch operations with per-item outcomes (§5.15) concurrency optional extension under extended Supports write-conflict detection (§5.16) dry-run optional extension under extended Supports dry-run mode (§5.17) migration — Supports migration operations (§8) templating templating Supports create-time templating (§5.3.5)"},{"route":"/developers/specification/08-compatibility-and-migrations/","title":"8. Compatibility and Migrations","description":"This section defines how implementations transition from historical behavior to canonical specification behavior without silent data breakage.","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:08-compatibility-and-migrations.md","namespace":"specification","relativePath":"08-compatibility-and-migrations.md","raw":"# 8. Compatibility and Migrations\n\n## 8.1 Purpose\n\nThis section defines how implementations transition from historical behavior to canonical specification behavior without silent data breakage.\n\n## 8.2 Compatibility modes\n\nImplementations MAY support compatibility modes for legacy behavior.\n\nIf supported, compatibility modes MUST:\n\n- be explicitly enabled or disabled,\n- be discoverable through configuration or capability metadata,\n- not be silently enabled by default in new collections.\n\n## 8.3 Migration expectations\n\nWhen canonical behavior differs from historical behavior, implementations SHOULD provide:\n\n1. deterministic migration rules,\n2. dry-run preview support,\n3. rollback-safe workflow guidance.\n\n## 8.4 Alias normalization migration\n\nFor legacy key aliases, a migration SHOULD:\n\n- read both canonical and alias keys,\n- choose canonical value deterministically (recommended: canonical key precedence),\n- rewrite persisted file using canonical keys,\n- preserve unrelated unknown fields.\n\n### 8.4.1 Example\n\nBefore:\n\n```yaml\nrecurrenceAnchor: scheduled\nrecurrence_anchor: completion\n```\n\nAfter normalization:\n\n```yaml\nrecurrenceAnchor: scheduled\n```\n\nWith warning:\n\n- `alias_conflict_ignored`: alias value ignored because canonical key present.\n\n## 8.5 Temporal normalization migration\n\nIf historical writes include mixed datetime styles, migration SHOULD normalize to canonical UTC ISO `Z` for datetime roles while preserving date-only roles as dates.\n\nExample:\n\nBefore:\n\n```yaml\ndateCreated: 2026-02-20 10:00:00+00:00\n```\n\nAfter:\n\n```yaml\ndateCreated: 2026-02-20T10:00:00Z\n```\n\n## 8.6 Recurrence state migration\n\nIf historical data allows overlapping complete/skip dates, migration MUST resolve overlap deterministically.\n\nRecommended resolution policy:\n\n- if overlap exists, prefer most recent user action where recoverable,\n- otherwise prefer `complete_instances` and remove overlapping skip entries,\n- emit migration report for affected dates.\n\nPolicy choice MUST be documented.\n\n## 8.7 Materialized occurrence migration\n\nWhen introducing materialized occurrence notes into an existing collection, implementations SHOULD avoid automatic bulk creation.\nRecommended migration behavior:\n\n- do not materialize historical or future occurrence notes unless explicitly requested;\n- preserve existing parent `complete_instances` and `skipped_instances`;\n- when importing existing per-occurrence task files, require deterministic parent/date matching before adding `recurrence_parent` and `occurrence_date`;\n- when materialized occurrence state conflicts with parent instance lists, prefer the occurrence note for that date and report `occurrence_state_conflict`;\n- provide a dry-run report before converting existing task files into materialized occurrence notes.\n\nMigration tooling MUST NOT silently delete occurrence notes or parent recurring tasks.\n\n## 8.8 Dependency migration\n\nWhen migrating legacy dependency data, implementations SHOULD:\n\n- normalize dependency key names to mapped canonical key,\n- ensure each entry has `uid` and canonical `reltype`,\n- normalize legacy string/path references into configured canonical reference style,\n- remove duplicate dependency entries by policy.\n\nIf historical data omits `reltype`, migration MAY apply `dependencies.default_reltype` and SHOULD report count of inferred values.\n\n## 8.9 Reminder migration\n\nWhen migrating legacy reminder data, implementations SHOULD:\n\n- normalize reminder key names,\n- normalize `type` values to canonical enum (`absolute` or `relative`),\n- normalize `relatedTo` values to canonical enum (`due` or `scheduled`),\n- normalize `absoluteTime` to canonical UTC ISO `Z`,\n- validate and normalize offsets to ISO 8601 duration syntax.\n\nIf reminder `id` values are missing, migration MAY generate IDs and MUST report generated count.\n\n## 8.10 Link migration\n\nWhen migrating legacy link values, implementations SHOULD:\n\n- normalize supported link syntaxes according to §11 parsing rules,\n- preserve alias and anchor components where possible,\n- normalize resolved targets into canonical write format by policy,\n- detect and report ambiguous links instead of silently choosing non-deterministically.\n\n## 8.11 Divergence register\n\nImplementations SHOULD maintain a divergence register with columns:\n\n- section\n- current behavior\n- target canonical behavior\n- migration strategy\n- deprecation timeline\n\n## 8.12 Deprecation policy\n\nFor any behavior deprecated by the specification:\n\n1. announce deprecation in release notes,\n2. provide warning period,\n3. provide migration tooling where feasible,\n4. remove deprecated behavior only in a version aligned with compatibility commitments.\n\n## 8.13 Data safety requirements\n\nMigrations MUST NOT:\n\n- silently drop unknown fields,\n- silently convert valid date-only fields to datetime,\n- silently rewrite recurrence semantics without explicit policy,\n- silently materialize occurrence notes outside explicit user/configured materialization policy,\n- silently delete materialized occurrence notes during recurrence edits,\n- silently drop unresolved dependency entries,\n- silently rewrite link targets to different destinations without explicit policy,\n- silently delete reminders unless explicitly requested.\n\n## 8.14 Suggested migration report format\n\n```yaml\nspec_version_from: 0.1.0-draft\nspec_version_to: 0.3.0-rc.3\nfiles_scanned: 214\nfiles_changed: 67\nwarnings:\n alias_conflict_ignored: 3\n instance_state_overlap_resolved: 2\n occurrence_state_conflict: 1\n unresolved_dependency_target: 4\nchanges:\n normalized_datetime_fields: 41\n alias_keys_removed: 29\n instance_overlaps_fixed: 2\n occurrence_state_conflicts: 1\n inferred_dependency_reltype: 5\n generated_reminder_ids: 8\n normalized_link_targets: 14\n```\n\n## 8.15 Compatibility statement example\n\n```text\nCompatibility mode: legacy-aliases=true, legacy-timeentry-duration=true\nPlanned removal: v2.0.0\nMigration command: tasknotes migrate --normalize-frontmatter\n```\n","aliases":["/spec/08-compatibility-and-migrations/"],"toc":[{"level":2,"id":"81-purpose","text":"8.1 Purpose"},{"level":2,"id":"82-compatibility-modes","text":"8.2 Compatibility modes"},{"level":2,"id":"83-migration-expectations","text":"8.3 Migration expectations"},{"level":2,"id":"84-alias-normalization-migration","text":"8.4 Alias normalization migration"},{"level":3,"id":"841-example","text":"8.4.1 Example"},{"level":2,"id":"85-temporal-normalization-migration","text":"8.5 Temporal normalization migration"},{"level":2,"id":"86-recurrence-state-migration","text":"8.6 Recurrence state migration"},{"level":2,"id":"87-materialized-occurrence-migration","text":"8.7 Materialized occurrence migration"},{"level":2,"id":"88-dependency-migration","text":"8.8 Dependency migration"},{"level":2,"id":"89-reminder-migration","text":"8.9 Reminder migration"},{"level":2,"id":"810-link-migration","text":"8.10 Link migration"},{"level":2,"id":"811-divergence-register","text":"8.11 Divergence register"},{"level":2,"id":"812-deprecation-policy","text":"8.12 Deprecation policy"},{"level":2,"id":"813-data-safety-requirements","text":"8.13 Data safety requirements"},{"level":2,"id":"814-suggested-migration-report-format","text":"8.14 Suggested migration report format"},{"level":2,"id":"815-compatibility-statement-example","text":"8.15 Compatibility statement example"}],"html":"

8.1 Purpose#

\n

This section defines how implementations transition from historical behavior to canonical specification behavior without silent data breakage.

\n

8.2 Compatibility modes#

\n

Implementations MAY support compatibility modes for legacy behavior.

\n

If supported, compatibility modes MUST:

\n
    \n
  • be explicitly enabled or disabled,
  • \n
  • be discoverable through configuration or capability metadata,
  • \n
  • not be silently enabled by default in new collections.
  • \n
\n

8.3 Migration expectations#

\n

When canonical behavior differs from historical behavior, implementations SHOULD provide:

\n
    \n
  1. deterministic migration rules,
  2. \n
  3. dry-run preview support,
  4. \n
  5. rollback-safe workflow guidance.
  6. \n
\n

8.4 Alias normalization migration#

\n

For legacy key aliases, a migration SHOULD:

\n
    \n
  • read both canonical and alias keys,
  • \n
  • choose canonical value deterministically (recommended: canonical key precedence),
  • \n
  • rewrite persisted file using canonical keys,
  • \n
  • preserve unrelated unknown fields.
  • \n
\n

8.4.1 Example#

\n

Before:

\n
recurrenceAnchor: scheduled\nrecurrence_anchor: completion\n

After normalization:

\n
recurrenceAnchor: scheduled\n

With warning:

\n
    \n
  • alias_conflict_ignored: alias value ignored because canonical key present.
  • \n
\n

8.5 Temporal normalization migration#

\n

If historical writes include mixed datetime styles, migration SHOULD normalize to canonical UTC ISO Z for datetime roles while preserving date-only roles as dates.

\n

Example:

\n

Before:

\n
dateCreated: 2026-02-20 10:00:00+00:00\n

After:

\n
dateCreated: 2026-02-20T10:00:00Z\n

8.6 Recurrence state migration#

\n

If historical data allows overlapping complete/skip dates, migration MUST resolve overlap deterministically.

\n

Recommended resolution policy:

\n
    \n
  • if overlap exists, prefer most recent user action where recoverable,
  • \n
  • otherwise prefer complete_instances and remove overlapping skip entries,
  • \n
  • emit migration report for affected dates.
  • \n
\n

Policy choice MUST be documented.

\n

8.7 Materialized occurrence migration#

\n

When introducing materialized occurrence notes into an existing collection, implementations SHOULD avoid automatic bulk creation.\nRecommended migration behavior:

\n
    \n
  • do not materialize historical or future occurrence notes unless explicitly requested;
  • \n
  • preserve existing parent complete_instances and skipped_instances;
  • \n
  • when importing existing per-occurrence task files, require deterministic parent/date matching before adding recurrence_parent and occurrence_date;
  • \n
  • when materialized occurrence state conflicts with parent instance lists, prefer the occurrence note for that date and report occurrence_state_conflict;
  • \n
  • provide a dry-run report before converting existing task files into materialized occurrence notes.
  • \n
\n

Migration tooling MUST NOT silently delete occurrence notes or parent recurring tasks.

\n

8.8 Dependency migration#

\n

When migrating legacy dependency data, implementations SHOULD:

\n
    \n
  • normalize dependency key names to mapped canonical key,
  • \n
  • ensure each entry has uid and canonical reltype,
  • \n
  • normalize legacy string/path references into configured canonical reference style,
  • \n
  • remove duplicate dependency entries by policy.
  • \n
\n

If historical data omits reltype, migration MAY apply dependencies.default_reltype and SHOULD report count of inferred values.

\n

8.9 Reminder migration#

\n

When migrating legacy reminder data, implementations SHOULD:

\n
    \n
  • normalize reminder key names,
  • \n
  • normalize type values to canonical enum (absolute or relative),
  • \n
  • normalize relatedTo values to canonical enum (due or scheduled),
  • \n
  • normalize absoluteTime to canonical UTC ISO Z,
  • \n
  • validate and normalize offsets to ISO 8601 duration syntax.
  • \n
\n

If reminder id values are missing, migration MAY generate IDs and MUST report generated count.

\n\n

When migrating legacy link values, implementations SHOULD:

\n
    \n
  • normalize supported link syntaxes according to §11 parsing rules,
  • \n
  • preserve alias and anchor components where possible,
  • \n
  • normalize resolved targets into canonical write format by policy,
  • \n
  • detect and report ambiguous links instead of silently choosing non-deterministically.
  • \n
\n

8.11 Divergence register#

\n

Implementations SHOULD maintain a divergence register with columns:

\n
    \n
  • section
  • \n
  • current behavior
  • \n
  • target canonical behavior
  • \n
  • migration strategy
  • \n
  • deprecation timeline
  • \n
\n

8.12 Deprecation policy#

\n

For any behavior deprecated by the specification:

\n
    \n
  1. announce deprecation in release notes,
  2. \n
  3. provide warning period,
  4. \n
  5. provide migration tooling where feasible,
  6. \n
  7. remove deprecated behavior only in a version aligned with compatibility commitments.
  8. \n
\n

8.13 Data safety requirements#

\n

Migrations MUST NOT:

\n
    \n
  • silently drop unknown fields,
  • \n
  • silently convert valid date-only fields to datetime,
  • \n
  • silently rewrite recurrence semantics without explicit policy,
  • \n
  • silently materialize occurrence notes outside explicit user/configured materialization policy,
  • \n
  • silently delete materialized occurrence notes during recurrence edits,
  • \n
  • silently drop unresolved dependency entries,
  • \n
  • silently rewrite link targets to different destinations without explicit policy,
  • \n
  • silently delete reminders unless explicitly requested.
  • \n
\n

8.14 Suggested migration report format#

\n
spec_version_from: 0.1.0-draft\nspec_version_to: 0.3.0-rc.3\nfiles_scanned: 214\nfiles_changed: 67\nwarnings:\n  alias_conflict_ignored: 3\n  instance_state_overlap_resolved: 2\n  occurrence_state_conflict: 1\n  unresolved_dependency_target: 4\nchanges:\n  normalized_datetime_fields: 41\n  alias_keys_removed: 29\n  instance_overlaps_fixed: 2\n  occurrence_state_conflicts: 1\n  inferred_dependency_reltype: 5\n  generated_reminder_ids: 8\n  normalized_link_targets: 14\n

8.15 Compatibility statement example#

\n
Compatibility mode: legacy-aliases=true, legacy-timeentry-duration=true\nPlanned removal: v2.0.0\nMigration command: tasknotes migrate --normalize-frontmatter\n
","text":"8.1 Purpose# This section defines how implementations transition from historical behavior to canonical specification behavior without silent data breakage. 8.2 Compatibility modes# Implementations MAY support compatibility modes for legacy behavior. If supported, compatibility modes MUST: be explicitly enabled or disabled, be discoverable through configuration or capability metadata, not be silently enabled by default in new collections. 8.3 Migration expectations# When canonical behavior differs from historical behavior, implementations SHOULD provide: deterministic migration rules, dry-run preview support, rollback-safe workflow guidance. 8.4 Alias normalization migration# For legacy key aliases, a migration SHOULD: read both canonical and alias keys, choose canonical value deterministically (recommended: canonical key precedence), rewrite persisted file using canonical keys, preserve unrelated unknown fields. 8.4.1 Example# Before: recurrenceAnchor: scheduled recurrence_anchor: completion After normalization: recurrenceAnchor: scheduled With warning: alias_conflict_ignored: alias value ignored because canonical key present. 8.5 Temporal normalization migration# If historical writes include mixed datetime styles, migration SHOULD normalize to canonical UTC ISO Z for datetime roles while preserving date-only roles as dates. Example: Before: dateCreated: 2026-02-20 10:00:00+00:00 After: dateCreated: 2026-02-20T10:00:00Z 8.6 Recurrence state migration# If historical data allows overlapping complete/skip dates, migration MUST resolve overlap deterministically. Recommended resolution policy: if overlap exists, prefer most recent user action where recoverable, otherwise prefer complete_instances and remove overlapping skip entries, emit migration report for affected dates. Policy choice MUST be documented. 8.7 Materialized occurrence migration# When introducing materialized occurrence notes into an existing collection, implementations SHOULD avoid automatic bulk creation. Recommended migration behavior: do not materialize historical or future occurrence notes unless explicitly requested; preserve existing parent complete_instances and skipped_instances; when importing existing per-occurrence task files, require deterministic parent/date matching before adding recurrence_parent and occurrence_date; when materialized occurrence state conflicts with parent instance lists, prefer the occurrence note for that date and report occurrence_state_conflict; provide a dry-run report before converting existing task files into materialized occurrence notes. Migration tooling MUST NOT silently delete occurrence notes or parent recurring tasks. 8.8 Dependency migration# When migrating legacy dependency data, implementations SHOULD: normalize dependency key names to mapped canonical key, ensure each entry has uid and canonical reltype, normalize legacy string/path references into configured canonical reference style, remove duplicate dependency entries by policy. If historical data omits reltype, migration MAY apply dependencies.default_reltype and SHOULD report count of inferred values. 8.9 Reminder migration# When migrating legacy reminder data, implementations SHOULD: normalize reminder key names, normalize type values to canonical enum (absolute or relative), normalize relatedTo values to canonical enum (due or scheduled), normalize absoluteTime to canonical UTC ISO Z, validate and normalize offsets to ISO 8601 duration syntax. If reminder id values are missing, migration MAY generate IDs and MUST report generated count. 8.10 Link migration# When migrating legacy link values, implementations SHOULD: normalize supported link syntaxes according to §11 parsing rules, preserve alias and anchor components where possible, normalize resolved targets into canonical write format by policy, detect and report ambiguous links instead of silently choosing non-deterministically. 8.11 Divergence register# Implementations SHOULD maintain a divergence register with columns: section current behavior target canonical behavior migration strategy deprecation timeline 8.12 Deprecation policy# For any behavior deprecated by the specification: announce deprecation in release notes, provide warning period, provide migration tooling where feasible, remove deprecated behavior only in a version aligned with compatibility commitments. 8.13 Data safety requirements# Migrations MUST NOT: silently drop unknown fields, silently convert valid date-only fields to datetime, silently rewrite recurrence semantics without explicit policy, silently materialize occurrence notes outside explicit user/configured materialization policy, silently delete materialized occurrence notes during recurrence edits, silently drop unresolved dependency entries, silently rewrite link targets to different destinations without explicit policy, silently delete reminders unless explicitly requested. 8.14 Suggested migration report format# spec_version_from: 0.1.0-draft spec_version_to: 0.3.0-rc.3 files_scanned: 214 files_changed: 67 warnings: alias_conflict_ignored: 3 instance_state_overlap_resolved: 2 occurrence_state_conflict: 1 unresolved_dependency_target: 4 changes: normalized_datetime_fields: 41 alias_keys_removed: 29 instance_overlaps_fixed: 2 occurrence_state_conflicts: 1 inferred_dependency_reltype: 5 generated_reminder_ids: 8 normalized_link_targets: 14 8.15 Compatibility statement example# Compatibility mode: legacy-aliases=true, legacy-timeentry-duration=true Planned removal: v2.0.0 Migration command: tasknotes migrate --normalize-frontmatter"},{"route":"/developers/specification/09-configuration/","title":"9. Configuration","description":"This section defines the normative configuration model for collections using tasknotes-spec.","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:09-configuration.md","namespace":"specification","relativePath":"09-configuration.md","raw":"# 9. Configuration\n\n## 9.1 Purpose\n\nThis section defines the normative configuration model for collections using `tasknotes-spec`.\n\n## 9.2 Configuration provider model\n\nImplementations MUST derive an **effective configuration** from one or more configuration providers.\n\nA provider is a source adapter that returns a partial configuration normalized to this section's schema.\n\nImplementations MUST:\n\n- support at least one provider,\n- document supported providers,\n- document provider precedence order,\n- disclose active providers and fallback behavior in conformance output (§7).\n\n### 9.2.1 Common provider types\n\nCommon providers include:\n\n- `yaml_file`: a `tasknotes.yaml` document at collection root,\n- `tasknotes_plugin_data_json`: `.obsidian/plugins/tasknotes/data.json`,\n- `built_in_defaults`: implementation defaults,\n- optional runtime/CLI/env overrides.\n\nThis list is not exhaustive.\n\n### 9.2.2 Deterministic precedence and merge\n\nProvider precedence MUST be deterministic.\n\nUnless explicitly documented otherwise, implementations MUST resolve configuration per top-level key:\n\n- for each key in §9.3/§9.4, the highest-precedence provider that supplies that key wins,\n- winning object values replace lower-precedence object values as whole objects (no implicit deep merge),\n- after top-level selection, implementations MUST apply documented schema defaults for missing nested keys before exposing effective configuration.\n\nIf an implementation supports deep-merge behavior, it MUST be explicitly documented and deterministic.\n\n### 9.2.3 Strict vs permissive provider behavior\n\nIn strict mode:\n\n- failure to resolve required effective keys (`spec_version`, `mapping`) MUST be a configuration error.\n\nIf permissive mode is implemented, then in permissive mode:\n\n- implementations MAY continue with defaults when providers are missing/unreadable,\n- implementations MUST emit configuration warnings,\n- implementations MUST disclose that effective configuration is partial/default-derived.\n\n### 9.2.4 TaskNotes plugin provider (`data.json`)\n\nThe TaskNotes plugin stores settings in `.obsidian/plugins/tasknotes/data.json` within the vault root. When using this file as a configuration provider, normalization MUST apply the field mapping in the table below.\n\n**Key mapping table** (`data.json` key → spec effective config):\n\n| `data.json` key | Spec key | Notes |\n|---|---|---|\n| `fieldMapping` | `mapping` | Normalize role names: `dateCreated`→`date_created`, `completedDate`→`completed_date`, `recurrenceAnchor`→`recurrence_anchor`, `completeInstances`→`complete_instances`, `skippedInstances`→`skipped_instances`, `recurrenceParent`→`recurrence_parent`, `occurrenceDate`→`occurrence_date`, `occurrenceMaterialization`→`occurrence_materialization`, `occurrenceNextTrigger`→`occurrence_next_trigger`, `occurrenceTemplate`→`occurrence_template`, `occurrencePastHorizon`→`occurrence_past_horizon`, `occurrenceFutureHorizon`→`occurrence_future_horizon`, `blockedBy`→`blocked_by`, `timeEntries`→`time_entries`, `timeEstimate`→`time_estimate` |\n| `storeTitleInFilename` | `title.storage` | `true` → `\"filename\"`, `false` → `\"frontmatter\"` |\n| `taskFilenameFormat` | `title.filename_format` | Values: `\"title\"`, `\"zettel\"`, `\"timestamp\"`, `\"custom\"`; used only when `title.storage=frontmatter` for canonical writes, but preserved as compatibility input when present |\n| `customFilenameTemplate` | `title.custom_filename_template` | Template string, e.g. `\"{title}\"`; used only when `title.storage=frontmatter` and `filename_format=custom` |\n| `taskCreationDefaults.useBodyTemplate` | `templating.enabled` | boolean |\n| `taskCreationDefaults.bodyTemplate` | `templating.template_path` | Path to template file |\n| `customStatuses[*].value` | `status.values` | Ordered array of status value strings |\n| `defaultTaskStatus` | `status.default` | Default status string |\n| `customStatuses[isCompleted=true][*].value` | `status.completed_values` | Statuses where `isCompleted: true` |\n| `defaultTaskPriority` | `defaults.priority` | Default priority string |\n| `autoStopTimeTrackingOnComplete` | `time_tracking.auto_stop_on_complete` | boolean |\n| `autoStopTimeTrackingNotification` | `time_tracking.auto_stop_notification` | boolean |\n| `taskIdentificationMethod` | `task_detection.method` | `\"tag\"` or `\"property\"` |\n| `taskTag` | `task_detection.tag` | Tag string used when `method=\"tag\"` |\n| `taskPropertyName` | `task_detection.property_name` | Frontmatter key used when `method=\"property\"` |\n| `taskPropertyValue` | `task_detection.property_value` | Expected value; empty means key must exist |\n| `tasksFolder` | `task_detection.default_folder` | Default folder for new tasks |\n| `excludedFolders` | `task_detection.excluded_folders` | Comma-separated folder paths to exclude |\n| `moveArchivedTasks` | `archive.move_on_archive` | boolean |\n| `archiveFolder` | `archive.folder` | Archive destination folder |\n| `useFrontmatterMarkdownLinks` | `links.use_markdown_format` | boolean; see §11 |\n\n**Key `data.json` fields with defaults** (for cold-start reading of a vault with no `tasknotes.yaml`):\n\n| Field | Type | Default | Meaning |\n|---|---|---|---|\n| `tasksFolder` | string | `\"TaskNotes/Tasks\"` | Default folder for new task files |\n| `taskIdentificationMethod` | `\"tag\" \\| \"property\"` | `\"tag\"` | How task files are identified |\n| `taskTag` | string | `\"task\"` | Tag that identifies task files (when `method=\"tag\"`) |\n| `taskPropertyName` | string | `\"\"` | Frontmatter key for property-based identification |\n| `taskPropertyValue` | string | `\"\"` | Expected value for property-based identification (empty = key presence) |\n| `storeTitleInFilename` | boolean | `true` | Title storage mode |\n| `taskFilenameFormat` | `\"title\" \\| \"zettel\" \\| \"timestamp\" \\| \"custom\"` | `\"title\"` | Filename generation format |\n| `customFilenameTemplate` | string | `\"{title}\"` | Template for `\"custom\"` filename format |\n| `defaultTaskStatus` | string | `\"open\"` | Default status on create |\n| `defaultTaskPriority` | string | `\"normal\"` | Default priority on create |\n| `customStatuses` | StatusConfig[] | see object shape below | Ordered status definitions |\n| `autoStopTimeTrackingOnComplete` | boolean | `true` | Auto-stop active session on completion |\n| `autoStopTimeTrackingNotification` | boolean | `false` | Show notification when auto-stopping |\n| `useFrontmatterMarkdownLinks` | boolean | `false` | Use markdown links in frontmatter (requires obsidian-frontmatter-markdown-links plugin) |\n| `moveArchivedTasks` | boolean | `false` | Move task file to archive folder on archive |\n| `archiveFolder` | string | `\"TaskNotes/Archive\"` | Archive destination folder |\n| `excludedFolders` | string | `\"\"` | Comma-separated folders to exclude from task indexing |\n\n**StatusConfig object shape:**\n\n```json\n{\n \"id\": \"done\",\n \"value\": \"done\",\n \"label\": \"Done\",\n \"color\": \"#00aa00\",\n \"isCompleted\": true,\n \"order\": 3,\n \"autoArchive\": false,\n \"autoArchiveDelay\": 5\n}\n```\n\n`spec_version` is not present in `data.json`. Implementations MUST synthesize an effective `spec_version` as described in §9.5.\n\nProvider keys not listed above MAY be ignored by `tasknotes-spec` consumers.\n\n## 9.3 Required top-level keys\n\nRequired keys apply to the effective configuration after provider resolution.\n\n| Key | Type | Required | Description |\n|---|---|---|---|\n| `spec_version` | string | yes | target spec version (provider-supplied or synthesized per §9.5) |\n| `mapping` | object | yes | semantic role to storage key mapping |\n\n## 9.4 Recommended top-level keys\n\n| Key | Type | Description |\n|---|---|---|\n| `task_detection` | object | task file identification rules |\n| `defaults` | object | role defaults used during create |\n| `status` | object | status set and completed-value semantics |\n| `validation` | object | validation behavior (`strict` required, `permissive` optional) |\n| `links` | object | link parsing/resolution behavior |\n| `title` | object | title source and filename behavior policy |\n| `templating` | object | optional create-time templating behavior policy |\n| `dependencies` | object | dependency behavior policy |\n| `reminders` | object | reminder behavior policy |\n| `time_tracking` | object | time-tracking management behavior policy |\n| `occurrences` | object | recurrence materialization defaults and bounds |\n| `compatibility` | object | legacy alias/behavior switches |\n\n## 9.5 spec_version behavior\n\n`spec_version` MUST be a semantic version string.\nPre-release identifiers are valid (for example `0.3.0-rc.3`).\n\nImplementations in strict mode MUST reject unsupported major versions.\n\nIf permissive mode is implemented, permissive mode MAY proceed with warning when major version differs.\n\nIf a provider does not supply `spec_version` (for example TaskNotes `data.json`), implementations MUST synthesize an effective `spec_version` matching their target `tasknotes-spec` version and SHOULD disclose that it was synthesized.\n\n## 9.6 mapping schema\n\n`mapping` MUST map semantic roles (from §2) to string storage keys.\n\nMinimum required roles in mapping:\n\n- `title`\n- `status`\n- `completed_date`\n- `date_created`\n- `date_modified`\n\nIf semantic role `id` is supported (§2.6.5), mapping SHOULD include `id`.\nIf profile `materialized-occurrences` is claimed, mapping MUST include `recurrence_parent` and `occurrence_date`, and SHOULD include parent policy roles (`occurrence_materialization`, `occurrence_next_trigger`, `occurrence_template`, `occurrence_past_horizon`, `occurrence_future_horizon`).\n\nExample:\n\n```yaml\nmapping:\n title: title\n status: status\n date_created: dateCreated\n date_modified: dateModified\n completed_date: completedDate\n recurrence: recurrence\n recurrence_anchor: recurrenceAnchor\n complete_instances: completeInstances\n skipped_instances: skippedInstances\n recurrence_parent: recurrence_parent\n occurrence_date: occurrence_date\n occurrence_materialization: occurrence_materialization\n occurrence_next_trigger: occurrence_next_trigger\n occurrence_template: occurrence_template\n occurrence_past_horizon: occurrence_past_horizon\n occurrence_future_horizon: occurrence_future_horizon\n time_entries: timeEntries\n blocked_by: blockedBy\n reminders: reminders\n attachments: attachments\n```\n\n## 9.7 task_detection schema\n\n`task_detection` controls how task files are identified within the vault.\n\n### Detection methods\n\nThe tasknotes plugin natively supports two identification methods, controlled by `taskIdentificationMethod` in `data.json` (mapped to `task_detection.method`):\n\n**`tag` (default)** — A markdown file is a task if it contains the configured tag (default `#task`) in its frontmatter `tags` array or inline in the body. Configured by `task_detection.tag`.\n\n**`property`** — A markdown file is a task if a specified frontmatter property has a specified value (or exists, if value is empty). Configured by `task_detection.property_name` and `task_detection.property_value`.\n\nSchema and selection rules:\n\n1. `task_detection` MAY specify either:\n - `method` (single-method form), or\n - `methods` (multi-method form; non-empty list).\n2. If both are present, `methods` MUST take precedence and implementations SHOULD emit a configuration warning.\n3. If neither is present, effective detection method MUST default to `tag`.\n4. `method` MUST be `tag` or `property`.\n5. `methods` entries MUST be unique and MUST be from:\n - `tag`\n - `property`\n - `field_presence`\n - `field_match`\n6. Method-specific required keys:\n - when `tag` is enabled, effective `task_detection.tag` MUST be non-empty (default `task` when absent);\n - when `property` is enabled, `task_detection.property_name` MUST be provided and non-empty; `task_detection.property_value` MAY be empty (empty means key-exists semantics).\n7. If `methods` has more than one entry, `task_detection.combine` controls combination semantics (§9.7.3). If omitted, it MUST default to `or`.\n\n### 9.7.1 Tag matching semantics\n\nWhen `task_detection.method=tag`, matching MUST follow these rules:\n\n1. Normalize configured `task_detection.tag` by stripping one leading `#` when present.\n2. Compare tag names case-insensitively after normalization.\n3. Frontmatter matching:\n - `tags` MAY be a list of strings or a single string.\n - each tag value is normalized by trimming surrounding whitespace and stripping one leading `#`.\n - match requires exact normalized equality (for example `task` matches `#task`; `task` does not match `tasking`).\n4. Body matching:\n - only markdown text outside fenced code blocks and inline code spans is considered,\n - a match requires a hashtag token with exact normalized name (for example `#task`),\n - partial-word matches MUST NOT count (for example `#tasking` does not match configured `task`).\n\nIf either frontmatter or body matches, the file is identified as a task.\n\n### 9.7.2 Property matching semantics\n\nWhen property detection is enabled (`method=property` or `methods` includes `property`):\n\n1. `task_detection.property_name` MUST name the frontmatter key to inspect.\n2. If `task_detection.property_value` is non-empty, match requires semantic equality with the configured value.\n3. If `task_detection.property_value` is empty or absent, match requires key presence only.\n\n### 9.7.3 Multi-method extension semantics\n\n`tasknotes.yaml`-level providers MAY additionally support:\n\n- `field_presence` (example: required key `status`)\n- `field_match` (example: `type == \"task\"`)\n\nExtension-key shape:\n\n- `field_presence`: string or list of required frontmatter keys.\n- `field_match`: object map of `key -> expected scalar value` for exact semantic equality checks.\n\nIf multiple methods are configured in `tasknotes.yaml`, `task_detection.combine` MUST define combinator semantics:\n\n- `or` (default): file is a task if any enabled method matches.\n- `and`: file is a task only if all enabled methods match.\n\nIf `task_detection.combine` is absent, implementations MUST default to `or`.\n\nImplementations MUST exclude folders listed in `task_detection.excluded_folders` from task indexing.\n\nExecutable conformance: adapters participating in the fixture suite SHOULD expose `config.detect_task_file` to evaluate these detection semantics against fixture inputs.\n\nExample (`tasknotes.yaml`, equivalent to tag-based default):\n\n```yaml\ntask_detection:\n method: tag\n tag: task\n default_folder: TaskNotes/Tasks\n```\n\nExample (property-based):\n\n```yaml\ntask_detection:\n method: property\n property_name: type\n property_value: task\n```\n\n## 9.8 defaults schema\n\n`defaults` defines values used at create time when caller input omits a role.\n\nDefaults MUST NOT override explicit user input.\n\nExample:\n\n```yaml\ndefaults:\n status: open\n priority: normal\n recurrence_anchor: scheduled\n reminders:\n - id: due_minus_1d\n type: relative\n relatedTo: due\n offset: -P1D\n```\n\n`defaults.reminders` behavior is defined in §10.3.9.\n\n## 9.9 status schema\n\n`status` defines known status values and completion semantics.\n\nExample:\n\n```yaml\nstatus:\n values: [open, in-progress, done, cancelled]\n default: open\n completed_values: [done]\n skipped_values: [cancelled]\n default_skipped: cancelled\n```\n\nRules:\n\n- `default` MUST be one of `values`.\n- `completed_values` MUST be a non-empty list.\n- Each `completed_values` entry MUST be in `values`.\n- `skipped_values`, when present, MUST be a list whose entries are in `values`.\n- `default_skipped`, when present, MUST be in `skipped_values`.\n- For implementations claiming `materialized-occurrences`, `skipped_values` MUST NOT overlap `completed_values`.\n- Implementations claiming `materialized-occurrences` MUST provide at least one skipped value or fail skip of materialized occurrence notes deterministically (§5.20.3).\n- Non-recurring completion MUST use this list, not hardcoded literals.\n- When a complete operation does not provide an explicit target status, writers MUST use the first entry of `completed_values`.\n- When a materialized occurrence skip operation does not provide an explicit skipped status, writers MUST use `default_skipped` when present, otherwise the first entry of `skipped_values`.\n\n## 9.10 validation schema\n\nExample:\n\n```yaml\nvalidation:\n mode: strict\n reject_unknown_fields: false\n```\n\nRules:\n\n- `mode` MUST be `strict` or `permissive` when present.\n- If `mode` is absent, effective mode MUST default to `strict`.\n- Conforming implementations MUST support `strict`.\n- Implementations MAY support `permissive`.\n- If `mode=permissive` is configured but not implemented, configuration MUST fail in strict mode and SHOULD emit warning/fallback in permissive mode.\n- `reject_unknown_fields=true` enforces closed-schema behavior for mapped roles.\n\n## 9.11 dependencies schema\n\nExample:\n\n```yaml\ndependencies:\n default_reltype: FINISHTOSTART\n treat_missing_target_as_blocked: true\n enforce_unique_uid: true\n unresolved_target_severity: warning\n require_resolved_uid_on_write: false\n```\n\nRules:\n\n- `default_reltype` MUST be one of the allowed reltype values in §10.2.\n- `treat_missing_target_as_blocked` controls whether missing/unresolvable dependency targets contribute to blocked-state evaluation (§10.2.5).\n- If `treat_missing_target_as_blocked` is absent, effective value MUST default to `true`.\n- `enforce_unique_uid=true` enforces uniqueness at validation/write time.\n- If `enforce_unique_uid` is absent, effective value MUST default to `true`.\n- `unresolved_target_severity` MUST be `warning` or `error`.\n- `require_resolved_uid_on_write=true` requires dependency UID resolution success for add/update operations.\n\n## 9.12 links schema\n\nExample:\n\n```yaml\nlinks:\n extensions: [\".md\"]\n unresolved_default_severity: warning\n update_references_on_rename: true\n```\n\nRules:\n\n- `extensions` defines extension trial order for extensionless targets.\n- `unresolved_default_severity` MUST be `warning` or `error`.\n- `update_references_on_rename=true` enables rename-time link rewrite behavior when supported.\n\n## 9.13 title schema\n\nExample (`storage=frontmatter`):\n\n```yaml\ntitle:\n storage: frontmatter\n filename_format: custom\n custom_filename_template: \"{{date}} {{title}}\"\n```\n\nExample (`storage=filename`):\n\n```yaml\ntitle:\n storage: filename\n```\n\nRules:\n\n- `storage` MUST be `frontmatter` or `filename`.\n- when `storage=frontmatter`, `filename_format` MUST be `title`, `zettel`, `timestamp`, or `custom`.\n- when `storage=frontmatter` and `filename_format=custom`, `custom_filename_template` MUST be provided and non-empty.\n- when `storage=filename`, `filename_format` and `custom_filename_template` MAY be present for compatibility input but MUST be ignored for canonical write behavior.\n- Read precedence MUST be storage-mode-aware:\n 1. when `storage=frontmatter`, use mapped `title` key when present and non-empty, then file basename fallback;\n 2. when `storage=filename`, use file basename first, then mapped `title` fallback when basename is unavailable.\n- If frontmatter and basename titles both exist and differ, the source authoritative for active `storage` MUST win.\n- If `storage=filename`, canonical writes MUST treat filename as title source, MUST rename on title change, and MUST ignore `filename_format` and `custom_filename_template`.\n- If `storage=frontmatter`, canonical writes MUST persist mapped title key; `filename_format` and `custom_filename_template` govern create-time filename generation.\n\nInformative mapping to TaskNotes settings:\n\n- `title.storage=filename` corresponds to `storeTitleInFilename=true`.\n- `title.filename_format` corresponds to `taskFilenameFormat`.\n- `title.custom_filename_template` corresponds to `customFilenameTemplate`.\n\n## 9.14 templating schema\n\n`templating` defines optional create-time template behavior.\nThis schema is required only for implementations claiming profile `templating` (§7.3.3).\n\nExample:\n\n```yaml\ntemplating:\n enabled: true\n template_path: Templates/Task.md\n failure_mode: warning_fallback\n unknown_variable_policy: preserve\n```\n\nRules:\n\n- `enabled` MUST be boolean.\n- If `enabled=true`, `template_path` MUST be provided and non-empty.\n- `failure_mode` MUST be `error` or `warning_fallback` when present.\n- `unknown_variable_policy` MUST be `preserve` or `empty` when present.\n- If `failure_mode` is absent, effective value MUST default to `warning_fallback`.\n- If `unknown_variable_policy` is absent, effective value MUST default to `preserve`.\n- Implementations claiming `templating` MUST support portable double-brace variables from §5.3.5.\n- Implementations not claiming `templating` MAY ignore `templating` settings.\n\n## 9.15 reminders schema\n\nExample:\n\n```yaml\nreminders:\n date_only_anchor_time: \"00:00\"\n apply_defaults_when_explicit: false\n```\n\nRules:\n\n- `date_only_anchor_time` MUST be `HH:MM` 24-hour local time format.\n- `date_only_anchor_time` is used by §10.3.4 for relative reminders against date-only bases.\n- `apply_defaults_when_explicit` MUST be boolean when present.\n- if `apply_defaults_when_explicit` is absent, effective value MUST default to `false`.\n- `apply_defaults_when_explicit=false` means explicit input reminders replace default-reminder application at create time.\n- `apply_defaults_when_explicit=true` means explicit create-time reminders are merged with defaults using §10.3.9 deterministic merge rules.\n\n## 9.16 time_tracking schema\n\nExample:\n\n```yaml\ntime_tracking:\n auto_stop_on_complete: true\n auto_stop_notification: false\n```\n\nRules:\n\n- `auto_stop_on_complete` MUST be boolean when present.\n- `auto_stop_notification` MUST be boolean when present.\n- if `auto_stop_on_complete=true`, completion-triggered stop behavior MUST follow §5.19.5.\n- if `auto_stop_notification` is absent, effective value MUST default to `false`.\n\n## 9.17 occurrences schema\n\n`occurrences` defines collection-level defaults for recurrence materialization.\nThis schema is required only for implementations claiming profile `materialized-occurrences` (§7.3.4).\n\nExample:\n\n```yaml\noccurrences:\n default_materialization: manual\n default_next_trigger: completion\n past_horizon: P0D\n future_horizon: P14D\n```\n\nRules:\n\n- `default_materialization` MUST be one of `manual`, `on_completion`, or `rolling`.\n- If `default_materialization` is absent, effective value MUST default to `manual`.\n- `default_next_trigger` MUST be `completion` or `completion_or_skip`.\n- If `default_next_trigger` is absent, effective value MUST default to `completion`.\n- `past_horizon` and `future_horizon`, when present, MUST be ISO 8601 duration strings.\n- If `default_materialization=rolling`, implementations MUST use finite rolling bounds. If bounds are absent, documented finite defaults MUST be used.\n- Parent task fields override collection defaults: `occurrence_materialization` overrides `occurrences.default_materialization`; `occurrence_next_trigger` overrides `occurrences.default_next_trigger`; `occurrence_past_horizon` and `occurrence_future_horizon` override `occurrences.past_horizon` and `occurrences.future_horizon`.\n- If `occurrences` is absent, the effective behavior is `manual` materialization and `completion` next trigger.\n\n## 9.17.1 nlp schema\n\n`nlp` advertises optional natural-language capture triggers. These settings\nallow another TaskNotes client to preserve the same capture vocabulary without\nmaking natural-language parsing a requirement of the core profile.\n\nExample:\n\n```yaml\nnlp:\n triggers:\n - property_id: tags\n trigger: \"#\"\n enabled: true\n - property_id: contexts\n trigger: \"@\"\n enabled: true\n - property_id: priority\n trigger: \"!\"\n enabled: false\n```\n\nRules:\n\n- `triggers` MUST be a list when present.\n- Every trigger entry MUST contain non-empty `property_id` and `trigger`\n strings.\n- `property_id` SHOULD use a stable TaskNotes role (`tags`, `contexts`,\n `projects`, `status`, or `priority`) or the stable identifier of a configured\n user field.\n- `enabled` MUST be boolean when present and MUST default to `true`.\n- Trigger strings MAY contain more than one character.\n- Trigger entries with unknown `property_id` values MUST be preserved by\n configuration round-trips and MAY be ignored by clients that cannot resolve\n the property.\n- If `nlp` is absent, clients MAY use documented local defaults.\n- This block controls capture parsing and suggestions only. It MUST NOT change\n persisted task field names or values.\n\nInformative mapping to TaskNotes settings:\n\n- `nlp.triggers` corresponds to `nlpTriggers.triggers`.\n- `property_id`, `trigger`, and `enabled` correspond to the plugin fields\n `propertyId`, `trigger`, and `enabled`.\n\n## 9.18 compatibility schema\n\nExample:\n\n```yaml\ncompatibility:\n read_aliases: true\n legacy_duration_field: true\n legacy_local_datetime_input: false\n```\n\nRules:\n\n- Compatibility flags MUST default to conservative behavior in new collections.\n- `legacy_local_datetime_input=true` MAY relax strict parsing for offset-less datetimes only in permissive mode; strict mode parsing rules in §3.4.2 still apply.\n- Enabled compatibility flags SHOULD be disclosed in conformance output (§7).\n\n## 9.19 Complete configuration example (`yaml_file` provider)\n\n```yaml\nspec_version: 0.3.0-rc.3\n\nmapping:\n title: title\n status: status\n priority: priority\n due: due\n scheduled: scheduled\n attachments: attachments\n completed_date: completedDate\n date_created: dateCreated\n date_modified: dateModified\n recurrence: recurrence\n recurrence_anchor: recurrenceAnchor\n complete_instances: completeInstances\n skipped_instances: skippedInstances\n recurrence_parent: recurrence_parent\n occurrence_date: occurrence_date\n occurrence_materialization: occurrence_materialization\n occurrence_next_trigger: occurrence_next_trigger\n occurrence_template: occurrence_template\n occurrence_past_horizon: occurrence_past_horizon\n occurrence_future_horizon: occurrence_future_horizon\n time_entries: timeEntries\n blocked_by: blockedBy\n reminders: reminders\n\ntask_detection:\n method: tag\n tag: task\n default_folder: TaskNotes/Tasks\n\ndefaults:\n status: open\n priority: normal\n recurrence_anchor: scheduled\n reminders:\n - id: due_minus_1d\n type: relative\n relatedTo: due\n offset: -P1D\n\nstatus:\n values: [open, in-progress, done, cancelled]\n default: open\n completed_values: [done]\n skipped_values: [cancelled]\n default_skipped: cancelled\n\nvalidation:\n mode: strict\n reject_unknown_fields: false\n\ndependencies:\n default_reltype: FINISHTOSTART\n treat_missing_target_as_blocked: true\n enforce_unique_uid: true\n unresolved_target_severity: warning\n require_resolved_uid_on_write: false\n\nlinks:\n extensions: [\".md\"]\n unresolved_default_severity: warning\n update_references_on_rename: true\n\ntitle:\n storage: filename\n\ntemplating:\n enabled: false\n failure_mode: warning_fallback\n unknown_variable_policy: preserve\n\nreminders:\n date_only_anchor_time: \"00:00\"\n apply_defaults_when_explicit: false\n\ntime_tracking:\n auto_stop_on_complete: true\n auto_stop_notification: false\n\noccurrences:\n default_materialization: manual\n default_next_trigger: completion\n past_horizon: P0D\n future_horizon: P14D\n\nnlp:\n triggers:\n - property_id: tags\n trigger: \"#\"\n enabled: true\n - property_id: contexts\n trigger: \"@\"\n enabled: true\n - property_id: projects\n trigger: \"+\"\n enabled: true\n - property_id: status\n trigger: \"*\"\n enabled: true\n - property_id: priority\n trigger: \"!\"\n enabled: false\n\ncompatibility:\n read_aliases: true\n legacy_duration_field: true\n```\n\n## 9.20 Configuration errors\n\nConfiguration validation MUST report structured errors with key path context.\n\nExamples:\n\n- no readable configuration provider available in strict mode\n- required effective key unresolved after provider resolution (`spec_version` or `mapping`)\n- missing `mapping.title`\n- `status.default` not present in `status.values`\n- `status.completed_values` contains a value not present in `status.values`\n- `status.skipped_values` contains a value not present in `status.values`\n- `status.default_skipped` not present in `status.skipped_values`\n- `status.skipped_values` overlaps `status.completed_values` when `materialized-occurrences` is claimed\n- unsupported `validation.mode`\n- `validation.mode=permissive` but permissive mode is not implemented\n- invalid `task_detection.method`\n- invalid `task_detection.methods` entry\n- empty `task_detection.tag` when `tag` method is enabled\n- missing `task_detection.property_name` when `property` method is enabled\n- invalid `task_detection.combine`\n- invalid `dependencies.default_reltype`\n- invalid `dependencies.unresolved_target_severity`\n- invalid `links.unresolved_default_severity`\n- invalid `title.storage`\n- invalid `title.filename_format`\n- missing `title.filename_format` when `title.storage=frontmatter`\n- missing `title.custom_filename_template` when `title.storage=frontmatter` and `title.filename_format=custom`\n- missing `templating.template_path` when `templating.enabled=true`\n- invalid `templating.failure_mode`\n- invalid `templating.unknown_variable_policy`\n- invalid `reminders.date_only_anchor_time`\n- invalid `reminders.apply_defaults_when_explicit`\n- invalid `time_tracking.auto_stop_on_complete`\n- invalid `time_tracking.auto_stop_notification`\n- invalid `occurrences.default_materialization`\n- invalid `occurrences.default_next_trigger`\n- invalid `occurrences.past_horizon`\n- invalid `occurrences.future_horizon`\n- invalid `nlp.triggers`\n- empty `nlp.triggers[].property_id`\n- empty `nlp.triggers[].trigger`\n- invalid `nlp.triggers[].enabled`\n\n## 9.21 Default collection state\n\nThis section describes what a fresh tasknotes vault looks like before any user customization. Implementations that read an existing tasknotes vault without a `tasknotes.yaml` SHOULD apply these defaults when `data.json` is absent or fields are missing.\n\n### Folder layout\n\n```text\nMyVault/\n├── TaskNotes/\n│ ├── Tasks/ ← new tasks created here by default\n│ └── Archive/ ← archived tasks moved here (if moveArchivedTasks=true)\n└── .obsidian/\n └── plugins/\n └── tasknotes/\n └── data.json\n```\n\n### Task detection\n\nDefault method: `tag`. A file is a task if it contains the tag `#task` in its frontmatter `tags` array or inline in the body.\n\n### Default field mapping\n\n| Semantic role | Default storage key |\n|---|---|\n| `title` | `title` |\n| `status` | `status` |\n| `priority` | `priority` |\n| `due` | `due` |\n| `scheduled` | `scheduled` |\n| `contexts` | `contexts` |\n| `projects` | `projects` |\n| `time_estimate` | `timeEstimate` |\n| `completed_date` | `completedDate` |\n| `date_created` | `dateCreated` |\n| `date_modified` | `dateModified` |\n| `recurrence` | `recurrence` |\n| `recurrence_anchor` | `recurrence_anchor` |\n| `complete_instances` | `complete_instances` |\n| `skipped_instances` | `skipped_instances` |\n| `recurrence_parent` | `recurrence_parent` |\n| `occurrence_date` | `occurrence_date` |\n| `occurrence_materialization` | `occurrence_materialization` |\n| `occurrence_next_trigger` | `occurrence_next_trigger` |\n| `occurrence_template` | `occurrence_template` |\n| `occurrence_past_horizon` | `occurrence_past_horizon` |\n| `occurrence_future_horizon` | `occurrence_future_horizon` |\n| `time_entries` | `timeEntries` |\n| `blocked_by` | `blockedBy` |\n| `reminders` | `reminders` |\n\nNote: `recurrenceAnchor`, `completeInstances`, and `skippedInstances` are accepted as aliases on read (§2.5). The mixed camelCase/snake_case defaults are intentional for compatibility with historical TaskNotes frontmatter.\n\n### Default statuses\n\n| Value | Label | `isCompleted` | Order |\n|---|---|---|---|\n| `none` | None | false | 0 |\n| `open` | Open | false | 1 |\n| `in-progress` | In progress | false | 2 |\n| `done` | Done | true | 3 |\n\nDefault status on create: `open`. Default completed status (first `isCompleted=true`): `done`.\nNo skipped status is configured by default; implementations that support materialized occurrence skips MUST require configuration or expose a documented default before writing skipped occurrence state.\n\n### Default priorities\n\n| Value | Label | Weight |\n|---|---|---|\n| `none` | None | 0 |\n| `low` | Low | 1 |\n| `normal` | Normal | 2 |\n| `high` | High | 3 |\n\nDefault priority on create: `normal`.\n\n### Title and filename defaults\n\n- `title.storage`: `filename` (filename/path is the authoritative title source)\n- default basename generation under `title.storage=filename` derives from semantic title using filename-safe sanitization\n- implementations MAY also keep mapped `title` in frontmatter as a synchronized compatibility mirror\n- TaskNotes `data.json` may still contain legacy `taskFilenameFormat` values such as `zettel`, but these are compatibility inputs rather than the forward default when `title.storage=filename`\n- title is read from filename first; frontmatter `title` is compatibility fallback when filename-derived title is unavailable (§2.2.2)\n\n### Time tracking defaults\n\n- `auto_stop_on_complete`: `true`\n- `auto_stop_notification`: `false`\n\n### Link format defaults\n\n- `useFrontmatterMarkdownLinks`: `false` — wikilinks used by default (e.g. `[[task-name]]`)\n- To use markdown link format, the `obsidian-frontmatter-markdown-links` plugin must also be installed\n\n### Effective configuration for a minimal fresh vault\n\nWhen neither `data.json` nor `tasknotes.yaml` is present, implementations MUST use the following effective configuration:\n\n```yaml\nspec_version: 0.3.0-rc.3 # synthesized\nmapping:\n title: title\n status: status\n priority: priority\n due: due\n scheduled: scheduled\n contexts: contexts\n projects: projects\n attachments: attachments\n time_estimate: timeEstimate\n completed_date: completedDate\n date_created: dateCreated\n date_modified: dateModified\n recurrence: recurrence\n recurrence_anchor: recurrence_anchor\n complete_instances: complete_instances\n skipped_instances: skipped_instances\n recurrence_parent: recurrence_parent\n occurrence_date: occurrence_date\n occurrence_materialization: occurrence_materialization\n occurrence_next_trigger: occurrence_next_trigger\n occurrence_template: occurrence_template\n occurrence_past_horizon: occurrence_past_horizon\n occurrence_future_horizon: occurrence_future_horizon\n time_entries: timeEntries\n blocked_by: blockedBy\n reminders: reminders\ntask_detection:\n method: tag\n tag: task\n default_folder: TaskNotes/Tasks\nstatus:\n values: [none, open, in-progress, done]\n default: open\n completed_values: [done]\ntitle:\n storage: filename\ntime_tracking:\n auto_stop_on_complete: true\n auto_stop_notification: false\nlinks:\n use_markdown_format: false\n extensions: [\".md\"]\n unresolved_default_severity: warning\n update_references_on_rename: true\n```\n","aliases":["/spec/09-configuration/"],"toc":[{"level":2,"id":"91-purpose","text":"9.1 Purpose"},{"level":2,"id":"92-configuration-provider-model","text":"9.2 Configuration provider model"},{"level":3,"id":"921-common-provider-types","text":"9.2.1 Common provider types"},{"level":3,"id":"922-deterministic-precedence-and-merge","text":"9.2.2 Deterministic precedence and merge"},{"level":3,"id":"923-strict-vs-permissive-provider-behavior","text":"9.2.3 Strict vs permissive provider behavior"},{"level":3,"id":"924-tasknotes-plugin-provider-datajson","text":"9.2.4 TaskNotes plugin provider (data.json)"},{"level":2,"id":"93-required-top-level-keys","text":"9.3 Required top-level keys"},{"level":2,"id":"94-recommended-top-level-keys","text":"9.4 Recommended top-level keys"},{"level":2,"id":"95-specversion-behavior","text":"9.5 spec_version behavior"},{"level":2,"id":"96-mapping-schema","text":"9.6 mapping schema"},{"level":2,"id":"97-taskdetection-schema","text":"9.7 task_detection schema"},{"level":3,"id":"detection-methods","text":"Detection methods"},{"level":3,"id":"971-tag-matching-semantics","text":"9.7.1 Tag matching semantics"},{"level":3,"id":"972-property-matching-semantics","text":"9.7.2 Property matching semantics"},{"level":3,"id":"973-multi-method-extension-semantics","text":"9.7.3 Multi-method extension semantics"},{"level":2,"id":"98-defaults-schema","text":"9.8 defaults schema"},{"level":2,"id":"99-status-schema","text":"9.9 status schema"},{"level":2,"id":"910-validation-schema","text":"9.10 validation schema"},{"level":2,"id":"911-dependencies-schema","text":"9.11 dependencies schema"},{"level":2,"id":"912-links-schema","text":"9.12 links schema"},{"level":2,"id":"913-title-schema","text":"9.13 title schema"},{"level":2,"id":"914-templating-schema","text":"9.14 templating schema"},{"level":2,"id":"915-reminders-schema","text":"9.15 reminders schema"},{"level":2,"id":"916-timetracking-schema","text":"9.16 time_tracking schema"},{"level":2,"id":"917-occurrences-schema","text":"9.17 occurrences schema"},{"level":2,"id":"9171-nlp-schema","text":"9.17.1 nlp schema"},{"level":2,"id":"918-compatibility-schema","text":"9.18 compatibility schema"},{"level":2,"id":"919-complete-configuration-example-yamlfile-provider","text":"9.19 Complete configuration example (yaml_file provider)"},{"level":2,"id":"920-configuration-errors","text":"9.20 Configuration errors"},{"level":2,"id":"921-default-collection-state","text":"9.21 Default collection state"},{"level":3,"id":"folder-layout","text":"Folder layout"},{"level":3,"id":"task-detection","text":"Task detection"},{"level":3,"id":"default-field-mapping","text":"Default field mapping"},{"level":3,"id":"default-statuses","text":"Default statuses"},{"level":3,"id":"default-priorities","text":"Default priorities"},{"level":3,"id":"title-and-filename-defaults","text":"Title and filename defaults"},{"level":3,"id":"time-tracking-defaults","text":"Time tracking defaults"},{"level":3,"id":"link-format-defaults","text":"Link format defaults"},{"level":3,"id":"effective-configuration-for-a-minimal-fresh-vault","text":"Effective configuration for a minimal fresh vault"}],"html":"

9.1 Purpose#

\n

This section defines the normative configuration model for collections using tasknotes-spec.

\n

9.2 Configuration provider model#

\n

Implementations MUST derive an effective configuration from one or more configuration providers.

\n

A provider is a source adapter that returns a partial configuration normalized to this section's schema.

\n

Implementations MUST:

\n
    \n
  • support at least one provider,
  • \n
  • document supported providers,
  • \n
  • document provider precedence order,
  • \n
  • disclose active providers and fallback behavior in conformance output (§7).
  • \n
\n

9.2.1 Common provider types#

\n

Common providers include:

\n
    \n
  • yaml_file: a tasknotes.yaml document at collection root,
  • \n
  • tasknotes_plugin_data_json: .obsidian/plugins/tasknotes/data.json,
  • \n
  • built_in_defaults: implementation defaults,
  • \n
  • optional runtime/CLI/env overrides.
  • \n
\n

This list is not exhaustive.

\n

9.2.2 Deterministic precedence and merge#

\n

Provider precedence MUST be deterministic.

\n

Unless explicitly documented otherwise, implementations MUST resolve configuration per top-level key:

\n
    \n
  • for each key in §9.3/§9.4, the highest-precedence provider that supplies that key wins,
  • \n
  • winning object values replace lower-precedence object values as whole objects (no implicit deep merge),
  • \n
  • after top-level selection, implementations MUST apply documented schema defaults for missing nested keys before exposing effective configuration.
  • \n
\n

If an implementation supports deep-merge behavior, it MUST be explicitly documented and deterministic.

\n

9.2.3 Strict vs permissive provider behavior#

\n

In strict mode:

\n
    \n
  • failure to resolve required effective keys (spec_version, mapping) MUST be a configuration error.
  • \n
\n

If permissive mode is implemented, then in permissive mode:

\n
    \n
  • implementations MAY continue with defaults when providers are missing/unreadable,
  • \n
  • implementations MUST emit configuration warnings,
  • \n
  • implementations MUST disclose that effective configuration is partial/default-derived.
  • \n
\n

9.2.4 TaskNotes plugin provider (data.json)#

\n

The TaskNotes plugin stores settings in .obsidian/plugins/tasknotes/data.json within the vault root. When using this file as a configuration provider, normalization MUST apply the field mapping in the table below.

\n

Key mapping table (data.json key → spec effective config):

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
data.json keySpec keyNotes
fieldMappingmappingNormalize role names: dateCreated→date_created, completedDate→completed_date, recurrenceAnchor→recurrence_anchor, completeInstances→complete_instances, skippedInstances→skipped_instances, recurrenceParent→recurrence_parent, occurrenceDate→occurrence_date, occurrenceMaterialization→occurrence_materialization, occurrenceNextTrigger→occurrence_next_trigger, occurrenceTemplate→occurrence_template, occurrencePastHorizon→occurrence_past_horizon, occurrenceFutureHorizon→occurrence_future_horizon, blockedBy→blocked_by, timeEntries→time_entries, timeEstimate→time_estimate
storeTitleInFilenametitle.storagetrue → "filename", false → "frontmatter"
taskFilenameFormattitle.filename_formatValues: "title", "zettel", "timestamp", "custom"; used only when title.storage=frontmatter for canonical writes, but preserved as compatibility input when present
customFilenameTemplatetitle.custom_filename_templateTemplate string, e.g. "{title}"; used only when title.storage=frontmatter and filename_format=custom
taskCreationDefaults.useBodyTemplatetemplating.enabledboolean
taskCreationDefaults.bodyTemplatetemplating.template_pathPath to template file
customStatuses[*].valuestatus.valuesOrdered array of status value strings
defaultTaskStatusstatus.defaultDefault status string
customStatuses[isCompleted=true][*].valuestatus.completed_valuesStatuses where isCompleted: true
defaultTaskPrioritydefaults.priorityDefault priority string
autoStopTimeTrackingOnCompletetime_tracking.auto_stop_on_completeboolean
autoStopTimeTrackingNotificationtime_tracking.auto_stop_notificationboolean
taskIdentificationMethodtask_detection.method"tag" or "property"
taskTagtask_detection.tagTag string used when method="tag"
taskPropertyNametask_detection.property_nameFrontmatter key used when method="property"
taskPropertyValuetask_detection.property_valueExpected value; empty means key must exist
tasksFoldertask_detection.default_folderDefault folder for new tasks
excludedFolderstask_detection.excluded_foldersComma-separated folder paths to exclude
moveArchivedTasksarchive.move_on_archiveboolean
archiveFolderarchive.folderArchive destination folder
useFrontmatterMarkdownLinkslinks.use_markdown_formatboolean; see §11
\n

Key data.json fields with defaults (for cold-start reading of a vault with no tasknotes.yaml):

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
FieldTypeDefaultMeaning
tasksFolderstring"TaskNotes/Tasks"Default folder for new task files
taskIdentificationMethod"tag" | "property""tag"How task files are identified
taskTagstring"task"Tag that identifies task files (when method="tag")
taskPropertyNamestring""Frontmatter key for property-based identification
taskPropertyValuestring""Expected value for property-based identification (empty = key presence)
storeTitleInFilenamebooleantrueTitle storage mode
taskFilenameFormat"title" | "zettel" | "timestamp" | "custom""title"Filename generation format
customFilenameTemplatestring"{title}"Template for "custom" filename format
defaultTaskStatusstring"open"Default status on create
defaultTaskPrioritystring"normal"Default priority on create
customStatusesStatusConfig[]see object shape belowOrdered status definitions
autoStopTimeTrackingOnCompletebooleantrueAuto-stop active session on completion
autoStopTimeTrackingNotificationbooleanfalseShow notification when auto-stopping
useFrontmatterMarkdownLinksbooleanfalseUse markdown links in frontmatter (requires obsidian-frontmatter-markdown-links plugin)
moveArchivedTasksbooleanfalseMove task file to archive folder on archive
archiveFolderstring"TaskNotes/Archive"Archive destination folder
excludedFoldersstring""Comma-separated folders to exclude from task indexing
\n

StatusConfig object shape:

\n
{\n  "id": "done",\n  "value": "done",\n  "label": "Done",\n  "color": "#00aa00",\n  "isCompleted": true,\n  "order": 3,\n  "autoArchive": false,\n  "autoArchiveDelay": 5\n}\n

spec_version is not present in data.json. Implementations MUST synthesize an effective spec_version as described in §9.5.

\n

Provider keys not listed above MAY be ignored by tasknotes-spec consumers.

\n

9.3 Required top-level keys#

\n

Required keys apply to the effective configuration after provider resolution.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
KeyTypeRequiredDescription
spec_versionstringyestarget spec version (provider-supplied or synthesized per §9.5)
mappingobjectyessemantic role to storage key mapping
\n\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
KeyTypeDescription
task_detectionobjecttask file identification rules
defaultsobjectrole defaults used during create
statusobjectstatus set and completed-value semantics
validationobjectvalidation behavior (strict required, permissive optional)
linksobjectlink parsing/resolution behavior
titleobjecttitle source and filename behavior policy
templatingobjectoptional create-time templating behavior policy
dependenciesobjectdependency behavior policy
remindersobjectreminder behavior policy
time_trackingobjecttime-tracking management behavior policy
occurrencesobjectrecurrence materialization defaults and bounds
compatibilityobjectlegacy alias/behavior switches
\n

9.5 spec_version behavior#

\n

spec_version MUST be a semantic version string.\nPre-release identifiers are valid (for example 0.3.0-rc.3).

\n

Implementations in strict mode MUST reject unsupported major versions.

\n

If permissive mode is implemented, permissive mode MAY proceed with warning when major version differs.

\n

If a provider does not supply spec_version (for example TaskNotes data.json), implementations MUST synthesize an effective spec_version matching their target tasknotes-spec version and SHOULD disclose that it was synthesized.

\n

9.6 mapping schema#

\n

mapping MUST map semantic roles (from §2) to string storage keys.

\n

Minimum required roles in mapping:

\n
    \n
  • title
  • \n
  • status
  • \n
  • completed_date
  • \n
  • date_created
  • \n
  • date_modified
  • \n
\n

If semantic role id is supported (§2.6.5), mapping SHOULD include id.\nIf profile materialized-occurrences is claimed, mapping MUST include recurrence_parent and occurrence_date, and SHOULD include parent policy roles (occurrence_materialization, occurrence_next_trigger, occurrence_template, occurrence_past_horizon, occurrence_future_horizon).

\n

Example:

\n
mapping:\n  title: title\n  status: status\n  date_created: dateCreated\n  date_modified: dateModified\n  completed_date: completedDate\n  recurrence: recurrence\n  recurrence_anchor: recurrenceAnchor\n  complete_instances: completeInstances\n  skipped_instances: skippedInstances\n  recurrence_parent: recurrence_parent\n  occurrence_date: occurrence_date\n  occurrence_materialization: occurrence_materialization\n  occurrence_next_trigger: occurrence_next_trigger\n  occurrence_template: occurrence_template\n  occurrence_past_horizon: occurrence_past_horizon\n  occurrence_future_horizon: occurrence_future_horizon\n  time_entries: timeEntries\n  blocked_by: blockedBy\n  reminders: reminders\n  attachments: attachments\n

9.7 task_detection schema#

\n

task_detection controls how task files are identified within the vault.

\n

Detection methods#

\n

The tasknotes plugin natively supports two identification methods, controlled by taskIdentificationMethod in data.json (mapped to task_detection.method):

\n

tag (default) — A markdown file is a task if it contains the configured tag (default #task) in its frontmatter tags array or inline in the body. Configured by task_detection.tag.

\n

property — A markdown file is a task if a specified frontmatter property has a specified value (or exists, if value is empty). Configured by task_detection.property_name and task_detection.property_value.

\n

Schema and selection rules:

\n
    \n
  1. task_detection MAY specify either:
      \n
    • method (single-method form), or
    • \n
    • methods (multi-method form; non-empty list).
    • \n
    \n
  2. \n
  3. If both are present, methods MUST take precedence and implementations SHOULD emit a configuration warning.
  4. \n
  5. If neither is present, effective detection method MUST default to tag.
  6. \n
  7. method MUST be tag or property.
  8. \n
  9. methods entries MUST be unique and MUST be from:
      \n
    • tag
    • \n
    • property
    • \n
    • field_presence
    • \n
    • field_match
    • \n
    \n
  10. \n
  11. Method-specific required keys:
      \n
    • when tag is enabled, effective task_detection.tag MUST be non-empty (default task when absent);
    • \n
    • when property is enabled, task_detection.property_name MUST be provided and non-empty; task_detection.property_value MAY be empty (empty means key-exists semantics).
    • \n
    \n
  12. \n
  13. If methods has more than one entry, task_detection.combine controls combination semantics (§9.7.3). If omitted, it MUST default to or.
  14. \n
\n

9.7.1 Tag matching semantics#

\n

When task_detection.method=tag, matching MUST follow these rules:

\n
    \n
  1. Normalize configured task_detection.tag by stripping one leading # when present.
  2. \n
  3. Compare tag names case-insensitively after normalization.
  4. \n
  5. Frontmatter matching:
      \n
    • tags MAY be a list of strings or a single string.
    • \n
    • each tag value is normalized by trimming surrounding whitespace and stripping one leading #.
    • \n
    • match requires exact normalized equality (for example task matches #task; task does not match tasking).
    • \n
    \n
  6. \n
  7. Body matching:
      \n
    • only markdown text outside fenced code blocks and inline code spans is considered,
    • \n
    • a match requires a hashtag token with exact normalized name (for example #task),
    • \n
    • partial-word matches MUST NOT count (for example #tasking does not match configured task).
    • \n
    \n
  8. \n
\n

If either frontmatter or body matches, the file is identified as a task.

\n

9.7.2 Property matching semantics#

\n

When property detection is enabled (method=property or methods includes property):

\n
    \n
  1. task_detection.property_name MUST name the frontmatter key to inspect.
  2. \n
  3. If task_detection.property_value is non-empty, match requires semantic equality with the configured value.
  4. \n
  5. If task_detection.property_value is empty or absent, match requires key presence only.
  6. \n
\n

9.7.3 Multi-method extension semantics#

\n

tasknotes.yaml-level providers MAY additionally support:

\n
    \n
  • field_presence (example: required key status)
  • \n
  • field_match (example: type == "task")
  • \n
\n

Extension-key shape:

\n
    \n
  • field_presence: string or list of required frontmatter keys.
  • \n
  • field_match: object map of key -> expected scalar value for exact semantic equality checks.
  • \n
\n

If multiple methods are configured in tasknotes.yaml, task_detection.combine MUST define combinator semantics:

\n
    \n
  • or (default): file is a task if any enabled method matches.
  • \n
  • and: file is a task only if all enabled methods match.
  • \n
\n

If task_detection.combine is absent, implementations MUST default to or.

\n

Implementations MUST exclude folders listed in task_detection.excluded_folders from task indexing.

\n

Executable conformance: adapters participating in the fixture suite SHOULD expose config.detect_task_file to evaluate these detection semantics against fixture inputs.

\n

Example (tasknotes.yaml, equivalent to tag-based default):

\n
task_detection:\n  method: tag\n  tag: task\n  default_folder: TaskNotes/Tasks\n

Example (property-based):

\n
task_detection:\n  method: property\n  property_name: type\n  property_value: task\n

9.8 defaults schema#

\n

defaults defines values used at create time when caller input omits a role.

\n

Defaults MUST NOT override explicit user input.

\n

Example:

\n
defaults:\n  status: open\n  priority: normal\n  recurrence_anchor: scheduled\n  reminders:\n    - id: due_minus_1d\n      type: relative\n      relatedTo: due\n      offset: -P1D\n

defaults.reminders behavior is defined in §10.3.9.

\n

9.9 status schema#

\n

status defines known status values and completion semantics.

\n

Example:

\n
status:\n  values: [open, in-progress, done, cancelled]\n  default: open\n  completed_values: [done]\n  skipped_values: [cancelled]\n  default_skipped: cancelled\n

Rules:

\n
    \n
  • default MUST be one of values.
  • \n
  • completed_values MUST be a non-empty list.
  • \n
  • Each completed_values entry MUST be in values.
  • \n
  • skipped_values, when present, MUST be a list whose entries are in values.
  • \n
  • default_skipped, when present, MUST be in skipped_values.
  • \n
  • For implementations claiming materialized-occurrences, skipped_values MUST NOT overlap completed_values.
  • \n
  • Implementations claiming materialized-occurrences MUST provide at least one skipped value or fail skip of materialized occurrence notes deterministically (§5.20.3).
  • \n
  • Non-recurring completion MUST use this list, not hardcoded literals.
  • \n
  • When a complete operation does not provide an explicit target status, writers MUST use the first entry of completed_values.
  • \n
  • When a materialized occurrence skip operation does not provide an explicit skipped status, writers MUST use default_skipped when present, otherwise the first entry of skipped_values.
  • \n
\n

9.10 validation schema#

\n

Example:

\n
validation:\n  mode: strict\n  reject_unknown_fields: false\n

Rules:

\n
    \n
  • mode MUST be strict or permissive when present.
  • \n
  • If mode is absent, effective mode MUST default to strict.
  • \n
  • Conforming implementations MUST support strict.
  • \n
  • Implementations MAY support permissive.
  • \n
  • If mode=permissive is configured but not implemented, configuration MUST fail in strict mode and SHOULD emit warning/fallback in permissive mode.
  • \n
  • reject_unknown_fields=true enforces closed-schema behavior for mapped roles.
  • \n
\n

9.11 dependencies schema#

\n

Example:

\n
dependencies:\n  default_reltype: FINISHTOSTART\n  treat_missing_target_as_blocked: true\n  enforce_unique_uid: true\n  unresolved_target_severity: warning\n  require_resolved_uid_on_write: false\n

Rules:

\n
    \n
  • default_reltype MUST be one of the allowed reltype values in §10.2.
  • \n
  • treat_missing_target_as_blocked controls whether missing/unresolvable dependency targets contribute to blocked-state evaluation (§10.2.5).
  • \n
  • If treat_missing_target_as_blocked is absent, effective value MUST default to true.
  • \n
  • enforce_unique_uid=true enforces uniqueness at validation/write time.
  • \n
  • If enforce_unique_uid is absent, effective value MUST default to true.
  • \n
  • unresolved_target_severity MUST be warning or error.
  • \n
  • require_resolved_uid_on_write=true requires dependency UID resolution success for add/update operations.
  • \n
\n\n

Example:

\n
links:\n  extensions: [".md"]\n  unresolved_default_severity: warning\n  update_references_on_rename: true\n

Rules:

\n
    \n
  • extensions defines extension trial order for extensionless targets.
  • \n
  • unresolved_default_severity MUST be warning or error.
  • \n
  • update_references_on_rename=true enables rename-time link rewrite behavior when supported.
  • \n
\n

9.13 title schema#

\n

Example (storage=frontmatter):

\n
title:\n  storage: frontmatter\n  filename_format: custom\n  custom_filename_template: "{{date}} {{title}}"\n

Example (storage=filename):

\n
title:\n  storage: filename\n

Rules:

\n
    \n
  • storage MUST be frontmatter or filename.
  • \n
  • when storage=frontmatter, filename_format MUST be title, zettel, timestamp, or custom.
  • \n
  • when storage=frontmatter and filename_format=custom, custom_filename_template MUST be provided and non-empty.
  • \n
  • when storage=filename, filename_format and custom_filename_template MAY be present for compatibility input but MUST be ignored for canonical write behavior.
  • \n
  • Read precedence MUST be storage-mode-aware:
      \n
    1. when storage=frontmatter, use mapped title key when present and non-empty, then file basename fallback;
    2. \n
    3. when storage=filename, use file basename first, then mapped title fallback when basename is unavailable.
    4. \n
    \n
  • \n
  • If frontmatter and basename titles both exist and differ, the source authoritative for active storage MUST win.
  • \n
  • If storage=filename, canonical writes MUST treat filename as title source, MUST rename on title change, and MUST ignore filename_format and custom_filename_template.
  • \n
  • If storage=frontmatter, canonical writes MUST persist mapped title key; filename_format and custom_filename_template govern create-time filename generation.
  • \n
\n

Informative mapping to TaskNotes settings:

\n
    \n
  • title.storage=filename corresponds to storeTitleInFilename=true.
  • \n
  • title.filename_format corresponds to taskFilenameFormat.
  • \n
  • title.custom_filename_template corresponds to customFilenameTemplate.
  • \n
\n

9.14 templating schema#

\n

templating defines optional create-time template behavior.\nThis schema is required only for implementations claiming profile templating (§7.3.3).

\n

Example:

\n
templating:\n  enabled: true\n  template_path: Templates/Task.md\n  failure_mode: warning_fallback\n  unknown_variable_policy: preserve\n

Rules:

\n
    \n
  • enabled MUST be boolean.
  • \n
  • If enabled=true, template_path MUST be provided and non-empty.
  • \n
  • failure_mode MUST be error or warning_fallback when present.
  • \n
  • unknown_variable_policy MUST be preserve or empty when present.
  • \n
  • If failure_mode is absent, effective value MUST default to warning_fallback.
  • \n
  • If unknown_variable_policy is absent, effective value MUST default to preserve.
  • \n
  • Implementations claiming templating MUST support portable double-brace variables from §5.3.5.
  • \n
  • Implementations not claiming templating MAY ignore templating settings.
  • \n
\n

9.15 reminders schema#

\n

Example:

\n
reminders:\n  date_only_anchor_time: "00:00"\n  apply_defaults_when_explicit: false\n

Rules:

\n
    \n
  • date_only_anchor_time MUST be HH:MM 24-hour local time format.
  • \n
  • date_only_anchor_time is used by §10.3.4 for relative reminders against date-only bases.
  • \n
  • apply_defaults_when_explicit MUST be boolean when present.
  • \n
  • if apply_defaults_when_explicit is absent, effective value MUST default to false.
  • \n
  • apply_defaults_when_explicit=false means explicit input reminders replace default-reminder application at create time.
  • \n
  • apply_defaults_when_explicit=true means explicit create-time reminders are merged with defaults using §10.3.9 deterministic merge rules.
  • \n
\n

9.16 time_tracking schema#

\n

Example:

\n
time_tracking:\n  auto_stop_on_complete: true\n  auto_stop_notification: false\n

Rules:

\n
    \n
  • auto_stop_on_complete MUST be boolean when present.
  • \n
  • auto_stop_notification MUST be boolean when present.
  • \n
  • if auto_stop_on_complete=true, completion-triggered stop behavior MUST follow §5.19.5.
  • \n
  • if auto_stop_notification is absent, effective value MUST default to false.
  • \n
\n

9.17 occurrences schema#

\n

occurrences defines collection-level defaults for recurrence materialization.\nThis schema is required only for implementations claiming profile materialized-occurrences (§7.3.4).

\n

Example:

\n
occurrences:\n  default_materialization: manual\n  default_next_trigger: completion\n  past_horizon: P0D\n  future_horizon: P14D\n

Rules:

\n
    \n
  • default_materialization MUST be one of manual, on_completion, or rolling.
  • \n
  • If default_materialization is absent, effective value MUST default to manual.
  • \n
  • default_next_trigger MUST be completion or completion_or_skip.
  • \n
  • If default_next_trigger is absent, effective value MUST default to completion.
  • \n
  • past_horizon and future_horizon, when present, MUST be ISO 8601 duration strings.
  • \n
  • If default_materialization=rolling, implementations MUST use finite rolling bounds. If bounds are absent, documented finite defaults MUST be used.
  • \n
  • Parent task fields override collection defaults: occurrence_materialization overrides occurrences.default_materialization; occurrence_next_trigger overrides occurrences.default_next_trigger; occurrence_past_horizon and occurrence_future_horizon override occurrences.past_horizon and occurrences.future_horizon.
  • \n
  • If occurrences is absent, the effective behavior is manual materialization and completion next trigger.
  • \n
\n

9.17.1 nlp schema#

\n

nlp advertises optional natural-language capture triggers. These settings\nallow another TaskNotes client to preserve the same capture vocabulary without\nmaking natural-language parsing a requirement of the core profile.

\n

Example:

\n
nlp:\n  triggers:\n    - property_id: tags\n      trigger: "#"\n      enabled: true\n    - property_id: contexts\n      trigger: "@"\n      enabled: true\n    - property_id: priority\n      trigger: "!"\n      enabled: false\n

Rules:

\n
    \n
  • triggers MUST be a list when present.
  • \n
  • Every trigger entry MUST contain non-empty property_id and trigger\nstrings.
  • \n
  • property_id SHOULD use a stable TaskNotes role (tags, contexts,\nprojects, status, or priority) or the stable identifier of a configured\nuser field.
  • \n
  • enabled MUST be boolean when present and MUST default to true.
  • \n
  • Trigger strings MAY contain more than one character.
  • \n
  • Trigger entries with unknown property_id values MUST be preserved by\nconfiguration round-trips and MAY be ignored by clients that cannot resolve\nthe property.
  • \n
  • If nlp is absent, clients MAY use documented local defaults.
  • \n
  • This block controls capture parsing and suggestions only. It MUST NOT change\npersisted task field names or values.
  • \n
\n

Informative mapping to TaskNotes settings:

\n
    \n
  • nlp.triggers corresponds to nlpTriggers.triggers.
  • \n
  • property_id, trigger, and enabled correspond to the plugin fields\npropertyId, trigger, and enabled.
  • \n
\n

9.18 compatibility schema#

\n

Example:

\n
compatibility:\n  read_aliases: true\n  legacy_duration_field: true\n  legacy_local_datetime_input: false\n

Rules:

\n
    \n
  • Compatibility flags MUST default to conservative behavior in new collections.
  • \n
  • legacy_local_datetime_input=true MAY relax strict parsing for offset-less datetimes only in permissive mode; strict mode parsing rules in §3.4.2 still apply.
  • \n
  • Enabled compatibility flags SHOULD be disclosed in conformance output (§7).
  • \n
\n

9.19 Complete configuration example (yaml_file provider)#

\n
spec_version: 0.3.0-rc.3\n\nmapping:\n  title: title\n  status: status\n  priority: priority\n  due: due\n  scheduled: scheduled\n  attachments: attachments\n  completed_date: completedDate\n  date_created: dateCreated\n  date_modified: dateModified\n  recurrence: recurrence\n  recurrence_anchor: recurrenceAnchor\n  complete_instances: completeInstances\n  skipped_instances: skippedInstances\n  recurrence_parent: recurrence_parent\n  occurrence_date: occurrence_date\n  occurrence_materialization: occurrence_materialization\n  occurrence_next_trigger: occurrence_next_trigger\n  occurrence_template: occurrence_template\n  occurrence_past_horizon: occurrence_past_horizon\n  occurrence_future_horizon: occurrence_future_horizon\n  time_entries: timeEntries\n  blocked_by: blockedBy\n  reminders: reminders\n\ntask_detection:\n  method: tag\n  tag: task\n  default_folder: TaskNotes/Tasks\n\ndefaults:\n  status: open\n  priority: normal\n  recurrence_anchor: scheduled\n  reminders:\n    - id: due_minus_1d\n      type: relative\n      relatedTo: due\n      offset: -P1D\n\nstatus:\n  values: [open, in-progress, done, cancelled]\n  default: open\n  completed_values: [done]\n  skipped_values: [cancelled]\n  default_skipped: cancelled\n\nvalidation:\n  mode: strict\n  reject_unknown_fields: false\n\ndependencies:\n  default_reltype: FINISHTOSTART\n  treat_missing_target_as_blocked: true\n  enforce_unique_uid: true\n  unresolved_target_severity: warning\n  require_resolved_uid_on_write: false\n\nlinks:\n  extensions: [".md"]\n  unresolved_default_severity: warning\n  update_references_on_rename: true\n\ntitle:\n  storage: filename\n\ntemplating:\n  enabled: false\n  failure_mode: warning_fallback\n  unknown_variable_policy: preserve\n\nreminders:\n  date_only_anchor_time: "00:00"\n  apply_defaults_when_explicit: false\n\ntime_tracking:\n  auto_stop_on_complete: true\n  auto_stop_notification: false\n\noccurrences:\n  default_materialization: manual\n  default_next_trigger: completion\n  past_horizon: P0D\n  future_horizon: P14D\n\nnlp:\n  triggers:\n    - property_id: tags\n      trigger: "#"\n      enabled: true\n    - property_id: contexts\n      trigger: "@"\n      enabled: true\n    - property_id: projects\n      trigger: "+"\n      enabled: true\n    - property_id: status\n      trigger: "*"\n      enabled: true\n    - property_id: priority\n      trigger: "!"\n      enabled: false\n\ncompatibility:\n  read_aliases: true\n  legacy_duration_field: true\n

9.20 Configuration errors#

\n

Configuration validation MUST report structured errors with key path context.

\n

Examples:

\n
    \n
  • no readable configuration provider available in strict mode
  • \n
  • required effective key unresolved after provider resolution (spec_version or mapping)
  • \n
  • missing mapping.title
  • \n
  • status.default not present in status.values
  • \n
  • status.completed_values contains a value not present in status.values
  • \n
  • status.skipped_values contains a value not present in status.values
  • \n
  • status.default_skipped not present in status.skipped_values
  • \n
  • status.skipped_values overlaps status.completed_values when materialized-occurrences is claimed
  • \n
  • unsupported validation.mode
  • \n
  • validation.mode=permissive but permissive mode is not implemented
  • \n
  • invalid task_detection.method
  • \n
  • invalid task_detection.methods entry
  • \n
  • empty task_detection.tag when tag method is enabled
  • \n
  • missing task_detection.property_name when property method is enabled
  • \n
  • invalid task_detection.combine
  • \n
  • invalid dependencies.default_reltype
  • \n
  • invalid dependencies.unresolved_target_severity
  • \n
  • invalid links.unresolved_default_severity
  • \n
  • invalid title.storage
  • \n
  • invalid title.filename_format
  • \n
  • missing title.filename_format when title.storage=frontmatter
  • \n
  • missing title.custom_filename_template when title.storage=frontmatter and title.filename_format=custom
  • \n
  • missing templating.template_path when templating.enabled=true
  • \n
  • invalid templating.failure_mode
  • \n
  • invalid templating.unknown_variable_policy
  • \n
  • invalid reminders.date_only_anchor_time
  • \n
  • invalid reminders.apply_defaults_when_explicit
  • \n
  • invalid time_tracking.auto_stop_on_complete
  • \n
  • invalid time_tracking.auto_stop_notification
  • \n
  • invalid occurrences.default_materialization
  • \n
  • invalid occurrences.default_next_trigger
  • \n
  • invalid occurrences.past_horizon
  • \n
  • invalid occurrences.future_horizon
  • \n
  • invalid nlp.triggers
  • \n
  • empty nlp.triggers[].property_id
  • \n
  • empty nlp.triggers[].trigger
  • \n
  • invalid nlp.triggers[].enabled
  • \n
\n

9.21 Default collection state#

\n

This section describes what a fresh tasknotes vault looks like before any user customization. Implementations that read an existing tasknotes vault without a tasknotes.yaml SHOULD apply these defaults when data.json is absent or fields are missing.

\n

Folder layout#

\n
MyVault/\n├── TaskNotes/\n│   ├── Tasks/          ← new tasks created here by default\n│   └── Archive/        ← archived tasks moved here (if moveArchivedTasks=true)\n└── .obsidian/\n    └── plugins/\n        └── tasknotes/\n            └── data.json\n

Task detection#

\n

Default method: tag. A file is a task if it contains the tag #task in its frontmatter tags array or inline in the body.

\n

Default field mapping#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Semantic roleDefault storage key
titletitle
statusstatus
prioritypriority
duedue
scheduledscheduled
contextscontexts
projectsprojects
time_estimatetimeEstimate
completed_datecompletedDate
date_createddateCreated
date_modifieddateModified
recurrencerecurrence
recurrence_anchorrecurrence_anchor
complete_instancescomplete_instances
skipped_instancesskipped_instances
recurrence_parentrecurrence_parent
occurrence_dateoccurrence_date
occurrence_materializationoccurrence_materialization
occurrence_next_triggeroccurrence_next_trigger
occurrence_templateoccurrence_template
occurrence_past_horizonoccurrence_past_horizon
occurrence_future_horizonoccurrence_future_horizon
time_entriestimeEntries
blocked_byblockedBy
remindersreminders
\n

Note: recurrenceAnchor, completeInstances, and skippedInstances are accepted as aliases on read (§2.5). The mixed camelCase/snake_case defaults are intentional for compatibility with historical TaskNotes frontmatter.

\n

Default statuses#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
ValueLabelisCompletedOrder
noneNonefalse0
openOpenfalse1
in-progressIn progressfalse2
doneDonetrue3
\n

Default status on create: open. Default completed status (first isCompleted=true): done.\nNo skipped status is configured by default; implementations that support materialized occurrence skips MUST require configuration or expose a documented default before writing skipped occurrence state.

\n

Default priorities#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
ValueLabelWeight
noneNone0
lowLow1
normalNormal2
highHigh3
\n

Default priority on create: normal.

\n

Title and filename defaults#

\n
    \n
  • title.storage: filename (filename/path is the authoritative title source)
  • \n
  • default basename generation under title.storage=filename derives from semantic title using filename-safe sanitization
  • \n
  • implementations MAY also keep mapped title in frontmatter as a synchronized compatibility mirror
  • \n
  • TaskNotes data.json may still contain legacy taskFilenameFormat values such as zettel, but these are compatibility inputs rather than the forward default when title.storage=filename
  • \n
  • title is read from filename first; frontmatter title is compatibility fallback when filename-derived title is unavailable (§2.2.2)
  • \n
\n

Time tracking defaults#

\n
    \n
  • auto_stop_on_complete: true
  • \n
  • auto_stop_notification: false
  • \n
\n\n
    \n
  • useFrontmatterMarkdownLinks: false — wikilinks used by default (e.g. [[task-name]])
  • \n
  • To use markdown link format, the obsidian-frontmatter-markdown-links plugin must also be installed
  • \n
\n

Effective configuration for a minimal fresh vault#

\n

When neither data.json nor tasknotes.yaml is present, implementations MUST use the following effective configuration:

\n
spec_version: 0.3.0-rc.3   # synthesized\nmapping:\n  title: title\n  status: status\n  priority: priority\n  due: due\n  scheduled: scheduled\n  contexts: contexts\n  projects: projects\n  attachments: attachments\n  time_estimate: timeEstimate\n  completed_date: completedDate\n  date_created: dateCreated\n  date_modified: dateModified\n  recurrence: recurrence\n  recurrence_anchor: recurrence_anchor\n  complete_instances: complete_instances\n  skipped_instances: skipped_instances\n  recurrence_parent: recurrence_parent\n  occurrence_date: occurrence_date\n  occurrence_materialization: occurrence_materialization\n  occurrence_next_trigger: occurrence_next_trigger\n  occurrence_template: occurrence_template\n  occurrence_past_horizon: occurrence_past_horizon\n  occurrence_future_horizon: occurrence_future_horizon\n  time_entries: timeEntries\n  blocked_by: blockedBy\n  reminders: reminders\ntask_detection:\n  method: tag\n  tag: task\n  default_folder: TaskNotes/Tasks\nstatus:\n  values: [none, open, in-progress, done]\n  default: open\n  completed_values: [done]\ntitle:\n  storage: filename\ntime_tracking:\n  auto_stop_on_complete: true\n  auto_stop_notification: false\nlinks:\n  use_markdown_format: false\n  extensions: [".md"]\n  unresolved_default_severity: warning\n  update_references_on_rename: true\n
","text":"9.1 Purpose# This section defines the normative configuration model for collections using tasknotes-spec. 9.2 Configuration provider model# Implementations MUST derive an effective configuration from one or more configuration providers. A provider is a source adapter that returns a partial configuration normalized to this section's schema. Implementations MUST: support at least one provider, document supported providers, document provider precedence order, disclose active providers and fallback behavior in conformance output (§7). 9.2.1 Common provider types# Common providers include: yaml_file: a tasknotes.yaml document at collection root, tasknotes_plugin_data_json: .obsidian/plugins/tasknotes/data.json, built_in_defaults: implementation defaults, optional runtime/CLI/env overrides. This list is not exhaustive. 9.2.2 Deterministic precedence and merge# Provider precedence MUST be deterministic. Unless explicitly documented otherwise, implementations MUST resolve configuration per top-level key: for each key in §9.3/§9.4, the highest-precedence provider that supplies that key wins, winning object values replace lower-precedence object values as whole objects (no implicit deep merge), after top-level selection, implementations MUST apply documented schema defaults for missing nested keys before exposing effective configuration. If an implementation supports deep-merge behavior, it MUST be explicitly documented and deterministic. 9.2.3 Strict vs permissive provider behavior# In strict mode: failure to resolve required effective keys (spec_version, mapping) MUST be a configuration error. If permissive mode is implemented, then in permissive mode: implementations MAY continue with defaults when providers are missing/unreadable, implementations MUST emit configuration warnings, implementations MUST disclose that effective configuration is partial/default-derived. 9.2.4 TaskNotes plugin provider (data.json)# The TaskNotes plugin stores settings in .obsidian/plugins/tasknotes/data.json within the vault root. When using this file as a configuration provider, normalization MUST apply the field mapping in the table below. Key mapping table (data.json key → spec effective config): data.json key Spec key Notes fieldMapping mapping Normalize role names: dateCreated→date_created, completedDate→completed_date, recurrenceAnchor→recurrence_anchor, completeInstances→complete_instances, skippedInstances→skipped_instances, recurrenceParent→recurrence_parent, occurrenceDate→occurrence_date, occurrenceMaterialization→occurrence_materialization, occurrenceNextTrigger→occurrence_next_trigger, occurrenceTemplate→occurrence_template, occurrencePastHorizon→occurrence_past_horizon, occurrenceFutureHorizon→occurrence_future_horizon, blockedBy→blocked_by, timeEntries→time_entries, timeEstimate→time_estimate storeTitleInFilename title.storage true → \"filename\", false → \"frontmatter\" taskFilenameFormat title.filename_format Values: \"title\", \"zettel\", \"timestamp\", \"custom\"; used only when title.storage=frontmatter for canonical writes, but preserved as compatibility input when present customFilenameTemplate title.custom_filename_template Template string, e.g. \"{title}\"; used only when title.storage=frontmatter and filename_format=custom taskCreationDefaults.useBodyTemplate templating.enabled boolean taskCreationDefaults.bodyTemplate templating.template_path Path to template file customStatuses[*].value status.values Ordered array of status value strings defaultTaskStatus status.default Default status string customStatuses[isCompleted=true][*].value status.completed_values Statuses where isCompleted: true defaultTaskPriority defaults.priority Default priority string autoStopTimeTrackingOnComplete time_tracking.auto_stop_on_complete boolean autoStopTimeTrackingNotification time_tracking.auto_stop_notification boolean taskIdentificationMethod task_detection.method \"tag\" or \"property\" taskTag task_detection.tag Tag string used when method=\"tag\" taskPropertyName task_detection.property_name Frontmatter key used when method=\"property\" taskPropertyValue task_detection.property_value Expected value; empty means key must exist tasksFolder task_detection.default_folder Default folder for new tasks excludedFolders task_detection.excluded_folders Comma-separated folder paths to exclude moveArchivedTasks archive.move_on_archive boolean archiveFolder archive.folder Archive destination folder useFrontmatterMarkdownLinks links.use_markdown_format boolean; see §11 Key data.json fields with defaults (for cold-start reading of a vault with no tasknotes.yaml): Field Type Default Meaning tasksFolder string \"TaskNotes/Tasks\" Default folder for new task files taskIdentificationMethod \"tag\" | \"property\" \"tag\" How task files are identified taskTag string \"task\" Tag that identifies task files (when method=\"tag\") taskPropertyName string \"\" Frontmatter key for property-based identification taskPropertyValue string \"\" Expected value for property-based identification (empty = key presence) storeTitleInFilename boolean true Title storage mode taskFilenameFormat \"title\" | \"zettel\" | \"timestamp\" | \"custom\" \"title\" Filename generation format customFilenameTemplate string \"{title}\" Template for \"custom\" filename format defaultTaskStatus string \"open\" Default status on create defaultTaskPriority string \"normal\" Default priority on create customStatuses StatusConfig[] see object shape below Ordered status definitions autoStopTimeTrackingOnComplete boolean true Auto-stop active session on completion autoStopTimeTrackingNotification boolean false Show notification when auto-stopping useFrontmatterMarkdownLinks boolean false Use markdown links in frontmatter (requires obsidian-frontmatter-markdown-links plugin) moveArchivedTasks boolean false Move task file to archive folder on archive archiveFolder string \"TaskNotes/Archive\" Archive destination folder excludedFolders string \"\" Comma-separated folders to exclude from task indexing StatusConfig object shape: { \"id\": \"done\", \"value\": \"done\", \"label\": \"Done\", \"color\": \"#00aa00\", \"isCompleted\": true, \"order\": 3, \"autoArchive\": false, \"autoArchiveDelay\": 5 } spec_version is not present in data.json. Implementations MUST synthesize an effective spec_version as described in §9.5. Provider keys not listed above MAY be ignored by tasknotes-spec consumers. 9.3 Required top-level keys# Required keys apply to the effective configuration after provider resolution. Key Type Required Description spec_version string yes target spec version (provider-supplied or synthesized per §9.5) mapping object yes semantic role to storage key mapping 9.4 Recommended top-level keys# Key Type Description task_detection object task file identification rules defaults object role defaults used during create status object status set and completed-value semantics validation object validation behavior (strict required, permissive optional) links object link parsing/resolution behavior title object title source and filename behavior policy templating object optional create-time templating behavior policy dependencies object dependency behavior policy reminders object reminder behavior policy time_tracking object time-tracking management behavior policy occurrences object recurrence materialization defaults and bounds compatibility object legacy alias/behavior switches 9.5 spec_version behavior# spec_version MUST be a semantic version string. Pre-release identifiers are valid (for example 0.3.0-rc.3). Implementations in strict mode MUST reject unsupported major versions. If permissive mode is implemented, permissive mode MAY proceed with warning when major version differs. If a provider does not supply spec_version (for example TaskNotes data.json), implementations MUST synthesize an effective spec_version matching their target tasknotes-spec version and SHOULD disclose that it was synthesized. 9.6 mapping schema# mapping MUST map semantic roles (from §2) to string storage keys. Minimum required roles in mapping: title status completed_date date_created date_modified If semantic role id is supported (§2.6.5), mapping SHOULD include id. If profile materialized-occurrences is claimed, mapping MUST include recurrence_parent and occurrence_date, and SHOULD include parent policy roles (occurrence_materialization, occurrence_next_trigger, occurrence_template, occurrence_past_horizon, occurrence_future_horizon). Example: mapping: title: title status: status date_created: dateCreated date_modified: dateModified completed_date: completedDate recurrence: recurrence recurrence_anchor: recurrenceAnchor complete_instances: completeInstances skipped_instances: skippedInstances recurrence_parent: recurrence_parent occurrence_date: occurrence_date occurrence_materialization: occurrence_materialization occurrence_next_trigger: occurrence_next_trigger occurrence_template: occurrence_template occurrence_past_horizon: occurrence_past_horizon occurrence_future_horizon: occurrence_future_horizon time_entries: timeEntries blocked_by: blockedBy reminders: reminders attachments: attachments 9.7 task_detection schema# task_detection controls how task files are identified within the vault. Detection methods# The tasknotes plugin natively supports two identification methods, controlled by taskIdentificationMethod in data.json (mapped to task_detection.method): tag (default) — A markdown file is a task if it contains the configured tag (default #task) in its frontmatter tags array or inline in the body. Configured by task_detection.tag. property — A markdown file is a task if a specified frontmatter property has a specified value (or exists, if value is empty). Configured by task_detection.property_name and task_detection.property_value. Schema and selection rules: task_detection MAY specify either: method (single-method form), or methods (multi-method form; non-empty list). If both are present, methods MUST take precedence and implementations SHOULD emit a configuration warning. If neither is present, effective detection method MUST default to tag. method MUST be tag or property. methods entries MUST be unique and MUST be from: tag property field_presence field_match Method-specific required keys: when tag is enabled, effective task_detection.tag MUST be non-empty (default task when absent); when property is enabled, task_detection.property_name MUST be provided and non-empty; task_detection.property_value MAY be empty (empty means key-exists semantics). If methods has more than one entry, task_detection.combine controls combination semantics (§9.7.3). If omitted, it MUST default to or. 9.7.1 Tag matching semantics# When task_detection.method=tag, matching MUST follow these rules: Normalize configured task_detection.tag by stripping one leading # when present. Compare tag names case-insensitively after normalization. Frontmatter matching: tags MAY be a list of strings or a single string. each tag value is normalized by trimming surrounding whitespace and stripping one leading #. match requires exact normalized equality (for example task matches #task; task does not match tasking). Body matching: only markdown text outside fenced code blocks and inline code spans is considered, a match requires a hashtag token with exact normalized name (for example #task), partial-word matches MUST NOT count (for example #tasking does not match configured task). If either frontmatter or body matches, the file is identified as a task. 9.7.2 Property matching semantics# When property detection is enabled (method=property or methods includes property): task_detection.property_name MUST name the frontmatter key to inspect. If task_detection.property_value is non-empty, match requires semantic equality with the configured value. If task_detection.property_value is empty or absent, match requires key presence only. 9.7.3 Multi-method extension semantics# tasknotes.yaml-level providers MAY additionally support: field_presence (example: required key status) field_match (example: type == \"task\") Extension-key shape: field_presence: string or list of required frontmatter keys. field_match: object map of key -> expected scalar value for exact semantic equality checks. If multiple methods are configured in tasknotes.yaml, task_detection.combine MUST define combinator semantics: or (default): file is a task if any enabled method matches. and: file is a task only if all enabled methods match. If task_detection.combine is absent, implementations MUST default to or. Implementations MUST exclude folders listed in task_detection.excluded_folders from task indexing. Executable conformance: adapters participating in the fixture suite SHOULD expose config.detect_task_file to evaluate these detection semantics against fixture inputs. Example (tasknotes.yaml, equivalent to tag-based default): task_detection: method: tag tag: task default_folder: TaskNotes/Tasks Example (property-based): task_detection: method: property property_name: type property_value: task 9.8 defaults schema# defaults defines values used at create time when caller input omits a role. Defaults MUST NOT override explicit user input. Example: defaults: status: open priority: normal recurrence_anchor: scheduled reminders: - id: due_minus_1d type: relative relatedTo: due offset: -P1D defaults.reminders behavior is defined in §10.3.9. 9.9 status schema# status defines known status values and completion semantics. Example: status: values: [open, in-progress, done, cancelled] default: open completed_values: [done] skipped_values: [cancelled] default_skipped: cancelled Rules: default MUST be one of values. completed_values MUST be a non-empty list. Each completed_values entry MUST be in values. skipped_values, when present, MUST be a list whose entries are in values. default_skipped, when present, MUST be in skipped_values. For implementations claiming materialized-occurrences, skipped_values MUST NOT overlap completed_values. Implementations claiming materialized-occurrences MUST provide at least one skipped value or fail skip of materialized occurrence notes deterministically (§5.20.3). Non-recurring completion MUST use this list, not hardcoded literals. When a complete operation does not provide an explicit target status, writers MUST use the first entry of completed_values. When a materialized occurrence skip operation does not provide an explicit skipped status, writers MUST use default_skipped when present, otherwise the first entry of skipped_values. 9.10 validation schema# Example: validation: mode: strict reject_unknown_fields: false Rules: mode MUST be strict or permissive when present. If mode is absent, effective mode MUST default to strict. Conforming implementations MUST support strict. Implementations MAY support permissive. If mode=permissive is configured but not implemented, configuration MUST fail in strict mode and SHOULD emit warning/fallback in permissive mode. reject_unknown_fields=true enforces closed-schema behavior for mapped roles. 9.11 dependencies schema# Example: dependencies: default_reltype: FINISHTOSTART treat_missing_target_as_blocked: true enforce_unique_uid: true unresolved_target_severity: warning require_resolved_uid_on_write: false Rules: default_reltype MUST be one of the allowed reltype values in §10.2. treat_missing_target_as_blocked controls whether missing/unresolvable dependency targets contribute to blocked-state evaluation (§10.2.5). If treat_missing_target_as_blocked is absent, effective value MUST default to true. enforce_unique_uid=true enforces uniqueness at validation/write time. If enforce_unique_uid is absent, effective value MUST default to true. unresolved_target_severity MUST be warning or error. require_resolved_uid_on_write=true requires dependency UID resolution success for add/update operations. 9.12 links schema# Example: links: extensions: [\".md\"] unresolved_default_severity: warning update_references_on_rename: true Rules: extensions defines extension trial order for extensionless targets"},{"route":"/developers/specification/10-dependencies-and-reminders/","title":"10. Dependencies and Reminders","description":"This section defines canonical semantics for task dependencies (blocked_by) and task reminders (reminders).","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:10-dependencies-and-reminders.md","namespace":"specification","relativePath":"10-dependencies-and-reminders.md","raw":"# 10. Dependencies and Reminders\n\n## 10.1 Purpose\n\nThis section defines canonical semantics for task dependencies (`blocked_by`) and task reminders (`reminders`).\n\n## 10.2 Dependencies (`blocked_by`)\n\n### 10.2.1 Data shape\n\n`blocked_by` MUST be a list of dependency entries.\n\nEach entry MUST be an object with:\n\n- `uid` (required): reference to a blocking task (link or string)\n- `reltype` (required): one of\n - `FINISHTOSTART`\n - `STARTTOSTART`\n - `FINISHTOFINISH`\n - `STARTTOFINISH`\n- `gap` (optional): ISO 8601 duration string\n\nIf `reltype` is omitted on read in compatibility mode, implementations MAY treat it as `FINISHTOSTART` and SHOULD emit a warning.\n\n### 10.2.2 UID normalization\n\nImplementations SHOULD normalize `uid` values to a canonical reference representation on write.\n\nIf link formats are supported, both wikilink and markdown-link forms MAY be read. Canonical write form MUST be documented.\nLink parsing and resolution MUST follow §11.\n\n### 10.2.3 Dependency uniqueness\n\nWithin a task, dependency entries are keyed by normalized `uid`.\n\nPolicy is configuration-driven and MUST be deterministic:\n\n- when `dependencies.enforce_unique_uid=true` (default), duplicate normalized `uid` values MUST NOT be accepted as canonical persisted state:\n - strict mode: duplicates MUST fail validation/write with `duplicate_dependency_uid`;\n - permissive mode: implementations MAY either fail or normalize to one entry, but MUST emit `duplicate_dependency_uid`.\n- when `dependencies.enforce_unique_uid=false`, duplicates MAY be preserved as compatibility behavior.\n\nThe active policy MUST be documented in conformance claims.\n\n### 10.2.4 Self-dependency\n\nA task MUST NOT depend on itself.\n\nSelf-dependency is a validation error.\n\n### 10.2.5 Blocking semantics (v0.1)\n\nFor v0.1, blocking evaluation MUST be status-presence based:\n\n1. A task is blocked if it has at least one unresolved dependency.\n2. A dependency on a resolvable task is unresolved when the referenced task is not in a completed status.\n3. Completed status MUST be determined from configured `status.completed_values`.\n4. For recurring referenced tasks in v0.1, unresolved/resolved evaluation MUST use base `status` only; `complete_instances`/`skipped_instances` are not consulted.\n5. When a referenced task is missing/unresolvable, whether that missing target contributes to blocked-state evaluation MUST follow `dependencies.treat_missing_target_as_blocked` (§9.11, default `true`).\n\nFor v0.1, `reltype` and `gap` are preserved and validated but MUST NOT change the unresolved/resolved decision.\n\n### 10.2.6 Missing referenced task\n\nWhen `uid` cannot be resolved:\n\n- implementations SHOULD emit `unresolved_dependency_target`.\n- blocked-state contribution for this missing target MUST follow `dependencies.treat_missing_target_as_blocked` (§9.11).\n- issue severity SHOULD follow `dependencies.unresolved_target_severity` (default: `warning`).\n- for `blocked_by.uid`, this dependency-specific severity policy MUST take precedence over `links.unresolved_default_severity`.\n- parse failures that produce `invalid_link_format` and containment violations that produce `path_traversal` remain error-severity conditions from §11.\n- if `dependencies.require_resolved_uid_on_write=true`, add/update MUST fail with error.\n\n### 10.2.7 Cycles\n\nImplementations MUST reject direct self-cycles.\n\nDetection of multi-hop dependency cycles is RECOMMENDED but not required for `core-lite` or `recurrence` profiles.\n\n### 10.2.8 Reverse relation field\n\nSome implementations maintain reverse relationships (for example `blocking`). Such fields are derived and non-canonical in this spec unless explicitly mapped.\n\nIf maintained, reverse updates SHOULD remain consistent with `blocked_by` edits.\n\n### 10.2.9 Dependency operation semantics\n\n#### Add dependency\n\nAdd dependency MUST:\n\n- validate entry shape,\n- handle duplicates by policy (preserve, normalize, or reject),\n- preserve unrelated dependency entries,\n- update `date_modified` on change.\n\n#### Remove dependency\n\nRemove dependency MUST remove by normalized `uid` and be idempotent.\n\n#### Replace dependencies\n\nReplace behavior MUST be explicit operation mode (not default for patch update).\n\n### 10.2.10 Dependency examples\n\nExample entry:\n\n```yaml\nblockedBy:\n - uid: \"[[prepare-metrics]]\"\n reltype: FINISHTOSTART\n gap: PT4H\n```\n\nExample unresolved dependency (target missing):\n\n```yaml\nblockedBy:\n - uid: \"[[non-existent-task]]\"\n reltype: FINISHTOSTART\n```\n\n## 10.3 Reminders (`reminders`)\n\n### 10.3.1 Data shape\n\n`reminders` MUST be a list of reminder entries.\n\nEach reminder MUST include:\n\n- `id` (required): unique string within the task\n- `type` (required): `absolute` or `relative`\n\nOptional field:\n\n- `description` string\n\nType-specific fields:\n\n- `absolute`: requires `absoluteTime` datetime\n- `relative`: requires `relatedTo` (`due` or `scheduled`) and `offset` (ISO 8601 duration)\n\n### 10.3.2 Reminder uniqueness\n\nReminder `id` values MUST be unique within the task.\n\nIf duplicates occur:\n\n- strict mode: MUST raise `duplicate_reminder_id`.\n- permissive mode: MAY normalize deterministically and emit warning.\n\n### 10.3.3 Relative reminder base\n\n`relatedTo` MUST reference semantic role `due` or `scheduled`.\n\nIf the referenced role is absent, the reminder is unresolved.\n\n### 10.3.4 Trigger instant computation\n\nTrigger instant MUST be computed as follows:\n\n1. If `type=absolute`, trigger = `absoluteTime` instant.\n2. If `type=relative`,\n - resolve base field from `relatedTo`,\n - if base is datetime: use that instant,\n - if base is date: convert to local datetime at configured `reminders.date_only_anchor_time`,\n - trigger = base + `offset`.\n\nIf `reminders.date_only_anchor_time` is not configured, implementations MUST use `00:00` local time.\n\n### 10.3.5 Offset semantics\n\n`offset` MUST be a valid ISO 8601 duration with optional sign.\n\n- negative offset = before base\n- positive offset = after base\n- zero offset = at base instant\n\n### 10.3.6 Invalid mixed fields\n\nEntries with incompatible field combinations MUST fail validation in strict mode.\n\nExamples:\n\n- `type=absolute` with `relatedTo` and no `absoluteTime`\n- `type=relative` with `absoluteTime` and missing `offset`\n\n### 10.3.7 Reminder ordering\n\nWhen computing reminder schedules, implementations MUST sort by trigger instant ascending.\n\nFor identical trigger instants, implementations MUST use stable tie-break ordering by `id` ascending.\n\n### 10.3.8 Reminder operation semantics\n\n#### Add reminder\n\nAdd reminder MUST validate shape and unique `id`, then update `date_modified`.\n\nIf `id` is omitted by caller and implementation supports auto-ID generation, generated IDs MUST be unique within the task.\n\n#### Update reminder\n\nUpdate reminder MUST address reminders by `id` and be patch-by-default.\n\n#### Remove reminder\n\nRemove reminder by `id` MUST be idempotent.\n\n### 10.3.9 Default reminders\n\nIf `defaults.reminders` is configured (see §9):\n\n- create without explicit reminders MUST apply defaults.\n- create with explicit reminders MUST follow `reminders.apply_defaults_when_explicit` (§9.15):\n - `false` (default): explicit reminders replace defaults.\n - `true`: explicit reminders are merged with defaults.\n\nDeterministic merge rules when `apply_defaults_when_explicit=true`:\n\n1. Start with explicit reminders in caller order.\n2. Append each default reminder whose `id` is not already present.\n3. If explicit and default reminders share an `id`, explicit reminder MUST win.\n\n### 10.3.10 Reminder examples\n\nRelative reminder:\n\n```yaml\nreminders:\n - id: due_minus_15m\n type: relative\n relatedTo: due\n offset: -PT15M\n```\n\nAbsolute reminder:\n\n```yaml\nreminders:\n - id: call_now\n type: absolute\n absoluteTime: 2026-02-20T09:00:00Z\n```\n\n### 10.3.11 Reminder resolution error handling\n\nIf relative reminder base is unavailable (`relatedTo=due` but no `due` field):\n\n- strict mode: validation error `unresolvable_reminder_base`.\n- permissive mode: warning and reminder excluded from trigger computation.\n\n## 10.4 Interactions\n\n### 10.4.1 Rename interaction\n\nIf implementation supports rename/reference updates, dependency `uid` references SHOULD be updated consistently with other link references.\n\n### 10.4.2 Completion interaction\n\nChanging task completion state does not automatically remove dependencies or reminders unless explicitly configured.\n\n### 10.4.3 Archive interaction\n\nArchive operations MAY suppress reminder delivery in runtime systems, but archive MUST NOT silently delete reminder records from persisted frontmatter unless explicitly requested.\n","aliases":["/spec/10-dependencies-and-reminders/"],"toc":[{"level":2,"id":"101-purpose","text":"10.1 Purpose"},{"level":2,"id":"102-dependencies-blockedby","text":"10.2 Dependencies (blocked_by)"},{"level":3,"id":"1021-data-shape","text":"10.2.1 Data shape"},{"level":3,"id":"1022-uid-normalization","text":"10.2.2 UID normalization"},{"level":3,"id":"1023-dependency-uniqueness","text":"10.2.3 Dependency uniqueness"},{"level":3,"id":"1024-self-dependency","text":"10.2.4 Self-dependency"},{"level":3,"id":"1025-blocking-semantics-v01","text":"10.2.5 Blocking semantics (v0.1)"},{"level":3,"id":"1026-missing-referenced-task","text":"10.2.6 Missing referenced task"},{"level":3,"id":"1027-cycles","text":"10.2.7 Cycles"},{"level":3,"id":"1028-reverse-relation-field","text":"10.2.8 Reverse relation field"},{"level":3,"id":"1029-dependency-operation-semantics","text":"10.2.9 Dependency operation semantics"},{"level":3,"id":"10210-dependency-examples","text":"10.2.10 Dependency examples"},{"level":2,"id":"103-reminders-reminders","text":"10.3 Reminders (reminders)"},{"level":3,"id":"1031-data-shape","text":"10.3.1 Data shape"},{"level":3,"id":"1032-reminder-uniqueness","text":"10.3.2 Reminder uniqueness"},{"level":3,"id":"1033-relative-reminder-base","text":"10.3.3 Relative reminder base"},{"level":3,"id":"1034-trigger-instant-computation","text":"10.3.4 Trigger instant computation"},{"level":3,"id":"1035-offset-semantics","text":"10.3.5 Offset semantics"},{"level":3,"id":"1036-invalid-mixed-fields","text":"10.3.6 Invalid mixed fields"},{"level":3,"id":"1037-reminder-ordering","text":"10.3.7 Reminder ordering"},{"level":3,"id":"1038-reminder-operation-semantics","text":"10.3.8 Reminder operation semantics"},{"level":3,"id":"1039-default-reminders","text":"10.3.9 Default reminders"},{"level":3,"id":"10310-reminder-examples","text":"10.3.10 Reminder examples"},{"level":3,"id":"10311-reminder-resolution-error-handling","text":"10.3.11 Reminder resolution error handling"},{"level":2,"id":"104-interactions","text":"10.4 Interactions"},{"level":3,"id":"1041-rename-interaction","text":"10.4.1 Rename interaction"},{"level":3,"id":"1042-completion-interaction","text":"10.4.2 Completion interaction"},{"level":3,"id":"1043-archive-interaction","text":"10.4.3 Archive interaction"}],"html":"

10.1 Purpose#

\n

This section defines canonical semantics for task dependencies (blocked_by) and task reminders (reminders).

\n

10.2 Dependencies (blocked_by)#

\n

10.2.1 Data shape#

\n

blocked_by MUST be a list of dependency entries.

\n

Each entry MUST be an object with:

\n
    \n
  • uid (required): reference to a blocking task (link or string)
  • \n
  • reltype (required): one of
      \n
    • FINISHTOSTART
    • \n
    • STARTTOSTART
    • \n
    • FINISHTOFINISH
    • \n
    • STARTTOFINISH
    • \n
    \n
  • \n
  • gap (optional): ISO 8601 duration string
  • \n
\n

If reltype is omitted on read in compatibility mode, implementations MAY treat it as FINISHTOSTART and SHOULD emit a warning.

\n

10.2.2 UID normalization#

\n

Implementations SHOULD normalize uid values to a canonical reference representation on write.

\n

If link formats are supported, both wikilink and markdown-link forms MAY be read. Canonical write form MUST be documented.\nLink parsing and resolution MUST follow §11.

\n

10.2.3 Dependency uniqueness#

\n

Within a task, dependency entries are keyed by normalized uid.

\n

Policy is configuration-driven and MUST be deterministic:

\n
    \n
  • when dependencies.enforce_unique_uid=true (default), duplicate normalized uid values MUST NOT be accepted as canonical persisted state:
      \n
    • strict mode: duplicates MUST fail validation/write with duplicate_dependency_uid;
    • \n
    • permissive mode: implementations MAY either fail or normalize to one entry, but MUST emit duplicate_dependency_uid.
    • \n
    \n
  • \n
  • when dependencies.enforce_unique_uid=false, duplicates MAY be preserved as compatibility behavior.
  • \n
\n

The active policy MUST be documented in conformance claims.

\n

10.2.4 Self-dependency#

\n

A task MUST NOT depend on itself.

\n

Self-dependency is a validation error.

\n

10.2.5 Blocking semantics (v0.1)#

\n

For v0.1, blocking evaluation MUST be status-presence based:

\n
    \n
  1. A task is blocked if it has at least one unresolved dependency.
  2. \n
  3. A dependency on a resolvable task is unresolved when the referenced task is not in a completed status.
  4. \n
  5. Completed status MUST be determined from configured status.completed_values.
  6. \n
  7. For recurring referenced tasks in v0.1, unresolved/resolved evaluation MUST use base status only; complete_instances/skipped_instances are not consulted.
  8. \n
  9. When a referenced task is missing/unresolvable, whether that missing target contributes to blocked-state evaluation MUST follow dependencies.treat_missing_target_as_blocked (§9.11, default true).
  10. \n
\n

For v0.1, reltype and gap are preserved and validated but MUST NOT change the unresolved/resolved decision.

\n

10.2.6 Missing referenced task#

\n

When uid cannot be resolved:

\n
    \n
  • implementations SHOULD emit unresolved_dependency_target.
  • \n
  • blocked-state contribution for this missing target MUST follow dependencies.treat_missing_target_as_blocked (§9.11).
  • \n
  • issue severity SHOULD follow dependencies.unresolved_target_severity (default: warning).
  • \n
  • for blocked_by.uid, this dependency-specific severity policy MUST take precedence over links.unresolved_default_severity.
  • \n
  • parse failures that produce invalid_link_format and containment violations that produce path_traversal remain error-severity conditions from §11.
  • \n
  • if dependencies.require_resolved_uid_on_write=true, add/update MUST fail with error.
  • \n
\n

10.2.7 Cycles#

\n

Implementations MUST reject direct self-cycles.

\n

Detection of multi-hop dependency cycles is RECOMMENDED but not required for core-lite or recurrence profiles.

\n

10.2.8 Reverse relation field#

\n

Some implementations maintain reverse relationships (for example blocking). Such fields are derived and non-canonical in this spec unless explicitly mapped.

\n

If maintained, reverse updates SHOULD remain consistent with blocked_by edits.

\n

10.2.9 Dependency operation semantics#

\n

Add dependency#

\n

Add dependency MUST:

\n
    \n
  • validate entry shape,
  • \n
  • handle duplicates by policy (preserve, normalize, or reject),
  • \n
  • preserve unrelated dependency entries,
  • \n
  • update date_modified on change.
  • \n
\n

Remove dependency#

\n

Remove dependency MUST remove by normalized uid and be idempotent.

\n

Replace dependencies#

\n

Replace behavior MUST be explicit operation mode (not default for patch update).

\n

10.2.10 Dependency examples#

\n

Example entry:

\n
blockedBy:\n  - uid: "[[prepare-metrics]]"\n    reltype: FINISHTOSTART\n    gap: PT4H\n

Example unresolved dependency (target missing):

\n
blockedBy:\n  - uid: "[[non-existent-task]]"\n    reltype: FINISHTOSTART\n

10.3 Reminders (reminders)#

\n

10.3.1 Data shape#

\n

reminders MUST be a list of reminder entries.

\n

Each reminder MUST include:

\n
    \n
  • id (required): unique string within the task
  • \n
  • type (required): absolute or relative
  • \n
\n

Optional field:

\n
    \n
  • description string
  • \n
\n

Type-specific fields:

\n
    \n
  • absolute: requires absoluteTime datetime
  • \n
  • relative: requires relatedTo (due or scheduled) and offset (ISO 8601 duration)
  • \n
\n

10.3.2 Reminder uniqueness#

\n

Reminder id values MUST be unique within the task.

\n

If duplicates occur:

\n
    \n
  • strict mode: MUST raise duplicate_reminder_id.
  • \n
  • permissive mode: MAY normalize deterministically and emit warning.
  • \n
\n

10.3.3 Relative reminder base#

\n

relatedTo MUST reference semantic role due or scheduled.

\n

If the referenced role is absent, the reminder is unresolved.

\n

10.3.4 Trigger instant computation#

\n

Trigger instant MUST be computed as follows:

\n
    \n
  1. If type=absolute, trigger = absoluteTime instant.
  2. \n
  3. If type=relative,
      \n
    • resolve base field from relatedTo,
    • \n
    • if base is datetime: use that instant,
    • \n
    • if base is date: convert to local datetime at configured reminders.date_only_anchor_time,
    • \n
    • trigger = base + offset.
    • \n
    \n
  4. \n
\n

If reminders.date_only_anchor_time is not configured, implementations MUST use 00:00 local time.

\n

10.3.5 Offset semantics#

\n

offset MUST be a valid ISO 8601 duration with optional sign.

\n
    \n
  • negative offset = before base
  • \n
  • positive offset = after base
  • \n
  • zero offset = at base instant
  • \n
\n

10.3.6 Invalid mixed fields#

\n

Entries with incompatible field combinations MUST fail validation in strict mode.

\n

Examples:

\n
    \n
  • type=absolute with relatedTo and no absoluteTime
  • \n
  • type=relative with absoluteTime and missing offset
  • \n
\n

10.3.7 Reminder ordering#

\n

When computing reminder schedules, implementations MUST sort by trigger instant ascending.

\n

For identical trigger instants, implementations MUST use stable tie-break ordering by id ascending.

\n

10.3.8 Reminder operation semantics#

\n

Add reminder#

\n

Add reminder MUST validate shape and unique id, then update date_modified.

\n

If id is omitted by caller and implementation supports auto-ID generation, generated IDs MUST be unique within the task.

\n

Update reminder#

\n

Update reminder MUST address reminders by id and be patch-by-default.

\n

Remove reminder#

\n

Remove reminder by id MUST be idempotent.

\n

10.3.9 Default reminders#

\n

If defaults.reminders is configured (see §9):

\n
    \n
  • create without explicit reminders MUST apply defaults.
  • \n
  • create with explicit reminders MUST follow reminders.apply_defaults_when_explicit (§9.15):
      \n
    • false (default): explicit reminders replace defaults.
    • \n
    • true: explicit reminders are merged with defaults.
    • \n
    \n
  • \n
\n

Deterministic merge rules when apply_defaults_when_explicit=true:

\n
    \n
  1. Start with explicit reminders in caller order.
  2. \n
  3. Append each default reminder whose id is not already present.
  4. \n
  5. If explicit and default reminders share an id, explicit reminder MUST win.
  6. \n
\n

10.3.10 Reminder examples#

\n

Relative reminder:

\n
reminders:\n  - id: due_minus_15m\n    type: relative\n    relatedTo: due\n    offset: -PT15M\n

Absolute reminder:

\n
reminders:\n  - id: call_now\n    type: absolute\n    absoluteTime: 2026-02-20T09:00:00Z\n

10.3.11 Reminder resolution error handling#

\n

If relative reminder base is unavailable (relatedTo=due but no due field):

\n
    \n
  • strict mode: validation error unresolvable_reminder_base.
  • \n
  • permissive mode: warning and reminder excluded from trigger computation.
  • \n
\n

10.4 Interactions#

\n

10.4.1 Rename interaction#

\n

If implementation supports rename/reference updates, dependency uid references SHOULD be updated consistently with other link references.

\n

10.4.2 Completion interaction#

\n

Changing task completion state does not automatically remove dependencies or reminders unless explicitly configured.

\n

10.4.3 Archive interaction#

\n

Archive operations MAY suppress reminder delivery in runtime systems, but archive MUST NOT silently delete reminder records from persisted frontmatter unless explicitly requested.

\n","text":"10.1 Purpose# This section defines canonical semantics for task dependencies (blocked_by) and task reminders (reminders). 10.2 Dependencies (blocked_by)# 10.2.1 Data shape# blocked_by MUST be a list of dependency entries. Each entry MUST be an object with: uid (required): reference to a blocking task (link or string) reltype (required): one of FINISHTOSTART STARTTOSTART FINISHTOFINISH STARTTOFINISH gap (optional): ISO 8601 duration string If reltype is omitted on read in compatibility mode, implementations MAY treat it as FINISHTOSTART and SHOULD emit a warning. 10.2.2 UID normalization# Implementations SHOULD normalize uid values to a canonical reference representation on write. If link formats are supported, both wikilink and markdown-link forms MAY be read. Canonical write form MUST be documented. Link parsing and resolution MUST follow §11. 10.2.3 Dependency uniqueness# Within a task, dependency entries are keyed by normalized uid. Policy is configuration-driven and MUST be deterministic: when dependencies.enforce_unique_uid=true (default), duplicate normalized uid values MUST NOT be accepted as canonical persisted state: strict mode: duplicates MUST fail validation/write with duplicate_dependency_uid; permissive mode: implementations MAY either fail or normalize to one entry, but MUST emit duplicate_dependency_uid. when dependencies.enforce_unique_uid=false, duplicates MAY be preserved as compatibility behavior. The active policy MUST be documented in conformance claims. 10.2.4 Self-dependency# A task MUST NOT depend on itself. Self-dependency is a validation error. 10.2.5 Blocking semantics (v0.1)# For v0.1, blocking evaluation MUST be status-presence based: A task is blocked if it has at least one unresolved dependency. A dependency on a resolvable task is unresolved when the referenced task is not in a completed status. Completed status MUST be determined from configured status.completed_values. For recurring referenced tasks in v0.1, unresolved/resolved evaluation MUST use base status only; complete_instances/skipped_instances are not consulted. When a referenced task is missing/unresolvable, whether that missing target contributes to blocked-state evaluation MUST follow dependencies.treat_missing_target_as_blocked (§9.11, default true). For v0.1, reltype and gap are preserved and validated but MUST NOT change the unresolved/resolved decision. 10.2.6 Missing referenced task# When uid cannot be resolved: implementations SHOULD emit unresolved_dependency_target. blocked-state contribution for this missing target MUST follow dependencies.treat_missing_target_as_blocked (§9.11). issue severity SHOULD follow dependencies.unresolved_target_severity (default: warning). for blocked_by.uid, this dependency-specific severity policy MUST take precedence over links.unresolved_default_severity. parse failures that produce invalid_link_format and containment violations that produce path_traversal remain error-severity conditions from §11. if dependencies.require_resolved_uid_on_write=true, add/update MUST fail with error. 10.2.7 Cycles# Implementations MUST reject direct self-cycles. Detection of multi-hop dependency cycles is RECOMMENDED but not required for core-lite or recurrence profiles. 10.2.8 Reverse relation field# Some implementations maintain reverse relationships (for example blocking). Such fields are derived and non-canonical in this spec unless explicitly mapped. If maintained, reverse updates SHOULD remain consistent with blocked_by edits. 10.2.9 Dependency operation semantics# Add dependency# Add dependency MUST: validate entry shape, handle duplicates by policy (preserve, normalize, or reject), preserve unrelated dependency entries, update date_modified on change. Remove dependency# Remove dependency MUST remove by normalized uid and be idempotent. Replace dependencies# Replace behavior MUST be explicit operation mode (not default for patch update). 10.2.10 Dependency examples# Example entry: blockedBy: - uid: \"[[prepare-metrics]]\" reltype: FINISHTOSTART gap: PT4H Example unresolved dependency (target missing): blockedBy: - uid: \"[[non-existent-task]]\" reltype: FINISHTOSTART 10.3 Reminders (reminders)# 10.3.1 Data shape# reminders MUST be a list of reminder entries. Each reminder MUST include: id (required): unique string within the task type (required): absolute or relative Optional field: description string Type-specific fields: absolute: requires absoluteTime datetime relative: requires relatedTo (due or scheduled) and offset (ISO 8601 duration) 10.3.2 Reminder uniqueness# Reminder id values MUST be unique within the task. If duplicates occur: strict mode: MUST raise duplicate_reminder_id. permissive mode: MAY normalize deterministically and emit warning. 10.3.3 Relative reminder base# relatedTo MUST reference semantic role due or scheduled. If the referenced role is absent, the reminder is unresolved. 10.3.4 Trigger instant computation# Trigger instant MUST be computed as follows: If type=absolute, trigger = absoluteTime instant. If type=relative, resolve base field from relatedTo, if base is datetime: use that instant, if base is date: convert to local datetime at configured reminders.date_only_anchor_time, trigger = base + offset. If reminders.date_only_anchor_time is not configured, implementations MUST use 00:00 local time. 10.3.5 Offset semantics# offset MUST be a valid ISO 8601 duration with optional sign. negative offset = before base positive offset = after base zero offset = at base instant 10.3.6 Invalid mixed fields# Entries with incompatible field combinations MUST fail validation in strict mode. Examples: type=absolute with relatedTo and no absoluteTime type=relative with absoluteTime and missing offset 10.3.7 Reminder ordering# When computing reminder schedules, implementations MUST sort by trigger instant ascending. For identical trigger instants, implementations MUST use stable tie-break ordering by id ascending. 10.3.8 Reminder operation semantics# Add reminder# Add reminder MUST validate shape and unique id, then update date_modified. If id is omitted by caller and implementation supports auto-ID generation, generated IDs MUST be unique within the task. Update reminder# Update reminder MUST address reminders by id and be patch-by-default. Remove reminder# Remove reminder by id MUST be idempotent. 10.3.9 Default reminders# If defaults.reminders is configured (see §9): create without explicit reminders MUST apply defaults. create with explicit reminders MUST follow reminders.apply_defaults_when_explicit (§9.15): false (default): explicit reminders replace defaults. true: explicit reminders are merged with defaults. Deterministic merge rules when apply_defaults_when_explicit=true: Start with explicit reminders in caller order. Append each default reminder whose id is not already present. If explicit and default reminders share an id, explicit reminder MUST win. 10.3.10 Reminder examples# Relative reminder: reminders: - id: due_minus_15m type: relative relatedTo: due offset: -PT15M Absolute reminder: reminders: - id: call_now type: absolute absoluteTime: 2026-02-20T09:00:00Z 10.3.11 Reminder resolution error handling# If relative reminder base is unavailable (relatedTo=due but no due field): strict mode: validation error unresolvable_reminder_base. permissive mode: warning and reminder excluded from trigger computation. 10.4 Interactions# 10.4.1 Rename interaction# If implementation supports rename/reference updates, dependency uid references SHOULD be updated consistently with other link references. 10.4.2 Completion interaction# Changing task completion state does not automatically remove dependencies or reminders unless explicitly configured. 10.4.3 Archive interaction# Archive operations MAY suppress reminder delivery in runtime systems, but archive MUST NOT silently delete reminder records from persisted frontmatter unless explicitly requested."},{"route":"/developers/specification/11-links/","title":"11. Links","description":"This section defines link syntax, parsing, resolution, and write-format semantics for link-bearing task fields — primarily projects, blocked_by.uid, and attachments. Alignment w...","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:11-links.md","namespace":"specification","relativePath":"11-links.md","raw":"# 11. Links\n\n## 11.1 Purpose\n\nThis section defines link syntax, parsing, resolution, and write-format semantics for link-bearing task fields — primarily `projects`, `blocked_by.uid`, and `attachments`.\nAlignment with Obsidian and other ecosystems is informative context only; normative conformance is defined entirely by this section.\n\nApplicability:\n\n- Implementations claiming profile `extended` (§7.3.5) MUST conform to this section for supported link-bearing roles.\n- Implementations claiming profile `materialized-occurrences` (§7.3.4) MUST conform to this section for `recurrence_parent` links, but are not required to support unrelated extended link-bearing roles solely because of that profile.\n- Implementations supporting the `attachments` role MUST conform to this section for attachment references regardless of profile.\n- Implementations that claim neither `extended` nor `materialized-occurrences` MAY treat link-shaped strings as opaque data and are not required to implement §11 behavior.\n\n---\n\n## 11.2 Link formats\n\nImplementations that conform to §11 (see §11.1 applicability) MUST support three link formats.\n\n### 11.2.1 Wikilinks\n\n```\n[[target]]\n[[target|alias]]\n[[target#anchor]]\n[[target#anchor|alias]]\n[[folder/target]]\n[[./relative]]\n[[../parent/target]]\n```\n\n**Components:**\n- **target**: The file being linked to (without extension by default)\n- **alias**: Display text; does not affect resolution\n- **anchor**: A heading or block reference within the target\n- **path**: May be absolute (from collection root) or relative (from current file)\n\nExamples in frontmatter:\n\n```yaml\nprojects:\n - \"[[home-project]]\"\n - \"[[projects/alpha|Alpha Project]]\"\nblockedBy:\n - uid: \"[[prepare-metrics]]\"\n reltype: FINISHTOSTART\n```\n\n### 11.2.2 Markdown links\n\n```\n[text](path.md)\n[text](./relative.md)\n[text](../other/file.md)\n[text](path.md#anchor)\n```\n\nThe text portion is treated as an alias and does not affect resolution.\n\nMarkdown links in frontmatter require the `obsidian-frontmatter-markdown-links` Obsidian plugin. Implementations MUST NOT write markdown-format links by default unless `links.use_markdown_format=true` is configured (§11.7).\n\n### 11.2.3 Bare paths\n\n```\n./sibling.md\n../other/file.md\nfolder/file.md\n```\n\nBare paths follow the same resolution rules as markdown links (relative to containing file's directory unless starting with `/`).\n\n---\n\n## 11.3 Link parsing\n\nWhen a link value is read, implementations MUST parse it into a structured representation:\n\n| Component | Type | Description |\n|---|---|---|\n| `raw` | string | Original string value exactly as written |\n| `target` | string | File path or identifier (without anchor or alias) |\n| `alias` | string? | Display text if provided, otherwise null |\n| `anchor` | string? | Heading or block reference if provided, otherwise null |\n| `format` | enum | One of: `wikilink`, `markdown`, `path` |\n| `is_relative` | boolean | Whether target begins with `./` or `../` |\n\nParsing examples:\n\n| Input | target | alias | anchor | format | is_relative |\n|---|---|---|---|---|---|\n| `[[task-001]]` | `task-001` | null | null | wikilink | false |\n| `[[task-001\\|My Task]]` | `task-001` | `My Task` | null | wikilink | false |\n| `[[docs/api#auth]]` | `docs/api` | null | `auth` | wikilink | false |\n| `[[./sibling]]` | `./sibling` | null | null | wikilink | true |\n| `[Link](file.md)` | `file.md` | `Link` | null | markdown | false |\n| `./other.md` | `./other.md` | null | null | path | true |\n\n---\n\n## 11.4 Resolution algorithm\n\nResolution transforms a parsed link into an absolute path (relative to collection root) pointing to the target file.\n\nGiven a parsed link and the path of the source file containing it:\n\n### Step 1: Parse the link into components (target, format, is_relative)\n\n### Step 2: Route by format\n\n**If format is `markdown` or `path`:**\n- If target starts with `/`, resolve from collection root (strip the leading `/`)\n- Otherwise, resolve relative to the source file's directory (standard markdown behavior)\n- Example: link `[Docs](docs/api.md)` in `notes/meeting.md` resolves to `notes/docs/api.md`\n\n**If format is `wikilink`:**\n- If target starts with `./` or `../`, resolve relative to the source file's directory\n- If target starts with `/`, resolve from collection root (strip the leading `/`)\n- If target contains `/` (and is not relative), resolve from collection root\n - Example: `[[docs/api]]` resolves to `docs/api`\n- If simple name (no `/`, no `./` or `../`): proceed to Step 3\n\n### Step 3: Simple-name resolution (wikilinks only)\n\nFor simple wikilink names (no path separator):\n\n1. **Define the search scope:**\n - For `blocked_by.uid`: scope to files matching `task_detection` (task files only)\n - For `projects`: scope to all markdown files in the collection unless narrowed by explicit configuration\n - For `attachments`: scope to all non-directory files in the collection\n\n2. **ID match pass:** search scoped files for semantic role `id` (§2.6.5) equal to the name.\n - Implementations MAY treat literal frontmatter key `id` as compatibility input when semantic mapping for `id` is unavailable.\n - Equality MUST be exact string equality.\n - If exactly one match: resolve to that file\n - If multiple matches: fail with `ambiguous_link`\n\n3. **Filename match pass:** if no ID match, search scoped markdown files by filename (without extension).\n4. Implementations MUST deduplicate normalized candidate paths before final selection.\n5. If exactly one filename candidate remains after normalization and extension handling, resolve to that file.\n6. If multiple filename candidates remain, resolve to `null` and emit `ambiguous_link`. Callers SHOULD use a path-qualified or relative target to disambiguate.\n\n### Step 4: Extension handling\n\nIf the target has no extension, implementations SHOULD try configured extensions in order.\n\nDefault extension order: `[\".md\"]`.\n\nExample: `[[readme]]` tries `readme.md`, `readme.mdx`, etc.\n\n### Step 5: Path traversal check\n\nAfter resolution and normalization, if the resolved path would escape the collection root, abort with `path_traversal`. See §11.5.\n\n### Step 6: Return result\n\n- The normalized collection-relative path if found\n- `null` if no matching file exists\n\n### Resolution examples\n\nGiven collection structure:\n```\n/\n├── TaskNotes/\n│ ├── Tasks/\n│ │ ├── task-001.md\n│ │ └── subtasks/\n│ │ └── task-002.md\n├── notes/\n│ └── meeting.md\n└── projects/\n └── alpha.md\n```\n\nResolution from `TaskNotes/Tasks/subtasks/task-002.md`:\n\n| Link value | Resolved path | Notes |\n|---|---|---|\n| `[[task-001]]` | `TaskNotes/Tasks/task-001.md` | Simple-name search |\n| `[[../task-001]]` | `TaskNotes/Tasks/task-001.md` | Relative wikilink |\n| `[[./task-003]]` | `TaskNotes/Tasks/subtasks/task-003.md` | Relative (may not exist) |\n| `[[notes/meeting]]` | `notes/meeting.md` | Absolute from root |\n| `[[alpha]]` | `projects/alpha.md` | Simple-name search (projects scope) |\n| `[link](../task-001.md)` | `TaskNotes/Tasks/task-001.md` | Markdown, relative |\n| `../task-001.md` | `TaskNotes/Tasks/task-001.md` | Bare path, relative |\n\n---\n\n## 11.5 Path sandboxing\n\nLink resolution MUST NOT produce paths outside the collection root.\n\n**Rules:**\n- After resolving relative paths (applying `../` segments), the resulting path MUST be within the collection root directory\n- If resolution would escape the collection root, the link MUST resolve to `null` and implementations MUST emit a `path_traversal` error\n- This applies to all link formats: wikilinks, markdown links, and bare paths\n- Implementations MUST normalize paths (resolve `.` and `..` segments) before checking containment\n\n**Examples** (collection rooted at `/home/user/MyVault/`):\n\n| Link | From file | Result |\n|---|---|---|\n| `[[../../../etc/passwd]]` | `TaskNotes/Tasks/task.md` | `null` + `path_traversal` |\n| `[[../../secrets/key]]` | `deep/nested/file.md` | `null` + `path_traversal` |\n| `[[../task-001]]` | `TaskNotes/Tasks/subtasks/t.md` | Resolves normally |\n\n---\n\n## 11.6 Canonical write format\n\nWhen creating new link values or changing a link target, implementations MUST use a deterministic canonical form.\n\n### Default (wikilink format)\n\nBy default (`links.use_markdown_format=false`), the canonical write format is a **simple wikilink**:\n\n```yaml\nblockedBy:\n - uid: \"[[task-001]]\"\n reltype: FINISHTOSTART\nprojects:\n - \"[[projects/alpha]]\"\n```\n\nRules:\n- Use the filename without extension as the target when the file can be identified by simple-name resolution within the appropriate scope.\n- Use a path-qualified target (`folder/name`) when the simple name would be ambiguous.\n- Do NOT include the alias component in dependency `uid` writes.\n- Do NOT include the anchor component in dependency `uid` writes.\n- Preserve the alias component in `projects` entries when the alias was provided by the user.\n- For `attachments`, always write a path-qualified collection-relative target\n with its file extension, for example `[[Attachments/01K1-photo.jpg]]`.\n Attachment writes MUST NOT include an alias or anchor.\n\n### Markdown link format (`links.use_markdown_format=true`)\n\nWhen `links.use_markdown_format=true` is configured (requires the `obsidian-frontmatter-markdown-links` Obsidian plugin), the canonical write format for link-bearing fields is a **markdown link** using the collection-relative path:\n\n```yaml\nblockedBy:\n - uid: \"[task-001](TaskNotes/Tasks/task-001.md)\"\n reltype: FINISHTOSTART\n```\n\n### Round-trip preservation\n\nWhen writing an existing link field and the resolved target is unchanged, implementations MUST preserve the original format when possible:\n- If the user wrote `[[task-001|My Task]]`, preserve alias for `projects` entries.\n- If the user wrote a relative path, preserve relativity when possible.\n- For `blocked_by.uid`, alias and anchor components MUST still be removed on canonical writes.\n- If preservation is not possible (for example unresolved/ambiguous reconstruction), implementations MUST fall back to canonical write rules in this section.\n\n---\n\n## 11.7 Configuration\n\n`links` configuration keys (see §9.12):\n\n```yaml\nlinks:\n extensions: [\".md\"] # Extension trial order for extensionless targets\n use_markdown_format: false # Write markdown links instead of wikilinks\n unresolved_default_severity: warning # \"warning\" or \"error\"\n update_references_on_rename: true # Update link targets when files are renamed\n```\n\nRules:\n- `extensions` MUST be a non-empty list when present\n- `unresolved_default_severity` MUST be `\"warning\"` or `\"error\"`\n- `update_references_on_rename=true` enables rename-time link rewrite behavior (§11.9)\n- `use_markdown_format=true` requires the `obsidian-frontmatter-markdown-links` plugin in Obsidian deployments\n\n---\n\n## 11.8 Role-specific rules\n\n### 11.8.1 `projects`\n\n`projects` entries SHOULD be interpreted with this section's parsing/resolution rules.\n\nIf a `projects` entry is a plain string (not a wikilink or markdown link), implementations SHOULD treat it as a bare filename or path and attempt resolution.\n\nIf unresolved:\n- `links.unresolved_default_severity=error`: validation error\n- otherwise: SHOULD emit `unresolved_link_target` warning\n\n### 11.8.2 `blocked_by.uid`\n\n`blocked_by.uid` values MUST use this section's parsing/resolution rules.\n\nFor dependency semantics, unresolved `uid` handling follows §10.2.6.\nFor unresolved-target severity, `dependencies.unresolved_target_severity` controls and takes precedence over `links.unresolved_default_severity`.\n\nThe canonical write form for `uid` values is specified in §11.6.\n\n### 11.8.3 `attachments`\n\nAttachment references MUST resolve to files, not directories. Canonical\nattachment targets MUST be collection-relative, path-qualified, and retain an\nexplicit file extension. This avoids ambiguous simple-name lookup, makes the\nfrontmatter portable without a media-specific extension search policy, and\npreserves the actual filename.\n\nReaders MUST accept wikilinks, Markdown links, and bare paths. They MAY accept\nsimple-name or extensionless values as non-canonical compatibility input, but\ncanonical writes MUST resolve and replace them with an explicit path and\nextension. Aliases and anchors are not part of attachment identity and MUST be\nremoved on canonical writes.\n\nThe normalized resolved collection path defines attachment identity for\nduplicate detection. Implementations MUST preserve list order and MUST reject\nduplicates after path normalization. Unresolved attachment targets use the\nconfigured `unresolved_link_target` severity; offline-capable clients SHOULD\ndistinguish a known-but-not-locally-cached file from a genuinely unresolved\ntarget.\n\n---\n\n## 11.9 Rename and reference updates\n\nIf an implementation supports reference updates on rename (i.e. claims the `rename` capability):\n\n1. It MUST update resolvable references in `blocked_by.uid`, `projects`, and `attachments` link fields.\n2. It SHOULD update links in body content.\n3. It SHOULD preserve the original link format when possible.\n4. It MUST preserve alias and anchor components where valid for the target field. For `blocked_by.uid`, alias and anchor are non-canonical and MUST be removed on write (§11.6).\n5. It MUST report unresolved or ambiguous rewrite cases.\n\nIf reference updates are not supported, this limitation MUST be disclosed in conformance claims.\n\n---\n\n## 11.10 Validation\n\nLink validation issues:\n\n| Code | Severity | Trigger |\n|---|---|---|\n| `invalid_link_format` | error | Link value cannot be parsed as any supported format |\n| `ambiguous_link` | warning | Simple-name resolution found multiple candidates after normalization |\n| `unresolved_link_target` | warning | Link target cannot be resolved to an existing file |\n| `path_traversal` | error | Resolved path escapes collection root |\n\n`unresolved_link_target` severity may be promoted to error via `links.unresolved_default_severity=error`.\nFor `blocked_by.uid`, use `unresolved_dependency_target` severity policy from §10.2.6 instead of `unresolved_link_target`.\n\n---\n\n## 11.11 Examples\n\n### Dependency with wikilink (default)\n\n```yaml\n---\ntitle: Implement API\nstatus: open\ntags: [task]\nblockedBy:\n - uid: \"[[design-api]]\"\n reltype: FINISHTOSTART\n - uid: \"[[projects/infra/setup-server]]\"\n reltype: FINISHTOSTART\n gap: P1D\nprojects:\n - \"[[projects/alpha]]\"\ndateCreated: 2026-02-20T10:00:00Z\ndateModified: 2026-02-20T10:00:00Z\n---\n```\n\n### Dependency with markdown links (`links.use_markdown_format=true`)\n\n```yaml\n---\ntitle: Implement API\nstatus: open\ntags: [task]\nblockedBy:\n - uid: \"[design-api](TaskNotes/Tasks/design-api.md)\"\n reltype: FINISHTOSTART\n---\n```\n\n### Relative links from nested task\n\n```yaml\n# TaskNotes/Tasks/subtasks/task-002.md\n---\ntitle: Sub-task\nstatus: open\ntags: [task]\nblockedBy:\n - uid: \"[[../task-001]]\" # resolves to TaskNotes/Tasks/task-001.md\n reltype: FINISHTOSTART\nprojects:\n - \"[[projects/alpha]]\" # resolves from collection root\n---\n```\n","aliases":["/spec/11-links/"],"toc":[{"level":2,"id":"111-purpose","text":"11.1 Purpose"},{"level":2,"id":"112-link-formats","text":"11.2 Link formats"},{"level":3,"id":"1121-wikilinks","text":"11.2.1 Wikilinks"},{"level":3,"id":"1122-markdown-links","text":"11.2.2 Markdown links"},{"level":3,"id":"1123-bare-paths","text":"11.2.3 Bare paths"},{"level":2,"id":"113-link-parsing","text":"11.3 Link parsing"},{"level":2,"id":"114-resolution-algorithm","text":"11.4 Resolution algorithm"},{"level":3,"id":"step-1-parse-the-link-into-components-target-format-isrelative","text":"Step 1: Parse the link into components (target, format, is_relative)"},{"level":3,"id":"step-2-route-by-format","text":"Step 2: Route by format"},{"level":3,"id":"step-3-simple-name-resolution-wikilinks-only","text":"Step 3: Simple-name resolution (wikilinks only)"},{"level":3,"id":"step-4-extension-handling","text":"Step 4: Extension handling"},{"level":3,"id":"step-5-path-traversal-check","text":"Step 5: Path traversal check"},{"level":3,"id":"step-6-return-result","text":"Step 6: Return result"},{"level":3,"id":"resolution-examples","text":"Resolution examples"},{"level":2,"id":"115-path-sandboxing","text":"11.5 Path sandboxing"},{"level":2,"id":"116-canonical-write-format","text":"11.6 Canonical write format"},{"level":3,"id":"default-wikilink-format","text":"Default (wikilink format)"},{"level":3,"id":"markdown-link-format-linksusemarkdownformattrue","text":"Markdown link format (links.use_markdown_format=true)"},{"level":3,"id":"round-trip-preservation","text":"Round-trip preservation"},{"level":2,"id":"117-configuration","text":"11.7 Configuration"},{"level":2,"id":"118-role-specific-rules","text":"11.8 Role-specific rules"},{"level":3,"id":"1181-projects","text":"11.8.1 projects"},{"level":3,"id":"1182-blockedbyuid","text":"11.8.2 blocked_by.uid"},{"level":3,"id":"1183-attachments","text":"11.8.3 attachments"},{"level":2,"id":"119-rename-and-reference-updates","text":"11.9 Rename and reference updates"},{"level":2,"id":"1110-validation","text":"11.10 Validation"},{"level":2,"id":"1111-examples","text":"11.11 Examples"},{"level":3,"id":"dependency-with-wikilink-default","text":"Dependency with wikilink (default)"},{"level":3,"id":"dependency-with-markdown-links-linksusemarkdownformattrue","text":"Dependency with markdown links (links.use_markdown_format=true)"},{"level":3,"id":"relative-links-from-nested-task","text":"Relative links from nested task"}],"html":"

11.1 Purpose#

\n

This section defines link syntax, parsing, resolution, and write-format semantics for link-bearing task fields — primarily projects, blocked_by.uid, and attachments.\nAlignment with Obsidian and other ecosystems is informative context only; normative conformance is defined entirely by this section.

\n

Applicability:

\n
    \n
  • Implementations claiming profile extended (§7.3.5) MUST conform to this section for supported link-bearing roles.
  • \n
  • Implementations claiming profile materialized-occurrences (§7.3.4) MUST conform to this section for recurrence_parent links, but are not required to support unrelated extended link-bearing roles solely because of that profile.
  • \n
  • Implementations supporting the attachments role MUST conform to this section for attachment references regardless of profile.
  • \n
  • Implementations that claim neither extended nor materialized-occurrences MAY treat link-shaped strings as opaque data and are not required to implement §11 behavior.
  • \n
\n
\n\n

Implementations that conform to §11 (see §11.1 applicability) MUST support three link formats.

\n

11.2.1 Wikilinks#

\n
[[target]]\n[[target|alias]]\n[[target#anchor]]\n[[target#anchor|alias]]\n[[folder/target]]\n[[./relative]]\n[[../parent/target]]\n

Components:

\n
    \n
  • target: The file being linked to (without extension by default)
  • \n
  • alias: Display text; does not affect resolution
  • \n
  • anchor: A heading or block reference within the target
  • \n
  • path: May be absolute (from collection root) or relative (from current file)
  • \n
\n

Examples in frontmatter:

\n
projects:\n  - "[[home-project]]"\n  - "[[projects/alpha|Alpha Project]]"\nblockedBy:\n  - uid: "[[prepare-metrics]]"\n    reltype: FINISHTOSTART\n

11.2.2 Markdown links#

\n
[text](path.md)\n[text](./relative.md)\n[text](../other/file.md)\n[text](path.md#anchor)\n

The text portion is treated as an alias and does not affect resolution.

\n

Markdown links in frontmatter require the obsidian-frontmatter-markdown-links Obsidian plugin. Implementations MUST NOT write markdown-format links by default unless links.use_markdown_format=true is configured (§11.7).

\n

11.2.3 Bare paths#

\n
./sibling.md\n../other/file.md\nfolder/file.md\n

Bare paths follow the same resolution rules as markdown links (relative to containing file's directory unless starting with /).

\n
\n\n

When a link value is read, implementations MUST parse it into a structured representation:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
ComponentTypeDescription
rawstringOriginal string value exactly as written
targetstringFile path or identifier (without anchor or alias)
aliasstring?Display text if provided, otherwise null
anchorstring?Heading or block reference if provided, otherwise null
formatenumOne of: wikilink, markdown, path
is_relativebooleanWhether target begins with ./ or ../
\n

Parsing examples:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Inputtargetaliasanchorformatis_relative
[[task-001]]task-001nullnullwikilinkfalse
[[task-001|My Task]]task-001My Tasknullwikilinkfalse
[[docs/api#auth]]docs/apinullauthwikilinkfalse
[[./sibling]]./siblingnullnullwikilinktrue
[Link](file.md)file.mdLinknullmarkdownfalse
./other.md./other.mdnullnullpathtrue
\n
\n

11.4 Resolution algorithm#

\n

Resolution transforms a parsed link into an absolute path (relative to collection root) pointing to the target file.

\n

Given a parsed link and the path of the source file containing it:

\n\n

Step 2: Route by format#

\n

If format is markdown or path:

\n
    \n
  • If target starts with /, resolve from collection root (strip the leading /)
  • \n
  • Otherwise, resolve relative to the source file's directory (standard markdown behavior)
  • \n
  • Example: link [Docs](docs/api.md) in notes/meeting.md resolves to notes/docs/api.md
  • \n
\n

If format is wikilink:

\n
    \n
  • If target starts with ./ or ../, resolve relative to the source file's directory
  • \n
  • If target starts with /, resolve from collection root (strip the leading /)
  • \n
  • If target contains / (and is not relative), resolve from collection root
      \n
    • Example: [[docs/api]] resolves to docs/api
    • \n
    \n
  • \n
  • If simple name (no /, no ./ or ../): proceed to Step 3
  • \n
\n\n

For simple wikilink names (no path separator):

\n
    \n
  1. Define the search scope:

    \n
      \n
    • For blocked_by.uid: scope to files matching task_detection (task files only)
    • \n
    • For projects: scope to all markdown files in the collection unless narrowed by explicit configuration
    • \n
    • For attachments: scope to all non-directory files in the collection
    • \n
    \n
  2. \n
  3. ID match pass: search scoped files for semantic role id (§2.6.5) equal to the name.

    \n
      \n
    • Implementations MAY treat literal frontmatter key id as compatibility input when semantic mapping for id is unavailable.
    • \n
    • Equality MUST be exact string equality.
    • \n
    • If exactly one match: resolve to that file
    • \n
    • If multiple matches: fail with ambiguous_link
    • \n
    \n
  4. \n
  5. Filename match pass: if no ID match, search scoped markdown files by filename (without extension).

    \n
  6. \n
  7. Implementations MUST deduplicate normalized candidate paths before final selection.

    \n
  8. \n
  9. If exactly one filename candidate remains after normalization and extension handling, resolve to that file.

    \n
  10. \n
  11. If multiple filename candidates remain, resolve to null and emit ambiguous_link. Callers SHOULD use a path-qualified or relative target to disambiguate.

    \n
  12. \n
\n

Step 4: Extension handling#

\n

If the target has no extension, implementations SHOULD try configured extensions in order.

\n

Default extension order: [".md"].

\n

Example: [[readme]] tries readme.md, readme.mdx, etc.

\n

Step 5: Path traversal check#

\n

After resolution and normalization, if the resolved path would escape the collection root, abort with path_traversal. See §11.5.

\n

Step 6: Return result#

\n
    \n
  • The normalized collection-relative path if found
  • \n
  • null if no matching file exists
  • \n
\n

Resolution examples#

\n

Given collection structure:

\n
/\n├── TaskNotes/\n│   ├── Tasks/\n│   │   ├── task-001.md\n│   │   └── subtasks/\n│   │       └── task-002.md\n├── notes/\n│   └── meeting.md\n└── projects/\n    └── alpha.md\n

Resolution from TaskNotes/Tasks/subtasks/task-002.md:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Link valueResolved pathNotes
[[task-001]]TaskNotes/Tasks/task-001.mdSimple-name search
[[../task-001]]TaskNotes/Tasks/task-001.mdRelative wikilink
[[./task-003]]TaskNotes/Tasks/subtasks/task-003.mdRelative (may not exist)
[[notes/meeting]]notes/meeting.mdAbsolute from root
[[alpha]]projects/alpha.mdSimple-name search (projects scope)
[link](../task-001.md)TaskNotes/Tasks/task-001.mdMarkdown, relative
../task-001.mdTaskNotes/Tasks/task-001.mdBare path, relative
\n
\n

11.5 Path sandboxing#

\n

Link resolution MUST NOT produce paths outside the collection root.

\n

Rules:

\n
    \n
  • After resolving relative paths (applying ../ segments), the resulting path MUST be within the collection root directory
  • \n
  • If resolution would escape the collection root, the link MUST resolve to null and implementations MUST emit a path_traversal error
  • \n
  • This applies to all link formats: wikilinks, markdown links, and bare paths
  • \n
  • Implementations MUST normalize paths (resolve . and .. segments) before checking containment
  • \n
\n

Examples (collection rooted at /home/user/MyVault/):

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
LinkFrom fileResult
[[../../../etc/passwd]]TaskNotes/Tasks/task.mdnull + path_traversal
[[../../secrets/key]]deep/nested/file.mdnull + path_traversal
[[../task-001]]TaskNotes/Tasks/subtasks/t.mdResolves normally
\n
\n

11.6 Canonical write format#

\n

When creating new link values or changing a link target, implementations MUST use a deterministic canonical form.

\n\n

By default (links.use_markdown_format=false), the canonical write format is a simple wikilink:

\n
blockedBy:\n  - uid: "[[task-001]]"\n    reltype: FINISHTOSTART\nprojects:\n  - "[[projects/alpha]]"\n

Rules:

\n
    \n
  • Use the filename without extension as the target when the file can be identified by simple-name resolution within the appropriate scope.
  • \n
  • Use a path-qualified target (folder/name) when the simple name would be ambiguous.
  • \n
  • Do NOT include the alias component in dependency uid writes.
  • \n
  • Do NOT include the anchor component in dependency uid writes.
  • \n
  • Preserve the alias component in projects entries when the alias was provided by the user.
  • \n
  • For attachments, always write a path-qualified collection-relative target\nwith its file extension, for example [[Attachments/01K1-photo.jpg]].\nAttachment writes MUST NOT include an alias or anchor.
  • \n
\n\n

When links.use_markdown_format=true is configured (requires the obsidian-frontmatter-markdown-links Obsidian plugin), the canonical write format for link-bearing fields is a markdown link using the collection-relative path:

\n
blockedBy:\n  - uid: "[task-001](TaskNotes/Tasks/task-001.md)"\n    reltype: FINISHTOSTART\n

Round-trip preservation#

\n

When writing an existing link field and the resolved target is unchanged, implementations MUST preserve the original format when possible:

\n
    \n
  • If the user wrote [[task-001|My Task]], preserve alias for projects entries.
  • \n
  • If the user wrote a relative path, preserve relativity when possible.
  • \n
  • For blocked_by.uid, alias and anchor components MUST still be removed on canonical writes.
  • \n
  • If preservation is not possible (for example unresolved/ambiguous reconstruction), implementations MUST fall back to canonical write rules in this section.
  • \n
\n
\n

11.7 Configuration#

\n

links configuration keys (see §9.12):

\n
links:\n  extensions: [".md"]                  # Extension trial order for extensionless targets\n  use_markdown_format: false           # Write markdown links instead of wikilinks\n  unresolved_default_severity: warning # "warning" or "error"\n  update_references_on_rename: true    # Update link targets when files are renamed\n

Rules:

\n
    \n
  • extensions MUST be a non-empty list when present
  • \n
  • unresolved_default_severity MUST be "warning" or "error"
  • \n
  • update_references_on_rename=true enables rename-time link rewrite behavior (§11.9)
  • \n
  • use_markdown_format=true requires the obsidian-frontmatter-markdown-links plugin in Obsidian deployments
  • \n
\n
\n

11.8 Role-specific rules#

\n

11.8.1 projects#

\n

projects entries SHOULD be interpreted with this section's parsing/resolution rules.

\n

If a projects entry is a plain string (not a wikilink or markdown link), implementations SHOULD treat it as a bare filename or path and attempt resolution.

\n

If unresolved:

\n
    \n
  • links.unresolved_default_severity=error: validation error
  • \n
  • otherwise: SHOULD emit unresolved_link_target warning
  • \n
\n

11.8.2 blocked_by.uid#

\n

blocked_by.uid values MUST use this section's parsing/resolution rules.

\n

For dependency semantics, unresolved uid handling follows §10.2.6.\nFor unresolved-target severity, dependencies.unresolved_target_severity controls and takes precedence over links.unresolved_default_severity.

\n

The canonical write form for uid values is specified in §11.6.

\n

11.8.3 attachments#

\n

Attachment references MUST resolve to files, not directories. Canonical\nattachment targets MUST be collection-relative, path-qualified, and retain an\nexplicit file extension. This avoids ambiguous simple-name lookup, makes the\nfrontmatter portable without a media-specific extension search policy, and\npreserves the actual filename.

\n

Readers MUST accept wikilinks, Markdown links, and bare paths. They MAY accept\nsimple-name or extensionless values as non-canonical compatibility input, but\ncanonical writes MUST resolve and replace them with an explicit path and\nextension. Aliases and anchors are not part of attachment identity and MUST be\nremoved on canonical writes.

\n

The normalized resolved collection path defines attachment identity for\nduplicate detection. Implementations MUST preserve list order and MUST reject\nduplicates after path normalization. Unresolved attachment targets use the\nconfigured unresolved_link_target severity; offline-capable clients SHOULD\ndistinguish a known-but-not-locally-cached file from a genuinely unresolved\ntarget.

\n
\n

11.9 Rename and reference updates#

\n

If an implementation supports reference updates on rename (i.e. claims the rename capability):

\n
    \n
  1. It MUST update resolvable references in blocked_by.uid, projects, and attachments link fields.
  2. \n
  3. It SHOULD update links in body content.
  4. \n
  5. It SHOULD preserve the original link format when possible.
  6. \n
  7. It MUST preserve alias and anchor components where valid for the target field. For blocked_by.uid, alias and anchor are non-canonical and MUST be removed on write (§11.6).
  8. \n
  9. It MUST report unresolved or ambiguous rewrite cases.
  10. \n
\n

If reference updates are not supported, this limitation MUST be disclosed in conformance claims.

\n
\n

11.10 Validation#

\n

Link validation issues:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
CodeSeverityTrigger
invalid_link_formaterrorLink value cannot be parsed as any supported format
ambiguous_linkwarningSimple-name resolution found multiple candidates after normalization
unresolved_link_targetwarningLink target cannot be resolved to an existing file
path_traversalerrorResolved path escapes collection root
\n

unresolved_link_target severity may be promoted to error via links.unresolved_default_severity=error.\nFor blocked_by.uid, use unresolved_dependency_target severity policy from §10.2.6 instead of unresolved_link_target.

\n
\n

11.11 Examples#

\n\n
---\ntitle: Implement API\nstatus: open\ntags: [task]\nblockedBy:\n  - uid: "[[design-api]]"\n    reltype: FINISHTOSTART\n  - uid: "[[projects/infra/setup-server]]"\n    reltype: FINISHTOSTART\n    gap: P1D\nprojects:\n  - "[[projects/alpha]]"\ndateCreated: 2026-02-20T10:00:00Z\ndateModified: 2026-02-20T10:00:00Z\n---\n
\n
---\ntitle: Implement API\nstatus: open\ntags: [task]\nblockedBy:\n  - uid: "[design-api](TaskNotes/Tasks/design-api.md)"\n    reltype: FINISHTOSTART\n---\n
\n
# TaskNotes/Tasks/subtasks/task-002.md\n---\ntitle: Sub-task\nstatus: open\ntags: [task]\nblockedBy:\n  - uid: "[[../task-001]]"    # resolves to TaskNotes/Tasks/task-001.md\n    reltype: FINISHTOSTART\nprojects:\n  - "[[projects/alpha]]"      # resolves from collection root\n---\n
","text":"11.1 Purpose# This section defines link syntax, parsing, resolution, and write-format semantics for link-bearing task fields — primarily projects, blocked_by.uid, and attachments. Alignment with Obsidian and other ecosystems is informative context only; normative conformance is defined entirely by this section. Applicability: Implementations claiming profile extended (§7.3.5) MUST conform to this section for supported link-bearing roles. Implementations claiming profile materialized-occurrences (§7.3.4) MUST conform to this section for recurrence_parent links, but are not required to support unrelated extended link-bearing roles solely because of that profile. Implementations supporting the attachments role MUST conform to this section for attachment references regardless of profile. Implementations that claim neither extended nor materialized-occurrences MAY treat link-shaped strings as opaque data and are not required to implement §11 behavior. 11.2 Link formats# Implementations that conform to §11 (see §11.1 applicability) MUST support three link formats. 11.2.1 Wikilinks# [[target]] [[target|alias]] [[target#anchor]] [[target#anchor|alias]] [[folder/target]] [[./relative]] [[../parent/target]] Components: target: The file being linked to (without extension by default) alias: Display text; does not affect resolution anchor: A heading or block reference within the target path: May be absolute (from collection root) or relative (from current file) Examples in frontmatter: projects: - \"[[home-project]]\" - \"[[projects/alpha|Alpha Project]]\" blockedBy: - uid: \"[[prepare-metrics]]\" reltype: FINISHTOSTART 11.2.2 Markdown links# [text](path.md) [text](./relative.md) [text](../other/file.md) [text](path.md#anchor) The text portion is treated as an alias and does not affect resolution. Markdown links in frontmatter require the obsidian-frontmatter-markdown-links Obsidian plugin. Implementations MUST NOT write markdown-format links by default unless links.use_markdown_format=true is configured (§11.7). 11.2.3 Bare paths# ./sibling.md ../other/file.md folder/file.md Bare paths follow the same resolution rules as markdown links (relative to containing file's directory unless starting with /). 11.3 Link parsing# When a link value is read, implementations MUST parse it into a structured representation: Component Type Description raw string Original string value exactly as written target string File path or identifier (without anchor or alias) alias string? Display text if provided, otherwise null anchor string? Heading or block reference if provided, otherwise null format enum One of: wikilink, markdown, path is_relative boolean Whether target begins with ./ or ../ Parsing examples: Input target alias anchor format is_relative [[task-001]] task-001 null null wikilink false [[task-001|My Task]] task-001 My Task null wikilink false [[docs/api#auth]] docs/api null auth wikilink false [[./sibling]] ./sibling null null wikilink true [Link](file.md) file.md Link null markdown false ./other.md ./other.md null null path true 11.4 Resolution algorithm# Resolution transforms a parsed link into an absolute path (relative to collection root) pointing to the target file. Given a parsed link and the path of the source file containing it: Step 1: Parse the link into components (target, format, is_relative)# Step 2: Route by format# If format is markdown or path: If target starts with /, resolve from collection root (strip the leading /) Otherwise, resolve relative to the source file's directory (standard markdown behavior) Example: link [Docs](docs/api.md) in notes/meeting.md resolves to notes/docs/api.md If format is wikilink: If target starts with ./ or ../, resolve relative to the source file's directory If target starts with /, resolve from collection root (strip the leading /) If target contains / (and is not relative), resolve from collection root Example: [[docs/api]] resolves to docs/api If simple name (no /, no ./ or ../): proceed to Step 3 Step 3: Simple-name resolution (wikilinks only)# For simple wikilink names (no path separator): Define the search scope: For blocked_by.uid: scope to files matching task_detection (task files only) For projects: scope to all markdown files in the collection unless narrowed by explicit configuration For attachments: scope to all non-directory files in the collection ID match pass: search scoped files for semantic role id (§2.6.5) equal to the name. Implementations MAY treat literal frontmatter key id as compatibility input when semantic mapping for id is unavailable. Equality MUST be exact string equality. If exactly one match: resolve to that file If multiple matches: fail with ambiguous_link Filename match pass: if no ID match, search scoped markdown files by filename (without extension). Implementations MUST deduplicate normalized candidate paths before final selection. If exactly one filename candidate remains after normalization and extension handling, resolve to that file. If multiple filename candidates remain, resolve to null and emit ambiguous_link. Callers SHOULD use a path-qualified or relative target to disambiguate. Step 4: Extension handling# If the target has no extension, implementations SHOULD try configured extensions in order. Default extension order: [\".md\"]. Example: [[readme]] tries readme.md, readme.mdx, etc. Step 5: Path traversal check# After resolution and normalization, if the resolved path would escape the collection root, abort with path_traversal. See §11.5. Step 6: Return result# The normalized collection-relative path if found null if no matching file exists Resolution examples# Given collection structure: / ├── TaskNotes/ │ ├── Tasks/ │ │ ├── task-001.md │ │ └── subtasks/ │ │ └── task-002.md ├── notes/ │ └── meeting.md └── projects/ └── alpha.md Resolution from TaskNotes/Tasks/subtasks/task-002.md: Link value Resolved path Notes [[task-001]] TaskNotes/Tasks/task-001.md Simple-name search [[../task-001]] TaskNotes/Tasks/task-001.md Relative wikilink [[./task-003]] TaskNotes/Tasks/subtasks/task-003.md Relative (may not exist) [[notes/meeting]] notes/meeting.md Absolute from root [[alpha]] projects/alpha.md Simple-name search (projects scope) [link](../task-001.md) TaskNotes/Tasks/task-001.md Markdown, relative ../task-001.md TaskNotes/Tasks/task-001.md Bare path, relative 11.5 Path sandboxing# Link resolution MUST NOT produce paths outside the collection root. Rules: After resolving relative paths (applying ../ segments), the resulting path MUST be within the collection root directory If resolution would escape the collection root, the link MUST resolve to null and implementations MUST emit a path_traversal error This applies to all link formats: wikilinks, markdown links, and bare paths Implementations MUST normalize paths (resolve . and .. segments) before checking containment Examples (collection rooted at /home/user/MyVault/): Link From file Result [[../../../etc/passwd]] TaskNotes/Tasks/task.md null + path_traversal [[../../secrets/key]] deep/nested/file.md null + path_traversal [[../task-001]] TaskNotes/Tasks/subtasks/t.md Resolves normally 11.6 Canonical write format# When creating new link values or changing a link target, implementations MUST use a deterministic canonical form. Default (wikilink format)# By default (links.use_markdown_format=false), the canonical write format is a simple wikilink: blockedBy: - uid: \"[[task-001]]\" reltype: FINISHTOSTART projects: - \"[[projects/alpha]]\" Rules: Use the filename without extension as the target when the file can be identified by simple-name resolution within the appropriate scope. Use a path-qualified target (folder/name) when the simple name would be ambiguous. Do NOT include the alias component in dependency uid writes. Do NOT include the anchor component in dependency uid writes. Preserve the alias component in projects entries when the alias was provided by the user. For attachments, always write a path-qualified collection-relative target with its file extension, for example [[Attachments/01K1-photo.jpg]]. Attachment writes MUST NOT include an alias or anchor. Markdown link format (links.use_markdown_format=true)# When links.use_markdown_format=true is configured (requires the obsidian-frontmatter-markdown-links Obsidian plugin), the canonical write format for link-bearing fields is a markdown link using the collection-relative path: blockedBy: - uid: \"[task-001](TaskNotes/Tasks/task-001.md)\" reltype: FINISHTOSTART Round-trip preservation# When writing an existing link field and the resolved target is unchanged, implementations MUST preserve the original format when possible: If the user wrote [[task-001|My Task]], preserve alias for projects entries. If the user wrote a relative path, preserve relativity when possible. For blocked_by.uid, alias and anchor components MUST still be removed on canonical writes. If preservation is not possible (for example unresolved/ambiguous reconstruction), implementations MUST fall back to canonical write rules in this section. 11.7 Configuration# links configuration keys (see §9.12): links: extensions: [\".md\"] # Extension trial order for extensionless targets use_markdown_format: false # Write markdown links instead of wikilinks unresolved_default_severity: warning # \"warning\" or \"error\" update_references_on_rename: true # Update link targets when files are renamed Rules: extensions MUST be a non-empty list when present unresolved_default_severity MUST be \"warning\" or \"error\" update_references_on_rename=true enables rename-time link rewrite behavior (§11.9) use_markdown_format=true requires the obsidian-frontmatter-markdown-links plugin in Obsidian deployments 11.8 Role-specific rules# 11.8.1 projects# projects entries SHOULD be interpreted with this section's parsing/resolution rules. If a projects entry is a plain string (not a wikilink or markdown link), implementations SHOULD treat it as a bare filename or path and attempt resolution. If unresolved: links.unresolved_default_severity=error: validation error otherwise: SHOULD emit unresolved_link_target warning 11.8.2 blocked_by.uid# blocked_by.uid values MUST use this section's parsing/resolution rules. For dependency semantics, unresolved uid handling follows §10.2.6. For unresolved-target severity, dependencies.unresolved_target_severity controls and takes precedence over links.unresolved_default_severity. The canonical write form for uid values is specified in §11.6. 11.8.3 attachments# Attachment references MUST resolve to files, not directories. Canonical attachment targets MUST be collection-relative, path-qualified, and retain an explicit file extension. This avoids ambiguous simple-name lookup, makes the frontmatter portable without a media-specific extension search policy, and preserves the actual filename. Readers MUST accept wikilinks, Markdown links, and bare paths. They MAY accept simple-name or extensionless values as non-canonical compatibility input, but canonical writes MUST resolve and replace them with an explicit path and extension. Aliases and anchors are not part of attachment identity and MUST be removed on canonical writes. The normalized resolved collection path defines attachment identity for duplicate detection. Implementations MUST preserve list order and MUST reject duplicates after path normalization. Unresolved attachment targets use the configured unresolved_link_target severity; offline-capable clients SHOULD distinguish a known-but-not-locally-cached file from a genuinely unresolved target. 11.9 Rename and reference updates# If an implementation supports reference updates on rename (i.e. claims the rename capability): It MUST update resolvable references in blocked_by.uid, projects, and attachments link fields. It SHOULD update links in body content. It SHOULD preserve the original link format when possible. It MUST preserve alias and anchor components where valid for the target field. For blocked_by.uid, alias and anchor are non-canonical and MUST be removed on write (§11.6). It MUST report unresolved or ambiguous rewrite cases. If reference updates are not supported, this limitation MUST be disclosed in conformance claims. 11.10 Validation# Link validation issues: Code Severity Trigger invalid_link_format error Link value cannot be parsed as any supported format ambiguous_link warning Simple-name resolution found multiple candidates after normalization unresolved_link_target warning Link target cannot be resolved to an existing file path_traversal error Resolved path escapes collection root unresolved_link_target severity may be promoted to error via links.unresolved_default_severity=error. For blocked_by.uid, use unresolved_dependency_target severity policy from §10.2.6 instead of unresolved_link_target. 11.11 Examples# Dependency with wikilink (default)# --- title: Implement API status: open tags: [task] blockedBy: - uid: \"[[design-api]]\" reltype: FINISHTOSTART - uid: \"[[projects/infra/setup-server]]\" reltype: FINISHTOSTART gap: P1D projects: - \"[[projects/alpha]]\" dateCreated: 2026-02-20T10:00:00Z dateModified: 2026-02-20T10:00:00Z --- Dependency with markdown links (links.use_markdown_format=true)# --- title: Implement API status: open tags: [task] blockedBy: - uid: \"[design-api](TaskNotes/Tasks/design-api.md)\" reltype: FINISHTOSTART --- Relative links from nested task# # TaskNotes/Tasks/subtasks/task-002.md --- title: Sub-task status: open tags: [task] blockedBy: - uid: \"[[../task-001]]\" # resolves to TaskNotes/Tasks/task-001.md reltype: FINISHTOSTART projects: - \"[[projects/alpha]]\" # resolves from collection root ---"},{"route":"/developers/specification/12-mdbase-v0.3-binding/","title":"12. mdbase v0.3 Data-Contract Binding","description":"Status: Draft","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:12-mdbase-v0.3-binding.md","namespace":"specification","relativePath":"12-mdbase-v0.3-binding.md","raw":"# 12. mdbase v0.3 Data-Contract Binding\n\n**Status:** Draft\n\n**Record contract:** `tasknotes.task` `0.3.0-rc.3`\n\n**Event contract:** `tasknotes.task.completed` `1.0.0`\n\n**Target:** mdbase `0.3.x`\n\n## 12.1 Purpose\n\nThis chapter defines how a TaskNotes task model is exposed through mdbase\nwithout coupling TaskNotes to one record type or one application's private\nextension.\n\nThe binding has three deliberately separate parts:\n\n1. the `tasknotes.task` data contract defines the portable task view;\n2. an mdbase type's `implements` entry maps that view to its own frontmatter\n fields and supplies TaskNotes behavior; and\n3. the rest of the type file continues to define that type's storage,\n matching, defaults, lifecycle, links, and paths.\n\nThe normative artifacts are:\n\n- [`mdbase/tasknotes.task.md`](mdbase/tasknotes.task.md), the record contract;\n- [`schemas/tasknotes-task.schema.json`](schemas/tasknotes-task.schema.json),\n the projected task-view schema; and\n- [`schemas/tasknotes-task-binding.schema.json`](schemas/tasknotes-task-binding.schema.json),\n the implementation binding schema.\n\nThe optional event-interoperability artifacts are:\n\n- [`mdbase/tasknotes.task.completed.md`](mdbase/tasknotes.task.completed.md),\n the event contract; and\n- [`schemas/tasknotes-task-completed.schema.json`](schemas/tasknotes-task-completed.schema.json),\n its event-data schema.\n\n## 12.2 The mental model\n\nA contract is not another record type. It is a view that several record types\ncan implement and several applications can consume.\n\n```text\npersonal_task ─┐\nwork_task ─────┼─ implements tasknotes.task 0.3.0-rc.3 ── TaskNotes\nissue_task ────┘ ├─ automation\n └─ another task app\n```\n\nReading or listing through the contract uses the union of all implementing\ntypes. Creating a task is different: the caller MUST choose one exact target\ntype because the contract does not choose storage, paths, or lifecycle policy.\n\nThe contract version is an exact semantic version. For this draft it is also\nthe tasknotes-spec version whose task semantics the contract exposes. There is\nno independent `x-tasknotes.version` or `spec_version` mirror.\n\nRecord types use `implements` because they adapt persisted fields and semantic\nbindings to the `tasknotes.task` record contract. Event sources do not use a\ntype file. A TaskNotes application instead registers an event-source\ndeclaration for `tasknotes.task.completed` with an active mdbase\ninteroperability bridge.\n\n## 12.3 Layering\n\nAn implementing type MUST keep these responsibilities in their canonical\nlocations:\n\n| Information | mdbase v0.3 location |\n|---|---|\n| Persisted frontmatter shape, required fields, enum values, formats | `schema` |\n| Type identification | `match` |\n| Display field, defaults, links, uniqueness, and path generation | `collection` |\n| Managed create/update values | `lifecycle` |\n| Contract identity and custom field names | `implements[].contract`, `version`, and `fields` |\n| TaskNotes semantic behavior | `implements[].binding` |\n\nTaskNotes metadata MUST NOT be encoded as custom JSON Schema keywords.\n`x-tasknotes` MUST NOT be used for contract discovery, field mapping,\nconformance, or authorization.\n\n## 12.4 Declaring an implementation\n\nAn mdbase TaskNotes type declares one implementation:\n\n```yaml\nimplements:\n - contract: tasknotes.task\n version: 0.3.0-rc.3\n fields:\n title: summary\n status: state\n priority: importance\n dateCreated: created_at\n binding:\n # TaskNotes behavior; abbreviated here\n profiles: [core-lite]\n capabilities: []\n title:\n storage: frontmatter\n filename_format: title\n status:\n values: [todo, doing, done]\n default: todo\n completed_values: [done]\n definitions: []\n priority:\n values: [normal]\n default: normal\n definitions: []\n```\n\nThe contract file identified by the exact `contract` and `version` MUST exist\nin the collection contract registry. The `binding` MUST validate against that\ncontract's `binding_schema`.\n\nEach type MUST declare at most one implementation of one exact contract\nidentity. A type may implement several different contracts.\n\n## 12.5 Portable fields\n\n`fields` maps contract field paths to record field paths. Consumers access\ncontract fields and MUST NOT assume that their names are also frontmatter\nproperty names.\n\n```yaml\nfields:\n title: summary\n status: state\n blockedBy: dependencies\n attachments: files\n```\n\nEvery unconditionally required contract field MUST be mapped. Every mapped\ncontract field and record field MUST exist in its respective JSON Schema.\n\nThe contract view contains only mapped fields. It does not expose unmapped\nfrontmatter or the Markdown body. A consumer that requires either needs\nseparate, explicit whole-record access.\n\n`title` is optional in the portable schema because TaskNotes permits filename\ntitle storage. When `binding.title.storage` is `filename`, consumers derive\nthe effective title from the record identity/path rules in §9.13 instead of\nexpecting a projected frontmatter value.\n\nThe camel-case contract field names are stable portable identifiers. Their\nsnake-case tasknotes-spec counterparts include:\n\n| Contract field | tasknotes-spec role |\n|---|---|\n| `timeEstimate` | `time_estimate` |\n| `completedDate` | `completed_date` |\n| `dateCreated` | `date_created` |\n| `dateModified` | `date_modified` |\n| `recurrenceAnchor` | `recurrence_anchor` |\n| `completeInstances` | `complete_instances` |\n| `skippedInstances` | `skipped_instances` |\n| `recurrenceParent` | `recurrence_parent` |\n| `occurrenceDate` | `occurrence_date` |\n| `occurrenceMaterialization` | `occurrence_materialization` |\n| `occurrenceNextTrigger` | `occurrence_next_trigger` |\n| `occurrenceTemplate` | `occurrence_template` |\n| `occurrencePastHorizon` | `occurrence_past_horizon` |\n| `occurrenceFutureHorizon` | `occurrence_future_horizon` |\n| `timeEntries` | `time_entries` |\n| `blockedBy` | `blocked_by` |\n| `attachments` | `attachments` |\n\n## 12.6 Semantic profiles and capabilities\n\n`binding.profiles` and `binding.capabilities` describe semantics that records\nof this implementation may use:\n\n```yaml\nbinding:\n profiles: [core-lite, recurrence, materialized-occurrences]\n capabilities:\n - dependencies\n - reminders\n - attachments\n - links\n - time-tracking\n - materialized-occurrences\n - archive\n```\n\nThese are properties of the implementation, not claims that every consuming\napplication supports them. Before mutating a governed field, a consumer SHOULD\nverify its own corresponding capability. It may still perform unrelated\noperations when it preserves unsupported fields and invariants.\n\n## 12.7 Status and priority semantics\n\nThe implementing type schema defines the legal persisted values of the mapped\nfields. The binding gives those values TaskNotes meaning:\n\n```yaml\nbinding:\n status:\n values: [todo, doing, done, cancelled]\n default: todo\n completed_values: [done]\n skipped_values: [cancelled]\n default_skipped: cancelled\n definitions: []\n priority:\n values: [low, normal, high]\n default: normal\n definitions: []\n```\n\nThe following consistency rules apply:\n\n- binding values MUST equal the mapped type-schema enum values;\n- defaults MUST equal mapped `collection.read_defaults` values when present;\n- completed and skipped values MUST be members of `status.values`;\n- `default_skipped` MUST be a skipped value;\n- completed and skipped values MUST NOT overlap for materialized occurrences;\n and\n- definition semantics MUST agree with completed/skipped membership.\n\nStatus and priority labels, colors, and icons are presentation hints. Status\ncycle, completion, skipping, auto-archive, and priority weight are semantic.\n\n## 12.8 Title, recurrence, links, and operations\n\nThe remaining binding sections project the effective TaskNotes behavior\ndefined elsewhere in this specification:\n\n- `title` follows §9.13 and MUST agree with `collection.display` and\n `collection.path`;\n- `recurrence` follows §4;\n- `occurrences` follows §2.6.6, §4.18, §5.20, and §9.17;\n- `links` follows §11;\n- attachment membership is the portable `attachments` contract field; binary\n MIME type, digest, byte size, revision, and timestamps remain authoritative\n in mdbase file descriptors and are not projected into task frontmatter;\n- `archive` follows §5.12;\n- `time_tracking` follows §5.19 and §9.16;\n- `templating` follows §5.3.5 and §9.14; and\n- optional `nlp` triggers follow §9.18.\n\nArchive always operates on the portable `tags` contract field, so the binding\ndoes not repeat a record-specific `tags_field`. The implementation's `fields`\nmap determines the actual frontmatter property.\n\nApplication-local notification preferences and generator bookkeeping MUST NOT\nbe placed in the binding.\n\n## 12.9 Multiple implementations\n\nA collection may contain any number of types implementing\n`tasknotes.task 0.3.0-rc.3`. TaskNotes-aware readers MUST:\n\n1. resolve the exact local contract;\n2. enumerate every implementation in canonical type-name order;\n3. read each matching record through that implementation's projected view;\n4. validate the projected view; and\n5. retain the concrete type identity for updates.\n\nImplementations MUST NOT merge type schemas into one synthetic schema. A record\nis validated by its concrete type and then by its projected contract view.\n\nWhen an approval, cache, or external protocol pins an implementation set, it\nMUST pin the exact contract digest and sorted implementation descriptors,\nincluding each implementation digest. A newly installed type is therefore not\nsilently added to an existing approval.\n\nCreation MUST name one concrete implementing type. If no type is selected,\ncreation fails as ambiguous.\n\n## 12.10 Task-completed event\n\nAn event source that claims `tasknotes.task.completed 1.0.0` MUST emit one\nCloudEvents structured event for each observed transition from a\nnon-completed status to a completed status. Its `data` contains only:\n\n- `task_id`, using the stable TaskNotes ID when present and otherwise the\n normalized path;\n- `task_path`;\n- the current `title` and completed `status`; and\n- `completed_at`, the instant when TaskNotes observed the transition.\n\nThe event source MUST use the mdbase event/action interoperability profile\n`0.1`, pin the exact event-contract digest, and preserve any correlation and\ncausation identifiers supplied by the mutation context. It MUST NOT include a\ncomplete task record merely because one is locally available. An authorized\nconsumer can retrieve current state separately, avoiding stale snapshots and\nunnecessary disclosure.\n\nContract compatibility and bridge authorization are independent. Installing\nTaskNotes or resolving this contract does not grant permission to publish or\nconsume the event.\n\n## 12.11 Precedence and consistency\n\nThe complete implementation is self-describing:\n\n1. the contract schema is authoritative for the portable projected view;\n2. the type schema is authoritative for persisted value shapes;\n3. `collection` is authoritative for generic mdbase behavior;\n4. `lifecycle` is authoritative for generic managed writes; and\n5. `implements[].binding` is authoritative for TaskNotes semantics.\n\nWhere values intentionally mirror each other, producers MUST keep them equal.\nA TaskNotes-aware consumer MUST report a configuration error instead of\nsilently choosing between contradictory values.\n\n## 12.12 Safe writes\n\nTaskNotes-aware consumers MUST preserve:\n\n- unknown frontmatter properties unless explicit replacement or migration was\n requested;\n- Markdown body content unless an operation explicitly replaces it;\n- fields governed by unsupported capabilities; and\n- unrelated type metadata and implementations.\n\nGeneric mdbase operations are safe only when they preserve the same data.\nCompletion, recurrence mutation, occurrence materialization, dependency\nupdates, time tracking, archive, and other domain operations MUST follow the\nTaskNotes semantics referenced by the binding.\n\n## 12.13 Complete custom-field example\n\n```yaml\n---\nkind: mdbase.type\nname: work_task\nversion: 1\nschema:\n dialect: json-schema-2020-12\n value:\n type: object\n additionalProperties: true\n required: [summary, state, created_at]\n properties:\n summary: { type: string, minLength: 1 }\n state: { enum: [todo, doing, done, cancelled] }\n importance: { enum: [low, normal, high] }\n created_at: { type: string, format: date-time }\n tags:\n type: array\n items: { type: string }\ncollection:\n display:\n name_field: summary\n read_defaults:\n state: todo\n importance: normal\nlifecycle:\n on_create:\n set:\n created_at: { now: true }\nimplements:\n - contract: tasknotes.task\n version: 0.3.0-rc.3\n fields:\n title: summary\n status: state\n priority: importance\n dateCreated: created_at\n tags: tags\n binding:\n profiles: [core-lite]\n capabilities: [archive]\n title:\n storage: frontmatter\n filename_format: title\n status:\n values: [todo, doing, done, cancelled]\n default: todo\n completed_values: [done]\n skipped_values: [cancelled]\n default_skipped: cancelled\n definitions: []\n priority:\n values: [low, normal, high]\n default: normal\n definitions: []\n recurrence:\n syntax: tasknotes\n maintain_due_date_offset: false\n reset_body_checkboxes: false\n occurrences:\n identity_roles: [recurrenceParent, occurrenceDate]\n default_materialization: manual\n default_next_trigger: completion\n links:\n accepted_formats: [wikilink, markdown]\n write_format: wikilink\n archive:\n archived_tag: archived\n move_on_archive: false\n time_tracking:\n auto_stop_on_complete: true\n templating:\n enabled: false\n occurrence_enabled: false\n---\n```\n","aliases":["/spec/12-mdbase-v0.3-binding/"],"toc":[{"level":2,"id":"121-purpose","text":"12.1 Purpose"},{"level":2,"id":"122-the-mental-model","text":"12.2 The mental model"},{"level":2,"id":"123-layering","text":"12.3 Layering"},{"level":2,"id":"124-declaring-an-implementation","text":"12.4 Declaring an implementation"},{"level":2,"id":"125-portable-fields","text":"12.5 Portable fields"},{"level":2,"id":"126-semantic-profiles-and-capabilities","text":"12.6 Semantic profiles and capabilities"},{"level":2,"id":"127-status-and-priority-semantics","text":"12.7 Status and priority semantics"},{"level":2,"id":"128-title-recurrence-links-and-operations","text":"12.8 Title, recurrence, links, and operations"},{"level":2,"id":"129-multiple-implementations","text":"12.9 Multiple implementations"},{"level":2,"id":"1210-task-completed-event","text":"12.10 Task-completed event"},{"level":2,"id":"1211-precedence-and-consistency","text":"12.11 Precedence and consistency"},{"level":2,"id":"1212-safe-writes","text":"12.12 Safe writes"},{"level":2,"id":"1213-complete-custom-field-example","text":"12.13 Complete custom-field example"}],"html":"

Status: Draft

\n

Record contract: tasknotes.task 0.3.0-rc.3

\n

Event contract: tasknotes.task.completed 1.0.0

\n

Target: mdbase 0.3.x

\n

12.1 Purpose#

\n

This chapter defines how a TaskNotes task model is exposed through mdbase\nwithout coupling TaskNotes to one record type or one application's private\nextension.

\n

The binding has three deliberately separate parts:

\n
    \n
  1. the tasknotes.task data contract defines the portable task view;
  2. \n
  3. an mdbase type's implements entry maps that view to its own frontmatter\nfields and supplies TaskNotes behavior; and
  4. \n
  5. the rest of the type file continues to define that type's storage,\nmatching, defaults, lifecycle, links, and paths.
  6. \n
\n

The normative artifacts are:

\n\n

The optional event-interoperability artifacts are:

\n\n

12.2 The mental model#

\n

A contract is not another record type. It is a view that several record types\ncan implement and several applications can consume.

\n
personal_task ─┐\nwork_task ─────┼─ implements tasknotes.task 0.3.0-rc.3 ── TaskNotes\nissue_task ────┘                                  ├─ automation\n                                                  └─ another task app\n

Reading or listing through the contract uses the union of all implementing\ntypes. Creating a task is different: the caller MUST choose one exact target\ntype because the contract does not choose storage, paths, or lifecycle policy.

\n

The contract version is an exact semantic version. For this draft it is also\nthe tasknotes-spec version whose task semantics the contract exposes. There is\nno independent x-tasknotes.version or spec_version mirror.

\n

Record types use implements because they adapt persisted fields and semantic\nbindings to the tasknotes.task record contract. Event sources do not use a\ntype file. A TaskNotes application instead registers an event-source\ndeclaration for tasknotes.task.completed with an active mdbase\ninteroperability bridge.

\n

12.3 Layering#

\n

An implementing type MUST keep these responsibilities in their canonical\nlocations:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Informationmdbase v0.3 location
Persisted frontmatter shape, required fields, enum values, formatsschema
Type identificationmatch
Display field, defaults, links, uniqueness, and path generationcollection
Managed create/update valueslifecycle
Contract identity and custom field namesimplements[].contract, version, and fields
TaskNotes semantic behaviorimplements[].binding
\n

TaskNotes metadata MUST NOT be encoded as custom JSON Schema keywords.\nx-tasknotes MUST NOT be used for contract discovery, field mapping,\nconformance, or authorization.

\n

12.4 Declaring an implementation#

\n

An mdbase TaskNotes type declares one implementation:

\n
implements:\n  - contract: tasknotes.task\n    version: 0.3.0-rc.3\n    fields:\n      title: summary\n      status: state\n      priority: importance\n      dateCreated: created_at\n    binding:\n      # TaskNotes behavior; abbreviated here\n      profiles: [core-lite]\n      capabilities: []\n      title:\n        storage: frontmatter\n        filename_format: title\n      status:\n        values: [todo, doing, done]\n        default: todo\n        completed_values: [done]\n        definitions: []\n      priority:\n        values: [normal]\n        default: normal\n        definitions: []\n

The contract file identified by the exact contract and version MUST exist\nin the collection contract registry. The binding MUST validate against that\ncontract's binding_schema.

\n

Each type MUST declare at most one implementation of one exact contract\nidentity. A type may implement several different contracts.

\n

12.5 Portable fields#

\n

fields maps contract field paths to record field paths. Consumers access\ncontract fields and MUST NOT assume that their names are also frontmatter\nproperty names.

\n
fields:\n  title: summary\n  status: state\n  blockedBy: dependencies\n  attachments: files\n

Every unconditionally required contract field MUST be mapped. Every mapped\ncontract field and record field MUST exist in its respective JSON Schema.

\n

The contract view contains only mapped fields. It does not expose unmapped\nfrontmatter or the Markdown body. A consumer that requires either needs\nseparate, explicit whole-record access.

\n

title is optional in the portable schema because TaskNotes permits filename\ntitle storage. When binding.title.storage is filename, consumers derive\nthe effective title from the record identity/path rules in §9.13 instead of\nexpecting a projected frontmatter value.

\n

The camel-case contract field names are stable portable identifiers. Their\nsnake-case tasknotes-spec counterparts include:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Contract fieldtasknotes-spec role
timeEstimatetime_estimate
completedDatecompleted_date
dateCreateddate_created
dateModifieddate_modified
recurrenceAnchorrecurrence_anchor
completeInstancescomplete_instances
skippedInstancesskipped_instances
recurrenceParentrecurrence_parent
occurrenceDateoccurrence_date
occurrenceMaterializationoccurrence_materialization
occurrenceNextTriggeroccurrence_next_trigger
occurrenceTemplateoccurrence_template
occurrencePastHorizonoccurrence_past_horizon
occurrenceFutureHorizonoccurrence_future_horizon
timeEntriestime_entries
blockedByblocked_by
attachmentsattachments
\n

12.6 Semantic profiles and capabilities#

\n

binding.profiles and binding.capabilities describe semantics that records\nof this implementation may use:

\n
binding:\n  profiles: [core-lite, recurrence, materialized-occurrences]\n  capabilities:\n    - dependencies\n    - reminders\n    - attachments\n    - links\n    - time-tracking\n    - materialized-occurrences\n    - archive\n

These are properties of the implementation, not claims that every consuming\napplication supports them. Before mutating a governed field, a consumer SHOULD\nverify its own corresponding capability. It may still perform unrelated\noperations when it preserves unsupported fields and invariants.

\n

12.7 Status and priority semantics#

\n

The implementing type schema defines the legal persisted values of the mapped\nfields. The binding gives those values TaskNotes meaning:

\n
binding:\n  status:\n    values: [todo, doing, done, cancelled]\n    default: todo\n    completed_values: [done]\n    skipped_values: [cancelled]\n    default_skipped: cancelled\n    definitions: []\n  priority:\n    values: [low, normal, high]\n    default: normal\n    definitions: []\n

The following consistency rules apply:

\n
    \n
  • binding values MUST equal the mapped type-schema enum values;
  • \n
  • defaults MUST equal mapped collection.read_defaults values when present;
  • \n
  • completed and skipped values MUST be members of status.values;
  • \n
  • default_skipped MUST be a skipped value;
  • \n
  • completed and skipped values MUST NOT overlap for materialized occurrences;\nand
  • \n
  • definition semantics MUST agree with completed/skipped membership.
  • \n
\n

Status and priority labels, colors, and icons are presentation hints. Status\ncycle, completion, skipping, auto-archive, and priority weight are semantic.

\n\n

The remaining binding sections project the effective TaskNotes behavior\ndefined elsewhere in this specification:

\n
    \n
  • title follows §9.13 and MUST agree with collection.display and\ncollection.path;
  • \n
  • recurrence follows §4;
  • \n
  • occurrences follows §2.6.6, §4.18, §5.20, and §9.17;
  • \n
  • links follows §11;
  • \n
  • attachment membership is the portable attachments contract field; binary\nMIME type, digest, byte size, revision, and timestamps remain authoritative\nin mdbase file descriptors and are not projected into task frontmatter;
  • \n
  • archive follows §5.12;
  • \n
  • time_tracking follows §5.19 and §9.16;
  • \n
  • templating follows §5.3.5 and §9.14; and
  • \n
  • optional nlp triggers follow §9.18.
  • \n
\n

Archive always operates on the portable tags contract field, so the binding\ndoes not repeat a record-specific tags_field. The implementation's fields\nmap determines the actual frontmatter property.

\n

Application-local notification preferences and generator bookkeeping MUST NOT\nbe placed in the binding.

\n

12.9 Multiple implementations#

\n

A collection may contain any number of types implementing\ntasknotes.task 0.3.0-rc.3. TaskNotes-aware readers MUST:

\n
    \n
  1. resolve the exact local contract;
  2. \n
  3. enumerate every implementation in canonical type-name order;
  4. \n
  5. read each matching record through that implementation's projected view;
  6. \n
  7. validate the projected view; and
  8. \n
  9. retain the concrete type identity for updates.
  10. \n
\n

Implementations MUST NOT merge type schemas into one synthetic schema. A record\nis validated by its concrete type and then by its projected contract view.

\n

When an approval, cache, or external protocol pins an implementation set, it\nMUST pin the exact contract digest and sorted implementation descriptors,\nincluding each implementation digest. A newly installed type is therefore not\nsilently added to an existing approval.

\n

Creation MUST name one concrete implementing type. If no type is selected,\ncreation fails as ambiguous.

\n

12.10 Task-completed event#

\n

An event source that claims tasknotes.task.completed 1.0.0 MUST emit one\nCloudEvents structured event for each observed transition from a\nnon-completed status to a completed status. Its data contains only:

\n
    \n
  • task_id, using the stable TaskNotes ID when present and otherwise the\nnormalized path;
  • \n
  • task_path;
  • \n
  • the current title and completed status; and
  • \n
  • completed_at, the instant when TaskNotes observed the transition.
  • \n
\n

The event source MUST use the mdbase event/action interoperability profile\n0.1, pin the exact event-contract digest, and preserve any correlation and\ncausation identifiers supplied by the mutation context. It MUST NOT include a\ncomplete task record merely because one is locally available. An authorized\nconsumer can retrieve current state separately, avoiding stale snapshots and\nunnecessary disclosure.

\n

Contract compatibility and bridge authorization are independent. Installing\nTaskNotes or resolving this contract does not grant permission to publish or\nconsume the event.

\n

12.11 Precedence and consistency#

\n

The complete implementation is self-describing:

\n
    \n
  1. the contract schema is authoritative for the portable projected view;
  2. \n
  3. the type schema is authoritative for persisted value shapes;
  4. \n
  5. collection is authoritative for generic mdbase behavior;
  6. \n
  7. lifecycle is authoritative for generic managed writes; and
  8. \n
  9. implements[].binding is authoritative for TaskNotes semantics.
  10. \n
\n

Where values intentionally mirror each other, producers MUST keep them equal.\nA TaskNotes-aware consumer MUST report a configuration error instead of\nsilently choosing between contradictory values.

\n

12.12 Safe writes#

\n

TaskNotes-aware consumers MUST preserve:

\n
    \n
  • unknown frontmatter properties unless explicit replacement or migration was\nrequested;
  • \n
  • Markdown body content unless an operation explicitly replaces it;
  • \n
  • fields governed by unsupported capabilities; and
  • \n
  • unrelated type metadata and implementations.
  • \n
\n

Generic mdbase operations are safe only when they preserve the same data.\nCompletion, recurrence mutation, occurrence materialization, dependency\nupdates, time tracking, archive, and other domain operations MUST follow the\nTaskNotes semantics referenced by the binding.

\n

12.13 Complete custom-field example#

\n
---\nkind: mdbase.type\nname: work_task\nversion: 1\nschema:\n  dialect: json-schema-2020-12\n  value:\n    type: object\n    additionalProperties: true\n    required: [summary, state, created_at]\n    properties:\n      summary: { type: string, minLength: 1 }\n      state: { enum: [todo, doing, done, cancelled] }\n      importance: { enum: [low, normal, high] }\n      created_at: { type: string, format: date-time }\n      tags:\n        type: array\n        items: { type: string }\ncollection:\n  display:\n    name_field: summary\n  read_defaults:\n    state: todo\n    importance: normal\nlifecycle:\n  on_create:\n    set:\n      created_at: { now: true }\nimplements:\n  - contract: tasknotes.task\n    version: 0.3.0-rc.3\n    fields:\n      title: summary\n      status: state\n      priority: importance\n      dateCreated: created_at\n      tags: tags\n    binding:\n      profiles: [core-lite]\n      capabilities: [archive]\n      title:\n        storage: frontmatter\n        filename_format: title\n      status:\n        values: [todo, doing, done, cancelled]\n        default: todo\n        completed_values: [done]\n        skipped_values: [cancelled]\n        default_skipped: cancelled\n        definitions: []\n      priority:\n        values: [low, normal, high]\n        default: normal\n        definitions: []\n      recurrence:\n        syntax: tasknotes\n        maintain_due_date_offset: false\n        reset_body_checkboxes: false\n      occurrences:\n        identity_roles: [recurrenceParent, occurrenceDate]\n        default_materialization: manual\n        default_next_trigger: completion\n      links:\n        accepted_formats: [wikilink, markdown]\n        write_format: wikilink\n      archive:\n        archived_tag: archived\n        move_on_archive: false\n      time_tracking:\n        auto_stop_on_complete: true\n      templating:\n        enabled: false\n        occurrence_enabled: false\n---\n
","text":"Status: Draft Record contract: tasknotes.task 0.3.0-rc.3 Event contract: tasknotes.task.completed 1.0.0 Target: mdbase 0.3.x 12.1 Purpose# This chapter defines how a TaskNotes task model is exposed through mdbase without coupling TaskNotes to one record type or one application's private extension. The binding has three deliberately separate parts: the tasknotes.task data contract defines the portable task view; an mdbase type's implements entry maps that view to its own frontmatter fields and supplies TaskNotes behavior; and the rest of the type file continues to define that type's storage, matching, defaults, lifecycle, links, and paths. The normative artifacts are: mdbase/tasknotes.task.md, the record contract; schemas/tasknotes-task.schema.json, the projected task-view schema; and schemas/tasknotes-task-binding.schema.json, the implementation binding schema. The optional event-interoperability artifacts are: mdbase/tasknotes.task.completed.md, the event contract; and schemas/tasknotes-task-completed.schema.json, its event-data schema. 12.2 The mental model# A contract is not another record type. It is a view that several record types can implement and several applications can consume. personal_task ─┐ work_task ─────┼─ implements tasknotes.task 0.3.0-rc.3 ── TaskNotes issue_task ────┘ ├─ automation └─ another task app Reading or listing through the contract uses the union of all implementing types. Creating a task is different: the caller MUST choose one exact target type because the contract does not choose storage, paths, or lifecycle policy. The contract version is an exact semantic version. For this draft it is also the tasknotes-spec version whose task semantics the contract exposes. There is no independent x-tasknotes.version or spec_version mirror. Record types use implements because they adapt persisted fields and semantic bindings to the tasknotes.task record contract. Event sources do not use a type file. A TaskNotes application instead registers an event-source declaration for tasknotes.task.completed with an active mdbase interoperability bridge. 12.3 Layering# An implementing type MUST keep these responsibilities in their canonical locations: Information mdbase v0.3 location Persisted frontmatter shape, required fields, enum values, formats schema Type identification match Display field, defaults, links, uniqueness, and path generation collection Managed create/update values lifecycle Contract identity and custom field names implements[].contract, version, and fields TaskNotes semantic behavior implements[].binding TaskNotes metadata MUST NOT be encoded as custom JSON Schema keywords. x-tasknotes MUST NOT be used for contract discovery, field mapping, conformance, or authorization. 12.4 Declaring an implementation# An mdbase TaskNotes type declares one implementation: implements: - contract: tasknotes.task version: 0.3.0-rc.3 fields: title: summary status: state priority: importance dateCreated: created_at binding: # TaskNotes behavior; abbreviated here profiles: [core-lite] capabilities: [] title: storage: frontmatter filename_format: title status: values: [todo, doing, done] default: todo completed_values: [done] definitions: [] priority: values: [normal] default: normal definitions: [] The contract file identified by the exact contract and version MUST exist in the collection contract registry. The binding MUST validate against that contract's binding_schema. Each type MUST declare at most one implementation of one exact contract identity. A type may implement several different contracts. 12.5 Portable fields# fields maps contract field paths to record field paths. Consumers access contract fields and MUST NOT assume that their names are also frontmatter property names. fields: title: summary status: state blockedBy: dependencies attachments: files Every unconditionally required contract field MUST be mapped. Every mapped contract field and record field MUST exist in its respective JSON Schema. The contract view contains only mapped fields. It does not expose unmapped frontmatter or the Markdown body. A consumer that requires either needs separate, explicit whole-record access. title is optional in the portable schema because TaskNotes permits filename title storage. When binding.title.storage is filename, consumers derive the effective title from the record identity/path rules in §9.13 instead of expecting a projected frontmatter value. The camel-case contract field names are stable portable identifiers. Their snake-case tasknotes-spec counterparts include: Contract field tasknotes-spec role timeEstimate time_estimate completedDate completed_date dateCreated date_created dateModified date_modified recurrenceAnchor recurrence_anchor completeInstances complete_instances skippedInstances skipped_instances recurrenceParent recurrence_parent occurrenceDate occurrence_date occurrenceMaterialization occurrence_materialization occurrenceNextTrigger occurrence_next_trigger occurrenceTemplate occurrence_template occurrencePastHorizon occurrence_past_horizon occurrenceFutureHorizon occurrence_future_horizon timeEntries time_entries blockedBy blocked_by attachments attachments 12.6 Semantic profiles and capabilities# binding.profiles and binding.capabilities describe semantics that records of this implementation may use: binding: profiles: [core-lite, recurrence, materialized-occurrences] capabilities: - dependencies - reminders - attachments - links - time-tracking - materialized-occurrences - archive These are properties of the implementation, not claims that every consuming application supports them. Before mutating a governed field, a consumer SHOULD verify its own corresponding capability. It may still perform unrelated operations when it preserves unsupported fields and invariants. 12.7 Status and priority semantics# The implementing type schema defines the legal persisted values of the mapped fields. The binding gives those values TaskNotes meaning: binding: status: values: [todo, doing, done, cancelled] default: todo completed_values: [done] skipped_values: [cancelled] default_skipped: cancelled definitions: [] priority: values: [low, normal, high] default: normal definitions: [] The following consistency rules apply: binding values MUST equal the mapped type-schema enum values; defaults MUST equal mapped collection.read_defaults values when present; completed and skipped values MUST be members of status.values; default_skipped MUST be a skipped value; completed and skipped values MUST NOT overlap for materialized occurrences; and definition semantics MUST agree with completed/skipped membership. Status and priority labels, colors, and icons are presentation hints. Status cycle, completion, skipping, auto-archive, and priority weight are semantic. 12.8 Title, recurrence, links, and operations# The remaining binding sections project the effective TaskNotes behavior defined elsewhere in this specification: title follows §9.13 and MUST agree with collection.display and collection.path; recurrence follows §4; occurrences follows §2.6.6, §4.18, §5.20, and §9.17; links follows §11; attachment membership is the portable attachments contract field; binary MIME type, digest, byte size, revision, and timestamps remain authoritative in mdbase file descriptors and are not projected into task frontmatter; archive follows §5.12; time_tracking follows §5.19 and §9.16; templating follows §5.3.5 and §9.14; and optional nlp triggers follow §9.18. Archive always operates on the portable tags contract field, so the binding does not repeat a record-specific tags_field. The implementation's fields map determines the actual frontmatter property. Application-local notification preferences and generator bookkeeping MUST NOT be placed in the binding. 12.9 Multiple implementations# A collection may contain any number of types implementing tasknotes.task 0.3.0-rc.3. TaskNotes-aware readers MUST: resolve the exact local contract; enumerate every implementation in canonical type-name order; read each matching record through that implementation's projected view; validate the projected view; and retain the concrete type identity for updates. Implementations MUST NOT merge type schemas into one synthetic schema. A record is validated by its concrete type and then by its projected contract view. When an approval, cache, or external protocol pins an implementation set, it MUST pin the exact contract digest and sorted implementation descriptors, including each implementation digest. A newly installed type is therefore not silently added to an existing approval. Creation MUST name one concrete implementing type. If no type is selected, creation fails as ambiguous. 12.10 Task-completed event# An event source that claims tasknotes.task.completed 1.0.0 MUST emit one CloudEvents structured event for each observed transition from a non-completed status to a completed status. Its data contains only: task_id, using the stable TaskNotes ID when present and otherwise the normalized path; task_path; the current title and completed status; and completed_at, the instant when TaskNotes observed the transition. The event source MUST use the mdbase event/action interoperability profile 0.1, pin the exact event-contract digest, and preserve any correlation and causation identifiers supplied by the mutation context. It MUST NOT include a complete task record merely because one is locally available. An authorized consumer can retrieve current state separately, avoiding stale snapshots and unnecessary disclosure. Contract compatibility and bridge authorization are independent. Installing TaskNotes or resolving this contract does not grant permission to publish or consume the event. 12.11 Precedence and consistency# The complete implementation is self-describing: the contract schema is authoritative for the portable projected view; the type schema is authoritative for persisted value shapes; collection is authoritative for generic mdbase behavior; lifecycle is authoritative for generic managed writes; and implements[].binding is authoritative for TaskNotes semantics. Where values intentionally mirror each other, producers MUST keep them equal. A TaskNotes-aware consumer MUST report a configuration error instead of silently choosing between contradictory values. 12.12 Safe writes# TaskNotes-aware consumers MUST preserve: unknown frontmatter properties unless explicit replacement or migration was requested; Markdown body content unless an operation explicitly replaces it; fields governed by unsupported capabilities; and unrelated type metadata and implementations. Generic mdbase operations are safe only when they preserve the same data. Completion, recurrence mutation, occurrence materialization, dependency updates, time tracking, archive, and other domain operations MUST follow the TaskNotes semantics referenced by the binding. 12.13 Complete custom-field example# --- kind: mdbase.type name: work_task version: 1 schema: dialect: json-schema-2020-12 value: type: object additionalProperties: true required: [summary, state, created_at] properties: summary: { type: string, minLength: 1 } state: { enum: [todo, doing, done, cancelled] } importance: { enum: [low, normal, high] } created_at: { type: string, format: date-time } tags: type: array items: { type: string } collection: display: name_field: summary read_defaults: state: todo importance: normal lifecycle: on_create: set: created_at: { now: true } implements: - contract: tasknotes.task version: 0.3.0-rc.3 fields: title: summary status: state priority: importance dateCreated: created_at tags: tags binding: profiles: [core-lite] capabilities: [archive] title: storage: frontmatter filename_format: title status: values: [todo, doing, done, cancelled] default: todo completed_values: [done] skipped_values: [cancelled] default_skipped: cancelled definitions: [] priority: values: [low, normal, high] default: normal definitions: [] recurrence: syntax: tasknotes maintain_due_date_offset: false reset_body_checkboxes: false occurrences: identity_roles: [recurrenceParent, occurrenceDate] default_materialization: manual default_next_trigger: completion links: accepted_formats: [wikilink, markdown] write_format: wikilink archive: archived_tag: archived move_on_archive: false time_tracking: auto_stop_on_complete: true templating: enabled: false occurrence_enabled: false ---"},{"route":"/developers/specification/CHANGELOG/","title":"Changelog","description":"Initial standalone draft of tasknotes-spec including:","product":"specification","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes-spec:CHANGELOG.md","namespace":"specification","relativePath":"CHANGELOG.md","raw":"# Changelog\n\n## 0.3.0-rc.3 - 2026-08-02\n\n- define manual ordering as an opaque string rank so clients can insert and\n reorder tasks without renumbering an entire view\n\n## 0.3.0-rc.2 - 2026-08-02\n\n- add first-class `attachments` as an ordered frontmatter list of portable file\n links, with explicit membership, canonical-path, reference-safety, and\n materialized-occurrence semantics\n- expose attachment references in the `tasknotes.task` mdbase contract while\n leaving binary metadata authoritative in the file store\n\n## 0.3.0-rc.1 - 2026-07-28\n\n- adopt the discriminated first-class mdbase contract shape for\n `tasknotes.task`, including explicit `contract_type: record`\n- add the `tasknotes.task.completed 1.0.0` event contract and minimal\n privacy-preserving event-data schema for the mdbase interoperability profile\n- separate type-file record implementation bindings from application-level\n event-source declarations\n\n## 0.2.0-draft - 2026-05-31\n\n- add optional `materialized-occurrences` profile for recurrence occurrence notes, on-completion materialization, and occurrence-state reconciliation\n- add optional NLP trigger configuration so TaskNotes clients can share capture\n suggestion vocabulary\n- replace the private `x-tasknotes` discovery envelope with the first-class\n `tasknotes.task 0.2.0` mdbase data contract, portable task-view schema, and\n implementation binding schema\n- document the precedence and consistency rules between JSON Schema,\n `collection`, `lifecycle`, contract field mappings, and TaskNotes behavior\n\n## 0.1.0-draft - 2026-02-20\n\nInitial standalone draft of `tasknotes-spec` including:\n\n- motivation, scope, and normative conventions\n- terminology\n- task model and field mapping\n- temporal semantics\n- recurrence semantics\n- operation semantics\n- validation model\n- conformance profiles\n- compatibility and migration policy\n- collection configuration schema and provider model (`tasknotes.yaml`, TaskNotes `data.json`)\n- full dependency (`blocked_by`) semantics\n- full reminder (`reminders`) semantics\n- explicit time-tracking management semantics (`time_entries` lifecycle, start/stop/edit/remove, and completion-triggered auto-stop configuration)\n- explicit links chapter and link-resolution rules for projects/dependencies\n- optional `templating` conformance profile with create-time template expansion/merge semantics\n","aliases":["/spec/CHANGELOG/"],"toc":[{"level":2,"id":"030-rc3-2026-08-02","text":"0.3.0-rc.3 - 2026-08-02"},{"level":2,"id":"030-rc2-2026-08-02","text":"0.3.0-rc.2 - 2026-08-02"},{"level":2,"id":"030-rc1-2026-07-28","text":"0.3.0-rc.1 - 2026-07-28"},{"level":2,"id":"020-draft-2026-05-31","text":"0.2.0-draft - 2026-05-31"},{"level":2,"id":"010-draft-2026-02-20","text":"0.1.0-draft - 2026-02-20"}],"html":"

0.3.0-rc.3 - 2026-08-02#

\n
    \n
  • define manual ordering as an opaque string rank so clients can insert and\nreorder tasks without renumbering an entire view
  • \n
\n

0.3.0-rc.2 - 2026-08-02#

\n
    \n
  • add first-class attachments as an ordered frontmatter list of portable file\nlinks, with explicit membership, canonical-path, reference-safety, and\nmaterialized-occurrence semantics
  • \n
  • expose attachment references in the tasknotes.task mdbase contract while\nleaving binary metadata authoritative in the file store
  • \n
\n

0.3.0-rc.1 - 2026-07-28#

\n
    \n
  • adopt the discriminated first-class mdbase contract shape for\ntasknotes.task, including explicit contract_type: record
  • \n
  • add the tasknotes.task.completed 1.0.0 event contract and minimal\nprivacy-preserving event-data schema for the mdbase interoperability profile
  • \n
  • separate type-file record implementation bindings from application-level\nevent-source declarations
  • \n
\n

0.2.0-draft - 2026-05-31#

\n
    \n
  • add optional materialized-occurrences profile for recurrence occurrence notes, on-completion materialization, and occurrence-state reconciliation
  • \n
  • add optional NLP trigger configuration so TaskNotes clients can share capture\nsuggestion vocabulary
  • \n
  • replace the private x-tasknotes discovery envelope with the first-class\ntasknotes.task 0.2.0 mdbase data contract, portable task-view schema, and\nimplementation binding schema
  • \n
  • document the precedence and consistency rules between JSON Schema,\ncollection, lifecycle, contract field mappings, and TaskNotes behavior
  • \n
\n

0.1.0-draft - 2026-02-20#

\n

Initial standalone draft of tasknotes-spec including:

\n
    \n
  • motivation, scope, and normative conventions
  • \n
  • terminology
  • \n
  • task model and field mapping
  • \n
  • temporal semantics
  • \n
  • recurrence semantics
  • \n
  • operation semantics
  • \n
  • validation model
  • \n
  • conformance profiles
  • \n
  • compatibility and migration policy
  • \n
  • collection configuration schema and provider model (tasknotes.yaml, TaskNotes data.json)
  • \n
  • full dependency (blocked_by) semantics
  • \n
  • full reminder (reminders) semantics
  • \n
  • explicit time-tracking management semantics (time_entries lifecycle, start/stop/edit/remove, and completion-triggered auto-stop configuration)
  • \n
  • explicit links chapter and link-resolution rules for projects/dependencies
  • \n
  • optional templating conformance profile with create-time template expansion/merge semantics
  • \n
\n","text":"0.3.0-rc.3 - 2026-08-02# define manual ordering as an opaque string rank so clients can insert and reorder tasks without renumbering an entire view 0.3.0-rc.2 - 2026-08-02# add first-class attachments as an ordered frontmatter list of portable file links, with explicit membership, canonical-path, reference-safety, and materialized-occurrence semantics expose attachment references in the tasknotes.task mdbase contract while leaving binary metadata authoritative in the file store 0.3.0-rc.1 - 2026-07-28# adopt the discriminated first-class mdbase contract shape for tasknotes.task, including explicit contract_type: record add the tasknotes.task.completed 1.0.0 event contract and minimal privacy-preserving event-data schema for the mdbase interoperability profile separate type-file record implementation bindings from application-level event-source declarations 0.2.0-draft - 2026-05-31# add optional materialized-occurrences profile for recurrence occurrence notes, on-completion materialization, and occurrence-state reconciliation add optional NLP trigger configuration so TaskNotes clients can share capture suggestion vocabulary replace the private x-tasknotes discovery envelope with the first-class tasknotes.task 0.2.0 mdbase data contract, portable task-view schema, and implementation binding schema document the precedence and consistency rules between JSON Schema, collection, lifecycle, contract field mappings, and TaskNotes behavior 0.1.0-draft - 2026-02-20# Initial standalone draft of tasknotes-spec including: motivation, scope, and normative conventions terminology task model and field mapping temporal semantics recurrence semantics operation semantics validation model conformance profiles compatibility and migration policy collection configuration schema and provider model (tasknotes.yaml, TaskNotes data.json) full dependency (blocked_by) semantics full reminder (reminders) semantics explicit time-tracking management semantics (time_entries lifecycle, start/stop/edit/remove, and completion-triggered auto-stop configuration) explicit links chapter and link-resolution rules for projects/dependencies optional templating conformance profile with create-time template expansion/merge semantics"},{"route":"/obsidian/","title":"TaskNotes for Obsidian","description":"Install TaskNotes, create a first task, and open the default Obsidian Base views.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/index.md","namespace":"obsidian","relativePath":"index.md","raw":"---\ndescription: Install TaskNotes, create a first task, and open the default Obsidian Base views.\nhide:\n - toc\n---\n\n# TaskNotes for Obsidian\n\nThis guide covers the TaskNotes plugin for Obsidian. It follows the \"one note per task\" principle: each task is a Markdown file with structured metadata in YAML frontmatter.\n\n![Task List view](assets/views-tasks-list.png)\n\n## Requirements\n\nTaskNotes 4.13.0 requires **Obsidian 1.12.2** or later and depends on the **Bases** core plugin. Before you begin, open Obsidian Settings and confirm Bases is enabled under Core Plugins.\n\n## Getting Started\n\n### 1. Install and Enable\n\nInstall TaskNotes from Community Plugins in Obsidian settings, then enable it. If Bases is still disabled, enable it right away so TaskNotes views can open correctly.\n\n### 2. Create Your First Task\n\nPress Ctrl+P (or Cmd+P on macOS), run **TaskNotes: Create new task**, fill in the modal, and save. If you prefer inline workflows, start with a checkbox like `- [ ] Buy groceries` and convert it using the inline task command.\n\n![Create task modal](assets/modal-task-create.png)\n\n### 3. Open the Task List\n\nOpen your first view from the TaskNotes ribbon icon or by running **TaskNotes: Open tasks view** from the command palette. This opens the default Task List `.base` file inside `TaskNotes/Views`.\n\n### 4. Explore\n\nUse [Core Concepts](core-concepts.md) to understand the data model, [Features](features.md) for workflow capabilities, [Views](views.md) for interface behaviour, and [Settings](settings.md) to tune TaskNotes for your vault. If you already have task-like notes, start with [Adopt TaskNotes in an existing vault](getting-started/existing-vault.md).\n\n## Quick Links\n\n\n","aliases":[],"toc":[{"level":2,"id":"requirements","text":"Requirements"},{"level":2,"id":"getting-started","text":"Getting Started"},{"level":3,"id":"1-install-and-enable","text":"1. Install and Enable"},{"level":3,"id":"2-create-your-first-task","text":"2. Create Your First Task"},{"level":3,"id":"3-open-the-task-list","text":"3. Open the Task List"},{"level":3,"id":"4-explore","text":"4. Explore"},{"level":2,"id":"quick-links","text":"Quick Links"}],"html":"

This guide covers the TaskNotes plugin for Obsidian. It follows the "one note per task" principle: each task is a Markdown file with structured metadata in YAML frontmatter.

\n

\"Task

\n

Requirements#

\n

TaskNotes 4.13.0 requires Obsidian 1.12.2 or later and depends on the Bases core plugin. Before you begin, open Obsidian Settings and confirm Bases is enabled under Core Plugins.

\n

Getting Started#

\n

1. Install and Enable#

\n

Install TaskNotes from Community Plugins in Obsidian settings, then enable it. If Bases is still disabled, enable it right away so TaskNotes views can open correctly.

\n

2. Create Your First Task#

\n

Press Ctrl+P (or Cmd+P on macOS), run TaskNotes: Create new task, fill in the modal, and save. If you prefer inline workflows, start with a checkbox like - [ ] Buy groceries and convert it using the inline task command.

\n

\"Create

\n

3. Open the Task List#

\n

Open your first view from the TaskNotes ribbon icon or by running TaskNotes: Open tasks view from the command palette. This opens the default Task List .base file inside TaskNotes/Views.

\n

4. Explore#

\n

Use Core Concepts to understand the data model, Features for workflow capabilities, Views for interface behaviour, and Settings to tune TaskNotes for your vault. If you already have task-like notes, start with Adopt TaskNotes in an existing vault.

\n

Quick Links#

\n\n","text":"This guide covers the TaskNotes plugin for Obsidian. It follows the \"one note per task\" principle: each task is a Markdown file with structured metadata in YAML frontmatter. Requirements# TaskNotes 4.13.0 requires Obsidian 1.12.2 or later and depends on the Bases core plugin. Before you begin, open Obsidian Settings and confirm Bases is enabled under Core Plugins. Getting Started# 1. Install and Enable# Install TaskNotes from Community Plugins in Obsidian settings, then enable it. If Bases is still disabled, enable it right away so TaskNotes views can open correctly. 2. Create Your First Task# Press Ctrl+P (or Cmd+P on macOS), run TaskNotes: Create new task, fill in the modal, and save. If you prefer inline workflows, start with a checkbox like - [ ] Buy groceries and convert it using the inline task command. 3. Open the Task List# Open your first view from the TaskNotes ribbon icon or by running TaskNotes: Open tasks view from the command palette. This opens the default Task List .base file inside TaskNotes/Views. 4. Explore# Use Core Concepts to understand the data model, Features for workflow capabilities, Views for interface behaviour, and Settings to tune TaskNotes for your vault. If you already have task-like notes, start with Adopt TaskNotes in an existing vault. Quick Links# GitHub Repository Source code, issues, releases, and contribution discussions Task Management Status, priority, dates, reminders, and recurring tasks Inline Tasks Widgets, natural language parsing, and checkbox conversion Calendar Integration Google Calendar, Outlook, and ICS subscriptions HTTP API REST API for automation and external integrations JavaScript API In-process API for companion plugins and in-vault scripts Companion Plugins Optional plugins such as Canvas Bases and TaskNotes Workflows that build on TaskNotes Migration Guide Upgrading from TaskNotes v3 to v4 Troubleshooting Common issues and how to resolve them Command Reference Every registered command, generated from the plugin source Backup & Recovery Protect task notes, Base files, settings, and integration data Specification The formal spec behind TaskNotes: data model, operations, recurrence, and conformance"},{"route":"/obsidian/calendar-setup/","title":"Calendar Integration Setup","description":"TaskNotes supports Google Calendar and Microsoft Calendar integration via OAuth 2.0.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/calendar-setup.md","namespace":"obsidian","relativePath":"calendar-setup.md","raw":"# Calendar Integration Setup\n\nTaskNotes supports Google Calendar and Microsoft Calendar integration via OAuth 2.0.\n\n## Setup (Your Own OAuth Credentials)\n\nTo connect calendars, create OAuth credentials with Google and/or Microsoft, then paste them into TaskNotes Integrations settings. The sections below walk through each provider.\n\n![Integrations calendar settings](assets/settings-integrations-calendar.png)\n\n### Google Calendar\n\n\n\n*Video by [@antoneheyward](https://www.youtube.com/@antoneheyward)*\n\nIn [Google Cloud Console](https://console.cloud.google.com), create or select a project, enable the Google Calendar API, and create OAuth 2.0 credentials using the Desktop application type. Then copy the Client ID and Client Secret into TaskNotes (`Settings -> TaskNotes -> Integrations`) and click **Connect Google Calendar**.\n\nIf your Google OAuth app is still in testing mode, add the Google account you will connect with under **Google Auth Platform -> Audience -> Test users**. Otherwise Google may block sign-in with a 403 `access_denied` error saying the app has not completed verification.\n\n### Microsoft Calendar\n\nIn [Azure Portal](https://portal.azure.com), create an App Registration for your Microsoft account type. TaskNotes currently uses Microsoft's `common` OAuth authority, so the app registration must allow the account type you plan to connect through that authority. Tenant-specific single-tenant authorities are not configurable yet.\n\nUnder **Authentication**, add the **Mobile and desktop applications** platform and add this redirect URI:\n\n```text\nhttp://localhost\n```\n\nAlso turn on **Allow public client flows**. TaskNotes uses a local loopback callback with a dynamic port, which Microsoft matches against the registered loopback URI.\n\nIf Azure does not accept the loopback redirect URI through the normal UI, configure loopback redirect support in the manifest by adding:\n\n```json\n{\n \"url\": \"http://127.0.0.1\",\n \"type\": \"Web\"\n}\n```\n\nNext, add delegated Microsoft Graph API permissions (`Calendars.Read`, `Calendars.ReadWrite`, and `offline_access`) and grant consent when required by your organization. Copy the Application (client) ID into TaskNotes, then click **Connect Microsoft Calendar**. The client secret field can be left blank for public-client desktop setup.\n\n## Security Notes\n\nOAuth client IDs, client secrets, and account tokens are stored locally in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system. They are not written to TaskNotes' `data.json`. Tokens refresh automatically, calendar data syncs directly between your vault and provider, and you can disconnect at any time to revoke account access.\n\nSecret Storage is local to the Obsidian installation and vault. When setting up TaskNotes on another device, enter the OAuth app credentials and connect the calendar again. After disconnecting, use **Forget saved credentials** if you also want to remove the client ID and client secret.\n\n## Troubleshooting\n\n**\"Failed to connect\"**\n\nVerify credentials first, then confirm loopback redirect configuration. TaskNotes uses a local callback on `127.0.0.1` with a dynamically selected port. For Microsoft, ensure loopback redirect support is configured in the app registration. Also confirm required permissions/scopes are granted.\n\nFor Google 403 `access_denied` errors during sign-in, confirm the account is listed as a test user in the Google Auth Platform audience settings while your OAuth app is in testing mode.\n\n**\"Failed to fetch events\"**\n\nDisconnect and reconnect to refresh OAuth tokens, then re-check provider-side calendar permissions.\n\n**Connection lost after Obsidian restart**\n\nTokens should persist between sessions. If reconnection is required each restart, check whether Obsidian Secret Storage is available and retaining secrets for the vault.\n","aliases":["/calendar-setup/"],"toc":[{"level":2,"id":"setup-your-own-oauth-credentials","text":"Setup (Your Own OAuth Credentials)"},{"level":3,"id":"google-calendar","text":"Google Calendar"},{"level":3,"id":"microsoft-calendar","text":"Microsoft Calendar"},{"level":2,"id":"security-notes","text":"Security Notes"},{"level":2,"id":"troubleshooting","text":"Troubleshooting"}],"html":"

TaskNotes supports Google Calendar and Microsoft Calendar integration via OAuth 2.0.

\n

Setup (Your Own OAuth Credentials)#

\n

To connect calendars, create OAuth credentials with Google and/or Microsoft, then paste them into TaskNotes Integrations settings. The sections below walk through each provider.

\n

\"Integrations

\n

Google Calendar#

\n\n\n

Video by @antoneheyward

\n

In Google Cloud Console, create or select a project, enable the Google Calendar API, and create OAuth 2.0 credentials using the Desktop application type. Then copy the Client ID and Client Secret into TaskNotes (Settings -> TaskNotes -> Integrations) and click Connect Google Calendar.

\n

If your Google OAuth app is still in testing mode, add the Google account you will connect with under Google Auth Platform -> Audience -> Test users. Otherwise Google may block sign-in with a 403 access_denied error saying the app has not completed verification.

\n

Microsoft Calendar#

\n

In Azure Portal, create an App Registration for your Microsoft account type. TaskNotes currently uses Microsoft's common OAuth authority, so the app registration must allow the account type you plan to connect through that authority. Tenant-specific single-tenant authorities are not configurable yet.

\n

Under Authentication, add the Mobile and desktop applications platform and add this redirect URI:

\n
http://localhost\n

Also turn on Allow public client flows. TaskNotes uses a local loopback callback with a dynamic port, which Microsoft matches against the registered loopback URI.

\n

If Azure does not accept the loopback redirect URI through the normal UI, configure loopback redirect support in the manifest by adding:

\n
{\n  "url": "http://127.0.0.1",\n  "type": "Web"\n}\n

Next, add delegated Microsoft Graph API permissions (Calendars.Read, Calendars.ReadWrite, and offline_access) and grant consent when required by your organization. Copy the Application (client) ID into TaskNotes, then click Connect Microsoft Calendar. The client secret field can be left blank for public-client desktop setup.

\n

Security Notes#

\n

OAuth client IDs, client secrets, and account tokens are stored locally in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system. They are not written to TaskNotes' data.json. Tokens refresh automatically, calendar data syncs directly between your vault and provider, and you can disconnect at any time to revoke account access.

\n

Secret Storage is local to the Obsidian installation and vault. When setting up TaskNotes on another device, enter the OAuth app credentials and connect the calendar again. After disconnecting, use Forget saved credentials if you also want to remove the client ID and client secret.

\n

Troubleshooting#

\n

"Failed to connect"

\n

Verify credentials first, then confirm loopback redirect configuration. TaskNotes uses a local callback on 127.0.0.1 with a dynamically selected port. For Microsoft, ensure loopback redirect support is configured in the app registration. Also confirm required permissions/scopes are granted.

\n

For Google 403 access_denied errors during sign-in, confirm the account is listed as a test user in the Google Auth Platform audience settings while your OAuth app is in testing mode.

\n

"Failed to fetch events"

\n

Disconnect and reconnect to refresh OAuth tokens, then re-check provider-side calendar permissions.

\n

Connection lost after Obsidian restart

\n

Tokens should persist between sessions. If reconnection is required each restart, check whether Obsidian Secret Storage is available and retaining secrets for the vault.

\n","text":"TaskNotes supports Google Calendar and Microsoft Calendar integration via OAuth 2.0. Setup (Your Own OAuth Credentials)# To connect calendars, create OAuth credentials with Google and/or Microsoft, then paste them into TaskNotes Integrations settings. The sections below walk through each provider. Google Calendar# Video by @antoneheyward In Google Cloud Console, create or select a project, enable the Google Calendar API, and create OAuth 2.0 credentials using the Desktop application type. Then copy the Client ID and Client Secret into TaskNotes (Settings -> TaskNotes -> Integrations) and click Connect Google Calendar. If your Google OAuth app is still in testing mode, add the Google account you will connect with under Google Auth Platform -> Audience -> Test users. Otherwise Google may block sign-in with a 403 access_denied error saying the app has not completed verification. Microsoft Calendar# In Azure Portal, create an App Registration for your Microsoft account type. TaskNotes currently uses Microsoft's common OAuth authority, so the app registration must allow the account type you plan to connect through that authority. Tenant-specific single-tenant authorities are not configurable yet. Under Authentication, add the Mobile and desktop applications platform and add this redirect URI: http://localhost Also turn on Allow public client flows. TaskNotes uses a local loopback callback with a dynamic port, which Microsoft matches against the registered loopback URI. If Azure does not accept the loopback redirect URI through the normal UI, configure loopback redirect support in the manifest by adding: { \"url\": \"http://127.0.0.1\", \"type\": \"Web\" } Next, add delegated Microsoft Graph API permissions (Calendars.Read, Calendars.ReadWrite, and offline_access) and grant consent when required by your organization. Copy the Application (client) ID into TaskNotes, then click Connect Microsoft Calendar. The client secret field can be left blank for public-client desktop setup. Security Notes# OAuth client IDs, client secrets, and account tokens are stored locally in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system. They are not written to TaskNotes' data.json. Tokens refresh automatically, calendar data syncs directly between your vault and provider, and you can disconnect at any time to revoke account access. Secret Storage is local to the Obsidian installation and vault. When setting up TaskNotes on another device, enter the OAuth app credentials and connect the calendar again. After disconnecting, use Forget saved credentials if you also want to remove the client ID and client secret. Troubleshooting# \"Failed to connect\" Verify credentials first, then confirm loopback redirect configuration. TaskNotes uses a local callback on 127.0.0.1 with a dynamically selected port. For Microsoft, ensure loopback redirect support is configured in the app registration. Also confirm required permissions/scopes are granted. For Google 403 access_denied errors during sign-in, confirm the account is listed as a test user in the Google Auth Platform audience settings while your OAuth app is in testing mode. \"Failed to fetch events\" Disconnect and reconnect to refresh OAuth tokens, then re-check provider-side calendar permissions. Connection lost after Obsidian restart Tokens should persist between sessions. If reconnection is required each restart, check whether Obsidian Secret Storage is available and retaining secrets for the vault."},{"route":"/obsidian/companion-plugins/","title":"Companion Plugins","description":"Companion plugins are optional Obsidian plugins that build on TaskNotes without adding every workflow to the core plugin. They run inside the same Obsidian app, use TaskNotes...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/companion-plugins.md","namespace":"obsidian","relativePath":"companion-plugins.md","raw":"# Companion Plugins\n\nCompanion plugins are optional Obsidian plugins that build on TaskNotes without adding every workflow to the core plugin. They run inside the same Obsidian app, use TaskNotes' runtime API for live task reads and writes, and keep task data in ordinary Markdown files.\n\nUse companion plugins when you want a deeper product surface than a script or webhook, but you still want TaskNotes itself to stay focused on task storage, editing, views, time tracking, and calendar behavior.\n\n## Available Companion Plugins\n\n| Plugin | Purpose | Documentation |\n| --- | --- | --- |\n| Canvas Bases | TaskNotes canvas companion for Obsidian Bases views, with canvas-style boards, JSON Canvas snapshots, optional TaskNotes badges, actions, and relationship edges. | [Canvas Bases](companion-plugins/canvas-bases.md) |\n| TaskNotes Workflows | Markdown-defined automation for TaskNotes tasks, schedules, events, and manual command-palette workflows. | [TaskNotes Workflows](companion-plugins/tasknotes-workflows.md) |\n\nMore companion plugins may be documented here over time.\n\n## How Companion Plugins Relate to TaskNotes\n\nTaskNotes remains the source of truth for task behavior. Companion plugins should use the [TaskNotes JavaScript Runtime API](javascript-api.md) for live vault operations instead of rewriting TaskNotes frontmatter directly. This keeps task updates consistent with TaskNotes settings, task cache, events, calendar behavior, time tracking, and future data-model changes.\n\nCompanion plugins can also publish their own runtime surface through `api.extensions`. Other plugins and scripts can discover those extension APIs from TaskNotes:\n\n```js\nconst tasknotes = app.plugins.getPlugin(\"tasknotes\");\nconst workflows = tasknotes?.api?.extensions.get(\"tasknotes-workflows\");\n```\n\nThe extension registry is useful when companion plugins need to expose commands, validation helpers, catalogs, or run APIs to other in-vault tools.\n\n## Choosing an Integration Surface\n\n| Use case | Prefer |\n| --- | --- |\n| A user-facing Obsidian UI that works with TaskNotes tasks | Companion plugin |\n| In-vault scripting with Templater, QuickAdd, MetaBind, or another plugin | [JavaScript Runtime API](javascript-api.md) |\n| Local tools outside Obsidian | [HTTP API](HTTP_API.md) or [TaskNotes Obsidian CLI](obsidian-cli.md) |\n| Notifications to external services when tasks change | [Webhooks](webhooks.md) |\n| Direct file analysis without Obsidian running | [mdbase-tasknotes CLI](mdbase-tasknotes-cli.md) |\n\n## Compatibility Expectations\n\nCompanion plugins should:\n\n- Check `api.apiVersion` and `api.hasCapability(...)` before using runtime features.\n- Use `api.catalog` and canonical runtime query DTOs from `api.query` instead of reaching into TaskNotes filter/view internals.\n- Include a `source` value when mutating tasks so TaskNotes events are debuggable.\n- Avoid reacting to their own mutations unless the behavior is explicit.\n- Keep user data in the vault where possible, using readable Markdown or JSON files.\n- Treat TaskNotes task notes and Bases files as user-owned documents.\n\nTaskNotes does not need every companion plugin installed. If a companion plugin is disabled, TaskNotes task notes remain normal Markdown files and TaskNotes core views continue to work.\n","aliases":["/companion-plugins/"],"toc":[{"level":2,"id":"available-companion-plugins","text":"Available Companion Plugins"},{"level":2,"id":"how-companion-plugins-relate-to-tasknotes","text":"How Companion Plugins Relate to TaskNotes"},{"level":2,"id":"choosing-an-integration-surface","text":"Choosing an Integration Surface"},{"level":2,"id":"compatibility-expectations","text":"Compatibility Expectations"}],"html":"

Companion plugins are optional Obsidian plugins that build on TaskNotes without adding every workflow to the core plugin. They run inside the same Obsidian app, use TaskNotes' runtime API for live task reads and writes, and keep task data in ordinary Markdown files.

\n

Use companion plugins when you want a deeper product surface than a script or webhook, but you still want TaskNotes itself to stay focused on task storage, editing, views, time tracking, and calendar behavior.

\n

Available Companion Plugins#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
PluginPurposeDocumentation
Canvas BasesTaskNotes canvas companion for Obsidian Bases views, with canvas-style boards, JSON Canvas snapshots, optional TaskNotes badges, actions, and relationship edges.Canvas Bases
TaskNotes WorkflowsMarkdown-defined automation for TaskNotes tasks, schedules, events, and manual command-palette workflows.TaskNotes Workflows
\n

More companion plugins may be documented here over time.

\n

How Companion Plugins Relate to TaskNotes#

\n

TaskNotes remains the source of truth for task behavior. Companion plugins should use the TaskNotes JavaScript Runtime API for live vault operations instead of rewriting TaskNotes frontmatter directly. This keeps task updates consistent with TaskNotes settings, task cache, events, calendar behavior, time tracking, and future data-model changes.

\n

Companion plugins can also publish their own runtime surface through api.extensions. Other plugins and scripts can discover those extension APIs from TaskNotes:

\n
const tasknotes = app.plugins.getPlugin("tasknotes");\nconst workflows = tasknotes?.api?.extensions.get("tasknotes-workflows");\n

The extension registry is useful when companion plugins need to expose commands, validation helpers, catalogs, or run APIs to other in-vault tools.

\n

Choosing an Integration Surface#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Use casePrefer
A user-facing Obsidian UI that works with TaskNotes tasksCompanion plugin
In-vault scripting with Templater, QuickAdd, MetaBind, or another pluginJavaScript Runtime API
Local tools outside ObsidianHTTP API or TaskNotes Obsidian CLI
Notifications to external services when tasks changeWebhooks
Direct file analysis without Obsidian runningmdbase-tasknotes CLI
\n

Compatibility Expectations#

\n

Companion plugins should:

\n
    \n
  • Check api.apiVersion and api.hasCapability(...) before using runtime features.
  • \n
  • Use api.catalog and canonical runtime query DTOs from api.query instead of reaching into TaskNotes filter/view internals.
  • \n
  • Include a source value when mutating tasks so TaskNotes events are debuggable.
  • \n
  • Avoid reacting to their own mutations unless the behavior is explicit.
  • \n
  • Keep user data in the vault where possible, using readable Markdown or JSON files.
  • \n
  • Treat TaskNotes task notes and Bases files as user-owned documents.
  • \n
\n

TaskNotes does not need every companion plugin installed. If a companion plugin is disabled, TaskNotes task notes remain normal Markdown files and TaskNotes core views continue to work.

\n","text":"Companion plugins are optional Obsidian plugins that build on TaskNotes without adding every workflow to the core plugin. They run inside the same Obsidian app, use TaskNotes' runtime API for live task reads and writes, and keep task data in ordinary Markdown files. Use companion plugins when you want a deeper product surface than a script or webhook, but you still want TaskNotes itself to stay focused on task storage, editing, views, time tracking, and calendar behavior. Available Companion Plugins# Plugin Purpose Documentation Canvas Bases TaskNotes canvas companion for Obsidian Bases views, with canvas-style boards, JSON Canvas snapshots, optional TaskNotes badges, actions, and relationship edges. Canvas Bases TaskNotes Workflows Markdown-defined automation for TaskNotes tasks, schedules, events, and manual command-palette workflows. TaskNotes Workflows More companion plugins may be documented here over time. How Companion Plugins Relate to TaskNotes# TaskNotes remains the source of truth for task behavior. Companion plugins should use the TaskNotes JavaScript Runtime API for live vault operations instead of rewriting TaskNotes frontmatter directly. This keeps task updates consistent with TaskNotes settings, task cache, events, calendar behavior, time tracking, and future data-model changes. Companion plugins can also publish their own runtime surface through api.extensions. Other plugins and scripts can discover those extension APIs from TaskNotes: const tasknotes = app.plugins.getPlugin(\"tasknotes\"); const workflows = tasknotes?.api?.extensions.get(\"tasknotes-workflows\"); The extension registry is useful when companion plugins need to expose commands, validation helpers, catalogs, or run APIs to other in-vault tools. Choosing an Integration Surface# Use case Prefer A user-facing Obsidian UI that works with TaskNotes tasks Companion plugin In-vault scripting with Templater, QuickAdd, MetaBind, or another plugin JavaScript Runtime API Local tools outside Obsidian HTTP API or TaskNotes Obsidian CLI Notifications to external services when tasks change Webhooks Direct file analysis without Obsidian running mdbase-tasknotes CLI Compatibility Expectations# Companion plugins should: Check api.apiVersion and api.hasCapability(...) before using runtime features. Use api.catalog and canonical runtime query DTOs from api.query instead of reaching into TaskNotes filter/view internals. Include a source value when mutating tasks so TaskNotes events are debuggable. Avoid reacting to their own mutations unless the behavior is explicit. Keep user data in the vault where possible, using readable Markdown or JSON files. Treat TaskNotes task notes and Bases files as user-owned documents. TaskNotes does not need every companion plugin installed. If a companion plugin is disabled, TaskNotes task notes remain normal Markdown files and TaskNotes core views continue to work."},{"route":"/obsidian/companion-plugins/canvas-bases/","title":"Canvas Bases","description":"Canvas Bases is the TaskNotes canvas companion plugin for Obsidian Bases and Canvas. It turns the current Bases result set into a canvas-style board, either as a live Bases layo...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/companion-plugins/canvas-bases.md","namespace":"obsidian","relativePath":"companion-plugins/canvas-bases.md","raw":"# Canvas Bases\n\nCanvas Bases is the TaskNotes canvas companion plugin for Obsidian Bases and Canvas. It turns the current Bases result set into a canvas-style board, either as a live Bases layout named **Canvas Bases** or as a generated JSON Canvas snapshot.\n\nCanvas Bases works with normal notes and with TaskNotes task notes. Bases remains the source for which notes appear: filters, sorting, grouping, formulas, and visible properties all come from the `.base` file. Canvas Bases handles spatial layout, cards, edges, zones, pinned notes, text cards, and linked canvas updates.\n\n## Requirements\n\n- Obsidian 1.10.1 or newer.\n- The Obsidian Bases core plugin.\n- The Obsidian Canvas core plugin when opening or editing generated `.canvas` files.\n- TaskNotes is optional, but must be installed and enabled for TaskNotes-specific badges, task menus, dependency edges, subtasks, time tracking, Pomodoro actions, and recurring-task zone actions.\n\nIf TaskNotes is disabled, Canvas Bases still works as a Bases and Canvas plugin. TaskNotes-specific actions are skipped when TaskNotes is absent or does not expose the required runtime API capability.\n\n## When to Use Canvas Bases\n\nUse Canvas Bases when a task view benefits from spatial arrangement instead of a list, table, calendar, or Kanban column set.\n\nCommon uses include:\n\n- Planning project tasks on a visual board.\n- Seeing dependencies or related notes as edges between cards.\n- Embedding a board in a daily note, project note, or meeting note.\n- Turning a filtered Base view into a reusable `.canvas` snapshot.\n- Grouping notes with Bases, then manually arranging the result.\n- Dropping cards into assignment zones to update a note property or run a supported TaskNotes action.\n\nIf the question is only \"which tasks should appear?\", keep that in Bases filters, formulas, sorting, and grouping. Canvas Bases is for visualizing and arranging the current Bases result set.\n\n## Canvas Bases Layout\n\nAfter Canvas Bases is installed, open or create a `.base` file and add a view using the **Canvas Bases** layout.\n\nIn the live layout:\n\n- Each Base result row becomes a file card.\n- Displayed Base properties appear on each card in the same order as the Base properties menu.\n- Base groups become group frames.\n- Cards and group frames can be dragged and resized.\n- Ungrouped views place cards directly on the board.\n- The initial card order follows the Base sort order.\n- Inline note-body editing is available when **Show body editor** is enabled.\n- Board controls support panning, zooming, fit view, reset view, and opening cards.\n- Manual notes, manual groups, and text cards can be added without changing the Base query.\n\nCanvas Bases stores layout and board state in Canvas Bases-owned keys in the `.base` view config. It does not need to rewrite the core query just to remember card positions, sizes, colors, pinned notes, text cards, zones, or the linked canvas path.\n\n## Materialize a Canvas\n\nCanvas Bases can also create or update a JSON Canvas file from any active Bases view, including native and third-party Bases layouts.\n\nRun these commands from the command palette:\n\n```text\nCanvas Bases: Create canvas from current bases view\nCanvas Bases: Update linked canvas\nCanvas Bases: Open linked canvas\n```\n\nThe create command asks for the canvas path, layout, edge options, node size, and update behavior. Canvas Bases-owned node and edge IDs are stable, so updating a linked canvas can preserve existing Canvas Bases node positions and keep unrelated manual Canvas nodes and edges.\n\nThe generated `.canvas` file is a snapshot, not a live query. Re-run **Canvas Bases: Update linked canvas** after changing the Base result set or board layout.\n\n## TaskNotes Integration\n\nCanvas Bases reads TaskNotes through the [TaskNotes JavaScript Runtime API](../javascript-api.md). It feature-detects API capabilities before using them, so the board can degrade cleanly when TaskNotes is unavailable or a capability is missing.\n\nWhen TaskNotes integration is enabled, Canvas Bases can:\n\n- Show TaskNotes status, priority, planning, recurrence, blocked, blocking, subtask, time estimate, tracked time, and active tracking badges on task cards.\n- Add TaskNotes task actions to card context menus through the TaskNotes task menu API.\n- Draw dependency edges between visible tasks.\n- Draw dependency and parent-subtask edges when the TaskNotes relationship mode is set to `all`.\n- Add or remove dependency and subtask relationships by dragging from one card's link handle to another.\n- Update mapped TaskNotes task properties when a card is dropped into a property zone.\n- Run supported zone actions such as complete, uncomplete, archive, unarchive, start or stop time tracking, start or assign a Pomodoro, complete an occurrence, or skip an occurrence.\n\nTaskNotes remains responsible for task semantics. Canvas Bases asks TaskNotes to read and mutate tasks instead of editing task frontmatter directly.\n\n## Edges and Relationships\n\nCanvas Bases can draw edges when both endpoint notes are present on the board.\n\nSupported edge sources include:\n\n| Source | What it uses |\n| --- | --- |\n| `wikilinks` | Links found in the note body. |\n| `properties` | Links stored in configured note properties. |\n| `all` | Wikilinks and configured property links. |\n| TaskNotes dependencies | Blocking relationships from TaskNotes. |\n| TaskNotes subtasks | Parent-child task relationships from TaskNotes when enabled. |\n\nFor property edges, configure a comma-separated list of property names, such as:\n\n```text\ndepends_on, related\n```\n\nEdges can be opened from their context menu. Removable TaskNotes and property relationships can also be removed from that menu.\n\n## Assignment Zones\n\nAssignment zones are board regions that do something when a card is dropped into them.\n\nThe default zone action updates a note property. A grouped Canvas Bases view can turn Bases groups into zones, so dragging a card into another status, priority, or custom-property group writes that property value back to the note.\n\nCustom zones can update another note property or run supported TaskNotes actions. This lets a board mix automatic Bases-derived groups with manual workflow areas such as review queues, time-tracking lanes, or Pomodoro focus zones.\n\n## Files and Data\n\nCanvas Bases keeps user data in normal vault files:\n\n| Data | Where it lives |\n| --- | --- |\n| Task and note content | Markdown files. |\n| Query, visible properties, sorting, and grouping | `.base` files. |\n| Live board geometry and Canvas Bases options | Canvas Bases-owned keys in the `.base` view config. |\n| Generated board snapshots | `.canvas` files. |\n| Options for non-Canvas Bases active views | Canvas Bases plugin data. |\n\nManual non-Canvas Bases nodes in a generated `.canvas` file are preserved when Canvas Bases updates that canvas.\n\n## First Board\n\nA practical first Canvas Bases setup is:\n\n1. Create or duplicate a TaskNotes `.base` view.\n2. Filter it to the tasks or notes you want on the board.\n3. Add a Canvas Bases layout view to that `.base` file.\n4. Choose which properties to show on cards.\n5. Enable TaskNotes badges, actions, or relationships if the board is task-focused.\n6. Arrange the cards and groups.\n7. Use the toolbar to create a linked `.canvas` snapshot when you want a Canvas file.\n\nCanvas Bases can also create starter files under `Canvas Bases/` with a demo Base, sample notes, and a linked Canvas path. Run **Canvas Bases: Create starter files** from the command palette if you want a small example board to inspect before adapting your own TaskNotes views.\n","aliases":["/companion-plugins/canvas-bases/"],"toc":[{"level":2,"id":"requirements","text":"Requirements"},{"level":2,"id":"when-to-use-canvas-bases","text":"When to Use Canvas Bases"},{"level":2,"id":"canvas-bases-layout","text":"Canvas Bases Layout"},{"level":2,"id":"materialize-a-canvas","text":"Materialize a Canvas"},{"level":2,"id":"tasknotes-integration","text":"TaskNotes Integration"},{"level":2,"id":"edges-and-relationships","text":"Edges and Relationships"},{"level":2,"id":"assignment-zones","text":"Assignment Zones"},{"level":2,"id":"files-and-data","text":"Files and Data"},{"level":2,"id":"first-board","text":"First Board"}],"html":"

Canvas Bases is the TaskNotes canvas companion plugin for Obsidian Bases and Canvas. It turns the current Bases result set into a canvas-style board, either as a live Bases layout named Canvas Bases or as a generated JSON Canvas snapshot.

\n

Canvas Bases works with normal notes and with TaskNotes task notes. Bases remains the source for which notes appear: filters, sorting, grouping, formulas, and visible properties all come from the .base file. Canvas Bases handles spatial layout, cards, edges, zones, pinned notes, text cards, and linked canvas updates.

\n

Requirements#

\n
    \n
  • Obsidian 1.10.1 or newer.
  • \n
  • The Obsidian Bases core plugin.
  • \n
  • The Obsidian Canvas core plugin when opening or editing generated .canvas files.
  • \n
  • TaskNotes is optional, but must be installed and enabled for TaskNotes-specific badges, task menus, dependency edges, subtasks, time tracking, Pomodoro actions, and recurring-task zone actions.
  • \n
\n

If TaskNotes is disabled, Canvas Bases still works as a Bases and Canvas plugin. TaskNotes-specific actions are skipped when TaskNotes is absent or does not expose the required runtime API capability.

\n

When to Use Canvas Bases#

\n

Use Canvas Bases when a task view benefits from spatial arrangement instead of a list, table, calendar, or Kanban column set.

\n

Common uses include:

\n
    \n
  • Planning project tasks on a visual board.
  • \n
  • Seeing dependencies or related notes as edges between cards.
  • \n
  • Embedding a board in a daily note, project note, or meeting note.
  • \n
  • Turning a filtered Base view into a reusable .canvas snapshot.
  • \n
  • Grouping notes with Bases, then manually arranging the result.
  • \n
  • Dropping cards into assignment zones to update a note property or run a supported TaskNotes action.
  • \n
\n

If the question is only "which tasks should appear?", keep that in Bases filters, formulas, sorting, and grouping. Canvas Bases is for visualizing and arranging the current Bases result set.

\n

Canvas Bases Layout#

\n

After Canvas Bases is installed, open or create a .base file and add a view using the Canvas Bases layout.

\n

In the live layout:

\n
    \n
  • Each Base result row becomes a file card.
  • \n
  • Displayed Base properties appear on each card in the same order as the Base properties menu.
  • \n
  • Base groups become group frames.
  • \n
  • Cards and group frames can be dragged and resized.
  • \n
  • Ungrouped views place cards directly on the board.
  • \n
  • The initial card order follows the Base sort order.
  • \n
  • Inline note-body editing is available when Show body editor is enabled.
  • \n
  • Board controls support panning, zooming, fit view, reset view, and opening cards.
  • \n
  • Manual notes, manual groups, and text cards can be added without changing the Base query.
  • \n
\n

Canvas Bases stores layout and board state in Canvas Bases-owned keys in the .base view config. It does not need to rewrite the core query just to remember card positions, sizes, colors, pinned notes, text cards, zones, or the linked canvas path.

\n

Materialize a Canvas#

\n

Canvas Bases can also create or update a JSON Canvas file from any active Bases view, including native and third-party Bases layouts.

\n

Run these commands from the command palette:

\n
Canvas Bases: Create canvas from current bases view\nCanvas Bases: Update linked canvas\nCanvas Bases: Open linked canvas\n

The create command asks for the canvas path, layout, edge options, node size, and update behavior. Canvas Bases-owned node and edge IDs are stable, so updating a linked canvas can preserve existing Canvas Bases node positions and keep unrelated manual Canvas nodes and edges.

\n

The generated .canvas file is a snapshot, not a live query. Re-run Canvas Bases: Update linked canvas after changing the Base result set or board layout.

\n

TaskNotes Integration#

\n

Canvas Bases reads TaskNotes through the TaskNotes JavaScript Runtime API. It feature-detects API capabilities before using them, so the board can degrade cleanly when TaskNotes is unavailable or a capability is missing.

\n

When TaskNotes integration is enabled, Canvas Bases can:

\n
    \n
  • Show TaskNotes status, priority, planning, recurrence, blocked, blocking, subtask, time estimate, tracked time, and active tracking badges on task cards.
  • \n
  • Add TaskNotes task actions to card context menus through the TaskNotes task menu API.
  • \n
  • Draw dependency edges between visible tasks.
  • \n
  • Draw dependency and parent-subtask edges when the TaskNotes relationship mode is set to all.
  • \n
  • Add or remove dependency and subtask relationships by dragging from one card's link handle to another.
  • \n
  • Update mapped TaskNotes task properties when a card is dropped into a property zone.
  • \n
  • Run supported zone actions such as complete, uncomplete, archive, unarchive, start or stop time tracking, start or assign a Pomodoro, complete an occurrence, or skip an occurrence.
  • \n
\n

TaskNotes remains responsible for task semantics. Canvas Bases asks TaskNotes to read and mutate tasks instead of editing task frontmatter directly.

\n

Edges and Relationships#

\n

Canvas Bases can draw edges when both endpoint notes are present on the board.

\n

Supported edge sources include:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
SourceWhat it uses
wikilinksLinks found in the note body.
propertiesLinks stored in configured note properties.
allWikilinks and configured property links.
TaskNotes dependenciesBlocking relationships from TaskNotes.
TaskNotes subtasksParent-child task relationships from TaskNotes when enabled.
\n

For property edges, configure a comma-separated list of property names, such as:

\n
depends_on, related\n

Edges can be opened from their context menu. Removable TaskNotes and property relationships can also be removed from that menu.

\n

Assignment Zones#

\n

Assignment zones are board regions that do something when a card is dropped into them.

\n

The default zone action updates a note property. A grouped Canvas Bases view can turn Bases groups into zones, so dragging a card into another status, priority, or custom-property group writes that property value back to the note.

\n

Custom zones can update another note property or run supported TaskNotes actions. This lets a board mix automatic Bases-derived groups with manual workflow areas such as review queues, time-tracking lanes, or Pomodoro focus zones.

\n

Files and Data#

\n

Canvas Bases keeps user data in normal vault files:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
DataWhere it lives
Task and note contentMarkdown files.
Query, visible properties, sorting, and grouping.base files.
Live board geometry and Canvas Bases optionsCanvas Bases-owned keys in the .base view config.
Generated board snapshots.canvas files.
Options for non-Canvas Bases active viewsCanvas Bases plugin data.
\n

Manual non-Canvas Bases nodes in a generated .canvas file are preserved when Canvas Bases updates that canvas.

\n

First Board#

\n

A practical first Canvas Bases setup is:

\n
    \n
  1. Create or duplicate a TaskNotes .base view.
  2. \n
  3. Filter it to the tasks or notes you want on the board.
  4. \n
  5. Add a Canvas Bases layout view to that .base file.
  6. \n
  7. Choose which properties to show on cards.
  8. \n
  9. Enable TaskNotes badges, actions, or relationships if the board is task-focused.
  10. \n
  11. Arrange the cards and groups.
  12. \n
  13. Use the toolbar to create a linked .canvas snapshot when you want a Canvas file.
  14. \n
\n

Canvas Bases can also create starter files under Canvas Bases/ with a demo Base, sample notes, and a linked Canvas path. Run Canvas Bases: Create starter files from the command palette if you want a small example board to inspect before adapting your own TaskNotes views.

\n","text":"Canvas Bases is the TaskNotes canvas companion plugin for Obsidian Bases and Canvas. It turns the current Bases result set into a canvas-style board, either as a live Bases layout named Canvas Bases or as a generated JSON Canvas snapshot. Canvas Bases works with normal notes and with TaskNotes task notes. Bases remains the source for which notes appear: filters, sorting, grouping, formulas, and visible properties all come from the .base file. Canvas Bases handles spatial layout, cards, edges, zones, pinned notes, text cards, and linked canvas updates. Requirements# Obsidian 1.10.1 or newer. The Obsidian Bases core plugin. The Obsidian Canvas core plugin when opening or editing generated .canvas files. TaskNotes is optional, but must be installed and enabled for TaskNotes-specific badges, task menus, dependency edges, subtasks, time tracking, Pomodoro actions, and recurring-task zone actions. If TaskNotes is disabled, Canvas Bases still works as a Bases and Canvas plugin. TaskNotes-specific actions are skipped when TaskNotes is absent or does not expose the required runtime API capability. When to Use Canvas Bases# Use Canvas Bases when a task view benefits from spatial arrangement instead of a list, table, calendar, or Kanban column set. Common uses include: Planning project tasks on a visual board. Seeing dependencies or related notes as edges between cards. Embedding a board in a daily note, project note, or meeting note. Turning a filtered Base view into a reusable .canvas snapshot. Grouping notes with Bases, then manually arranging the result. Dropping cards into assignment zones to update a note property or run a supported TaskNotes action. If the question is only \"which tasks should appear?\", keep that in Bases filters, formulas, sorting, and grouping. Canvas Bases is for visualizing and arranging the current Bases result set. Canvas Bases Layout# After Canvas Bases is installed, open or create a .base file and add a view using the Canvas Bases layout. In the live layout: Each Base result row becomes a file card. Displayed Base properties appear on each card in the same order as the Base properties menu. Base groups become group frames. Cards and group frames can be dragged and resized. Ungrouped views place cards directly on the board. The initial card order follows the Base sort order. Inline note-body editing is available when Show body editor is enabled. Board controls support panning, zooming, fit view, reset view, and opening cards. Manual notes, manual groups, and text cards can be added without changing the Base query. Canvas Bases stores layout and board state in Canvas Bases-owned keys in the .base view config. It does not need to rewrite the core query just to remember card positions, sizes, colors, pinned notes, text cards, zones, or the linked canvas path. Materialize a Canvas# Canvas Bases can also create or update a JSON Canvas file from any active Bases view, including native and third-party Bases layouts. Run these commands from the command palette: Canvas Bases: Create canvas from current bases view Canvas Bases: Update linked canvas Canvas Bases: Open linked canvas The create command asks for the canvas path, layout, edge options, node size, and update behavior. Canvas Bases-owned node and edge IDs are stable, so updating a linked canvas can preserve existing Canvas Bases node positions and keep unrelated manual Canvas nodes and edges. The generated .canvas file is a snapshot, not a live query. Re-run Canvas Bases: Update linked canvas after changing the Base result set or board layout. TaskNotes Integration# Canvas Bases reads TaskNotes through the TaskNotes JavaScript Runtime API. It feature-detects API capabilities before using them, so the board can degrade cleanly when TaskNotes is unavailable or a capability is missing. When TaskNotes integration is enabled, Canvas Bases can: Show TaskNotes status, priority, planning, recurrence, blocked, blocking, subtask, time estimate, tracked time, and active tracking badges on task cards. Add TaskNotes task actions to card context menus through the TaskNotes task menu API. Draw dependency edges between visible tasks. Draw dependency and parent-subtask edges when the TaskNotes relationship mode is set to all. Add or remove dependency and subtask relationships by dragging from one card's link handle to another. Update mapped TaskNotes task properties when a card is dropped into a property zone. Run supported zone actions such as complete, uncomplete, archive, unarchive, start or stop time tracking, start or assign a Pomodoro, complete an occurrence, or skip an occurrence. TaskNotes remains responsible for task semantics. Canvas Bases asks TaskNotes to read and mutate tasks instead of editing task frontmatter directly. Edges and Relationships# Canvas Bases can draw edges when both endpoint notes are present on the board. Supported edge sources include: Source What it uses wikilinks Links found in the note body. properties Links stored in configured note properties. all Wikilinks and configured property links. TaskNotes dependencies Blocking relationships from TaskNotes. TaskNotes subtasks Parent-child task relationships from TaskNotes when enabled. For property edges, configure a comma-separated list of property names, such as: depends_on, related Edges can be opened from their context menu. Removable TaskNotes and property relationships can also be removed from that menu. Assignment Zones# Assignment zones are board regions that do something when a card is dropped into them. The default zone action updates a note property. A grouped Canvas Bases view can turn Bases groups into zones, so dragging a card into another status, priority, or custom-property group writes that property value back to the note. Custom zones can update another note property or run supported TaskNotes actions. This lets a board mix automatic Bases-derived groups with manual workflow areas such as review queues, time-tracking lanes, or Pomodoro focus zones. Files and Data# Canvas Bases keeps user data in normal vault files: Data Where it lives Task and note content Markdown files. Query, visible properties, sorting, and grouping .base files. Live board geometry and Canvas Bases options Canvas Bases-owned keys in the .base view config. Generated board snapshots .canvas files. Options for non-Canvas Bases active views Canvas Bases plugin data. Manual non-Canvas Bases nodes in a generated .canvas file are preserved when Canvas Bases updates that canvas. First Board# A practical first Canvas Bases setup is: Create or duplicate a TaskNotes .base view. Filter it to the tasks or notes you want on the board. Add a Canvas Bases layout view to that .base file. Choose which properties to show on cards. Enable TaskNotes badges, actions, or relationships if the board is task-focused. Arrange the cards and groups. Use the toolbar to create a linked .canvas snapshot when you want a Canvas file. Canvas Bases can also create starter files under Canvas Bases/ with a demo Base, sample notes, and a linked Canvas path. Run Canvas Bases: Create starter files from the command palette if you want a small example board to inspect before adapting your own TaskNotes views."},{"route":"/obsidian/companion-plugins/tasknotes-workflows/","title":"TaskNotes Workflows","description":"TaskNotes Workflows is a companion plugin for Markdown-defined automation. It lets you create workflow notes that respond to TaskNotes events, schedules, manual commands, and se...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/companion-plugins/tasknotes-workflows.md","namespace":"obsidian","relativePath":"companion-plugins/tasknotes-workflows.md","raw":"# TaskNotes Workflows\n\nTaskNotes Workflows is a companion plugin for Markdown-defined automation. It lets you create workflow notes that respond to TaskNotes events, schedules, manual commands, and selected Obsidian events, then run typed actions against TaskNotes tasks.\n\n## Install TaskNotes Workflows\n\n\n\nYou can also install it from Obsidian: open Settings > Community plugins > Browse, then search for `TaskNotes Workflows`.\n\nThe plugin is designed for workflows users often ask TaskNotes core to handle, such as:\n\n- Start time tracking when a task becomes active.\n- Stop time tracking when a task is completed.\n- Move completed tasks into a review folder.\n- Copy parent task context, tags, priority, dates, or dependencies to subtasks.\n- Warn when a blocked task is moved to active.\n- Run a daily review query.\n\nTaskNotes Workflows keeps this behavior outside TaskNotes core while still using the [TaskNotes JavaScript Runtime API](../javascript-api.md) for safe task reads, writes, canonical queries, events, and relationship resolution.\n\n## Requirements\n\n- TaskNotes must be installed and enabled.\n- TaskNotes must expose the JavaScript runtime API.\n- Obsidian must be open for workflows to run.\n- Scheduled workflows run while Obsidian is running. They are not a background service when Obsidian is closed.\n- The plugin runtime uses Obsidian APIs only. Node is used for development and build scripts, not for workflow execution, so Markdown workflow definitions can work on Obsidian mobile while the plugin is loaded.\n\nIf TaskNotes is disabled or unavailable, the workflow Base can still validate and display workflow files, but TaskNotes read/write steps cannot run.\n\n## Files Created by the Plugin\n\nBy default, TaskNotes Workflows uses:\n\n| Path | Purpose |\n| --- | --- |\n| `TaskNotes/Workflows/` | Workflow Markdown files. |\n| `TaskNotes/Views/workflows.base` | Generated Obsidian Base that renders workflow cards through the custom workflow view. |\n| Plugin config folder | Run history and detail logs, unless a run-log folder is configured. |\n\nWorkflow notes are ordinary Markdown files. The YAML frontmatter is executable configuration, and the note body is for human explanation, testing notes, and maintenance guidance.\n\n## First Run\n\nOn first load, the plugin can create a default workflow folder, a workflow Base, and a set of example workflow notes. The default workflow notes are disabled so they can be inspected, dry-run, edited, and enabled intentionally.\n\nThe generated Base is the main workbench. It shows workflow cards with status, trigger and step summaries, recent run state, and buttons for editing, dry-running, running, and opening the source note.\n\nWorkflow notes also show a compact workflow card in reading mode and live preview, so the note remains useful even when opened directly.\n\n## Default Workflows\n\nThe plugin can write these starter workflows:\n\n| Workflow | What it demonstrates |\n| --- | --- |\n| Auto-start time tracking | Starts a timer when a task status changes to active. |\n| Stop time tracking on complete | Stops the timer when a task is completed. |\n| Morning overdue review | Runs a daily cron query and marks overdue open tasks high priority. |\n| Move completed tasks to review | Moves completed task notes into a review folder. |\n| Inherit subtask contexts and tags | Copies contexts and tags from the first parent task when a task becomes a subtask. |\n| Inherit subtask priority | Copies priority from the first parent task when a task becomes a subtask. |\n| Inherit subtask planning dates | Copies scheduled and due dates from the first parent task when a task becomes a subtask. |\n| Inherit subtask dependencies | Adds the first parent task's blocking dependencies to new subtasks. |\n| Mirror parent priority to subtasks | Updates existing subtasks when a parent task priority changes. |\n| Mirror parent planning dates to subtasks | Updates existing subtasks when a parent scheduled or due date changes. |\n| Mirror parent dependencies to subtasks | Replaces each subtask's dependencies with the parent task's current dependencies. |\n| Warn when starting a blocked task | Shows a notice when a task becomes active while dependencies remain. |\n| Daily active task review | Shows a daily count of tasks still marked active. |\n\nTreat these as editable examples. Adjust folders, statuses, priorities, dates, and filters to match your vault before enabling mutating workflows.\n\n## Workflow Shape\n\nA workflow file looks like this:\n\n```markdown\n---\ntype: tasknotes-workflow\nschemaVersion: 1\nid: auto-start-time-tracking\nname: Auto-start time tracking\nenabled: false\ndescription: Start a timer when a task status changes to active.\ntriggers:\n - id: status-active\n type: tasknotes.event\n event: task.status.changed\n to: active\nconditions:\n - field: trigger.after.path\n operator: exists\nsteps:\n - id: start-time\n type: time.start\n input:\n task: \"{{trigger.after.path}}\"\n options:\n description: \"Started by {{workflow.name}}\"\nrun:\n mode: sequential\n noOverlap: true\n source: tasknotes-workflows\n maxTasks: 1\n onError: stop\n---\n\n# Auto-start time tracking\n\nEnable this workflow to start time tracking when a TaskNotes task moves to `active`.\n```\n\nRequired frontmatter fields:\n\n| Field | Type | Notes |\n| --- | --- | --- |\n| `type` | string | Must be `tasknotes-workflow`. |\n| `schemaVersion` | number | Must be `1`. |\n| `id` | string | Stable lowercase identifier. Use letters, numbers, dots, underscores, and dashes. |\n| `name` | string | Human-readable name shown in workflow cards and command-palette commands. |\n| `enabled` | boolean | Disabled workflows can be edited and dry-run but do not run automatically or from manual commands. |\n| `triggers` | array | One or more trigger definitions. |\n| `conditions` | array | Optional workflow-level guards. |\n| `steps` | array | Linear typed step pipeline. |\n| `run` | object | Run policy and safety limits. |\n\n## Triggers\n\nTriggers decide when a workflow should run.\n\n### TaskNotes Events\n\nUse `tasknotes.event` to react to TaskNotes runtime events:\n\n```yaml\ntriggers:\n - id: status-active\n type: tasknotes.event\n event: task.status.changed\n from: open\n to: active\n```\n\nCommon event names include:\n\n- `task.created`\n- `task.updated`\n- `task.deleted`\n- `task.moved`\n- `task.status.changed`\n- `task.completed`\n- `task.uncompleted`\n- `task.archived`\n- `task.unarchived`\n- `task.scheduled.changed`\n- `task.due.changed`\n- `task.priority.changed`\n- `task.tags.changed`\n- `task.contexts.changed`\n- `task.projects.changed`\n- `task.reminders.changed`\n- `task.dependencies.changed`\n- `task.recurrence.changed`\n- `time.started`\n- `time.stopped`\n- `pomodoro.started`\n- `pomodoro.completed`\n- `pomodoro.interrupted`\n- `recurring.instance.completed`\n- `recurring.instance.skipped`\n\nThe workflow editor loads available TaskNotes events dynamically from `api.events.list()`, so event pickers can follow the runtime API instead of relying on a hardcoded list.\n\nTaskNotes event triggers can use these filters:\n\n| Field | Purpose |\n| --- | --- |\n| `event` | Runtime event name. |\n| `from` | Previous status or value for status-change workflows. |\n| `to` | New status or value for status-change workflows. |\n| `path.glob` | Optional path glob limiting which task files can trigger the workflow. |\n| `allowSelfTrigger` | Allows this workflow to react to writes caused by `tasknotes-workflows`. Leave off unless you have a clear reason. |\n\nTaskNotes event output fields include values such as `trigger.after.path`, `trigger.after.status`, `trigger.before.status`, `trigger.changes`, `trigger.source`, and `trigger.correlationId`.\n\n### Cron\n\nCron triggers run on matching minutes while Obsidian is open:\n\n```yaml\ntriggers:\n - id: weekday-review\n type: cron\n schedule: \"0 17 * * 1-5\"\n timezone: local\n```\n\nThe schedule uses five fields: minute, hour, day of month, month, day of week. Keep cron workflows bounded with `run.maxTasks`, especially if they query many tasks.\n\n### Interval\n\nInterval triggers run repeatedly while Obsidian is open:\n\n```yaml\ntriggers:\n - id: half-hour-check\n type: interval\n every: 30m\n```\n\nThe plugin enforces a minimum interval to avoid excessive background work.\n\n### Manual\n\nManual triggers let a workflow run from a card button, another plugin, or the Obsidian command palette:\n\n```yaml\ntriggers:\n - id: manual\n type: manual\n```\n\nEnabled workflows with a manual trigger are registered as Obsidian commands named `Run: `. You can launch them from the command palette or assign hotkeys in Obsidian settings.\n\nThe generated command id is based on the workflow `id`. Changing a workflow id creates a different command, so any hotkey assigned to the old command id will need to be reassigned.\n\n### Obsidian Events\n\nAdvanced Obsidian triggers are opt-in from the plugin settings. They can listen to selected vault, metadata, and workspace events:\n\n```yaml\ntriggers:\n - id: project-note-opened\n type: obsidian.workspace\n event: file-open\n path:\n glob: \"Projects/**/*.md\"\n\n - id: task-note-modified\n type: obsidian.vault\n event: modify\n path:\n glob: \"Tasks/**/*.md\"\n\n - id: metadata-changed\n type: obsidian.metadata\n event: changed\n path:\n glob: \"Projects/**/*.md\"\n```\n\nKeep path filters narrow for Obsidian triggers. Vault and metadata events can be frequent.\n\n## Conditions\n\nConditions can appear at workflow level or on individual steps.\n\n```yaml\nconditions:\n - field: trigger.after.path\n operator: exists\n - field: trigger.after.status\n operator: is\n value: active\n```\n\nSupported operators:\n\n| Operator | Meaning |\n| --- | --- |\n| `is` / `isNot` | Exact comparison after scalar normalization. |\n| `in` / `notIn` | Check a value against an array. |\n| `exists` / `missing` | Check whether a field has a value. |\n| `contains` | Check whether a string contains text or an array contains a value. |\n| `startsWith` | String prefix check. |\n| `before` / `after` | Date comparison. |\n| `onOrBefore` / `onOrAfter` | Inclusive date comparison. |\n\nStep-level conditions use the same shape:\n\n```yaml\nsteps:\n - id: warn\n type: notice.show\n if:\n - field: steps.dependencies.tasks[0].path\n operator: exists\n input:\n message: \"This task still has dependencies.\"\n```\n\n## References\n\nReferences use constrained template expressions. Arbitrary JavaScript is not evaluated.\n\n```text\n{{workflow.id}}\n{{workflow.name}}\n{{trigger.after.path}}\n{{trigger.changes.status.after}}\n{{steps.query.tasks}}\n{{steps.parents.tasks[0].path}}\n{{item.path}}\n{{today}}\n{{now}}\n```\n\nIf a string is exactly one reference, the underlying value is preserved. If a reference is embedded in other text, the value is stringified.\n\nUse `forEach` when a step should run once per item:\n\n```yaml\nsteps:\n - id: overdue\n type: task.query\n input:\n query:\n where:\n all:\n - field: task.due\n op: lt\n value:\n fn: today\n - field: task.status\n op: notIn\n value:\n - done\n - cancelled\n sort:\n - field: task.due\n direction: asc\n limit: 50\n scope:\n includeArchived: false\n\n - id: mark-high\n type: task.patch\n forEach: \"{{steps.overdue.tasks}}\"\n input:\n task: \"{{item.path}}\"\n patch:\n priority: high\n```\n\nWhen a step uses `forEach`, `{{item}}` refers to the current item and the step output becomes an array of per-item outputs.\n\n`task.query` uses the canonical TaskNotes runtime query DTO. Its output includes `tasks`, `count`, `total`, `matched`, `returned`, `groups`, `groupPaths`, `query`, and `warnings`.\n\nRuntime query conditions use canonical field IDs and operators:\n\n```yaml\nquery:\n where:\n all:\n - field: task.status\n op: ne\n value: done\n - any:\n - field: task.due\n op: lte\n value:\n fn: today\n - field: task.priority\n op: eq\n value: high\n sort:\n - field: task.due\n direction: asc\n group:\n - field: task.status\n limit: 25\n scope:\n includeArchived: false\n```\n\nCommon fields include `task.status`, `task.priority`, `task.due`, `task.scheduled`, `task.projects`, `task.contexts`, `task.tags`, `task.isBlocked`, and `file.path`. Operators include `eq`, `ne`, `contains`, `notContains`, `in`, `notIn`, `exists`, `missing`, `lt`, `lte`, `gt`, `gte`, `isTrue`, and `isFalse`. Use `api.catalog.filterProperties()` and `api.catalog.filterOperators()` for the complete runtime catalog.\n\n## Steps\n\nSteps are typed actions. The editor reads a step catalog so it can show expected inputs, output fields, examples, and TaskNotes option pickers.\n\nTask read steps:\n\n| Step | Output |\n| --- | --- |\n| `task.get` | One task. |\n| `task.query` | Tasks matching a canonical TaskNotes runtime query. |\n| `task.parents` | Parent tasks linked from the task's projects. |\n| `task.subtasks` | Tasks that reference the current task as a project. |\n| `task.dependencies` | Dependencies stored in `blockedBy`, with resolved task data when available. |\n| `task.blocking` | Tasks blocked by the current task. |\n| `task.relationships` | The task plus parents, subtasks, dependencies, and blocking tasks. |\n\nTask write steps:\n\n| Step | Purpose |\n| --- | --- |\n| `task.create` | Create a new TaskNotes task. |\n| `task.patch` | Update one or more fields. |\n| `task.set` | Set one field. |\n| `task.move` | Move the task note to a target folder. |\n| `task.archive` / `task.unarchive` | Archive or unarchive a task. |\n| `task.complete` / `task.uncomplete` | Complete or reopen a task. |\n| `task.reschedule` | Update planning dates. |\n| `task.setDue` / `task.clearDue` | Set or clear due date. |\n| `task.setScheduled` / `task.clearScheduled` | Set or clear scheduled date. |\n| `task.addTag` / `task.removeTag` | Mutate tags. |\n| `task.addProject` / `task.removeProject` | Mutate project links. |\n| `task.addContext` / `task.removeContext` | Mutate contexts. |\n| `task.addDependency` / `task.removeDependency` | Mutate blocking dependencies. |\n\nTime and utility steps:\n\n| Step | Purpose |\n| --- | --- |\n| `time.start` | Start time tracking for a task. |\n| `time.stop` | Stop active time tracking for a task. |\n| `time.appendEntry` | Append a time entry. |\n| `notice.show` | Show an Obsidian notice. |\n| `workflow.stop` | Stop a workflow early. |\n\nCompanion plugins and scripts can inspect the same catalog through the TaskNotes runtime extension:\n\n```js\nconst tasknotes = app.plugins.getPlugin(\"tasknotes\")?.api;\nconst workflows = tasknotes?.extensions.get(\"tasknotes-workflows\");\nconst steps = workflows?.listStepDefinitions();\n```\n\n## Run Policy\n\nEvery workflow has a run policy:\n\n```yaml\nrun:\n mode: sequential\n noOverlap: true\n source: tasknotes-workflows\n maxTasks: 25\n onError: stop\n timeout: 30s\n```\n\n| Field | Notes |\n| --- | --- |\n| `mode` | Currently `sequential`. Steps run in order. |\n| `noOverlap` | Skips a new run if the same workflow is already running. |\n| `source` | Mutation source passed to TaskNotes runtime API calls. |\n| `maxTasks` | Safety limit for `forEach` batch steps. |\n| `onError` | `stop` or `continue`. |\n| `timeout` | Optional duration string. |\n\nTaskNotes attaches `source`, correlation, and reason metadata to events caused by runtime API writes. Workflows use this to make runs debuggable and to avoid accidental self-trigger loops.\n\n## Run Logs and Debugging\n\nWorkflow run logs are stored under the plugin's Obsidian config folder by default. You can configure a run-log folder and a log level in the plugin settings.\n\nRun records include:\n\n- Workflow id, name, and source path.\n- Trigger payload.\n- Step statuses.\n- Inputs and outputs, depending on the configured log level.\n- Error text when a run fails.\n\nUse dry runs before enabling workflows that mutate tasks. Dry runs still execute the workflow path, but mutating steps should report what they would do instead of changing task files.\n\n## Example: Manual Command Workflow\n\nThis workflow can be run from the command palette after it is enabled:\n\n```markdown\n---\ntype: tasknotes-workflow\nschemaVersion: 1\nid: show-active-count\nname: Show active task count\nenabled: true\ndescription: Show a notice with the number of active tasks.\ntriggers:\n - id: manual\n type: manual\nsteps:\n - id: active\n type: task.query\n input:\n query:\n where:\n field: task.status\n op: eq\n value: active\n limit: 25\n scope:\n includeArchived: false\n - id: notice\n type: notice.show\n input:\n message: \"Active tasks: {{steps.active.count}}\"\nrun:\n mode: sequential\n noOverlap: true\n source: tasknotes-workflows\n maxTasks: 25\n onError: stop\n---\n\n# Show active task count\n\nRun this from the Obsidian command palette with `TaskNotes Workflows: Run: Show active task count`.\n```\n\n## Example: Inherit Parent Priority\n\nThis workflow copies priority from the first parent task when a task becomes a subtask:\n\n```yaml\ntype: tasknotes-workflow\nschemaVersion: 1\nid: inherit-subtask-priority\nname: Inherit subtask priority\nenabled: false\ntriggers:\n - id: projects-changed\n type: tasknotes.event\n event: task.projects.changed\n - id: task-created\n type: tasknotes.event\n event: task.created\nconditions:\n - field: trigger.after.path\n operator: exists\n - field: trigger.after.projects\n operator: exists\nsteps:\n - id: parents\n type: task.parents\n input:\n task: \"{{trigger.after.path}}\"\n - id: inherit-priority\n type: task.patch\n if:\n - field: steps.parents.tasks[0].priority\n operator: exists\n input:\n task: \"{{trigger.after.path}}\"\n patch:\n priority: \"{{steps.parents.tasks[0].priority}}\"\nrun:\n mode: sequential\n noOverlap: true\n source: tasknotes-workflows\n maxTasks: 1\n onError: stop\n```\n\nThis pattern uses `task.parents` rather than trying to parse project links manually.\n\n## Authoring Guidelines\n\nWhen writing workflow notes:\n\n- Start with `enabled: false` for any workflow that mutates tasks.\n- Give every trigger and step a stable `id`.\n- Prefer typed TaskNotes steps over direct frontmatter editing.\n- Use relationship read steps such as `task.parents`, `task.subtasks`, and `task.dependencies` for parent/subtask/dependency logic.\n- Add workflow-level conditions for required trigger fields such as `trigger.after.path`.\n- Add `run.noOverlap: true` unless overlapping runs are intentional.\n- Set `run.maxTasks` for batch workflows.\n- Use `allowSelfTrigger: true` only when the workflow really should react to its own writes.\n- Keep the Markdown body useful for future maintenance: describe what the workflow changes, how to test it, and why it exists.\n\n## Troubleshooting\n\n### Task steps do not run\n\nConfirm TaskNotes is enabled and exposes the runtime API. The workflow Base can display definitions without TaskNotes, but steps such as `task.patch`, `time.start`, or `task.dependencies` need TaskNotes.\n\n### A manual workflow is missing from the command palette\n\nCheck that:\n\n- The workflow is valid.\n- `enabled` is `true`.\n- It has a `manual` trigger.\n- The workflow `id` is valid and stable.\n- Workflows have reloaded after editing the file.\n\nDisabled manual workflows can still be dry-run from the workflow card, but they are not registered as run commands.\n\n### A cron or interval workflow did not run\n\nScheduled workflows only run while Obsidian is open and the plugin is loaded. Check the schedule, timezone, enabled state, and `run.maxTasks` limit.\n\n### A workflow runs more than once\n\nCheck whether multiple triggers match the same update. Also check `allowSelfTrigger`; most workflows should leave it unset so they do not react to writes caused by `tasknotes-workflows`.\n\n### A workflow is invalid\n\nOpen the workflow Base or the workflow note card. Validation messages point to the field path, such as `triggers[0].type` or `steps[1].input`.\n\nCommon causes are missing required fields, unsupported trigger types, invalid YAML, or references to step outputs that do not exist.\n","aliases":["/companion-plugins/tasknotes-workflows/"],"toc":[{"level":2,"id":"install-tasknotes-workflows","text":"Install TaskNotes Workflows"},{"level":2,"id":"requirements","text":"Requirements"},{"level":2,"id":"files-created-by-the-plugin","text":"Files Created by the Plugin"},{"level":2,"id":"first-run","text":"First Run"},{"level":2,"id":"default-workflows","text":"Default Workflows"},{"level":2,"id":"workflow-shape","text":"Workflow Shape"},{"level":2,"id":"triggers","text":"Triggers"},{"level":3,"id":"tasknotes-events","text":"TaskNotes Events"},{"level":3,"id":"cron","text":"Cron"},{"level":3,"id":"interval","text":"Interval"},{"level":3,"id":"manual","text":"Manual"},{"level":3,"id":"obsidian-events","text":"Obsidian Events"},{"level":2,"id":"conditions","text":"Conditions"},{"level":2,"id":"references","text":"References"},{"level":2,"id":"steps","text":"Steps"},{"level":2,"id":"run-policy","text":"Run Policy"},{"level":2,"id":"run-logs-and-debugging","text":"Run Logs and Debugging"},{"level":2,"id":"example-manual-command-workflow","text":"Example: Manual Command Workflow"},{"level":2,"id":"example-inherit-parent-priority","text":"Example: Inherit Parent Priority"},{"level":2,"id":"authoring-guidelines","text":"Authoring Guidelines"},{"level":2,"id":"troubleshooting","text":"Troubleshooting"},{"level":3,"id":"task-steps-do-not-run","text":"Task steps do not run"},{"level":3,"id":"a-manual-workflow-is-missing-from-the-command-palette","text":"A manual workflow is missing from the command palette"},{"level":3,"id":"a-cron-or-interval-workflow-did-not-run","text":"A cron or interval workflow did not run"},{"level":3,"id":"a-workflow-runs-more-than-once","text":"A workflow runs more than once"},{"level":3,"id":"a-workflow-is-invalid","text":"A workflow is invalid"}],"html":"

TaskNotes Workflows is a companion plugin for Markdown-defined automation. It lets you create workflow notes that respond to TaskNotes events, schedules, manual commands, and selected Obsidian events, then run typed actions against TaskNotes tasks.

\n

Install TaskNotes Workflows#

\n\n\n

You can also install it from Obsidian: open Settings > Community plugins > Browse, then search for TaskNotes Workflows.

\n

The plugin is designed for workflows users often ask TaskNotes core to handle, such as:

\n
    \n
  • Start time tracking when a task becomes active.
  • \n
  • Stop time tracking when a task is completed.
  • \n
  • Move completed tasks into a review folder.
  • \n
  • Copy parent task context, tags, priority, dates, or dependencies to subtasks.
  • \n
  • Warn when a blocked task is moved to active.
  • \n
  • Run a daily review query.
  • \n
\n

TaskNotes Workflows keeps this behavior outside TaskNotes core while still using the TaskNotes JavaScript Runtime API for safe task reads, writes, canonical queries, events, and relationship resolution.

\n

Requirements#

\n
    \n
  • TaskNotes must be installed and enabled.
  • \n
  • TaskNotes must expose the JavaScript runtime API.
  • \n
  • Obsidian must be open for workflows to run.
  • \n
  • Scheduled workflows run while Obsidian is running. They are not a background service when Obsidian is closed.
  • \n
  • The plugin runtime uses Obsidian APIs only. Node is used for development and build scripts, not for workflow execution, so Markdown workflow definitions can work on Obsidian mobile while the plugin is loaded.
  • \n
\n

If TaskNotes is disabled or unavailable, the workflow Base can still validate and display workflow files, but TaskNotes read/write steps cannot run.

\n

Files Created by the Plugin#

\n

By default, TaskNotes Workflows uses:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
PathPurpose
TaskNotes/Workflows/Workflow Markdown files.
TaskNotes/Views/workflows.baseGenerated Obsidian Base that renders workflow cards through the custom workflow view.
Plugin config folderRun history and detail logs, unless a run-log folder is configured.
\n

Workflow notes are ordinary Markdown files. The YAML frontmatter is executable configuration, and the note body is for human explanation, testing notes, and maintenance guidance.

\n

First Run#

\n

On first load, the plugin can create a default workflow folder, a workflow Base, and a set of example workflow notes. The default workflow notes are disabled so they can be inspected, dry-run, edited, and enabled intentionally.

\n

The generated Base is the main workbench. It shows workflow cards with status, trigger and step summaries, recent run state, and buttons for editing, dry-running, running, and opening the source note.

\n

Workflow notes also show a compact workflow card in reading mode and live preview, so the note remains useful even when opened directly.

\n

Default Workflows#

\n

The plugin can write these starter workflows:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
WorkflowWhat it demonstrates
Auto-start time trackingStarts a timer when a task status changes to active.
Stop time tracking on completeStops the timer when a task is completed.
Morning overdue reviewRuns a daily cron query and marks overdue open tasks high priority.
Move completed tasks to reviewMoves completed task notes into a review folder.
Inherit subtask contexts and tagsCopies contexts and tags from the first parent task when a task becomes a subtask.
Inherit subtask priorityCopies priority from the first parent task when a task becomes a subtask.
Inherit subtask planning datesCopies scheduled and due dates from the first parent task when a task becomes a subtask.
Inherit subtask dependenciesAdds the first parent task's blocking dependencies to new subtasks.
Mirror parent priority to subtasksUpdates existing subtasks when a parent task priority changes.
Mirror parent planning dates to subtasksUpdates existing subtasks when a parent scheduled or due date changes.
Mirror parent dependencies to subtasksReplaces each subtask's dependencies with the parent task's current dependencies.
Warn when starting a blocked taskShows a notice when a task becomes active while dependencies remain.
Daily active task reviewShows a daily count of tasks still marked active.
\n

Treat these as editable examples. Adjust folders, statuses, priorities, dates, and filters to match your vault before enabling mutating workflows.

\n

Workflow Shape#

\n

A workflow file looks like this:

\n
---\ntype: tasknotes-workflow\nschemaVersion: 1\nid: auto-start-time-tracking\nname: Auto-start time tracking\nenabled: false\ndescription: Start a timer when a task status changes to active.\ntriggers:\n  - id: status-active\n    type: tasknotes.event\n    event: task.status.changed\n    to: active\nconditions:\n  - field: trigger.after.path\n    operator: exists\nsteps:\n  - id: start-time\n    type: time.start\n    input:\n      task: "{{trigger.after.path}}"\n      options:\n        description: "Started by {{workflow.name}}"\nrun:\n  mode: sequential\n  noOverlap: true\n  source: tasknotes-workflows\n  maxTasks: 1\n  onError: stop\n---\n\n# Auto-start time tracking\n\nEnable this workflow to start time tracking when a TaskNotes task moves to `active`.\n

Required frontmatter fields:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
FieldTypeNotes
typestringMust be tasknotes-workflow.
schemaVersionnumberMust be 1.
idstringStable lowercase identifier. Use letters, numbers, dots, underscores, and dashes.
namestringHuman-readable name shown in workflow cards and command-palette commands.
enabledbooleanDisabled workflows can be edited and dry-run but do not run automatically or from manual commands.
triggersarrayOne or more trigger definitions.
conditionsarrayOptional workflow-level guards.
stepsarrayLinear typed step pipeline.
runobjectRun policy and safety limits.
\n

Triggers#

\n

Triggers decide when a workflow should run.

\n

TaskNotes Events#

\n

Use tasknotes.event to react to TaskNotes runtime events:

\n
triggers:\n  - id: status-active\n    type: tasknotes.event\n    event: task.status.changed\n    from: open\n    to: active\n

Common event names include:

\n
    \n
  • task.created
  • \n
  • task.updated
  • \n
  • task.deleted
  • \n
  • task.moved
  • \n
  • task.status.changed
  • \n
  • task.completed
  • \n
  • task.uncompleted
  • \n
  • task.archived
  • \n
  • task.unarchived
  • \n
  • task.scheduled.changed
  • \n
  • task.due.changed
  • \n
  • task.priority.changed
  • \n
  • task.tags.changed
  • \n
  • task.contexts.changed
  • \n
  • task.projects.changed
  • \n
  • task.reminders.changed
  • \n
  • task.dependencies.changed
  • \n
  • task.recurrence.changed
  • \n
  • time.started
  • \n
  • time.stopped
  • \n
  • pomodoro.started
  • \n
  • pomodoro.completed
  • \n
  • pomodoro.interrupted
  • \n
  • recurring.instance.completed
  • \n
  • recurring.instance.skipped
  • \n
\n

The workflow editor loads available TaskNotes events dynamically from api.events.list(), so event pickers can follow the runtime API instead of relying on a hardcoded list.

\n

TaskNotes event triggers can use these filters:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
FieldPurpose
eventRuntime event name.
fromPrevious status or value for status-change workflows.
toNew status or value for status-change workflows.
path.globOptional path glob limiting which task files can trigger the workflow.
allowSelfTriggerAllows this workflow to react to writes caused by tasknotes-workflows. Leave off unless you have a clear reason.
\n

TaskNotes event output fields include values such as trigger.after.path, trigger.after.status, trigger.before.status, trigger.changes, trigger.source, and trigger.correlationId.

\n

Cron#

\n

Cron triggers run on matching minutes while Obsidian is open:

\n
triggers:\n  - id: weekday-review\n    type: cron\n    schedule: "0 17 * * 1-5"\n    timezone: local\n

The schedule uses five fields: minute, hour, day of month, month, day of week. Keep cron workflows bounded with run.maxTasks, especially if they query many tasks.

\n

Interval#

\n

Interval triggers run repeatedly while Obsidian is open:

\n
triggers:\n  - id: half-hour-check\n    type: interval\n    every: 30m\n

The plugin enforces a minimum interval to avoid excessive background work.

\n

Manual#

\n

Manual triggers let a workflow run from a card button, another plugin, or the Obsidian command palette:

\n
triggers:\n  - id: manual\n    type: manual\n

Enabled workflows with a manual trigger are registered as Obsidian commands named Run: <workflow name>. You can launch them from the command palette or assign hotkeys in Obsidian settings.

\n

The generated command id is based on the workflow id. Changing a workflow id creates a different command, so any hotkey assigned to the old command id will need to be reassigned.

\n

Obsidian Events#

\n

Advanced Obsidian triggers are opt-in from the plugin settings. They can listen to selected vault, metadata, and workspace events:

\n
triggers:\n  - id: project-note-opened\n    type: obsidian.workspace\n    event: file-open\n    path:\n      glob: "Projects/**/*.md"\n\n  - id: task-note-modified\n    type: obsidian.vault\n    event: modify\n    path:\n      glob: "Tasks/**/*.md"\n\n  - id: metadata-changed\n    type: obsidian.metadata\n    event: changed\n    path:\n      glob: "Projects/**/*.md"\n

Keep path filters narrow for Obsidian triggers. Vault and metadata events can be frequent.

\n

Conditions#

\n

Conditions can appear at workflow level or on individual steps.

\n
conditions:\n  - field: trigger.after.path\n    operator: exists\n  - field: trigger.after.status\n    operator: is\n    value: active\n

Supported operators:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
OperatorMeaning
is / isNotExact comparison after scalar normalization.
in / notInCheck a value against an array.
exists / missingCheck whether a field has a value.
containsCheck whether a string contains text or an array contains a value.
startsWithString prefix check.
before / afterDate comparison.
onOrBefore / onOrAfterInclusive date comparison.
\n

Step-level conditions use the same shape:

\n
steps:\n  - id: warn\n    type: notice.show\n    if:\n      - field: steps.dependencies.tasks[0].path\n        operator: exists\n    input:\n      message: "This task still has dependencies."\n

References#

\n

References use constrained template expressions. Arbitrary JavaScript is not evaluated.

\n
{{workflow.id}}\n{{workflow.name}}\n{{trigger.after.path}}\n{{trigger.changes.status.after}}\n{{steps.query.tasks}}\n{{steps.parents.tasks[0].path}}\n{{item.path}}\n{{today}}\n{{now}}\n

If a string is exactly one reference, the underlying value is preserved. If a reference is embedded in other text, the value is stringified.

\n

Use forEach when a step should run once per item:

\n
steps:\n  - id: overdue\n    type: task.query\n    input:\n      query:\n        where:\n          all:\n            - field: task.due\n              op: lt\n              value:\n                fn: today\n            - field: task.status\n              op: notIn\n              value:\n                - done\n                - cancelled\n        sort:\n          - field: task.due\n            direction: asc\n        limit: 50\n        scope:\n          includeArchived: false\n\n  - id: mark-high\n    type: task.patch\n    forEach: "{{steps.overdue.tasks}}"\n    input:\n      task: "{{item.path}}"\n      patch:\n        priority: high\n

When a step uses forEach, {{item}} refers to the current item and the step output becomes an array of per-item outputs.

\n

task.query uses the canonical TaskNotes runtime query DTO. Its output includes tasks, count, total, matched, returned, groups, groupPaths, query, and warnings.

\n

Runtime query conditions use canonical field IDs and operators:

\n
query:\n  where:\n    all:\n      - field: task.status\n        op: ne\n        value: done\n      - any:\n          - field: task.due\n            op: lte\n            value:\n              fn: today\n          - field: task.priority\n            op: eq\n            value: high\n  sort:\n    - field: task.due\n      direction: asc\n  group:\n    - field: task.status\n  limit: 25\n  scope:\n    includeArchived: false\n

Common fields include task.status, task.priority, task.due, task.scheduled, task.projects, task.contexts, task.tags, task.isBlocked, and file.path. Operators include eq, ne, contains, notContains, in, notIn, exists, missing, lt, lte, gt, gte, isTrue, and isFalse. Use api.catalog.filterProperties() and api.catalog.filterOperators() for the complete runtime catalog.

\n

Steps#

\n

Steps are typed actions. The editor reads a step catalog so it can show expected inputs, output fields, examples, and TaskNotes option pickers.

\n

Task read steps:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StepOutput
task.getOne task.
task.queryTasks matching a canonical TaskNotes runtime query.
task.parentsParent tasks linked from the task's projects.
task.subtasksTasks that reference the current task as a project.
task.dependenciesDependencies stored in blockedBy, with resolved task data when available.
task.blockingTasks blocked by the current task.
task.relationshipsThe task plus parents, subtasks, dependencies, and blocking tasks.
\n

Task write steps:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StepPurpose
task.createCreate a new TaskNotes task.
task.patchUpdate one or more fields.
task.setSet one field.
task.moveMove the task note to a target folder.
task.archive / task.unarchiveArchive or unarchive a task.
task.complete / task.uncompleteComplete or reopen a task.
task.rescheduleUpdate planning dates.
task.setDue / task.clearDueSet or clear due date.
task.setScheduled / task.clearScheduledSet or clear scheduled date.
task.addTag / task.removeTagMutate tags.
task.addProject / task.removeProjectMutate project links.
task.addContext / task.removeContextMutate contexts.
task.addDependency / task.removeDependencyMutate blocking dependencies.
\n

Time and utility steps:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
StepPurpose
time.startStart time tracking for a task.
time.stopStop active time tracking for a task.
time.appendEntryAppend a time entry.
notice.showShow an Obsidian notice.
workflow.stopStop a workflow early.
\n

Companion plugins and scripts can inspect the same catalog through the TaskNotes runtime extension:

\n
const tasknotes = app.plugins.getPlugin("tasknotes")?.api;\nconst workflows = tasknotes?.extensions.get("tasknotes-workflows");\nconst steps = workflows?.listStepDefinitions();\n

Run Policy#

\n

Every workflow has a run policy:

\n
run:\n  mode: sequential\n  noOverlap: true\n  source: tasknotes-workflows\n  maxTasks: 25\n  onError: stop\n  timeout: 30s\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
FieldNotes
modeCurrently sequential. Steps run in order.
noOverlapSkips a new run if the same workflow is already running.
sourceMutation source passed to TaskNotes runtime API calls.
maxTasksSafety limit for forEach batch steps.
onErrorstop or continue.
timeoutOptional duration string.
\n

TaskNotes attaches source, correlation, and reason metadata to events caused by runtime API writes. Workflows use this to make runs debuggable and to avoid accidental self-trigger loops.

\n

Run Logs and Debugging#

\n

Workflow run logs are stored under the plugin's Obsidian config folder by default. You can configure a run-log folder and a log level in the plugin settings.

\n

Run records include:

\n
    \n
  • Workflow id, name, and source path.
  • \n
  • Trigger payload.
  • \n
  • Step statuses.
  • \n
  • Inputs and outputs, depending on the configured log level.
  • \n
  • Error text when a run fails.
  • \n
\n

Use dry runs before enabling workflows that mutate tasks. Dry runs still execute the workflow path, but mutating steps should report what they would do instead of changing task files.

\n

Example: Manual Command Workflow#

\n

This workflow can be run from the command palette after it is enabled:

\n
---\ntype: tasknotes-workflow\nschemaVersion: 1\nid: show-active-count\nname: Show active task count\nenabled: true\ndescription: Show a notice with the number of active tasks.\ntriggers:\n  - id: manual\n    type: manual\nsteps:\n  - id: active\n    type: task.query\n    input:\n      query:\n        where:\n          field: task.status\n          op: eq\n          value: active\n        limit: 25\n        scope:\n          includeArchived: false\n  - id: notice\n    type: notice.show\n    input:\n      message: "Active tasks: {{steps.active.count}}"\nrun:\n  mode: sequential\n  noOverlap: true\n  source: tasknotes-workflows\n  maxTasks: 25\n  onError: stop\n---\n\n# Show active task count\n\nRun this from the Obsidian command palette with `TaskNotes Workflows: Run: Show active task count`.\n

Example: Inherit Parent Priority#

\n

This workflow copies priority from the first parent task when a task becomes a subtask:

\n
type: tasknotes-workflow\nschemaVersion: 1\nid: inherit-subtask-priority\nname: Inherit subtask priority\nenabled: false\ntriggers:\n  - id: projects-changed\n    type: tasknotes.event\n    event: task.projects.changed\n  - id: task-created\n    type: tasknotes.event\n    event: task.created\nconditions:\n  - field: trigger.after.path\n    operator: exists\n  - field: trigger.after.projects\n    operator: exists\nsteps:\n  - id: parents\n    type: task.parents\n    input:\n      task: "{{trigger.after.path}}"\n  - id: inherit-priority\n    type: task.patch\n    if:\n      - field: steps.parents.tasks[0].priority\n        operator: exists\n    input:\n      task: "{{trigger.after.path}}"\n      patch:\n        priority: "{{steps.parents.tasks[0].priority}}"\nrun:\n  mode: sequential\n  noOverlap: true\n  source: tasknotes-workflows\n  maxTasks: 1\n  onError: stop\n

This pattern uses task.parents rather than trying to parse project links manually.

\n

Authoring Guidelines#

\n

When writing workflow notes:

\n
    \n
  • Start with enabled: false for any workflow that mutates tasks.
  • \n
  • Give every trigger and step a stable id.
  • \n
  • Prefer typed TaskNotes steps over direct frontmatter editing.
  • \n
  • Use relationship read steps such as task.parents, task.subtasks, and task.dependencies for parent/subtask/dependency logic.
  • \n
  • Add workflow-level conditions for required trigger fields such as trigger.after.path.
  • \n
  • Add run.noOverlap: true unless overlapping runs are intentional.
  • \n
  • Set run.maxTasks for batch workflows.
  • \n
  • Use allowSelfTrigger: true only when the workflow really should react to its own writes.
  • \n
  • Keep the Markdown body useful for future maintenance: describe what the workflow changes, how to test it, and why it exists.
  • \n
\n

Troubleshooting#

\n

Task steps do not run#

\n

Confirm TaskNotes is enabled and exposes the runtime API. The workflow Base can display definitions without TaskNotes, but steps such as task.patch, time.start, or task.dependencies need TaskNotes.

\n

A manual workflow is missing from the command palette#

\n

Check that:

\n
    \n
  • The workflow is valid.
  • \n
  • enabled is true.
  • \n
  • It has a manual trigger.
  • \n
  • The workflow id is valid and stable.
  • \n
  • Workflows have reloaded after editing the file.
  • \n
\n

Disabled manual workflows can still be dry-run from the workflow card, but they are not registered as run commands.

\n

A cron or interval workflow did not run#

\n

Scheduled workflows only run while Obsidian is open and the plugin is loaded. Check the schedule, timezone, enabled state, and run.maxTasks limit.

\n

A workflow runs more than once#

\n

Check whether multiple triggers match the same update. Also check allowSelfTrigger; most workflows should leave it unset so they do not react to writes caused by tasknotes-workflows.

\n

A workflow is invalid#

\n

Open the workflow Base or the workflow note card. Validation messages point to the field path, such as triggers[0].type or steps[1].input.

\n

Common causes are missing required fields, unsupported trigger types, invalid YAML, or references to step outputs that do not exist.

\n","text":"TaskNotes Workflows is a companion plugin for Markdown-defined automation. It lets you create workflow notes that respond to TaskNotes events, schedules, manual commands, and selected Obsidian events, then run typed actions against TaskNotes tasks. Install TaskNotes Workflows# Install from Obsidian Community Plugins Open the TaskNotes Workflows listing in the Obsidian plugin directory You can also install it from Obsidian: open Settings > Community plugins > Browse, then search for TaskNotes Workflows. The plugin is designed for workflows users often ask TaskNotes core to handle, such as: Start time tracking when a task becomes active. Stop time tracking when a task is completed. Move completed tasks into a review folder. Copy parent task context, tags, priority, dates, or dependencies to subtasks. Warn when a blocked task is moved to active. Run a daily review query. TaskNotes Workflows keeps this behavior outside TaskNotes core while still using the TaskNotes JavaScript Runtime API for safe task reads, writes, canonical queries, events, and relationship resolution. Requirements# TaskNotes must be installed and enabled. TaskNotes must expose the JavaScript runtime API. Obsidian must be open for workflows to run. Scheduled workflows run while Obsidian is running. They are not a background service when Obsidian is closed. The plugin runtime uses Obsidian APIs only. Node is used for development and build scripts, not for workflow execution, so Markdown workflow definitions can work on Obsidian mobile while the plugin is loaded. If TaskNotes is disabled or unavailable, the workflow Base can still validate and display workflow files, but TaskNotes read/write steps cannot run. Files Created by the Plugin# By default, TaskNotes Workflows uses: Path Purpose TaskNotes/Workflows/ Workflow Markdown files. TaskNotes/Views/workflows.base Generated Obsidian Base that renders workflow cards through the custom workflow view. Plugin config folder Run history and detail logs, unless a run-log folder is configured. Workflow notes are ordinary Markdown files. The YAML frontmatter is executable configuration, and the note body is for human explanation, testing notes, and maintenance guidance. First Run# On first load, the plugin can create a default workflow folder, a workflow Base, and a set of example workflow notes. The default workflow notes are disabled so they can be inspected, dry-run, edited, and enabled intentionally. The generated Base is the main workbench. It shows workflow cards with status, trigger and step summaries, recent run state, and buttons for editing, dry-running, running, and opening the source note. Workflow notes also show a compact workflow card in reading mode and live preview, so the note remains useful even when opened directly. Default Workflows# The plugin can write these starter workflows: Workflow What it demonstrates Auto-start time tracking Starts a timer when a task status changes to active. Stop time tracking on complete Stops the timer when a task is completed. Morning overdue review Runs a daily cron query and marks overdue open tasks high priority. Move completed tasks to review Moves completed task notes into a review folder. Inherit subtask contexts and tags Copies contexts and tags from the first parent task when a task becomes a subtask. Inherit subtask priority Copies priority from the first parent task when a task becomes a subtask. Inherit subtask planning dates Copies scheduled and due dates from the first parent task when a task becomes a subtask. Inherit subtask dependencies Adds the first parent task's blocking dependencies to new subtasks. Mirror parent priority to subtasks Updates existing subtasks when a parent task priority changes. Mirror parent planning dates to subtasks Updates existing subtasks when a parent scheduled or due date changes. Mirror parent dependencies to subtasks Replaces each subtask's dependencies with the parent task's current dependencies. Warn when starting a blocked task Shows a notice when a task becomes active while dependencies remain. Daily active task review Shows a daily count of tasks still marked active. Treat these as editable examples. Adjust folders, statuses, priorities, dates, and filters to match your vault before enabling mutating workflows. Workflow Shape# A workflow file looks like this: --- type: tasknotes-workflow schemaVersion: 1 id: auto-start-time-tracking name: Auto-start time tracking enabled: false description: Start a timer when a task status changes to active. triggers: - id: status-active type: tasknotes.event event: task.status.changed to: active conditions: - field: trigger.after.path operator: exists steps: - id: start-time type: time.start input: task: \"{{trigger.after.path}}\" options: description: \"Started by {{workflow.name}}\" run: mode: sequential noOverlap: true source: tasknotes-workflows maxTasks: 1 onError: stop --- # Auto-start time tracking Enable this workflow to start time tracking when a TaskNotes task moves to `active`. Required frontmatter fields: Field Type Notes type string Must be tasknotes-workflow. schemaVersion number Must be 1. id string Stable lowercase identifier. Use letters, numbers, dots, underscores, and dashes. name string Human-readable name shown in workflow cards and command-palette commands. enabled boolean Disabled workflows can be edited and dry-run but do not run automatically or from manual commands. triggers array One or more trigger definitions. conditions array Optional workflow-level guards. steps array Linear typed step pipeline. run object Run policy and safety limits. Triggers# Triggers decide when a workflow should run. TaskNotes Events# Use tasknotes.event to react to TaskNotes runtime events: triggers: - id: status-active type: tasknotes.event event: task.status.changed from: open to: active Common event names include: task.created task.updated task.deleted task.moved task.status.changed task.completed task.uncompleted task.archived task.unarchived task.scheduled.changed task.due.changed task.priority.changed task.tags.changed task.contexts.changed task.projects.changed task.reminders.changed task.dependencies.changed task.recurrence.changed time.started time.stopped pomodoro.started pomodoro.completed pomodoro.interrupted recurring.instance.completed recurring.instance.skipped The workflow editor loads available TaskNotes events dynamically from api.events.list(), so event pickers can follow the runtime API instead of relying on a hardcoded list. TaskNotes event triggers can use these filters: Field Purpose event Runtime event name. from Previous status or value for status-change workflows. to New status or value for status-change workflows. path.glob Optional path glob limiting which task files can trigger the workflow. allowSelfTrigger Allows this workflow to react to writes caused by tasknotes-workflows. Leave off unless you have a clear reason. TaskNotes event output fields include values such as trigger.after.path, trigger.after.status, trigger.before.status, trigger.changes, trigger.source, and trigger.correlationId. Cron# Cron triggers run on matching minutes while Obsidian is open: triggers: - id: weekday-review type: cron schedule: \"0 17 * * 1-5\" timezone: local The schedule uses five fields: minute, hour, day of month, month, day of week. Keep cron workflows bounded with run.maxTasks, especially if they query many tasks. Interval# Interval triggers run repeatedly while Obsidian is open: triggers: - id: half-hour-check type: interval every: 30m The plugin enforces a minimum interval to avoid excessive background work. Manual# Manual triggers let a workflow run from a card button, another plugin, or the Obsidian command palette: triggers: - id: manual type: manual Enabled workflows with a manual trigger are registered as Obsidian commands named Run: . You can launch them from the command palette or assign hotkeys in Obsidian settings. The generated command id is based on the workflow id. Changing a workflow id creates a different command, so any hotkey assigned to the old command id will need to be reassigned. Obsidian Events# Advanced Obsidian triggers are opt-in from the plugin settings. They can listen to selected vault, metadata, and workspace events: triggers: - id: project-note-opened type: obsidian.workspace event: file-open path: glob: \"Projects/**/*.md\" - id: task-note-modified type: obsidian.vault event: modify path: glob: \"Tasks/**/*.md\" - id: metadata-changed type: obsidian.metadata event: changed path: glob: \"Projects/**/*.md\" Keep path filters narrow for Obsidian triggers. Vault and metadata events can be frequent. Conditions# Conditions can appear at workflow level or on individual steps. conditions: - field: trigger.after.path operator: exists - field: trigger.after.status operator: is value: active Supported operators: Operator Meaning is / isNot Exact comparison after scalar normalization. in / notIn Check a value against an array. exists / missing Check whether a field has a value. contains Check whether a string contains text or an array contains a value. startsWith String prefix check. before / after Date comparison. onOrBefore / onOrAfter Inclusive date comparison. Step-level conditions use the same shape: steps: - id: warn type: notice.show if: - field: steps.dependencies.tasks[0].path operator: exists input: message: \"This task still has dependencies.\" References# References use constrained template expressions. Arbitrary JavaScript is not evaluated. {{workflow.id}} {{workflow.name}} {{trigger.after.path}} {{trigger.changes.status.after}} {{steps.query.tasks}} {{steps.parents.tasks[0].path}} {{item.path}} {{today}} {{now}} If a string is exactly one reference, the underlying value is preserved. If a reference is embedded in other text, the value is stringified. Use forEach when a step should run once per item: steps: - id: overdue type: task.query input: query: where: all: - field: task.due op: lt value: fn: today - field: task.status op: notIn value: - done - cancelled sort: - field: task.due direction: asc limit: 50 scope: includeArchived: false - id: mark-high type: task.patch forEach: \"{{steps.overdue.tasks}}\" input: task: \"{{item.path}}\" patch: priority: high When a step uses forEach, {{item}} refers to the current item and the step output becomes an array of per-item outputs. task.query uses the canonical TaskNotes runtime query DTO. Its output includes tasks, count, total, matched, returned, groups, groupPaths, query, and warnings. Runtime query conditions use canonical field IDs and operators: query: where: all: - field: task.status op: ne value: done - any: - field: task.due op: lte value: fn: today - field: task.priority op: eq value: high sort: - field: task.due direction: asc group: - field: task.status limit: 25 scope: includeArchived: false Common fields include task.status, task.priority, task.due, task.scheduled, task.projects, task.contexts, task.tags, task.isBlocked, and file.path. Operators include eq, ne, contains, notContains, in, notIn, exists, missing, lt, lte, gt, gte, isTrue, and isFalse. Use api.catalog.filterProperties() and api.catalog.filterOperators() for the complete runtime catalog. Steps# Steps are typed actions. The editor reads a step catalog so it can show expected inputs, output fields, examples, and TaskNotes option pickers. Task read steps: Step Output task.get One task. task.query Tasks matching a canonical TaskNotes runtime query. task.parents Parent tasks linked from the task's projects. task.subtasks Tasks that reference the current task as a project. task.dependencies Dependencies stored in blockedBy, with resolved task data when available. task.blocking Tasks blocked by the current task. task.relationships The task plus parents, subtasks, dependencies, and blocking tasks. Task write steps: Step Purpose task.create Create a new TaskNotes task. task.patch Update one or more fields. task.set Set one field. task.move Move the task note to a target folder. task.archive / task.unarchive Archive or unarchive a task. task.complete / task.uncomplete Complete or reopen a task. task.reschedule Update planning dates. task.setDue / task.clearDue Set or clear due date. task.setScheduled / task.clearScheduled Set or clear scheduled date. task.addTag / task.removeTag Mutate tags. task.addProject / task.removeProject Mutate project links. task.addContext / task.removeContext Mutate contexts. task.addDependency / task.removeDependency Mutate blocking dependencies. Time and utility steps: Step Purpose time.start Start time tracking for a task. time.stop Stop active time tracking for a task. time.appendEntry Append a time entry. notice.show Show an Obsidian notice. workflow.stop Stop a workflow early. Companion plugins and scripts can inspect the same catalog through the TaskNotes runtime extension: const tasknotes = app.plugins.getPlugin(\"tasknotes\")?.api; const workflows = tasknotes?.extensions.get(\"tasknotes-workflows\"); const steps = workflows?.listStepDefinitions(); Run Policy# Every workflow has a run policy: run: mode: sequential noOverlap: true source: tasknotes-workflows maxTasks: 25 onError: stop timeout: 30s Field Notes mode Currently sequential. Steps run in order. noOverlap Skips a new run if the same workflow is already running. source Mutation source passed to TaskNotes runtime API calls. maxTasks Safety limit for forEach batch steps. onError stop or continue. timeout Optional duration string. TaskNotes attaches source, correlation, and reason metadata to events caused by runtime API writes. Workflows use this to make runs debuggable and to avoid accidental self-trigger loops. Run Logs and Debugging# Workflow run logs are stored under the plugin's Obsidian config folder by default. You can configure a run-log folder and a log level in the plugin settings. Run records include: Workflow id, name, and source path. Trigger payload. Step statuses. Inputs and outputs, depending on the configured log level. Error text when a run fails. Use dry runs before enabling workflows that mutate tasks. Dry runs still execute the workflow path, but mutating steps should report what they would do instead of changing task files. Example: Manual Command Workflow# This workflow can be run from the command palette after it is enabled: --- type: tasknotes-workflow schemaVersion: 1 id: show-active-count name: Show active task count enabled: true description: Show a notice with the number of active tasks. triggers: - id: manual type: manual steps: - id: active type: task.query input: query: where: field: task.status op: eq value: active limit: 25 scope: includeArchived: false - id: notice type: notice.show input: message: \"Active tasks: {{steps.active.count}}\" run: mode: sequential noOverlap: true source: tasknotes-workflows maxTasks: 25 onError: stop --- # Show active task count Run this from the Obsidian command palette with `TaskNotes Workflows: Run: Show active task count`. Example: Inherit Parent Priority# This workflow copies priority from the first parent task when a task becomes a subtask: type: tasknotes-workflow schemaVersion: 1 id: inherit-subtask-priority name: Inherit subtask priority enabled: false triggers: - id: projects-changed type: tasknotes.event event: task.projects.changed - id: task-created type: tasknotes.event event: task.created conditions: - field: trigger.after.path operator: exists - field: trigger.after.projects operator: exists steps: - id: parents type: task.parents input: task: \"{{trigger.after.path}}\" - id: inherit-priority type: task.patch if: - field: steps.parents.tasks[0].priority operator: exists input: task: \"{{trigger.after.path}}\" patch: priority: \"{{steps.parents.tasks[0].priority}}\" run: mode: sequential noOverlap: true source: tasknotes-workflows maxTasks: 1 onError: stop This pattern uses task.parents rather than trying to parse project links manually. Authoring Guidelines# When writing workflow notes: Start with enabled: false fo"},{"route":"/obsidian/core-concepts/","title":"Core Concepts","description":"TaskNotes follows the \"one note per task\" principle, where each task lives as a separate Markdown note with structured metadata in YAML frontmatter.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/core-concepts.md","namespace":"obsidian","relativePath":"core-concepts.md","raw":"# Core Concepts\n\nTaskNotes follows the \"one note per task\" principle, where each task lives as a separate Markdown note with structured metadata in YAML frontmatter.\n\n## The Note-Per-Task Approach\n\nIndividual Markdown notes replace centralized databases or proprietary formats. Each task file can be read, edited, and backed up with any text editor or automation tool.\n\n### Task Structure\n\nA TaskNotes task is a standard Markdown file with YAML frontmatter:\n\n```markdown\n---\ntags:\n - task\ntitle: Review quarterly report\nstatus: in-progress\npriority: high\ndue: 2025-01-15\nscheduled: 2025-01-14\ncontexts:\n - office\nprojects:\n - \"[[Q1 Planning]]\"\n---\n\n## Notes\n\nKey points to review:\n- Revenue projections\n- Budget allocations\n\n## Meeting Notes\n\nDiscussion with finance team on 2025-01-10...\n```\n\nThe frontmatter contains structured, queryable properties. The note body holds freeform content—research findings, meeting notes, checklists, or links to related documents.\n\n### Obsidian Integration\n\nSince tasks are proper notes, they work with Obsidian's core features:\n\n- **Backlinks**: See which notes reference a task\n- **Graph View**: Visualize task relationships and project connections\n- **Tags**: Use Obsidian's tag system for additional categorization\n- **Search**: Find tasks using Obsidian's search\n- **Links**: Reference tasks from daily notes, meeting notes, or project documents\n\nThis approach creates many small files. TaskNotes stores tasks in a configurable folder (default: `TaskNotes/Tasks/`) to keep them organized.\nIn practice, this lets TaskNotes fit into existing vault habits instead of replacing them. You keep using normal note workflows, and TaskNotes adds structure, filtering, and commands on top.\n\n## YAML Frontmatter\n\nTask properties are stored in YAML frontmatter, a standard format with broad tool support.\nTreat frontmatter as the machine-readable layer and the note body as the human-readable layer. TaskNotes automations and Bases filters rely on frontmatter; your project notes and context stay in the body.\n\n### Property Types\n\nTaskNotes uses several property types:\n\n| Type | Example | Description |\n|------|---------|-------------|\n| Text | `title: Buy groceries` | Single text value |\n| List | `tags: [work, urgent]` | Multiple values |\n| Date | `due: 2025-01-15` | ISO 8601 date format |\n| DateTime | `scheduled: 2025-01-15T09:00` | Date with time |\n| Link | `projects: [\"[[Project A]]\"]` | Obsidian wikilinks |\n| Number | `timeEstimate: 60` | Numeric values (minutes) |\n\n### Field Mapping\n\nProperty keys are configurable. If your vault uses `deadline` instead of `due`, you can map TaskNotes to use your existing field names without modifying your files.\n\nThe exact rules for how fields map to semantic roles, how dates are interpreted, and how operations like completion and recurrence behave are defined in the [TaskNotes Specification](spec.md). The spec is the shared contract between the Obsidian plugin, the terminal UI, and any other tool that reads or writes TaskNotes data.\n\n### Custom Fields\n\nAdd any frontmatter property to your tasks. User-defined fields work in filtering, sorting, and templates. Define custom fields in `Settings -> TaskNotes -> Task Properties` to include them in task modals and views.\n\n## Bases Integration\n\nTaskNotes v4 uses Obsidian's Bases core plugin for its main views. Bases provides:\n\n- **Filtering**: Query tasks using AND/OR conditions\n- **Sorting**: Order tasks by any property\n- **Grouping**: Organize tasks by status, priority, project, or custom fields\n- **Views**: Task List, Kanban, Calendar, and Agenda are all Bases views\n\nViews are stored as `.base` files in `TaskNotes/Views/`. These files contain YAML configuration that defines the view's query and display settings. You can duplicate, modify, or create new views by editing these files.\nThis makes view behavior inspectable and predictable. If a task appears in the wrong place, you can open the `.base` file and see exactly which filter or grouping rule produced that result.\n\n### Enabling Bases\n\nBases is a core plugin included with Obsidian 1.10.1+:\n\n1. Open `Settings -> Core Plugins`\n2. Enable \"Bases\"\n3. TaskNotes views will now function\n","aliases":["/core-concepts/"],"toc":[{"level":2,"id":"the-note-per-task-approach","text":"The Note-Per-Task Approach"},{"level":3,"id":"task-structure","text":"Task Structure"},{"level":3,"id":"obsidian-integration","text":"Obsidian Integration"},{"level":2,"id":"yaml-frontmatter","text":"YAML Frontmatter"},{"level":3,"id":"property-types","text":"Property Types"},{"level":3,"id":"field-mapping","text":"Field Mapping"},{"level":3,"id":"custom-fields","text":"Custom Fields"},{"level":2,"id":"bases-integration","text":"Bases Integration"},{"level":3,"id":"enabling-bases","text":"Enabling Bases"}],"html":"

TaskNotes follows the "one note per task" principle, where each task lives as a separate Markdown note with structured metadata in YAML frontmatter.

\n

The Note-Per-Task Approach#

\n

Individual Markdown notes replace centralized databases or proprietary formats. Each task file can be read, edited, and backed up with any text editor or automation tool.

\n

Task Structure#

\n

A TaskNotes task is a standard Markdown file with YAML frontmatter:

\n
---\ntags:\n  - task\ntitle: Review quarterly report\nstatus: in-progress\npriority: high\ndue: 2025-01-15\nscheduled: 2025-01-14\ncontexts:\n  - office\nprojects:\n  - "[[Q1 Planning]]"\n---\n\n## Notes\n\nKey points to review:\n- Revenue projections\n- Budget allocations\n\n## Meeting Notes\n\nDiscussion with finance team on 2025-01-10...\n

The frontmatter contains structured, queryable properties. The note body holds freeform content—research findings, meeting notes, checklists, or links to related documents.

\n

Obsidian Integration#

\n

Since tasks are proper notes, they work with Obsidian's core features:

\n
    \n
  • Backlinks: See which notes reference a task
  • \n
  • Graph View: Visualize task relationships and project connections
  • \n
  • Tags: Use Obsidian's tag system for additional categorization
  • \n
  • Search: Find tasks using Obsidian's search
  • \n
  • Links: Reference tasks from daily notes, meeting notes, or project documents
  • \n
\n

This approach creates many small files. TaskNotes stores tasks in a configurable folder (default: TaskNotes/Tasks/) to keep them organized.\nIn practice, this lets TaskNotes fit into existing vault habits instead of replacing them. You keep using normal note workflows, and TaskNotes adds structure, filtering, and commands on top.

\n

YAML Frontmatter#

\n

Task properties are stored in YAML frontmatter, a standard format with broad tool support.\nTreat frontmatter as the machine-readable layer and the note body as the human-readable layer. TaskNotes automations and Bases filters rely on frontmatter; your project notes and context stay in the body.

\n

Property Types#

\n

TaskNotes uses several property types:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
TypeExampleDescription
Texttitle: Buy groceriesSingle text value
Listtags: [work, urgent]Multiple values
Datedue: 2025-01-15ISO 8601 date format
DateTimescheduled: 2025-01-15T09:00Date with time
Linkprojects: ["[[Project A]]"]Obsidian wikilinks
NumbertimeEstimate: 60Numeric values (minutes)
\n

Field Mapping#

\n

Property keys are configurable. If your vault uses deadline instead of due, you can map TaskNotes to use your existing field names without modifying your files.

\n

The exact rules for how fields map to semantic roles, how dates are interpreted, and how operations like completion and recurrence behave are defined in the TaskNotes Specification. The spec is the shared contract between the Obsidian plugin, the terminal UI, and any other tool that reads or writes TaskNotes data.

\n

Custom Fields#

\n

Add any frontmatter property to your tasks. User-defined fields work in filtering, sorting, and templates. Define custom fields in Settings -> TaskNotes -> Task Properties to include them in task modals and views.

\n

Bases Integration#

\n

TaskNotes v4 uses Obsidian's Bases core plugin for its main views. Bases provides:

\n
    \n
  • Filtering: Query tasks using AND/OR conditions
  • \n
  • Sorting: Order tasks by any property
  • \n
  • Grouping: Organize tasks by status, priority, project, or custom fields
  • \n
  • Views: Task List, Kanban, Calendar, and Agenda are all Bases views
  • \n
\n

Views are stored as .base files in TaskNotes/Views/. These files contain YAML configuration that defines the view's query and display settings. You can duplicate, modify, or create new views by editing these files.\nThis makes view behavior inspectable and predictable. If a task appears in the wrong place, you can open the .base file and see exactly which filter or grouping rule produced that result.

\n

Enabling Bases#

\n

Bases is a core plugin included with Obsidian 1.10.1+:

\n
    \n
  1. Open Settings -> Core Plugins
  2. \n
  3. Enable "Bases"
  4. \n
  5. TaskNotes views will now function
  6. \n
\n","text":"TaskNotes follows the \"one note per task\" principle, where each task lives as a separate Markdown note with structured metadata in YAML frontmatter. The Note-Per-Task Approach# Individual Markdown notes replace centralized databases or proprietary formats. Each task file can be read, edited, and backed up with any text editor or automation tool. Task Structure# A TaskNotes task is a standard Markdown file with YAML frontmatter: --- tags: - task title: Review quarterly report status: in-progress priority: high due: 2025-01-15 scheduled: 2025-01-14 contexts: - office projects: - \"[[Q1 Planning]]\" --- ## Notes Key points to review: - Revenue projections - Budget allocations ## Meeting Notes Discussion with finance team on 2025-01-10... The frontmatter contains structured, queryable properties. The note body holds freeform content—research findings, meeting notes, checklists, or links to related documents. Obsidian Integration# Since tasks are proper notes, they work with Obsidian's core features: Backlinks: See which notes reference a task Graph View: Visualize task relationships and project connections Tags: Use Obsidian's tag system for additional categorization Search: Find tasks using Obsidian's search Links: Reference tasks from daily notes, meeting notes, or project documents This approach creates many small files. TaskNotes stores tasks in a configurable folder (default: TaskNotes/Tasks/) to keep them organized. In practice, this lets TaskNotes fit into existing vault habits instead of replacing them. You keep using normal note workflows, and TaskNotes adds structure, filtering, and commands on top. YAML Frontmatter# Task properties are stored in YAML frontmatter, a standard format with broad tool support. Treat frontmatter as the machine-readable layer and the note body as the human-readable layer. TaskNotes automations and Bases filters rely on frontmatter; your project notes and context stay in the body. Property Types# TaskNotes uses several property types: Type Example Description Text title: Buy groceries Single text value List tags: [work, urgent] Multiple values Date due: 2025-01-15 ISO 8601 date format DateTime scheduled: 2025-01-15T09:00 Date with time Link projects: [\"[[Project A]]\"] Obsidian wikilinks Number timeEstimate: 60 Numeric values (minutes) Field Mapping# Property keys are configurable. If your vault uses deadline instead of due, you can map TaskNotes to use your existing field names without modifying your files. The exact rules for how fields map to semantic roles, how dates are interpreted, and how operations like completion and recurrence behave are defined in the TaskNotes Specification. The spec is the shared contract between the Obsidian plugin, the terminal UI, and any other tool that reads or writes TaskNotes data. Custom Fields# Add any frontmatter property to your tasks. User-defined fields work in filtering, sorting, and templates. Define custom fields in Settings -> TaskNotes -> Task Properties to include them in task modals and views. Bases Integration# TaskNotes v4 uses Obsidian's Bases core plugin for its main views. Bases provides: Filtering: Query tasks using AND/OR conditions Sorting: Order tasks by any property Grouping: Organize tasks by status, priority, project, or custom fields Views: Task List, Kanban, Calendar, and Agenda are all Bases views Views are stored as .base files in TaskNotes/Views/. These files contain YAML configuration that defines the view's query and display settings. You can duplicate, modify, or create new views by editing these files. This makes view behavior inspectable and predictable. If a task appears in the wrong place, you can open the .base file and see exactly which filter or grouping rule produced that result. Enabling Bases# Bases is a core plugin included with Obsidian 1.10.1+: Open Settings -> Core Plugins Enable \"Bases\" TaskNotes views will now function"},{"route":"/obsidian/features/","title":"Features","description":"TaskNotes includes task organization, time tracking, and calendar integration features.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/features.md","namespace":"obsidian","relativePath":"features.md","raw":"# Features\n\nTaskNotes includes task organization, time tracking, and calendar integration features.\n\n## Task Management\n\nTaskNotes gives each task a structured set of properties, including status, priority, due and scheduled dates, tags, contexts, and optional estimates. Because these values live in frontmatter, they stay readable and portable while still powering advanced filtering and grouping in Bases.\n\nReminders can be relative (for example, \"3 days before due\") or absolute, and completed tasks can be archived automatically to keep active work surfaces focused. Recurring tasks can stay virtual for lightweight checkoff workflows, or you can materialize individual occurrences into normal task notes when a specific instance needs its own checklist, comments, time tracking, or attachments. Occurrence notes inherit useful planning metadata from the parent while keeping their own completion state and time entries, and calendar views coalesce them with the matching virtual recurrence instance.\n\nSee [Task Management](features/task-management.md) for details.\nFor recurrence behavior, see [Recurring Tasks](features/recurring-tasks.md).\nFor reminder setup and data format, see [Task Reminders](features/reminders.md).\n\n## Filtering and Views\n\nTaskNotes uses Obsidian's Bases engine for filtering, sorting, and grouping. Each view is a `.base` file, so you can inspect or edit its query logic directly instead of relying on hidden plugin state.\n\nThis design also makes view customization practical: you can duplicate a default view, tweak grouping or formulas, and keep both versions side by side in your vault.\n\n![Kanban view](assets/views-kanban.png)\n\nFor details on how Bases integration works, see [Core Concepts](core-concepts.md#bases-integration). For Bases syntax documentation, see the [official Obsidian Bases documentation](https://help.obsidian.md/Bases/Introduction+to+Bases).\n\n## Inline Task Integration\n\nInline task features let you work from normal notes without context switching. Task links can display interactive cards, checkboxes can be converted into full task notes, and project notes can surface subtasks and dependency relationships in place.\n\nNatural language parsing supports date, priority, and context extraction across multiple languages, which helps keep fast capture while preserving structured data.\n\nSee [Inline Task Integration](features/inline-tasks.md) for details.\n\n## Time Management\n\nTime tracking records work sessions per task, and Pomodoro mode supports focused intervals with break handling. Over time, the statistics views help you compare estimated versus actual effort and spot trends in workload distribution.\n\n![Pomodoro timer](assets/feature-pomodoro-timer.png)\n\nSee [Time Management](features/time-management.md) for details.\n\n## Calendar Integration\n\nTaskNotes supports bidirectional OAuth sync with Google Calendar and Microsoft Outlook, plus read-only ICS subscriptions for external feeds. Calendar views include month, week, day, year, and list modes, and drag-and-drop scheduling can update tasks directly.\n\nFor planning workflows, time-blocking and calendar-linked task updates connect backlog management with schedule execution in the same workspace.\n\n![Calendar month view](assets/views-calendar-month.png)\n\nSee [Calendar Integration](features/calendar-integration.md) for details.\n\n## User Fields\n\nUser fields let you extend the core model with vault-specific metadata like client, energy level, billing code, or review state. Once added, these fields become available in filters, sorting, templates, and formulas.\n\nSee [User Fields](features/user-fields.md) for details.\n\n## Integrations\n\nBeyond calendar sync, TaskNotes includes an HTTP API and webhook support for automation workflows, external dashboards, or custom tooling.\n\nSee [Integrations](settings/integrations.md) for details.\n\n## Companion Plugins\n\nTaskNotes can be extended by optional companion plugins that use the JavaScript runtime API while keeping task data in Markdown files. [Canvas Bases](companion-plugins/canvas-bases.md) is the TaskNotes canvas companion, adding canvas-style boards and JSON Canvas snapshots for Bases views, with optional TaskNotes badges, actions, and relationship edges. [TaskNotes Workflows](companion-plugins/tasknotes-workflows.md) adds Markdown-defined automation for TaskNotes events, schedules, manual commands, and typed task actions.\n\nSee [Companion Plugins](companion-plugins.md) for details.\n\n## REST API\n\nExternal applications can interact with TaskNotes through its REST API for automation, reporting, and integration with other tools.\n\nSee [HTTP API](HTTP_API.md) for details.\n","aliases":["/features/"],"toc":[{"level":2,"id":"task-management","text":"Task Management"},{"level":2,"id":"filtering-and-views","text":"Filtering and Views"},{"level":2,"id":"inline-task-integration","text":"Inline Task Integration"},{"level":2,"id":"time-management","text":"Time Management"},{"level":2,"id":"calendar-integration","text":"Calendar Integration"},{"level":2,"id":"user-fields","text":"User Fields"},{"level":2,"id":"integrations","text":"Integrations"},{"level":2,"id":"companion-plugins","text":"Companion Plugins"},{"level":2,"id":"rest-api","text":"REST API"}],"html":"

TaskNotes includes task organization, time tracking, and calendar integration features.

\n

Task Management#

\n

TaskNotes gives each task a structured set of properties, including status, priority, due and scheduled dates, tags, contexts, and optional estimates. Because these values live in frontmatter, they stay readable and portable while still powering advanced filtering and grouping in Bases.

\n

Reminders can be relative (for example, "3 days before due") or absolute, and completed tasks can be archived automatically to keep active work surfaces focused. Recurring tasks can stay virtual for lightweight checkoff workflows, or you can materialize individual occurrences into normal task notes when a specific instance needs its own checklist, comments, time tracking, or attachments. Occurrence notes inherit useful planning metadata from the parent while keeping their own completion state and time entries, and calendar views coalesce them with the matching virtual recurrence instance.

\n

See Task Management for details.\nFor recurrence behavior, see Recurring Tasks.\nFor reminder setup and data format, see Task Reminders.

\n

Filtering and Views#

\n

TaskNotes uses Obsidian's Bases engine for filtering, sorting, and grouping. Each view is a .base file, so you can inspect or edit its query logic directly instead of relying on hidden plugin state.

\n

This design also makes view customization practical: you can duplicate a default view, tweak grouping or formulas, and keep both versions side by side in your vault.

\n

\"Kanban

\n

For details on how Bases integration works, see Core Concepts. For Bases syntax documentation, see the official Obsidian Bases documentation.

\n

Inline Task Integration#

\n

Inline task features let you work from normal notes without context switching. Task links can display interactive cards, checkboxes can be converted into full task notes, and project notes can surface subtasks and dependency relationships in place.

\n

Natural language parsing supports date, priority, and context extraction across multiple languages, which helps keep fast capture while preserving structured data.

\n

See Inline Task Integration for details.

\n

Time Management#

\n

Time tracking records work sessions per task, and Pomodoro mode supports focused intervals with break handling. Over time, the statistics views help you compare estimated versus actual effort and spot trends in workload distribution.

\n

\"Pomodoro

\n

See Time Management for details.

\n

Calendar Integration#

\n

TaskNotes supports bidirectional OAuth sync with Google Calendar and Microsoft Outlook, plus read-only ICS subscriptions for external feeds. Calendar views include month, week, day, year, and list modes, and drag-and-drop scheduling can update tasks directly.

\n

For planning workflows, time-blocking and calendar-linked task updates connect backlog management with schedule execution in the same workspace.

\n

\"Calendar

\n

See Calendar Integration for details.

\n

User Fields#

\n

User fields let you extend the core model with vault-specific metadata like client, energy level, billing code, or review state. Once added, these fields become available in filters, sorting, templates, and formulas.

\n

See User Fields for details.

\n

Integrations#

\n

Beyond calendar sync, TaskNotes includes an HTTP API and webhook support for automation workflows, external dashboards, or custom tooling.

\n

See Integrations for details.

\n

Companion Plugins#

\n

TaskNotes can be extended by optional companion plugins that use the JavaScript runtime API while keeping task data in Markdown files. Canvas Bases is the TaskNotes canvas companion, adding canvas-style boards and JSON Canvas snapshots for Bases views, with optional TaskNotes badges, actions, and relationship edges. TaskNotes Workflows adds Markdown-defined automation for TaskNotes events, schedules, manual commands, and typed task actions.

\n

See Companion Plugins for details.

\n

REST API#

\n

External applications can interact with TaskNotes through its REST API for automation, reporting, and integration with other tools.

\n

See HTTP API for details.

\n","text":"TaskNotes includes task organization, time tracking, and calendar integration features. Task Management# TaskNotes gives each task a structured set of properties, including status, priority, due and scheduled dates, tags, contexts, and optional estimates. Because these values live in frontmatter, they stay readable and portable while still powering advanced filtering and grouping in Bases. Reminders can be relative (for example, \"3 days before due\") or absolute, and completed tasks can be archived automatically to keep active work surfaces focused. Recurring tasks can stay virtual for lightweight checkoff workflows, or you can materialize individual occurrences into normal task notes when a specific instance needs its own checklist, comments, time tracking, or attachments. Occurrence notes inherit useful planning metadata from the parent while keeping their own completion state and time entries, and calendar views coalesce them with the matching virtual recurrence instance. See Task Management for details. For recurrence behavior, see Recurring Tasks. For reminder setup and data format, see Task Reminders. Filtering and Views# TaskNotes uses Obsidian's Bases engine for filtering, sorting, and grouping. Each view is a .base file, so you can inspect or edit its query logic directly instead of relying on hidden plugin state. This design also makes view customization practical: you can duplicate a default view, tweak grouping or formulas, and keep both versions side by side in your vault. For details on how Bases integration works, see Core Concepts. For Bases syntax documentation, see the official Obsidian Bases documentation. Inline Task Integration# Inline task features let you work from normal notes without context switching. Task links can display interactive cards, checkboxes can be converted into full task notes, and project notes can surface subtasks and dependency relationships in place. Natural language parsing supports date, priority, and context extraction across multiple languages, which helps keep fast capture while preserving structured data. See Inline Task Integration for details. Time Management# Time tracking records work sessions per task, and Pomodoro mode supports focused intervals with break handling. Over time, the statistics views help you compare estimated versus actual effort and spot trends in workload distribution. See Time Management for details. Calendar Integration# TaskNotes supports bidirectional OAuth sync with Google Calendar and Microsoft Outlook, plus read-only ICS subscriptions for external feeds. Calendar views include month, week, day, year, and list modes, and drag-and-drop scheduling can update tasks directly. For planning workflows, time-blocking and calendar-linked task updates connect backlog management with schedule execution in the same workspace. See Calendar Integration for details. User Fields# User fields let you extend the core model with vault-specific metadata like client, energy level, billing code, or review state. Once added, these fields become available in filters, sorting, templates, and formulas. See User Fields for details. Integrations# Beyond calendar sync, TaskNotes includes an HTTP API and webhook support for automation workflows, external dashboards, or custom tooling. See Integrations for details. Companion Plugins# TaskNotes can be extended by optional companion plugins that use the JavaScript runtime API while keeping task data in Markdown files. Canvas Bases is the TaskNotes canvas companion, adding canvas-style boards and JSON Canvas snapshots for Bases views, with optional TaskNotes badges, actions, and relationship edges. TaskNotes Workflows adds Markdown-defined automation for TaskNotes events, schedules, manual commands, and typed task actions. See Companion Plugins for details. REST API# External applications can interact with TaskNotes through its REST API for automation, reporting, and integration with other tools. See HTTP API for details."},{"route":"/obsidian/features/calendar-integration/","title":"Calendar Integration","description":"TaskNotes provides calendar integration through OAuth-connected calendar services, two Bases-powered calendar views, and read-only ICS calendar subscriptions.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/features/calendar-integration.md","namespace":"obsidian","relativePath":"features/calendar-integration.md","raw":"# Calendar Integration\n\nTaskNotes provides calendar integration through OAuth-connected calendar services, two Bases-powered calendar views, and read-only ICS calendar subscriptions.\n\n## OAuth Calendar Integration\n\nTaskNotes supports bidirectional synchronization with Google Calendar and Microsoft Outlook using OAuth authentication. This integration allows you to view external calendar events alongside your tasks and sync changes back to the calendar provider.\n\n### Supported Providers\n\n- **Google Calendar** - OAuth 2.0 authentication with access to all calendars in your Google account\n- **Microsoft Outlook** - OAuth 2.0 authentication with access to calendars in your Microsoft 365 or Outlook.com account\n\n### Setup Requirements\n\nOAuth calendar integration requires creating an OAuth application with your calendar provider. This process takes approximately 15 minutes per provider. You will need to:\n\n1. Create an OAuth application in Google Cloud Console or Microsoft Azure Portal\n2. Configure redirect URIs and scopes\n3. Obtain client ID and client secret\n4. Enter credentials in TaskNotes settings (`Settings -> TaskNotes -> Integrations`, OAuth calendar section)\n\n### Synchronization Behavior\n\n- Events are fetched automatically every 15 minutes\n- Events are also fetched when local changes occur (task creation, updates, rescheduling)\n- Dragging calendar events to new dates/times updates the event in the calendar provider\n- Per-calendar visibility toggles allow selective display of calendars\n- Access tokens are automatically refreshed when expired\n\n### Token Management\n\nTaskNotes stores OAuth client credentials, access tokens, and refresh tokens in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system and kept separate from TaskNotes' `data.json`. Tokens are refreshed automatically before expiration. You can revoke account access or forget the saved OAuth app credentials through the integrations settings.\n\n## Calendar Views\n\nTaskNotes provides Calendar and Mini Calendar views that display tasks alongside OAuth calendar events and ICS subscriptions. Both views support drag-and-drop scheduling.\n\nFor detailed view documentation, see [Calendar Views](../views/calendar-views.md).\n\nNotes linked from recurring external calendar events can be matched either across the loaded event series or only to the selected recurrence instance. Configure this in [Integrations settings](../settings/integrations.md#calendar-subscriptions-ics).\n\n## Time Entry Editor\n\nTaskNotes includes a time entry editor for tracking time spent on tasks. Time entries are created and managed through the Calendar View.\n\n### Creating Time Entries\n\nTo create a time entry on the Calendar View:\n\n1. Click and drag on a time slot in the calendar to select a time range\n2. When the selection menu appears, choose **Create time entry** (timeblock appears only if the feature is enabled)\n3. Choose a task in the task selector modal\n4. A time entry is created for that task with the selected start/end range\n\nTime entries are always associated with a specific task and stored in that task's frontmatter. Multiple time entries can exist for one task.\n\n### Managing Time Entries\n\nThe time entry editor modal provides functions to:\n\n- View all time entries for a task\n- Edit the start time, end time, and duration of time entries\n- Delete time entries\n- See the total time tracked across all entries for a task\n\nAccess the time entry editor by clicking an existing time entry in the calendar.\n\n## ICS Calendar Subscriptions\n\nTaskNotes can subscribe to external calendar feeds using the iCalendar (ICS) format. This provides read-only access to events from calendar services. ICS subscriptions differ from OAuth calendar integration in that they are read-only—dragging ICS events to new dates does not update the source calendar.\n\nAdd and manage ICS subscriptions from `Settings -> TaskNotes -> Integrations` (Calendar Subscriptions section).\n\nFor details on creating notes and tasks from calendar events, see [ICS Integration](ics-integration.md).\n\n## Time Blocking\n\nThe Calendar View supports time blocking for scheduling dedicated work periods. To create a time block:\n\n1. Click and drag on a time slot in the calendar to select a time range\n2. A context menu will appear with available options\n3. Select \"Create timeblock\" from the menu (this option only appears if timeblocking is enabled in settings)\n\nTime blocks are stored in the frontmatter of daily notes and can be linked to specific tasks. This differs from time entries, which track actual time spent and are stored in task frontmatter rather than daily notes.\n\nEnable time blocking under `Settings -> TaskNotes -> Features` (Timeblocking section).\n","aliases":["/features/calendar-integration/"],"toc":[{"level":2,"id":"oauth-calendar-integration","text":"OAuth Calendar Integration"},{"level":3,"id":"supported-providers","text":"Supported Providers"},{"level":3,"id":"setup-requirements","text":"Setup Requirements"},{"level":3,"id":"synchronization-behavior","text":"Synchronization Behavior"},{"level":3,"id":"token-management","text":"Token Management"},{"level":2,"id":"calendar-views","text":"Calendar Views"},{"level":2,"id":"time-entry-editor","text":"Time Entry Editor"},{"level":3,"id":"creating-time-entries","text":"Creating Time Entries"},{"level":3,"id":"managing-time-entries","text":"Managing Time Entries"},{"level":2,"id":"ics-calendar-subscriptions","text":"ICS Calendar Subscriptions"},{"level":2,"id":"time-blocking","text":"Time Blocking"}],"html":"

TaskNotes provides calendar integration through OAuth-connected calendar services, two Bases-powered calendar views, and read-only ICS calendar subscriptions.

\n

OAuth Calendar Integration#

\n

TaskNotes supports bidirectional synchronization with Google Calendar and Microsoft Outlook using OAuth authentication. This integration allows you to view external calendar events alongside your tasks and sync changes back to the calendar provider.

\n

Supported Providers#

\n
    \n
  • Google Calendar - OAuth 2.0 authentication with access to all calendars in your Google account
  • \n
  • Microsoft Outlook - OAuth 2.0 authentication with access to calendars in your Microsoft 365 or Outlook.com account
  • \n
\n

Setup Requirements#

\n

OAuth calendar integration requires creating an OAuth application with your calendar provider. This process takes approximately 15 minutes per provider. You will need to:

\n
    \n
  1. Create an OAuth application in Google Cloud Console or Microsoft Azure Portal
  2. \n
  3. Configure redirect URIs and scopes
  4. \n
  5. Obtain client ID and client secret
  6. \n
  7. Enter credentials in TaskNotes settings (Settings -> TaskNotes -> Integrations, OAuth calendar section)
  8. \n
\n

Synchronization Behavior#

\n
    \n
  • Events are fetched automatically every 15 minutes
  • \n
  • Events are also fetched when local changes occur (task creation, updates, rescheduling)
  • \n
  • Dragging calendar events to new dates/times updates the event in the calendar provider
  • \n
  • Per-calendar visibility toggles allow selective display of calendars
  • \n
  • Access tokens are automatically refreshed when expired
  • \n
\n

Token Management#

\n

TaskNotes stores OAuth client credentials, access tokens, and refresh tokens in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system and kept separate from TaskNotes' data.json. Tokens are refreshed automatically before expiration. You can revoke account access or forget the saved OAuth app credentials through the integrations settings.

\n

Calendar Views#

\n

TaskNotes provides Calendar and Mini Calendar views that display tasks alongside OAuth calendar events and ICS subscriptions. Both views support drag-and-drop scheduling.

\n

For detailed view documentation, see Calendar Views.

\n

Notes linked from recurring external calendar events can be matched either across the loaded event series or only to the selected recurrence instance. Configure this in Integrations settings.

\n

Time Entry Editor#

\n

TaskNotes includes a time entry editor for tracking time spent on tasks. Time entries are created and managed through the Calendar View.

\n

Creating Time Entries#

\n

To create a time entry on the Calendar View:

\n
    \n
  1. Click and drag on a time slot in the calendar to select a time range
  2. \n
  3. When the selection menu appears, choose Create time entry (timeblock appears only if the feature is enabled)
  4. \n
  5. Choose a task in the task selector modal
  6. \n
  7. A time entry is created for that task with the selected start/end range
  8. \n
\n

Time entries are always associated with a specific task and stored in that task's frontmatter. Multiple time entries can exist for one task.

\n

Managing Time Entries#

\n

The time entry editor modal provides functions to:

\n
    \n
  • View all time entries for a task
  • \n
  • Edit the start time, end time, and duration of time entries
  • \n
  • Delete time entries
  • \n
  • See the total time tracked across all entries for a task
  • \n
\n

Access the time entry editor by clicking an existing time entry in the calendar.

\n

ICS Calendar Subscriptions#

\n

TaskNotes can subscribe to external calendar feeds using the iCalendar (ICS) format. This provides read-only access to events from calendar services. ICS subscriptions differ from OAuth calendar integration in that they are read-only—dragging ICS events to new dates does not update the source calendar.

\n

Add and manage ICS subscriptions from Settings -> TaskNotes -> Integrations (Calendar Subscriptions section).

\n

For details on creating notes and tasks from calendar events, see ICS Integration.

\n

Time Blocking#

\n

The Calendar View supports time blocking for scheduling dedicated work periods. To create a time block:

\n
    \n
  1. Click and drag on a time slot in the calendar to select a time range
  2. \n
  3. A context menu will appear with available options
  4. \n
  5. Select "Create timeblock" from the menu (this option only appears if timeblocking is enabled in settings)
  6. \n
\n

Time blocks are stored in the frontmatter of daily notes and can be linked to specific tasks. This differs from time entries, which track actual time spent and are stored in task frontmatter rather than daily notes.

\n

Enable time blocking under Settings -> TaskNotes -> Features (Timeblocking section).

\n","text":"TaskNotes provides calendar integration through OAuth-connected calendar services, two Bases-powered calendar views, and read-only ICS calendar subscriptions. OAuth Calendar Integration# TaskNotes supports bidirectional synchronization with Google Calendar and Microsoft Outlook using OAuth authentication. This integration allows you to view external calendar events alongside your tasks and sync changes back to the calendar provider. Supported Providers# Google Calendar - OAuth 2.0 authentication with access to all calendars in your Google account Microsoft Outlook - OAuth 2.0 authentication with access to calendars in your Microsoft 365 or Outlook.com account Setup Requirements# OAuth calendar integration requires creating an OAuth application with your calendar provider. This process takes approximately 15 minutes per provider. You will need to: Create an OAuth application in Google Cloud Console or Microsoft Azure Portal Configure redirect URIs and scopes Obtain client ID and client secret Enter credentials in TaskNotes settings (Settings -> TaskNotes -> Integrations, OAuth calendar section) Synchronization Behavior# Events are fetched automatically every 15 minutes Events are also fetched when local changes occur (task creation, updates, rescheduling) Dragging calendar events to new dates/times updates the event in the calendar provider Per-calendar visibility toggles allow selective display of calendars Access tokens are automatically refreshed when expired Token Management# TaskNotes stores OAuth client credentials, access tokens, and refresh tokens in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system and kept separate from TaskNotes' data.json. Tokens are refreshed automatically before expiration. You can revoke account access or forget the saved OAuth app credentials through the integrations settings. Calendar Views# TaskNotes provides Calendar and Mini Calendar views that display tasks alongside OAuth calendar events and ICS subscriptions. Both views support drag-and-drop scheduling. For detailed view documentation, see Calendar Views. Notes linked from recurring external calendar events can be matched either across the loaded event series or only to the selected recurrence instance. Configure this in Integrations settings. Time Entry Editor# TaskNotes includes a time entry editor for tracking time spent on tasks. Time entries are created and managed through the Calendar View. Creating Time Entries# To create a time entry on the Calendar View: Click and drag on a time slot in the calendar to select a time range When the selection menu appears, choose Create time entry (timeblock appears only if the feature is enabled) Choose a task in the task selector modal A time entry is created for that task with the selected start/end range Time entries are always associated with a specific task and stored in that task's frontmatter. Multiple time entries can exist for one task. Managing Time Entries# The time entry editor modal provides functions to: View all time entries for a task Edit the start time, end time, and duration of time entries Delete time entries See the total time tracked across all entries for a task Access the time entry editor by clicking an existing time entry in the calendar. ICS Calendar Subscriptions# TaskNotes can subscribe to external calendar feeds using the iCalendar (ICS) format. This provides read-only access to events from calendar services. ICS subscriptions differ from OAuth calendar integration in that they are read-only—dragging ICS events to new dates does not update the source calendar. Add and manage ICS subscriptions from Settings -> TaskNotes -> Integrations (Calendar Subscriptions section). For details on creating notes and tasks from calendar events, see ICS Integration. Time Blocking# The Calendar View supports time blocking for scheduling dedicated work periods. To create a time block: Click and drag on a time slot in the calendar to select a time range A context menu will appear with available options Select \"Create timeblock\" from the menu (this option only appears if timeblocking is enabled in settings) Time blocks are stored in the frontmatter of daily notes and can be linked to specific tasks. This differs from time entries, which track actual time spent and are stored in task frontmatter rather than daily notes. Enable time blocking under Settings -> TaskNotes -> Features (Timeblocking section)."},{"route":"/obsidian/features/ics-integration/","title":"ICS Calendar Event Integration","description":"TaskNotes can use ICS calendar events to create notes and tasks directly from calendar entries. ICS integration creates linked notes and tasks from event data without manual re-...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/features/ics-integration.md","namespace":"obsidian","relativePath":"features/ics-integration.md","raw":"# ICS Calendar Event Integration\n\nTaskNotes can use ICS calendar events to create notes and tasks directly from calendar entries.\nICS integration creates linked notes and tasks from event data without manual re-entry.\n\n## Overview\n\nThe ICS integration allows you to:\n\n- View detailed information about calendar events\n- Create notes from calendar events with customizable templates\n- Generate tasks from events with proper scheduling and context\n- Link existing vault content to calendar events\n- Maintain relationships between events and created content\nEvent context, notes, and follow-up tasks remain connected through frontmatter links.\n\n## Event Information Modal\n\nWhen you interact with a calendar event in TaskNotes, an information modal displays event details and available actions. The modal provides:\n\n### Event Details\n\n- Event title and description\n- Start and end times (formatted according to your locale)\n- Location information\n- Source calendar name\n- Event URL (if available)\n\n### Related Content\n\nThe modal shows a list of existing notes and tasks that are linked to the calendar event. Content is automatically categorized as:\n\n- **Task** - Files containing the configured task tag\n- **Note** - Files without the task tag\n\nThe relationship is maintained through the ICS Event ID field in the content's frontmatter.\n\n### Available Actions\n\n**Create Note** - Opens a creation dialog for generating a new note from the event data.\n\n**Create Task** - Creates a task immediately using the event information with default settings.\n\n**Link Note** - Opens a file selection dialog to link an existing note to the calendar event.\n\n**Refresh** - Reloads the list of related content to reflect recent changes.\n\n## Note Creation from Events\n\nThe note creation process allows customization of the generated content:\n\n### Basic Settings\n\n- **Title** - Default combines event title and date, but can be modified\n- **Folder** - Destination for the new note (uses default ICS note folder if configured)\n- **Template** - Optional template file to structure the note content\n\n### Template Usage\n\nWhen a template is specified:\n\n- The template file is processed with ICS-specific variables\n- Standard TaskNotes template variables are also available\n- Template content replaces the default event description format\n- Frontmatter from templates is merged with required ICS fields\nTemplates apply a consistent note structure across imported events.\n\n### Default Content\n\nWithout a template, notes include:\n\n- Event title as the main heading\n- Formatted start and end times\n- Location information\n- Source calendar name\n- Event description (if provided)\n- Event URL (if available)\n\n## Task Creation from Events\n\nTasks created from calendar events include relevant event data:\n\n### Scheduled Date and Time\n\nTasks are scheduled using the event's start time as an ISO timestamp, preserving both date and time information. This allows for accurate scheduling that reflects the original event timing.\n\n### Task Properties\n\n- **Title** - Uses the event title\n- **Status** - Set to the default task status configured in settings\n- **Priority** - Set to the default task priority\n- **Contexts** - Event location is added as a context (if provided)\n- **Time Estimate** - Calculated from event duration (if start and end times are available)\n- **Tags** - Includes the ICS event tag and any default task tags\nAfter creation, priority, status, and schedule can be edited if event data does not match the final task plan.\n\n### Content\n\nTask content includes formatted event details similar to note creation, providing context about the original calendar event.\n\n## Linking Existing Content\n\nYou can establish connections between existing vault content and calendar events:\n\n### Link Process\n\n1. Select an existing markdown file from your vault\n2. The file's frontmatter is updated to include the event ID\n3. The modification date is updated to reflect the change\n4. The connection appears in the related content list\n\n### Bidirectional References\n\n- Calendar events can display all linked content\n- Content files maintain references to their associated events\n- Multiple pieces of content can be linked to a single event\n- Content can be linked to multiple events (stored as an array)\n\n## Field Mapping Integration\n\nThe ICS integration extends the field mapping system with two new fields:\n\n### ICS Event ID Field\n\n- Stores the unique identifier connecting content to calendar events\n- Default field name is `icsEventId`\n- Values are stored as arrays to support multiple event associations\n- Field name can be customized through field mapping settings\n\n### ICS Event Tag Field\n\n- Tag automatically applied to content created from events\n- Default tag is `ics_event`\n- Used to identify ICS-related content throughout the system\n- Can be customized through field mapping settings\n\n## Template Variables\n\nTemplates used for ICS content creation have access to event-specific variables in addition to standard TaskNotes variables:\n\n### Event Information\n\n- `{{icsEventTitle}}` - Event title\n- `{{icsEventStart}}` - Start date and time (ISO format)\n- `{{icsEventEnd}}` - End date and time (ISO format)\n- `{{icsEventLocation}}` - Event location\n- `{{icsEventDescription}}` - Event description\n- `{{icsEventUrl}}` - Event URL\n- `{{icsEventSubscription}}` - Calendar subscription name\n- `{{icsEventId}}` - Unique event identifier\n\n### Standard Variables\n\nAll standard TaskNotes template variables remain available:\n- `{{title}}`, `{{date}}`, `{{time}}`\n- `{{priority}}`, `{{status}}`, `{{contexts}}`\n- And others as documented in the template system\n\n## Configuration\n\nICS integration settings are located under `Settings -> TaskNotes -> Integrations`:\n\n### Default Templates\n\nConfigure template files for consistent content creation from events. Templates are optional and the system provides sensible defaults when not specified.\n\n### Default Folders\n\nSet destination folders for content created from events. This helps organize ICS-generated content separately from other vault content if desired.\n\nFolder paths support template variables for dynamic organization:\n\n- Date variables: `{{year}}`, `{{month}}`, `{{day}}`, `{{monthName}}`, etc.\n- ICS event variables: `{{icsEventTitle}}`, `{{icsEventLocation}}`, `{{icsEventDescription}}`\n- Other variables: See template variables section below\n\nExample folder paths:\n\n- `Daily/{{year}}/{{month}}/{{day}}` creates date-based hierarchy\n- `Events/{{year}}/{{icsEventTitle}}` organizes by year and event title\n- `Meetings/{{monthName}}` groups by month name\n\n### Filename Formats\n\nThe system uses the standard TaskNotes filename generation with event-specific context, ensuring unique and descriptive filenames for created content.\n\n## Technical Implementation\n\n### Event Identification\n\nCalendar events are identified by their unique ICS event ID, which is maintained in the frontmatter of created content. This allows the system to track relationships even if event details change.\n\n### Content Type Detection\n\nThe system distinguishes between tasks and notes by checking for the presence of the configured task tag in the content's frontmatter tags array, rather than relying on file structure or naming conventions.\n\n### Error Handling\n\nThe integration includes error boundaries for network issues, file operations, and template processing. Failed operations provide user feedback without interrupting the overall workflow.\n","aliases":["/features/ics-integration/"],"toc":[{"level":2,"id":"overview","text":"Overview"},{"level":2,"id":"event-information-modal","text":"Event Information Modal"},{"level":3,"id":"event-details","text":"Event Details"},{"level":3,"id":"related-content","text":"Related Content"},{"level":3,"id":"available-actions","text":"Available Actions"},{"level":2,"id":"note-creation-from-events","text":"Note Creation from Events"},{"level":3,"id":"basic-settings","text":"Basic Settings"},{"level":3,"id":"template-usage","text":"Template Usage"},{"level":3,"id":"default-content","text":"Default Content"},{"level":2,"id":"task-creation-from-events","text":"Task Creation from Events"},{"level":3,"id":"scheduled-date-and-time","text":"Scheduled Date and Time"},{"level":3,"id":"task-properties","text":"Task Properties"},{"level":3,"id":"content","text":"Content"},{"level":2,"id":"linking-existing-content","text":"Linking Existing Content"},{"level":3,"id":"link-process","text":"Link Process"},{"level":3,"id":"bidirectional-references","text":"Bidirectional References"},{"level":2,"id":"field-mapping-integration","text":"Field Mapping Integration"},{"level":3,"id":"ics-event-id-field","text":"ICS Event ID Field"},{"level":3,"id":"ics-event-tag-field","text":"ICS Event Tag Field"},{"level":2,"id":"template-variables","text":"Template Variables"},{"level":3,"id":"event-information","text":"Event Information"},{"level":3,"id":"standard-variables","text":"Standard Variables"},{"level":2,"id":"configuration","text":"Configuration"},{"level":3,"id":"default-templates","text":"Default Templates"},{"level":3,"id":"default-folders","text":"Default Folders"},{"level":3,"id":"filename-formats","text":"Filename Formats"},{"level":2,"id":"technical-implementation","text":"Technical Implementation"},{"level":3,"id":"event-identification","text":"Event Identification"},{"level":3,"id":"content-type-detection","text":"Content Type Detection"},{"level":3,"id":"error-handling","text":"Error Handling"}],"html":"

TaskNotes can use ICS calendar events to create notes and tasks directly from calendar entries.\nICS integration creates linked notes and tasks from event data without manual re-entry.

\n

Overview#

\n

The ICS integration allows you to:

\n
    \n
  • View detailed information about calendar events
  • \n
  • Create notes from calendar events with customizable templates
  • \n
  • Generate tasks from events with proper scheduling and context
  • \n
  • Link existing vault content to calendar events
  • \n
  • Maintain relationships between events and created content\nEvent context, notes, and follow-up tasks remain connected through frontmatter links.
  • \n
\n

Event Information Modal#

\n

When you interact with a calendar event in TaskNotes, an information modal displays event details and available actions. The modal provides:

\n

Event Details#

\n
    \n
  • Event title and description
  • \n
  • Start and end times (formatted according to your locale)
  • \n
  • Location information
  • \n
  • Source calendar name
  • \n
  • Event URL (if available)
  • \n
\n

Related Content#

\n

The modal shows a list of existing notes and tasks that are linked to the calendar event. Content is automatically categorized as:

\n
    \n
  • Task - Files containing the configured task tag
  • \n
  • Note - Files without the task tag
  • \n
\n

The relationship is maintained through the ICS Event ID field in the content's frontmatter.

\n

Available Actions#

\n

Create Note - Opens a creation dialog for generating a new note from the event data.

\n

Create Task - Creates a task immediately using the event information with default settings.

\n

Link Note - Opens a file selection dialog to link an existing note to the calendar event.

\n

Refresh - Reloads the list of related content to reflect recent changes.

\n

Note Creation from Events#

\n

The note creation process allows customization of the generated content:

\n

Basic Settings#

\n
    \n
  • Title - Default combines event title and date, but can be modified
  • \n
  • Folder - Destination for the new note (uses default ICS note folder if configured)
  • \n
  • Template - Optional template file to structure the note content
  • \n
\n

Template Usage#

\n

When a template is specified:

\n
    \n
  • The template file is processed with ICS-specific variables
  • \n
  • Standard TaskNotes template variables are also available
  • \n
  • Template content replaces the default event description format
  • \n
  • Frontmatter from templates is merged with required ICS fields\nTemplates apply a consistent note structure across imported events.
  • \n
\n

Default Content#

\n

Without a template, notes include:

\n
    \n
  • Event title as the main heading
  • \n
  • Formatted start and end times
  • \n
  • Location information
  • \n
  • Source calendar name
  • \n
  • Event description (if provided)
  • \n
  • Event URL (if available)
  • \n
\n

Task Creation from Events#

\n

Tasks created from calendar events include relevant event data:

\n

Scheduled Date and Time#

\n

Tasks are scheduled using the event's start time as an ISO timestamp, preserving both date and time information. This allows for accurate scheduling that reflects the original event timing.

\n

Task Properties#

\n
    \n
  • Title - Uses the event title
  • \n
  • Status - Set to the default task status configured in settings
  • \n
  • Priority - Set to the default task priority
  • \n
  • Contexts - Event location is added as a context (if provided)
  • \n
  • Time Estimate - Calculated from event duration (if start and end times are available)
  • \n
  • Tags - Includes the ICS event tag and any default task tags\nAfter creation, priority, status, and schedule can be edited if event data does not match the final task plan.
  • \n
\n

Content#

\n

Task content includes formatted event details similar to note creation, providing context about the original calendar event.

\n

Linking Existing Content#

\n

You can establish connections between existing vault content and calendar events:

\n\n
    \n
  1. Select an existing markdown file from your vault
  2. \n
  3. The file's frontmatter is updated to include the event ID
  4. \n
  5. The modification date is updated to reflect the change
  6. \n
  7. The connection appears in the related content list
  8. \n
\n

Bidirectional References#

\n
    \n
  • Calendar events can display all linked content
  • \n
  • Content files maintain references to their associated events
  • \n
  • Multiple pieces of content can be linked to a single event
  • \n
  • Content can be linked to multiple events (stored as an array)
  • \n
\n

Field Mapping Integration#

\n

The ICS integration extends the field mapping system with two new fields:

\n

ICS Event ID Field#

\n
    \n
  • Stores the unique identifier connecting content to calendar events
  • \n
  • Default field name is icsEventId
  • \n
  • Values are stored as arrays to support multiple event associations
  • \n
  • Field name can be customized through field mapping settings
  • \n
\n

ICS Event Tag Field#

\n
    \n
  • Tag automatically applied to content created from events
  • \n
  • Default tag is ics_event
  • \n
  • Used to identify ICS-related content throughout the system
  • \n
  • Can be customized through field mapping settings
  • \n
\n

Template Variables#

\n

Templates used for ICS content creation have access to event-specific variables in addition to standard TaskNotes variables:

\n

Event Information#

\n
    \n
  • {{icsEventTitle}} - Event title
  • \n
  • {{icsEventStart}} - Start date and time (ISO format)
  • \n
  • {{icsEventEnd}} - End date and time (ISO format)
  • \n
  • {{icsEventLocation}} - Event location
  • \n
  • {{icsEventDescription}} - Event description
  • \n
  • {{icsEventUrl}} - Event URL
  • \n
  • {{icsEventSubscription}} - Calendar subscription name
  • \n
  • {{icsEventId}} - Unique event identifier
  • \n
\n

Standard Variables#

\n

All standard TaskNotes template variables remain available:

\n
    \n
  • {{title}}, {{date}}, {{time}}
  • \n
  • {{priority}}, {{status}}, {{contexts}}
  • \n
  • And others as documented in the template system
  • \n
\n

Configuration#

\n

ICS integration settings are located under Settings -> TaskNotes -> Integrations:

\n

Default Templates#

\n

Configure template files for consistent content creation from events. Templates are optional and the system provides sensible defaults when not specified.

\n

Default Folders#

\n

Set destination folders for content created from events. This helps organize ICS-generated content separately from other vault content if desired.

\n

Folder paths support template variables for dynamic organization:

\n
    \n
  • Date variables: {{year}}, {{month}}, {{day}}, {{monthName}}, etc.
  • \n
  • ICS event variables: {{icsEventTitle}}, {{icsEventLocation}}, {{icsEventDescription}}
  • \n
  • Other variables: See template variables section below
  • \n
\n

Example folder paths:

\n
    \n
  • Daily/{{year}}/{{month}}/{{day}} creates date-based hierarchy
  • \n
  • Events/{{year}}/{{icsEventTitle}} organizes by year and event title
  • \n
  • Meetings/{{monthName}} groups by month name
  • \n
\n

Filename Formats#

\n

The system uses the standard TaskNotes filename generation with event-specific context, ensuring unique and descriptive filenames for created content.

\n

Technical Implementation#

\n

Event Identification#

\n

Calendar events are identified by their unique ICS event ID, which is maintained in the frontmatter of created content. This allows the system to track relationships even if event details change.

\n

Content Type Detection#

\n

The system distinguishes between tasks and notes by checking for the presence of the configured task tag in the content's frontmatter tags array, rather than relying on file structure or naming conventions.

\n

Error Handling#

\n

The integration includes error boundaries for network issues, file operations, and template processing. Failed operations provide user feedback without interrupting the overall workflow.

\n","text":"TaskNotes can use ICS calendar events to create notes and tasks directly from calendar entries. ICS integration creates linked notes and tasks from event data without manual re-entry. Overview# The ICS integration allows you to: View detailed information about calendar events Create notes from calendar events with customizable templates Generate tasks from events with proper scheduling and context Link existing vault content to calendar events Maintain relationships between events and created content Event context, notes, and follow-up tasks remain connected through frontmatter links. Event Information Modal# When you interact with a calendar event in TaskNotes, an information modal displays event details and available actions. The modal provides: Event Details# Event title and description Start and end times (formatted according to your locale) Location information Source calendar name Event URL (if available) Related Content# The modal shows a list of existing notes and tasks that are linked to the calendar event. Content is automatically categorized as: Task - Files containing the configured task tag Note - Files without the task tag The relationship is maintained through the ICS Event ID field in the content's frontmatter. Available Actions# Create Note - Opens a creation dialog for generating a new note from the event data. Create Task - Creates a task immediately using the event information with default settings. Link Note - Opens a file selection dialog to link an existing note to the calendar event. Refresh - Reloads the list of related content to reflect recent changes. Note Creation from Events# The note creation process allows customization of the generated content: Basic Settings# Title - Default combines event title and date, but can be modified Folder - Destination for the new note (uses default ICS note folder if configured) Template - Optional template file to structure the note content Template Usage# When a template is specified: The template file is processed with ICS-specific variables Standard TaskNotes template variables are also available Template content replaces the default event description format Frontmatter from templates is merged with required ICS fields Templates apply a consistent note structure across imported events. Default Content# Without a template, notes include: Event title as the main heading Formatted start and end times Location information Source calendar name Event description (if provided) Event URL (if available) Task Creation from Events# Tasks created from calendar events include relevant event data: Scheduled Date and Time# Tasks are scheduled using the event's start time as an ISO timestamp, preserving both date and time information. This allows for accurate scheduling that reflects the original event timing. Task Properties# Title - Uses the event title Status - Set to the default task status configured in settings Priority - Set to the default task priority Contexts - Event location is added as a context (if provided) Time Estimate - Calculated from event duration (if start and end times are available) Tags - Includes the ICS event tag and any default task tags After creation, priority, status, and schedule can be edited if event data does not match the final task plan. Content# Task content includes formatted event details similar to note creation, providing context about the original calendar event. Linking Existing Content# You can establish connections between existing vault content and calendar events: Link Process# Select an existing markdown file from your vault The file's frontmatter is updated to include the event ID The modification date is updated to reflect the change The connection appears in the related content list Bidirectional References# Calendar events can display all linked content Content files maintain references to their associated events Multiple pieces of content can be linked to a single event Content can be linked to multiple events (stored as an array) Field Mapping Integration# The ICS integration extends the field mapping system with two new fields: ICS Event ID Field# Stores the unique identifier connecting content to calendar events Default field name is icsEventId Values are stored as arrays to support multiple event associations Field name can be customized through field mapping settings ICS Event Tag Field# Tag automatically applied to content created from events Default tag is ics_event Used to identify ICS-related content throughout the system Can be customized through field mapping settings Template Variables# Templates used for ICS content creation have access to event-specific variables in addition to standard TaskNotes variables: Event Information# {{icsEventTitle}} - Event title {{icsEventStart}} - Start date and time (ISO format) {{icsEventEnd}} - End date and time (ISO format) {{icsEventLocation}} - Event location {{icsEventDescription}} - Event description {{icsEventUrl}} - Event URL {{icsEventSubscription}} - Calendar subscription name {{icsEventId}} - Unique event identifier Standard Variables# All standard TaskNotes template variables remain available: {{title}}, {{date}}, {{time}} {{priority}}, {{status}}, {{contexts}} And others as documented in the template system Configuration# ICS integration settings are located under Settings -> TaskNotes -> Integrations: Default Templates# Configure template files for consistent content creation from events. Templates are optional and the system provides sensible defaults when not specified. Default Folders# Set destination folders for content created from events. This helps organize ICS-generated content separately from other vault content if desired. Folder paths support template variables for dynamic organization: Date variables: {{year}}, {{month}}, {{day}}, {{monthName}}, etc. ICS event variables: {{icsEventTitle}}, {{icsEventLocation}}, {{icsEventDescription}} Other variables: See template variables section below Example folder paths: Daily/{{year}}/{{month}}/{{day}} creates date-based hierarchy Events/{{year}}/{{icsEventTitle}} organizes by year and event title Meetings/{{monthName}} groups by month name Filename Formats# The system uses the standard TaskNotes filename generation with event-specific context, ensuring unique and descriptive filenames for created content. Technical Implementation# Event Identification# Calendar events are identified by their unique ICS event ID, which is maintained in the frontmatter of created content. This allows the system to track relationships even if event details change. Content Type Detection# The system distinguishes between tasks and notes by checking for the presence of the configured task tag in the content's frontmatter tags array, rather than relying on file structure or naming conventions. Error Handling# The integration includes error boundaries for network issues, file operations, and template processing. Failed operations provide user feedback without interrupting the overall workflow."},{"route":"/obsidian/features/inline-tasks/","title":"Inline Task Integration","description":"TaskNotes integrates with the Obsidian editor to allow task management directly within notes. This is achieved through interactive widgets, a conversion feature for checkboxes,...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/features/inline-tasks.md","namespace":"obsidian","relativePath":"features/inline-tasks.md","raw":"# Inline Task Integration\n\n\nTaskNotes integrates with the Obsidian editor to allow task management directly within notes. This is achieved through interactive widgets, a conversion feature for checkboxes, and natural language processing.\nInline features support capture and task updates without leaving the current note.\n\n## Task Link Overlays\n\nWhen a wikilink to a task note is created, TaskNotes can replace it with an interactive **Task Link Overlay**. Enable or disable overlays from `Settings -> TaskNotes -> Features` (`Task link overlay`). The widget displays information about the task, such as status, priority, and due date, and allows actions like status/priority changes or opening the edit modal.\n\n![Task Link Overlays in Live Preview mode](../assets/2025-07-17_21-03-55.png)\n\n*Task link overlays in Live Preview mode show interactive widgets with status, dates, and quick actions*\n\n![Task Link Overlays in Source mode](../assets/2025-07-17_21-04-24.png)\n\n*In Source mode, task links appear as standard wikilinks until rendered*\n\n### Widget Features\n\nThe task link overlay displays:\n\n- **Status Dot**: Clickable circular indicator showing current task status. Click to cycle through available statuses.\n- **Priority Dot**: Color-coded indicator for task priority (only shown when assigned).\n- **Task Title**: Displays the task name (truncated to 80 characters). Click to open the task edit modal.\n- **Date Information**: Shows due dates (calendar icon) and scheduled dates (clock icon) with clickable context menus.\n- **Recurrence Indicator**: Rotating arrow icon for recurring tasks with modification options.\n- **Action Menu**: Ellipsis icon (shown on hover) provides additional task actions.\nThe widget exposes common task actions at the link location, so status and metadata can be updated in-place.\n\n### Mode-Specific Behavior\n\nTask link overlays work in both Live Preview and Reading modes:\n\n- **Live Preview Mode**: Widgets hide when the cursor is within the wikilink range, allowing for easy editing.\n- **Reading Mode**: Widgets display with full functionality and integrate with the reading mode typography.\n\nThe overlays support drag-and-drop to calendar views and provide keyboard shortcuts for quick navigation (Ctrl/Cmd+Click to open the source file).\n\n## Create New Inline Task Command\n\nThe `Create new inline task` command opens the task creation modal from the editor and inserts a link to the new task when it is saved. This command is available in the command palette.\n\nWhen the cursor is on an empty line, the link is inserted at the cursor. When the cursor is on a line with content, TaskNotes inserts a new line below it and places the task link there. The command does not use the current line as the task title.\n\nTo turn the current line into a TaskNote, use `Convert to TaskNote` or the instant conversion button next to a supported line. That flow uses the current line as the task title and replaces the original line with a link to the new task file.\n\n## Instant Task Conversion\n\nThe **Instant Task Conversion** feature transforms lines in your notes into TaskNotes files. This works with both checkbox tasks and regular lines of text. Turn the feature on or off from `Settings -> TaskNotes -> Features` (`Show convert button next to checkboxes`). When enabled, a \"convert\" button appears next to content in edit mode. Clicking this button creates a new task note using the line text as the title and replaces the original line with a link to the new task file.\nThis supports progressive conversion from draft notes to dedicated task files.\n\n### Folder Configuration\n\nBy default, converted tasks are placed in the same folder as the current note (`{{currentNotePath}}`). You can change this behavior in `Settings -> TaskNotes -> General` (`Folder for converted tasks`):\n\n- **Leave empty**: Uses your default tasks folder (configured in the same section)\n- **`{{currentNotePath}}`**: Places tasks in the same folder as the note you're editing (default)\n- **`{{currentNoteTitle}}`**: Creates a subfolder named after the current note\n- **Custom path**: Specify any folder path (e.g., `TaskNotes/Converted`)\n\n### Supported Line Types\n\nThe conversion feature works with:\n\n- **Checkbox tasks**: `- [ ] Task description` becomes a TaskNote with task metadata\n- **Bullet points**: `- Some task idea` becomes a TaskNote with the text as title\n- **Numbered lists**: `1. Important item` becomes a TaskNote\n- **Blockquoted content**: `> Task in callout` becomes a TaskNote (preserves blockquote formatting)\n- **Plain text lines**: `Important thing to do` becomes a TaskNote\n- **Mixed formats**: `> - [ ] Task in blockquote` handles both blockquote and checkbox formatting\n\n### Content Processing\n\nWhen converting lines:\n\n- **Special characters** like `>`, `#`, `-` are automatically removed from the task title\n- **Original formatting** is preserved in the note (e.g., `> [[Task Title]]` for blockquoted content)\n- **Task metadata** is extracted from checkbox tasks (due dates, priorities, etc.)\n- **Natural language processing** can extract dates and metadata from plain text (if enabled)\nConversion preserves surrounding formatting, including callouts, outlines, and nested lists.\n\nThe feature handles edge cases like nested blockquotes and maintains proper indentation in the final link replacement.\n\n## Bulk Task Conversion\n\nThe **Bulk Task Conversion** command converts all checkbox tasks in the current note to TaskNotes in a single operation. This command is available in the command palette as \"Convert all tasks in note to TaskNotes\".\n\n### How It Works\n\nThe command:\n\n1. Scans the entire current note for checkbox tasks (`- [ ]`, `* [ ]`, `1. [ ]`, etc.)\n2. Includes tasks inside blockquotes (e.g., `> - [ ] task in callout`)\n3. Applies the same enhanced conversion logic as instant task conversion\n4. Creates individual TaskNote files for each task\n5. Replaces the original checkboxes with links to the new task files\n6. Preserves original indentation and formatting (including blockquote markers)\n\nThe bulk conversion uses the same content processing as instant conversion, automatically removing special characters from task titles while preserving original formatting in the note.\n\n### Usage\n\nTo use bulk conversion:\n\n1. Open a note containing checkbox tasks\n2. Access the command palette (`Ctrl+P` / `Cmd+P`)\n3. Search for \"Convert all tasks in note to TaskNotes\"\n4. Execute the command\n\nThe command displays progress and shows a summary when complete (for example, \"Successfully converted 5 tasks to TaskNotes.\").\n\n!!! warning \"Important Considerations\"\n\n **This command modifies note content permanently.** Before using:\n\n - **Create a backup** of your note if it contains important data\n - **Review the tasks** to ensure they should become individual TaskNotes\n - **Expect processing time** - notes with many tasks may take several seconds to process\n - **Avoid interruption** - do not edit the note while conversion is running\n\n!!! note \"Performance\"\n\n Processing time depends on the number of tasks:\n\n - Small notes (1-10 tasks): Near-instant\n - Medium notes (10-50 tasks): 2-5 seconds\n - Large notes (50+ tasks): 10+ seconds\n\n The operation creates multiple files and updates the note content, which requires disk I/O and editor updates.\n\n### Error Handling\n\nIf some tasks fail to convert, the command will:\n\n- Complete successfully converted tasks\n- Display a summary showing both successes and failures\n- Log detailed error information to the console for troubleshooting\n\nFailed conversions typically occur due to:\n\n- Tasks with titles containing invalid filename characters\n- Insufficient disk permissions\n- Very long task titles (over 200 characters)\nFor large notes, converting a small section first helps validate folder and filename settings.\n\n## Relationships Widget\n\n**New in v4**: The Relationships Widget consolidates what were previously three separate widgets (project subtasks, task dependencies, and blocking tasks) into a single dynamic interface.\n\nThe widget appears in task notes and automatically displays up to five tabs based on available relationship data:\n\n- **Subtasks Tab (Kanban)**: Shows tasks that reference the current note as a project. Uses Kanban layout for visual task management.\n- **Occurrences Tab (List)**: Shows materialized occurrence notes that reference the current recurring task as their parent. Uses list layout sorted by occurrence date.\n- **Projects Tab (List)**: Shows projects that the current task belongs to. Uses list layout.\n- **Blocked By Tab (List)**: Shows tasks that are blocking the current task. Uses list layout.\n- **Blocking Tab (Kanban)**: Shows tasks that the current task is blocking. Uses Kanban layout.\n\n### Automatic Tab Management\n\nTabs automatically show or hide based on the presence of relationship data. If a task has no subtasks, the Subtasks tab does not appear. If a recurring task has no materialized occurrence notes, the Occurrences tab does not appear. If there are no blocking relationships, those tabs remain hidden. This keeps the interface focused on relevant information.\nThe widget layout changes with available data, so simple tasks show fewer sections.\n\n### Features\n\nThe widget embeds the `TaskNotes/Views/relationships.base` view directly in the editor. Every filter, grouping rule, or property shown in that `.base` file is exactly what appears inside the widget, so you can customize the experience by editing the file just like any other Bases view.\n\nAdditional behavior:\n\n- **Collapsible Interface**: Click the widget title to expand or collapse. The state is remembered between sessions.\n- **Persistent Grouping**: Any grouping defined in the `.base` file is honoured, and collapsed groups retain their state per note.\n- **Task Details**: Each task shows its status, priority, due date, and other configured properties.\n- **Real-time Updates**: The widget updates automatically when tasks are added, modified, or deleted via Bases views.\n\n### Configuration\n\nEnable or disable the widget in `Settings -> TaskNotes -> Appearance` (`Show relationships widget`).\n\nPosition the widget at the top (after frontmatter) or bottom of the note using the **Relationships Position** setting.\n\n### Expandable Subtasks Chevron\n\nTasks with subtasks can display an expand/collapse chevron that toggles subtask visibility.\n\n- The chevron can be positioned on the Right (default, hover to show) or on the Left (always visible, matches group chevrons).\n- Configure this in `Settings -> TaskNotes -> Appearance` (`Subtask chevron position`).\n\n![Left subtask chevron](../assets/left-task-subtask-chevron.gif)\n\n### Migration from v3\n\nIn v3, TaskNotes provided three separate widgets controlled by individual settings:\n\n- `showProjectSubtasks` and `projectSubtasksPosition`\n- `showTaskDependencies` and `taskDependenciesPosition`\n- `showBlockingTasks` and `blockingTasksPosition`\n\nThese settings are replaced in v4 by:\n\n- `showRelationships` and `relationshipsPosition`\n\nIf you had project subtasks enabled in v3, the relationships widget is enabled automatically after upgrading to v4. The underlying Bases file changed from `TaskNotes/Views/project-subtasks.base` to `TaskNotes/Views/relationships.base`. Run the **Create files** action in `Settings -> TaskNotes -> General -> Views & base files` if `relationships.base` is missing.\n\n## Natural Language Processing\n\nTaskNotes includes a **Natural Language Processor (NLP)** that parses task descriptions to extract structured data. This allows for task creation from conversational language, such as \"Prepare quarterly report due Friday #work high priority,\" which would automatically set the due date, tag, and priority.\n\nThe NLP engine supports multiple languages, including English, Spanish, French, German, Italian, Japanese, Dutch, Portuguese, Russian, Swedish, Chinese, and Ukrainian.\n\n### Supported Syntax\n\nThe NLP engine recognizes:\n\n- **Tags and Contexts**: `#tag` and `@context` syntax (triggers are customizable).\n- **Projects**: `+project` for simple projects or `+[[Project Name]]` for projects with spaces.\n- **Priority Levels**: Keywords like \"high,\" \"normal,\" and \"low\". Also supports a trigger character (default: `!`).\n- **Status Assignment**: Keywords like \"open,\" \"in-progress,\" and \"done\". Also supports a trigger character (default: `*`).\n- **Dates and Times**: Phrases like \"tomorrow,\" \"next Friday,\" and \"January 15th at 3pm\".\n- **Time Estimates**: Formats like \"2h,\" \"30min,\" and \"1h30m\".\n- **Recurrence Patterns**: Phrases like \"daily,\" \"weekly,\" and \"every Monday\".\n- **User-Defined Fields**: Custom fields can be assigned using configured triggers (e.g., `effort: high`). Supports quoted values for multi-word entries.\nNLP parses common patterns during capture; fields can be refined in the modal afterward.\n\n### Rich Markdown Editor\n\n**New in v4**: The task creation modal uses a rich CodeMirror markdown editor instead of a plain textarea.\n\nFeatures include:\n\n- **Live Preview**: Rendered markdown preview as you type.\n- **Syntax Highlighting**: Code blocks, links, and formatting are highlighted.\n- **Wikilink Support**: Create links to other notes using `[[Note Name]]` syntax.\n- **Keyboard Shortcuts**:\n - `Ctrl/Cmd+Enter` saves the task\n - `Esc` or `Tab` to navigate out of the editor\n- **Placeholder Text**: Shows an example task (e.g., \"Buy groceries tomorrow at 3pm @home #errands\") when the editor is empty.\n\n### Customizable Triggers\n\n**New in v4**: Triggers for NLP properties can be customized in `Settings -> TaskNotes -> Features` (`NLP Triggers`).\n\nYou can configure trigger characters or strings for:\n\n- **Tags** (default: `#`) - When set to `#`, Obsidian's native tag suggester is used\n- **Contexts** (default: `@`)\n- **Projects** (default: `+`)\n- **Status** (default: `*`)\n- **Priority** (default: `!`, disabled by default)\n- **User-Defined Fields** (default: `fieldname:`) - Each custom field can have its own trigger\n\nTriggers support up to 10 characters and can include trailing spaces (e.g., `\"def: \"` for a custom field).\n\n### Autocomplete\n\n**New in v4**: When typing a trigger in the NLP editor, an autocomplete menu appears with available values.\n\n- Navigate suggestions with arrow keys\n- Select with `Enter` or `Tab`\n- Autocomplete works for tags, contexts, projects, status, priority, and user-defined fields\n- Tag autocomplete uses Obsidian's native tag suggester when using the `#` trigger\n- For user fields with multi-word values, wrap the value in quotes (e.g., `effort: \"very high\"`)\n\nThe NLP engine is integrated with the task creation modal and bulk conversion features. Typing a natural language description populates the corresponding task fields automatically.\n","aliases":["/features/inline-tasks/"],"toc":[{"level":2,"id":"task-link-overlays","text":"Task Link Overlays"},{"level":3,"id":"widget-features","text":"Widget Features"},{"level":3,"id":"mode-specific-behavior","text":"Mode-Specific Behavior"},{"level":2,"id":"create-new-inline-task-command","text":"Create New Inline Task Command"},{"level":2,"id":"instant-task-conversion","text":"Instant Task Conversion"},{"level":3,"id":"folder-configuration","text":"Folder Configuration"},{"level":3,"id":"supported-line-types","text":"Supported Line Types"},{"level":3,"id":"content-processing","text":"Content Processing"},{"level":2,"id":"bulk-task-conversion","text":"Bulk Task Conversion"},{"level":3,"id":"how-it-works","text":"How It Works"},{"level":3,"id":"usage","text":"Usage"},{"level":3,"id":"error-handling","text":"Error Handling"},{"level":2,"id":"relationships-widget","text":"Relationships Widget"},{"level":3,"id":"automatic-tab-management","text":"Automatic Tab Management"},{"level":3,"id":"features","text":"Features"},{"level":3,"id":"configuration","text":"Configuration"},{"level":3,"id":"expandable-subtasks-chevron","text":"Expandable Subtasks Chevron"},{"level":3,"id":"migration-from-v3","text":"Migration from v3"},{"level":2,"id":"natural-language-processing","text":"Natural Language Processing"},{"level":3,"id":"supported-syntax","text":"Supported Syntax"},{"level":3,"id":"rich-markdown-editor","text":"Rich Markdown Editor"},{"level":3,"id":"customizable-triggers","text":"Customizable Triggers"},{"level":3,"id":"autocomplete","text":"Autocomplete"}],"html":"

TaskNotes integrates with the Obsidian editor to allow task management directly within notes. This is achieved through interactive widgets, a conversion feature for checkboxes, and natural language processing.\nInline features support capture and task updates without leaving the current note.

\n\n

When a wikilink to a task note is created, TaskNotes can replace it with an interactive Task Link Overlay. Enable or disable overlays from Settings -> TaskNotes -> Features (Task link overlay). The widget displays information about the task, such as status, priority, and due date, and allows actions like status/priority changes or opening the edit modal.

\n

\"Task

\n

Task link overlays in Live Preview mode show interactive widgets with status, dates, and quick actions

\n

\"Task

\n

In Source mode, task links appear as standard wikilinks until rendered

\n

Widget Features#

\n

The task link overlay displays:

\n
    \n
  • Status Dot: Clickable circular indicator showing current task status. Click to cycle through available statuses.
  • \n
  • Priority Dot: Color-coded indicator for task priority (only shown when assigned).
  • \n
  • Task Title: Displays the task name (truncated to 80 characters). Click to open the task edit modal.
  • \n
  • Date Information: Shows due dates (calendar icon) and scheduled dates (clock icon) with clickable context menus.
  • \n
  • Recurrence Indicator: Rotating arrow icon for recurring tasks with modification options.
  • \n
  • Action Menu: Ellipsis icon (shown on hover) provides additional task actions.\nThe widget exposes common task actions at the link location, so status and metadata can be updated in-place.
  • \n
\n

Mode-Specific Behavior#

\n

Task link overlays work in both Live Preview and Reading modes:

\n
    \n
  • Live Preview Mode: Widgets hide when the cursor is within the wikilink range, allowing for easy editing.
  • \n
  • Reading Mode: Widgets display with full functionality and integrate with the reading mode typography.
  • \n
\n

The overlays support drag-and-drop to calendar views and provide keyboard shortcuts for quick navigation (Ctrl/Cmd+Click to open the source file).

\n

Create New Inline Task Command#

\n

The Create new inline task command opens the task creation modal from the editor and inserts a link to the new task when it is saved. This command is available in the command palette.

\n

When the cursor is on an empty line, the link is inserted at the cursor. When the cursor is on a line with content, TaskNotes inserts a new line below it and places the task link there. The command does not use the current line as the task title.

\n

To turn the current line into a TaskNote, use Convert to TaskNote or the instant conversion button next to a supported line. That flow uses the current line as the task title and replaces the original line with a link to the new task file.

\n

Instant Task Conversion#

\n

The Instant Task Conversion feature transforms lines in your notes into TaskNotes files. This works with both checkbox tasks and regular lines of text. Turn the feature on or off from Settings -> TaskNotes -> Features (Show convert button next to checkboxes). When enabled, a "convert" button appears next to content in edit mode. Clicking this button creates a new task note using the line text as the title and replaces the original line with a link to the new task file.\nThis supports progressive conversion from draft notes to dedicated task files.

\n

Folder Configuration#

\n

By default, converted tasks are placed in the same folder as the current note ({{currentNotePath}}). You can change this behavior in Settings -> TaskNotes -> General (Folder for converted tasks):

\n
    \n
  • Leave empty: Uses your default tasks folder (configured in the same section)
  • \n
  • {{currentNotePath}}: Places tasks in the same folder as the note you're editing (default)
  • \n
  • {{currentNoteTitle}}: Creates a subfolder named after the current note
  • \n
  • Custom path: Specify any folder path (e.g., TaskNotes/Converted)
  • \n
\n

Supported Line Types#

\n

The conversion feature works with:

\n
    \n
  • Checkbox tasks: - [ ] Task description becomes a TaskNote with task metadata
  • \n
  • Bullet points: - Some task idea becomes a TaskNote with the text as title
  • \n
  • Numbered lists: 1. Important item becomes a TaskNote
  • \n
  • Blockquoted content: > Task in callout becomes a TaskNote (preserves blockquote formatting)
  • \n
  • Plain text lines: Important thing to do becomes a TaskNote
  • \n
  • Mixed formats: > - [ ] Task in blockquote handles both blockquote and checkbox formatting
  • \n
\n

Content Processing#

\n

When converting lines:

\n
    \n
  • Special characters like >, #, - are automatically removed from the task title
  • \n
  • Original formatting is preserved in the note (e.g., > [[Task Title]] for blockquoted content)
  • \n
  • Task metadata is extracted from checkbox tasks (due dates, priorities, etc.)
  • \n
  • Natural language processing can extract dates and metadata from plain text (if enabled)\nConversion preserves surrounding formatting, including callouts, outlines, and nested lists.
  • \n
\n

The feature handles edge cases like nested blockquotes and maintains proper indentation in the final link replacement.

\n

Bulk Task Conversion#

\n

The Bulk Task Conversion command converts all checkbox tasks in the current note to TaskNotes in a single operation. This command is available in the command palette as "Convert all tasks in note to TaskNotes".

\n

How It Works#

\n

The command:

\n
    \n
  1. Scans the entire current note for checkbox tasks (- [ ], * [ ], 1. [ ], etc.)
  2. \n
  3. Includes tasks inside blockquotes (e.g., > - [ ] task in callout)
  4. \n
  5. Applies the same enhanced conversion logic as instant task conversion
  6. \n
  7. Creates individual TaskNote files for each task
  8. \n
  9. Replaces the original checkboxes with links to the new task files
  10. \n
  11. Preserves original indentation and formatting (including blockquote markers)
  12. \n
\n

The bulk conversion uses the same content processing as instant conversion, automatically removing special characters from task titles while preserving original formatting in the note.

\n

Usage#

\n

To use bulk conversion:

\n
    \n
  1. Open a note containing checkbox tasks
  2. \n
  3. Access the command palette (Ctrl+P / Cmd+P)
  4. \n
  5. Search for "Convert all tasks in note to TaskNotes"
  6. \n
  7. Execute the command
  8. \n
\n

The command displays progress and shows a summary when complete (for example, "Successfully converted 5 tasks to TaskNotes.").

\n\n
**This command modifies note content permanently.** Before using:\n\n- **Create a backup** of your note if it contains important data\n- **Review the tasks** to ensure they should become individual TaskNotes\n- **Expect processing time** - notes with many tasks may take several seconds to process\n- **Avoid interruption** - do not edit the note while conversion is running\n
\n
Processing time depends on the number of tasks:\n\n- Small notes (1-10 tasks): Near-instant\n- Medium notes (10-50 tasks): 2-5 seconds\n- Large notes (50+ tasks): 10+ seconds\n\nThe operation creates multiple files and updates the note content, which requires disk I/O and editor updates.\n

Error Handling#

\n

If some tasks fail to convert, the command will:

\n
    \n
  • Complete successfully converted tasks
  • \n
  • Display a summary showing both successes and failures
  • \n
  • Log detailed error information to the console for troubleshooting
  • \n
\n

Failed conversions typically occur due to:

\n
    \n
  • Tasks with titles containing invalid filename characters
  • \n
  • Insufficient disk permissions
  • \n
  • Very long task titles (over 200 characters)\nFor large notes, converting a small section first helps validate folder and filename settings.
  • \n
\n

Relationships Widget#

\n

New in v4: The Relationships Widget consolidates what were previously three separate widgets (project subtasks, task dependencies, and blocking tasks) into a single dynamic interface.

\n

The widget appears in task notes and automatically displays up to five tabs based on available relationship data:

\n
    \n
  • Subtasks Tab (Kanban): Shows tasks that reference the current note as a project. Uses Kanban layout for visual task management.
  • \n
  • Occurrences Tab (List): Shows materialized occurrence notes that reference the current recurring task as their parent. Uses list layout sorted by occurrence date.
  • \n
  • Projects Tab (List): Shows projects that the current task belongs to. Uses list layout.
  • \n
  • Blocked By Tab (List): Shows tasks that are blocking the current task. Uses list layout.
  • \n
  • Blocking Tab (Kanban): Shows tasks that the current task is blocking. Uses Kanban layout.
  • \n
\n

Automatic Tab Management#

\n

Tabs automatically show or hide based on the presence of relationship data. If a task has no subtasks, the Subtasks tab does not appear. If a recurring task has no materialized occurrence notes, the Occurrences tab does not appear. If there are no blocking relationships, those tabs remain hidden. This keeps the interface focused on relevant information.\nThe widget layout changes with available data, so simple tasks show fewer sections.

\n

Features#

\n

The widget embeds the TaskNotes/Views/relationships.base view directly in the editor. Every filter, grouping rule, or property shown in that .base file is exactly what appears inside the widget, so you can customize the experience by editing the file just like any other Bases view.

\n

Additional behavior:

\n
    \n
  • Collapsible Interface: Click the widget title to expand or collapse. The state is remembered between sessions.
  • \n
  • Persistent Grouping: Any grouping defined in the .base file is honoured, and collapsed groups retain their state per note.
  • \n
  • Task Details: Each task shows its status, priority, due date, and other configured properties.
  • \n
  • Real-time Updates: The widget updates automatically when tasks are added, modified, or deleted via Bases views.
  • \n
\n

Configuration#

\n

Enable or disable the widget in Settings -> TaskNotes -> Appearance (Show relationships widget).

\n

Position the widget at the top (after frontmatter) or bottom of the note using the Relationships Position setting.

\n

Expandable Subtasks Chevron#

\n

Tasks with subtasks can display an expand/collapse chevron that toggles subtask visibility.

\n
    \n
  • The chevron can be positioned on the Right (default, hover to show) or on the Left (always visible, matches group chevrons).
  • \n
  • Configure this in Settings -> TaskNotes -> Appearance (Subtask chevron position).
  • \n
\n

\"Left

\n

Migration from v3#

\n

In v3, TaskNotes provided three separate widgets controlled by individual settings:

\n
    \n
  • showProjectSubtasks and projectSubtasksPosition
  • \n
  • showTaskDependencies and taskDependenciesPosition
  • \n
  • showBlockingTasks and blockingTasksPosition
  • \n
\n

These settings are replaced in v4 by:

\n
    \n
  • showRelationships and relationshipsPosition
  • \n
\n

If you had project subtasks enabled in v3, the relationships widget is enabled automatically after upgrading to v4. The underlying Bases file changed from TaskNotes/Views/project-subtasks.base to TaskNotes/Views/relationships.base. Run the Create files action in Settings -> TaskNotes -> General -> Views & base files if relationships.base is missing.

\n

Natural Language Processing#

\n

TaskNotes includes a Natural Language Processor (NLP) that parses task descriptions to extract structured data. This allows for task creation from conversational language, such as "Prepare quarterly report due Friday #work high priority," which would automatically set the due date, tag, and priority.

\n

The NLP engine supports multiple languages, including English, Spanish, French, German, Italian, Japanese, Dutch, Portuguese, Russian, Swedish, Chinese, and Ukrainian.

\n

Supported Syntax#

\n

The NLP engine recognizes:

\n
    \n
  • Tags and Contexts: #tag and @context syntax (triggers are customizable).
  • \n
  • Projects: +project for simple projects or +[[Project Name]] for projects with spaces.
  • \n
  • Priority Levels: Keywords like "high," "normal," and "low". Also supports a trigger character (default: !).
  • \n
  • Status Assignment: Keywords like "open," "in-progress," and "done". Also supports a trigger character (default: *).
  • \n
  • Dates and Times: Phrases like "tomorrow," "next Friday," and "January 15th at 3pm".
  • \n
  • Time Estimates: Formats like "2h," "30min," and "1h30m".
  • \n
  • Recurrence Patterns: Phrases like "daily," "weekly," and "every Monday".
  • \n
  • User-Defined Fields: Custom fields can be assigned using configured triggers (e.g., effort: high). Supports quoted values for multi-word entries.\nNLP parses common patterns during capture; fields can be refined in the modal afterward.
  • \n
\n

Rich Markdown Editor#

\n

New in v4: The task creation modal uses a rich CodeMirror markdown editor instead of a plain textarea.

\n

Features include:

\n
    \n
  • Live Preview: Rendered markdown preview as you type.
  • \n
  • Syntax Highlighting: Code blocks, links, and formatting are highlighted.
  • \n
  • Wikilink Support: Create links to other notes using [[Note Name]] syntax.
  • \n
  • Keyboard Shortcuts:
      \n
    • Ctrl/Cmd+Enter saves the task
    • \n
    • Esc or Tab to navigate out of the editor
    • \n
    \n
  • \n
  • Placeholder Text: Shows an example task (e.g., "Buy groceries tomorrow at 3pm @home #errands") when the editor is empty.
  • \n
\n

Customizable Triggers#

\n

New in v4: Triggers for NLP properties can be customized in Settings -> TaskNotes -> Features (NLP Triggers).

\n

You can configure trigger characters or strings for:

\n
    \n
  • Tags (default: #) - When set to #, Obsidian's native tag suggester is used
  • \n
  • Contexts (default: @)
  • \n
  • Projects (default: +)
  • \n
  • Status (default: *)
  • \n
  • Priority (default: !, disabled by default)
  • \n
  • User-Defined Fields (default: fieldname:) - Each custom field can have its own trigger
  • \n
\n

Triggers support up to 10 characters and can include trailing spaces (e.g., "def: " for a custom field).

\n

Autocomplete#

\n

New in v4: When typing a trigger in the NLP editor, an autocomplete menu appears with available values.

\n
    \n
  • Navigate suggestions with arrow keys
  • \n
  • Select with Enter or Tab
  • \n
  • Autocomplete works for tags, contexts, projects, status, priority, and user-defined fields
  • \n
  • Tag autocomplete uses Obsidian's native tag suggester when using the # trigger
  • \n
  • For user fields with multi-word values, wrap the value in quotes (e.g., effort: "very high")
  • \n
\n

The NLP engine is integrated with the task creation modal and bulk conversion features. Typing a natural language description populates the corresponding task fields automatically.

\n","text":"TaskNotes integrates with the Obsidian editor to allow task management directly within notes. This is achieved through interactive widgets, a conversion feature for checkboxes, and natural language processing. Inline features support capture and task updates without leaving the current note. Task Link Overlays# When a wikilink to a task note is created, TaskNotes can replace it with an interactive Task Link Overlay. Enable or disable overlays from Settings -> TaskNotes -> Features (Task link overlay). The widget displays information about the task, such as status, priority, and due date, and allows actions like status/priority changes or opening the edit modal. Task link overlays in Live Preview mode show interactive widgets with status, dates, and quick actions In Source mode, task links appear as standard wikilinks until rendered Widget Features# The task link overlay displays: Status Dot: Clickable circular indicator showing current task status. Click to cycle through available statuses. Priority Dot: Color-coded indicator for task priority (only shown when assigned). Task Title: Displays the task name (truncated to 80 characters). Click to open the task edit modal. Date Information: Shows due dates (calendar icon) and scheduled dates (clock icon) with clickable context menus. Recurrence Indicator: Rotating arrow icon for recurring tasks with modification options. Action Menu: Ellipsis icon (shown on hover) provides additional task actions. The widget exposes common task actions at the link location, so status and metadata can be updated in-place. Mode-Specific Behavior# Task link overlays work in both Live Preview and Reading modes: Live Preview Mode: Widgets hide when the cursor is within the wikilink range, allowing for easy editing. Reading Mode: Widgets display with full functionality and integrate with the reading mode typography. The overlays support drag-and-drop to calendar views and provide keyboard shortcuts for quick navigation (Ctrl/Cmd+Click to open the source file). Create New Inline Task Command# The Create new inline task command opens the task creation modal from the editor and inserts a link to the new task when it is saved. This command is available in the command palette. When the cursor is on an empty line, the link is inserted at the cursor. When the cursor is on a line with content, TaskNotes inserts a new line below it and places the task link there. The command does not use the current line as the task title. To turn the current line into a TaskNote, use Convert to TaskNote or the instant conversion button next to a supported line. That flow uses the current line as the task title and replaces the original line with a link to the new task file. Instant Task Conversion# The Instant Task Conversion feature transforms lines in your notes into TaskNotes files. This works with both checkbox tasks and regular lines of text. Turn the feature on or off from Settings -> TaskNotes -> Features (Show convert button next to checkboxes). When enabled, a \"convert\" button appears next to content in edit mode. Clicking this button creates a new task note using the line text as the title and replaces the original line with a link to the new task file. This supports progressive conversion from draft notes to dedicated task files. Folder Configuration# By default, converted tasks are placed in the same folder as the current note ({{currentNotePath}}). You can change this behavior in Settings -> TaskNotes -> General (Folder for converted tasks): Leave empty: Uses your default tasks folder (configured in the same section) {{currentNotePath}}: Places tasks in the same folder as the note you're editing (default) {{currentNoteTitle}}: Creates a subfolder named after the current note Custom path: Specify any folder path (e.g., TaskNotes/Converted) Supported Line Types# The conversion feature works with: Checkbox tasks: - [ ] Task description becomes a TaskNote with task metadata Bullet points: - Some task idea becomes a TaskNote with the text as title Numbered lists: 1. Important item becomes a TaskNote Blockquoted content: > Task in callout becomes a TaskNote (preserves blockquote formatting) Plain text lines: Important thing to do becomes a TaskNote Mixed formats: > - [ ] Task in blockquote handles both blockquote and checkbox formatting Content Processing# When converting lines: Special characters like >, #, - are automatically removed from the task title Original formatting is preserved in the note (e.g., > [[Task Title]] for blockquoted content) Task metadata is extracted from checkbox tasks (due dates, priorities, etc.) Natural language processing can extract dates and metadata from plain text (if enabled) Conversion preserves surrounding formatting, including callouts, outlines, and nested lists. The feature handles edge cases like nested blockquotes and maintains proper indentation in the final link replacement. Bulk Task Conversion# The Bulk Task Conversion command converts all checkbox tasks in the current note to TaskNotes in a single operation. This command is available in the command palette as \"Convert all tasks in note to TaskNotes\". How It Works# The command: Scans the entire current note for checkbox tasks (- [ ], * [ ], 1. [ ], etc.) Includes tasks inside blockquotes (e.g., > - [ ] task in callout) Applies the same enhanced conversion logic as instant task conversion Creates individual TaskNote files for each task Replaces the original checkboxes with links to the new task files Preserves original indentation and formatting (including blockquote markers) The bulk conversion uses the same content processing as instant conversion, automatically removing special characters from task titles while preserving original formatting in the note. Usage# To use bulk conversion: Open a note containing checkbox tasks Access the command palette (Ctrl+P / Cmd+P) Search for \"Convert all tasks in note to TaskNotes\" Execute the command The command displays progress and shows a summary when complete (for example, \"Successfully converted 5 tasks to TaskNotes.\"). Important Considerations **This command modifies note content permanently.** Before using: - **Create a backup** of your note if it contains important data - **Review the tasks** to ensure they should become individual TaskNotes - **Expect processing time** - notes with many tasks may take several seconds to process - **Avoid interruption** - do not edit the note while conversion is running Performance Processing time depends on the number of tasks: - Small notes (1-10 tasks): Near-instant - Medium notes (10-50 tasks): 2-5 seconds - Large notes (50+ tasks): 10+ seconds The operation creates multiple files and updates the note content, which requires disk I/O and editor updates. Error Handling# If some tasks fail to convert, the command will: Complete successfully converted tasks Display a summary showing both successes and failures Log detailed error information to the console for troubleshooting Failed conversions typically occur due to: Tasks with titles containing invalid filename characters Insufficient disk permissions Very long task titles (over 200 characters) For large notes, converting a small section first helps validate folder and filename settings. Relationships Widget# New in v4: The Relationships Widget consolidates what were previously three separate widgets (project subtasks, task dependencies, and blocking tasks) into a single dynamic interface. The widget appears in task notes and automatically displays up to five tabs based on available relationship data: Subtasks Tab (Kanban): Shows tasks that reference the current note as a project. Uses Kanban layout for visual task management. Occurrences Tab (List): Shows materialized occurrence notes that reference the current recurring task as their parent. Uses list layout sorted by occurrence date. Projects Tab (List): Shows projects that the current task belongs to. Uses list layout. Blocked By Tab (List): Shows tasks that are blocking the current task. Uses list layout. Blocking Tab (Kanban): Shows tasks that the current task is blocking. Uses Kanban layout. Automatic Tab Management# Tabs automatically show or hide based on the presence of relationship data. If a task has no subtasks, the Subtasks tab does not appear. If a recurring task has no materialized occurrence notes, the Occurrences tab does not appear. If there are no blocking relationships, those tabs remain hidden. This keeps the interface focused on relevant information. The widget layout changes with available data, so simple tasks show fewer sections. Features# The widget embeds the TaskNotes/Views/relationships.base view directly in the editor. Every filter, grouping rule, or property shown in that .base file is exactly what appears inside the widget, so you can customize the experience by editing the file just like any other Bases view. Additional behavior: Collapsible Interface: Click the widget title to expand or collapse. The state is remembered between sessions. Persistent Grouping: Any grouping defined in the .base file is honoured, and collapsed groups retain their state per note. Task Details: Each task shows its status, priority, due date, and other configured properties. Real-time Updates: The widget updates automatically when tasks are added, modified, or deleted via Bases views. Configuration# Enable or disable the widget in Settings -> TaskNotes -> Appearance (Show relationships widget). Position the widget at the top (after frontmatter) or bottom of the note using the Relationships Position setting. Expandable Subtasks Chevron# Tasks with subtasks can display an expand/collapse chevron that toggles subtask visibility. The chevron can be positioned on the Right (default, hover to show) or on the Left (always visible, matches group chevrons). Configure this in Settings -> TaskNotes -> Appearance (Subtask chevron position). Migration from v3# In v3, TaskNotes provided three separate widgets controlled by individual settings: showProjectSubtasks and projectSubtasksPosition showTaskDependencies and taskDependenciesPosition showBlockingTasks and blockingTasksPosition These settings are replaced in v4 by: showRelationships and relationshipsPosition If you had project subtasks enabled in v3, the relationships widget is enabled automatically after upgrading to v4. The underlying Bases file changed from TaskNotes/Views/project-subtasks.base to TaskNotes/Views/relationships.base. Run the Create files action in Settings -> TaskNotes -> General -> Views & base files if relationships.base is missing. Natural Language Processing# TaskNotes includes a Natural Language Processor (NLP) that parses task descriptions to extract structured data. This allows for task creation from conversational language, such as \"Prepare quarterly report due Friday #work high priority,\" which would automatically set the due date, tag, and priority. The NLP engine supports multiple languages, including English, Spanish, French, German, Italian, Japanese, Dutch, Portuguese, Russian, Swedish, Chinese, and Ukrainian. Supported Syntax# The NLP engine recognizes: Tags and Contexts: #tag and @context syntax (triggers are customizable). Projects: +project for simple projects or +[[Project Name]] for projects with spaces. Priority Levels: Keywords like \"high,\" \"normal,\" and \"low\". Also supports a trigger character (default: !). Status Assignment: Keywords like \"open,\" \"in-progress,\" and \"done\". Also supports a trigger character (default: *). Dates and Times: Phrases like \"tomorrow,\" \"next Friday,\" and \"January 15th at 3pm\". Time Estimates: Formats like \"2h,\" \"30min,\" and \"1h30m\". Recurrence Patterns: Phrases like \"daily,\" \"weekly,\" and \"every Monday\". User-Defined Fields: Custom fields can be assigned using configured triggers (e.g., effort: high). Supports quoted values for multi-word entries. NLP parses common patterns during capture; fields can be refined in the modal afterward. Rich Markdown Editor# New in v4: The task creation modal uses a rich CodeMirror markdown editor instead of a plain textarea. Features include: Live Preview: Rendered markdown preview as you type. Syntax Highlighting: Code blocks, links, and formatting are highlighted. Wikilink Support: Create links to other notes using [[Note Name]] syntax. Keyboard Shortcuts: Ctrl/Cmd+Enter saves the task Esc or Tab to navigate out of the editor Placeholder Text: Shows an example task (e.g., \"Buy groceries tomorrow at 3pm @home #errands\") when the editor is empty. Customizable Triggers# New in v4: Triggers for NLP properties can be customized in Settings -> TaskNotes -> Features (NLP Triggers). You can configure trigger characters or strings for: Tags (default: #) - When set to #, Obsidian's native tag suggester is used Contexts (default: @) Projects (default: +) Status (default: *) Priority (default: !, disabled by default) User-Defined Fields (default: fieldname:) - Each custom field can have its own trigger Triggers support up to 10 characters and can include trailing spaces (e.g., \"def: \" for a custom field). Autocomplete# New in v4: When typing a trigger in the NLP editor, an autocomplete menu appears with available values. Navigate suggestions with arrow keys Select with Enter or Tab Autocomplete works for tags, contexts, projects, status, priority, and user-defined fields Tag autocomplete uses Obsidian's native tag suggester when using the # trigger For user fields with multi-word values, wrap the value in quotes (e.g., effort: \"very high\") The NLP engine is integrated with the task creation modal and bulk conversion features. Typing a natural language description populates the corresponding task fields automatically."},{"route":"/obsidian/features/integrations/","title":"Integrations","description":"TaskNotes integrates with external services and Obsidian's core plugins.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/features/integrations.md","namespace":"obsidian","relativePath":"features/integrations.md","raw":"# Integrations\n\nTaskNotes integrates with external services and Obsidian's core plugins.\n\n\n## Bases Core Plugin\n\nTaskNotes v4 uses Obsidian's Bases core plugin for its main views (Task List, Kanban, Calendar, Agenda). Bases must be enabled in `Settings -> Core Plugins`.\n\nFor details on Bases integration, see [Core Concepts](../core-concepts.md#bases-integration).\n\n## External Calendars\n\nTaskNotes supports bidirectional sync with Google Calendar and Microsoft Outlook via OAuth, plus read-only access to any calendar via ICS subscriptions.\n\nFor setup instructions, see [Calendar Integration](calendar-integration.md).\n\n## HTTP API\n\nA REST API enables external applications to create, update, and query tasks. Use it for automation, browser extensions, or custom integrations.\n\nFor API documentation, see [HTTP API](../HTTP_API.md).\n\n## Webhooks\n\nWebhooks send task event payloads to external services when subscribed events occur. Optional payload transformations support service-specific formats.\n\nFor configuration, see [Webhooks](../webhooks.md).\n\n## Companion Plugins\n\nCompanion plugins run inside Obsidian alongside TaskNotes and use the JavaScript runtime API for live task operations. They are useful when an integration needs a real Obsidian UI, command-palette commands, or vault-local configuration files.\n\nFor the companion-plugin model and guides for Canvas Bases and TaskNotes Workflows, see [Companion Plugins](../companion-plugins.md).\n","aliases":["/features/integrations/"],"toc":[{"level":2,"id":"bases-core-plugin","text":"Bases Core Plugin"},{"level":2,"id":"external-calendars","text":"External Calendars"},{"level":2,"id":"http-api","text":"HTTP API"},{"level":2,"id":"webhooks","text":"Webhooks"},{"level":2,"id":"companion-plugins","text":"Companion Plugins"}],"html":"

TaskNotes integrates with external services and Obsidian's core plugins.

\n

Bases Core Plugin#

\n

TaskNotes v4 uses Obsidian's Bases core plugin for its main views (Task List, Kanban, Calendar, Agenda). Bases must be enabled in Settings -> Core Plugins.

\n

For details on Bases integration, see Core Concepts.

\n

External Calendars#

\n

TaskNotes supports bidirectional sync with Google Calendar and Microsoft Outlook via OAuth, plus read-only access to any calendar via ICS subscriptions.

\n

For setup instructions, see Calendar Integration.

\n

HTTP API#

\n

A REST API enables external applications to create, update, and query tasks. Use it for automation, browser extensions, or custom integrations.

\n

For API documentation, see HTTP API.

\n

Webhooks#

\n

Webhooks send task event payloads to external services when subscribed events occur. Optional payload transformations support service-specific formats.

\n

For configuration, see Webhooks.

\n

Companion Plugins#

\n

Companion plugins run inside Obsidian alongside TaskNotes and use the JavaScript runtime API for live task operations. They are useful when an integration needs a real Obsidian UI, command-palette commands, or vault-local configuration files.

\n

For the companion-plugin model and guides for Canvas Bases and TaskNotes Workflows, see Companion Plugins.

\n","text":"TaskNotes integrates with external services and Obsidian's core plugins. Bases Core Plugin# TaskNotes v4 uses Obsidian's Bases core plugin for its main views (Task List, Kanban, Calendar, Agenda). Bases must be enabled in Settings -> Core Plugins. For details on Bases integration, see Core Concepts. External Calendars# TaskNotes supports bidirectional sync with Google Calendar and Microsoft Outlook via OAuth, plus read-only access to any calendar via ICS subscriptions. For setup instructions, see Calendar Integration. HTTP API# A REST API enables external applications to create, update, and query tasks. Use it for automation, browser extensions, or custom integrations. For API documentation, see HTTP API. Webhooks# Webhooks send task event payloads to external services when subscribed events occur. Optional payload transformations support service-specific formats. For configuration, see Webhooks. Companion Plugins# Companion plugins run inside Obsidian alongside TaskNotes and use the JavaScript runtime API for live task operations. They are useful when an integration needs a real Obsidian UI, command-palette commands, or vault-local configuration files. For the companion-plugin model and guides for Canvas Bases and TaskNotes Workflows, see Companion Plugins."},{"route":"/obsidian/features/recurring-tasks/","title":"Recurring Tasks","description":"TaskNotes recurring tasks use RFC 5545 RRule strings with DTSTART support and dynamic next-occurrence scheduling. The model separates recurrence patterns from the next planned i...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/features/recurring-tasks.md","namespace":"obsidian","relativePath":"features/recurring-tasks.md","raw":"# Recurring Tasks\n\n\nTaskNotes recurring tasks use RFC 5545 RRule strings with `DTSTART` support and dynamic next-occurrence scheduling. The model separates recurrence patterns from the next planned instance, and can also create normal task notes for individual occurrences when an instance needs its own content.\n\nIf you are new to recurring tasks in TaskNotes, think of the recurrence rule as the long-term plan and the `scheduled` field as the next concrete commitment. Most day-to-day editing affects `scheduled`, while recurrence editing changes the plan itself.\n\n## Core Concepts\n\nRecurring tasks operate on two independent levels:\n\n1. **Recurring Pattern**: Defines when pattern instances appear (controlled by `DTSTART` in the recurrence rule)\n2. **Next Occurrence**: The specific date/time when you plan to work on the next instance (controlled by the `scheduled` field)\n3. **Materialized Occurrence Notes**: Optional child task notes for specific occurrence dates, used when an occurrence needs its own checklist, status, time tracking, or body content\n\nThis separation lets you reschedule the next occurrence without changing the pattern.\n\n## Setting Up Recurring Tasks\n\nIn practice, setup is usually a two-step flow: choose a pattern, then check whether the next scheduled occurrence matches how you actually want to execute the next instance.\n\n### Creating Recurrence Patterns\n\nYou can create recurring tasks through:\n\n1. **Recurrence Context Menu** in task modals for presets or custom options\n2. **Preset Options** such as daily, weekly, or monthly\n3. **Custom Recurrence Modal** with date/time pickers and RRule configuration\n\n### Required Components\n\nRecurring tasks require:\n\n- **Recurrence Rule**: RRule string with `DTSTART`\n- **Scheduled Date**: Next occurrence date (independent from the pattern)\n\nMaterialized occurrence notes add two system fields to the occurrence note:\n\n- `recurrence_parent`: link/path back to the recurring parent task\n- `occurrence_date`: the occurrence date represented by the note\n\n### DTSTART Integration\n\n`DTSTART` is the anchor for pattern generation. It controls where the rule begins and, when time is included, the default time for future pattern instances.\n\n- **Date-only**: `DTSTART:20250804;FREQ=DAILY`\n- **Date and time**: `DTSTART:20250804T090000Z;FREQ=DAILY`\n\n## Recurring Task Due Date\n\nWhen a recurring task is completed, `scheduled` advances to the next occurrence. By default, `due` does not change.\n\nEnable `Maintain due date offset in recurring tasks` in **Settings → TaskNotes → Features → Recurring Tasks** to preserve due/scheduled spacing.\n\nExample:\n\n- Scheduled: `2025-01-01`\n- Due: `2025-01-03`\n- Recurrence: weekly\n\nIf the task advances to `scheduled: 2025-01-08`, the due date becomes `2025-01-10` when this setting is enabled.\n\nThis setting is most useful when due dates represent a fixed lead/lag relative to scheduled work (for example, \"due two days after execution\"). If due dates are independent deadlines, leaving the setting off is usually clearer.\n\n## Recurrence Pattern Examples\n\n```text\nDTSTART:20250804T090000Z;FREQ=DAILY\n→ Daily at 9:00 AM, starting August 4, 2025\n\nDTSTART:20250804T140000Z;FREQ=WEEKLY;BYDAY=MO,WE,FR\n→ Monday, Wednesday, Friday at 2:00 PM, starting August 4, 2025\n\nDTSTART:20250815;FREQ=MONTHLY;BYMONTHDAY=15\n→ 15th of each month (all-day), starting August 15, 2025\n\nDTSTART:20250831;FREQ=MONTHLY;BYMONTHDAY=-1\n→ Last day of each month (all-day), starting August 31, 2025\n\nDTSTART:20250801T100000Z;FREQ=MONTHLY;BYDAY=-1FR\n→ Last Friday of each month at 10:00 AM, starting August 1, 2025\n```\n\n## Dynamic Scheduled Dates\n\nThe `scheduled` field automatically tracks the next uncompleted occurrence:\n\n1. Initially set to the `DTSTART` date\n2. Advances when occurrences are completed\n3. Recalculates when the rule changes\n4. Can be manually rescheduled independently\n\nThis behavior keeps recurring tasks practical in real planning: you can preserve a stable weekly/monthly pattern while still adapting the immediate next occurrence to calendar realities.\n\n## Materialized Occurrence Notes\n\nMost recurring tasks can remain virtual: the parent task stores `complete_instances` and `skipped_instances`, and TaskNotes renders each calendar/list instance from that parent. Materialized occurrence notes are for heavier instances where the date-specific work needs its own note.\n\nGood uses include:\n\n- A weekly review where each week needs a separate agenda and notes\n- A maintenance task where each visit needs photos, links, or a checklist\n- A recurring meeting where every occurrence should have its own time entries and completion state\n\nTo create one manually, right-click a recurring task card or calendar occurrence and choose **Open or create occurrence note**. The Task Action Palette also exposes **Open or create occurrence note** for recurring tasks. If a matching note already exists for the same parent and date, TaskNotes opens it instead of creating a duplicate.\n\nAn occurrence note is an ordinary TaskNotes task. It appears in views, can be edited like any other task, and shows an occurrence pill that links back to the recurring parent. On the calendar, a materialized occurrence replaces the matching virtual parent occurrence for the same parent/date pair, so you do not see both the generated instance and the note-backed instance at the same time.\n\nIts frontmatter includes:\n\n```yaml\nrecurrence_parent: \"[[Tasks/Weekly review]]\"\noccurrence_date: \"2026-06-01\"\nscheduled: \"2026-06-01T09:30\"\ntimeEstimate: 45\n```\n\nWhen TaskNotes creates an occurrence note, it copies the parent fields that describe how that instance should be planned: title, priority, scheduled time, due offset, contexts, projects, tags, reminders, dependencies, details, custom properties, and time estimate. Date-like fields are rebased onto the occurrence date, so a parent scheduled at `09:30` creates an occurrence scheduled at `09:30` on the selected date, and a due date one day after the parent scheduled date stays one day after the occurrence scheduled date.\n\nOccurrence notes can use a separate template from regular new tasks. Set `occurrence_template` on the recurring parent to point at a template note, or configure **Settings → Features → Body template → Occurrence note template file** as a global fallback. Parent-level `occurrence_template` wins over the global fallback. If neither occurrence-specific template is configured, occurrence note creation keeps the normal body template behavior.\n\nThe parent task remains the source of the recurrence rule and series history. Occurrence notes do not copy the parent's `recurrence`, `complete_instances`, `skipped_instances`, `completedDate`, calendar provider IDs, or `timeEntries`. New time entries belong to the occurrence note once you track time there.\n\n### Occurrence Filenames\n\nBy default, materialized occurrence notes use the existing filename behavior: the parent title followed by a numeric suffix. To opt in to custom filenames, set **Occurrence filename template** under **Settings → Task Properties → Title**. For example, `{{title}} — {{occurrenceDate}}` produces `Weekly review — 2026-08-01.md`.\n\nOccurrence filename templates support all regular filename variables plus these occurrence-specific variables:\n\n- `{{occurrenceDate}}` - occurrence date, such as `2026-08-01`\n- `{{occurrenceWeek}}` - ISO week, such as `2026-W31`\n- `{{occurrenceMonth}}` - month, such as `2026-08`\n- `{{occurrenceYear}}` - year, such as `2026`\n- `{{occurrenceMonthName}}` - full month name, such as `August`\n\nChoose the date granularity explicitly in the template; TaskNotes does not infer it from the recurrence rule. A recurring parent can override the global template with the frontmatter property configured by **Occurrence template override property** (by default, `occurrenceFilenameTemplate`):\n\n```yaml\noccurrenceFilenameTemplate: \"{{title}} ({{occurrenceWeek}})\"\n```\n\nLeaving the global template empty preserves the existing filename behavior. TaskNotes never renames existing occurrence notes, and filename collisions continue to receive a numeric suffix.\n\n### Occurrence Note Policies\n\nEach recurring parent has an **Occurrence notes** submenu under its recurrence menu:\n\n- **Create manually**: occurrence notes are only created by explicit action.\n- **Create next after completion**: after you complete a materialized occurrence note, TaskNotes creates the next occurrence note.\n- **Rolling window**: defined by the TaskNotes spec, but not automated in the plugin yet.\n\nWhen **Create next after completion** is enabled, creating the first occurrence is still a deliberate action. After that, completing the occurrence note advances the parent recurrence state and materializes the next scheduled occurrence.\n\nHTTP API and MCP clients can create occurrence notes without using the desktop context menu. Use `POST /api/tasks/:id/materialize-occurrence` or the MCP `tasknotes_materialize_occurrence` tool with a parent task path and occurrence date. Completing a recurring instance through the API or MCP also respects existing occurrence notes and the **Create next after completion** policy.\n\nThe same submenu also controls the next-note trigger:\n\n- **Completion only**: create the next occurrence note only when the current occurrence is completed.\n- **Completion or skip**: create the next occurrence note when the current occurrence is completed or skipped.\n\nSkip/unskip controls appear on materialized occurrence notes when a skipped status is configured. Skipping an occurrence preserves the note, updates its status, and reconciles the parent `skipped_instances` list.\n\n### Completion Reconciliation\n\nWhen a materialized occurrence note is completed, TaskNotes updates both sides of the relationship:\n\n- The occurrence note is completed like a normal task.\n- The parent adds the occurrence date to `complete_instances`.\n- The parent removes that date from `skipped_instances` if needed.\n- The parent recalculates `scheduled` to the next uncompleted occurrence.\n- If the parent policy is **Create next after completion**, TaskNotes creates the next occurrence note idempotently.\n\nUncompleting an occurrence note removes the date from the parent's `complete_instances` list, but it does not delete later occurrence notes that were already created.\n\n### Example Behavior\n\n```yaml\n# Initial state\nrecurrence: \"DTSTART:20250804T090000Z;FREQ=DAILY\"\nscheduled: \"2025-08-04T09:00\"\ncomplete_instances: []\n\n# After completing Aug 4\nrecurrence: \"DTSTART:20250804T090000Z;FREQ=DAILY\"\nscheduled: \"2025-08-05T09:00\"\ncomplete_instances: [\"2025-08-04\"]\n\n# After manually rescheduling next occurrence\nrecurrence: \"DTSTART:20250804T090000Z;FREQ=DAILY\"\nscheduled: \"2025-08-05T14:30\"\ncomplete_instances: [\"2025-08-04\"]\n```\n\n## Calendar Drag and Drop\n\nCalendar interactions follow the same model distinction: drag the concrete next item to reschedule execution, or drag a pattern instance to redefine the recurrence anchor.\n\nRecurring tasks can show:\n\n- **Next occurrence** (solid border): dragging updates only `scheduled`\n- **Pattern instances** (dashed border): dragging updates `DTSTART` and future pattern instances\n- **Materialized occurrence notes**: dragging updates the occurrence note's own `scheduled` or `due` date like a normal task, without changing the parent's recurrence rule\n\n![Recurring tasks in calendar week view](../assets/views-calendar-week.png)\n\nMaterialized occurrence notes keep `occurrence_date` as their identity. If you drag the note for the June 1 occurrence to June 2, it is still the June 1 recurrence instance, now scheduled for June 2. TaskNotes suppresses the June 1 virtual parent event and leaves the June 2 virtual occurrence alone unless that date also has its own materialized note.\n\n## Completion Tracking\n\nEach occurrence can be completed or skipped independently (task cards, calendar menus, task edit modal completion calendar).\n\nCompleted instances are stored in:\n\n```yaml\ncomplete_instances: [\"2025-08-04\", \"2025-08-06\", \"2025-08-08\"]\n```\n\nSkipped instances are stored in:\n\n```yaml\nskipped_instances: [\"2025-08-05\"]\n```\n\nWhen completion changes, `scheduled` updates to the next uncompleted instance. If a materialized occurrence note exists for a date, that note's own status takes precedence for that occurrence, and TaskNotes reconciles the parent compatibility lists during completion, uncompletion, skip, and unskip actions.\n\nThis means completion history and next-action planning stay synchronized automatically, without manually advancing recurring tasks.\n\n## Flexible Scheduling\n\nTaskNotes intentionally allows off-pattern scheduling so recurring tasks can absorb real-world disruptions without rewriting the entire recurrence rule.\n\nThe next occurrence can be:\n\n- Before `DTSTART`\n- Outside the pattern day\n- At a different time than pattern instances\n- Far ahead while pattern continues unchanged\n\n### Examples\n\n```yaml\n# Early start before DTSTART\nrecurrence: \"DTSTART:20250810T090000Z;FREQ=WEEKLY;BYDAY=MO\"\nscheduled: \"2025-08-07T14:00\"\n```\n\n```yaml\n# Off-pattern next occurrence\nrecurrence: \"DTSTART:20250804T090000Z;FREQ=WEEKLY;BYDAY=MO\"\nscheduled: \"2025-08-06T15:30\"\n```\n\n## Timezone Handling\n\nRecurring task logic uses a UTC anchor approach:\n\n- Pattern generation uses UTC dates\n- `DTSTART` dates are interpreted as UTC anchors\n- Display adapts to local timezone\n- Prevents common off-by-one date issues\n\nIn other words, calculations stay stable internally while display remains local, which avoids drift when traveling or sharing vaults across timezones.\n\n## Backward Compatibility\n\nRecurring behavior remains compatible with older task data, so upgrades do not require manual note rewrites.\n\n- Legacy RRule strings without `DTSTART` continue to work using `scheduled` as anchor\n- Legacy recurrence objects are converted to RRule format\n- Existing tasks continue to function without migration steps\n- Mixed formats are handled transparently\n","aliases":["/features/recurring-tasks/"],"toc":[{"level":2,"id":"core-concepts","text":"Core Concepts"},{"level":2,"id":"setting-up-recurring-tasks","text":"Setting Up Recurring Tasks"},{"level":3,"id":"creating-recurrence-patterns","text":"Creating Recurrence Patterns"},{"level":3,"id":"required-components","text":"Required Components"},{"level":3,"id":"dtstart-integration","text":"DTSTART Integration"},{"level":2,"id":"recurring-task-due-date","text":"Recurring Task Due Date"},{"level":2,"id":"recurrence-pattern-examples","text":"Recurrence Pattern Examples"},{"level":2,"id":"dynamic-scheduled-dates","text":"Dynamic Scheduled Dates"},{"level":2,"id":"materialized-occurrence-notes","text":"Materialized Occurrence Notes"},{"level":3,"id":"occurrence-filenames","text":"Occurrence Filenames"},{"level":3,"id":"occurrence-note-policies","text":"Occurrence Note Policies"},{"level":3,"id":"completion-reconciliation","text":"Completion Reconciliation"},{"level":3,"id":"example-behavior","text":"Example Behavior"},{"level":2,"id":"calendar-drag-and-drop","text":"Calendar Drag and Drop"},{"level":2,"id":"completion-tracking","text":"Completion Tracking"},{"level":2,"id":"flexible-scheduling","text":"Flexible Scheduling"},{"level":3,"id":"examples","text":"Examples"},{"level":2,"id":"timezone-handling","text":"Timezone Handling"},{"level":2,"id":"backward-compatibility","text":"Backward Compatibility"}],"html":"

TaskNotes recurring tasks use RFC 5545 RRule strings with DTSTART support and dynamic next-occurrence scheduling. The model separates recurrence patterns from the next planned instance, and can also create normal task notes for individual occurrences when an instance needs its own content.

\n

If you are new to recurring tasks in TaskNotes, think of the recurrence rule as the long-term plan and the scheduled field as the next concrete commitment. Most day-to-day editing affects scheduled, while recurrence editing changes the plan itself.

\n

Core Concepts#

\n

Recurring tasks operate on two independent levels:

\n
    \n
  1. Recurring Pattern: Defines when pattern instances appear (controlled by DTSTART in the recurrence rule)
  2. \n
  3. Next Occurrence: The specific date/time when you plan to work on the next instance (controlled by the scheduled field)
  4. \n
  5. Materialized Occurrence Notes: Optional child task notes for specific occurrence dates, used when an occurrence needs its own checklist, status, time tracking, or body content
  6. \n
\n

This separation lets you reschedule the next occurrence without changing the pattern.

\n

Setting Up Recurring Tasks#

\n

In practice, setup is usually a two-step flow: choose a pattern, then check whether the next scheduled occurrence matches how you actually want to execute the next instance.

\n

Creating Recurrence Patterns#

\n

You can create recurring tasks through:

\n
    \n
  1. Recurrence Context Menu in task modals for presets or custom options
  2. \n
  3. Preset Options such as daily, weekly, or monthly
  4. \n
  5. Custom Recurrence Modal with date/time pickers and RRule configuration
  6. \n
\n

Required Components#

\n

Recurring tasks require:

\n
    \n
  • Recurrence Rule: RRule string with DTSTART
  • \n
  • Scheduled Date: Next occurrence date (independent from the pattern)
  • \n
\n

Materialized occurrence notes add two system fields to the occurrence note:

\n
    \n
  • recurrence_parent: link/path back to the recurring parent task
  • \n
  • occurrence_date: the occurrence date represented by the note
  • \n
\n

DTSTART Integration#

\n

DTSTART is the anchor for pattern generation. It controls where the rule begins and, when time is included, the default time for future pattern instances.

\n
    \n
  • Date-only: DTSTART:20250804;FREQ=DAILY
  • \n
  • Date and time: DTSTART:20250804T090000Z;FREQ=DAILY
  • \n
\n

Recurring Task Due Date#

\n

When a recurring task is completed, scheduled advances to the next occurrence. By default, due does not change.

\n

Enable Maintain due date offset in recurring tasks in Settings → TaskNotes → Features → Recurring Tasks to preserve due/scheduled spacing.

\n

Example:

\n
    \n
  • Scheduled: 2025-01-01
  • \n
  • Due: 2025-01-03
  • \n
  • Recurrence: weekly
  • \n
\n

If the task advances to scheduled: 2025-01-08, the due date becomes 2025-01-10 when this setting is enabled.

\n

This setting is most useful when due dates represent a fixed lead/lag relative to scheduled work (for example, "due two days after execution"). If due dates are independent deadlines, leaving the setting off is usually clearer.

\n

Recurrence Pattern Examples#

\n
DTSTART:20250804T090000Z;FREQ=DAILY\n→ Daily at 9:00 AM, starting August 4, 2025\n\nDTSTART:20250804T140000Z;FREQ=WEEKLY;BYDAY=MO,WE,FR\n→ Monday, Wednesday, Friday at 2:00 PM, starting August 4, 2025\n\nDTSTART:20250815;FREQ=MONTHLY;BYMONTHDAY=15\n→ 15th of each month (all-day), starting August 15, 2025\n\nDTSTART:20250831;FREQ=MONTHLY;BYMONTHDAY=-1\n→ Last day of each month (all-day), starting August 31, 2025\n\nDTSTART:20250801T100000Z;FREQ=MONTHLY;BYDAY=-1FR\n→ Last Friday of each month at 10:00 AM, starting August 1, 2025\n

Dynamic Scheduled Dates#

\n

The scheduled field automatically tracks the next uncompleted occurrence:

\n
    \n
  1. Initially set to the DTSTART date
  2. \n
  3. Advances when occurrences are completed
  4. \n
  5. Recalculates when the rule changes
  6. \n
  7. Can be manually rescheduled independently
  8. \n
\n

This behavior keeps recurring tasks practical in real planning: you can preserve a stable weekly/monthly pattern while still adapting the immediate next occurrence to calendar realities.

\n

Materialized Occurrence Notes#

\n

Most recurring tasks can remain virtual: the parent task stores complete_instances and skipped_instances, and TaskNotes renders each calendar/list instance from that parent. Materialized occurrence notes are for heavier instances where the date-specific work needs its own note.

\n

Good uses include:

\n
    \n
  • A weekly review where each week needs a separate agenda and notes
  • \n
  • A maintenance task where each visit needs photos, links, or a checklist
  • \n
  • A recurring meeting where every occurrence should have its own time entries and completion state
  • \n
\n

To create one manually, right-click a recurring task card or calendar occurrence and choose Open or create occurrence note. The Task Action Palette also exposes Open or create occurrence note for recurring tasks. If a matching note already exists for the same parent and date, TaskNotes opens it instead of creating a duplicate.

\n

An occurrence note is an ordinary TaskNotes task. It appears in views, can be edited like any other task, and shows an occurrence pill that links back to the recurring parent. On the calendar, a materialized occurrence replaces the matching virtual parent occurrence for the same parent/date pair, so you do not see both the generated instance and the note-backed instance at the same time.

\n

Its frontmatter includes:

\n
recurrence_parent: "[[Tasks/Weekly review]]"\noccurrence_date: "2026-06-01"\nscheduled: "2026-06-01T09:30"\ntimeEstimate: 45\n

When TaskNotes creates an occurrence note, it copies the parent fields that describe how that instance should be planned: title, priority, scheduled time, due offset, contexts, projects, tags, reminders, dependencies, details, custom properties, and time estimate. Date-like fields are rebased onto the occurrence date, so a parent scheduled at 09:30 creates an occurrence scheduled at 09:30 on the selected date, and a due date one day after the parent scheduled date stays one day after the occurrence scheduled date.

\n

Occurrence notes can use a separate template from regular new tasks. Set occurrence_template on the recurring parent to point at a template note, or configure Settings → Features → Body template → Occurrence note template file as a global fallback. Parent-level occurrence_template wins over the global fallback. If neither occurrence-specific template is configured, occurrence note creation keeps the normal body template behavior.

\n

The parent task remains the source of the recurrence rule and series history. Occurrence notes do not copy the parent's recurrence, complete_instances, skipped_instances, completedDate, calendar provider IDs, or timeEntries. New time entries belong to the occurrence note once you track time there.

\n

Occurrence Filenames#

\n

By default, materialized occurrence notes use the existing filename behavior: the parent title followed by a numeric suffix. To opt in to custom filenames, set Occurrence filename template under Settings → Task Properties → Title. For example, {{title}} — {{occurrenceDate}} produces Weekly review — 2026-08-01.md.

\n

Occurrence filename templates support all regular filename variables plus these occurrence-specific variables:

\n
    \n
  • {{occurrenceDate}} - occurrence date, such as 2026-08-01
  • \n
  • {{occurrenceWeek}} - ISO week, such as 2026-W31
  • \n
  • {{occurrenceMonth}} - month, such as 2026-08
  • \n
  • {{occurrenceYear}} - year, such as 2026
  • \n
  • {{occurrenceMonthName}} - full month name, such as August
  • \n
\n

Choose the date granularity explicitly in the template; TaskNotes does not infer it from the recurrence rule. A recurring parent can override the global template with the frontmatter property configured by Occurrence template override property (by default, occurrenceFilenameTemplate):

\n
occurrenceFilenameTemplate: "{{title}} ({{occurrenceWeek}})"\n

Leaving the global template empty preserves the existing filename behavior. TaskNotes never renames existing occurrence notes, and filename collisions continue to receive a numeric suffix.

\n

Occurrence Note Policies#

\n

Each recurring parent has an Occurrence notes submenu under its recurrence menu:

\n
    \n
  • Create manually: occurrence notes are only created by explicit action.
  • \n
  • Create next after completion: after you complete a materialized occurrence note, TaskNotes creates the next occurrence note.
  • \n
  • Rolling window: defined by the TaskNotes spec, but not automated in the plugin yet.
  • \n
\n

When Create next after completion is enabled, creating the first occurrence is still a deliberate action. After that, completing the occurrence note advances the parent recurrence state and materializes the next scheduled occurrence.

\n

HTTP API and MCP clients can create occurrence notes without using the desktop context menu. Use POST /api/tasks/:id/materialize-occurrence or the MCP tasknotes_materialize_occurrence tool with a parent task path and occurrence date. Completing a recurring instance through the API or MCP also respects existing occurrence notes and the Create next after completion policy.

\n

The same submenu also controls the next-note trigger:

\n
    \n
  • Completion only: create the next occurrence note only when the current occurrence is completed.
  • \n
  • Completion or skip: create the next occurrence note when the current occurrence is completed or skipped.
  • \n
\n

Skip/unskip controls appear on materialized occurrence notes when a skipped status is configured. Skipping an occurrence preserves the note, updates its status, and reconciles the parent skipped_instances list.

\n

Completion Reconciliation#

\n

When a materialized occurrence note is completed, TaskNotes updates both sides of the relationship:

\n
    \n
  • The occurrence note is completed like a normal task.
  • \n
  • The parent adds the occurrence date to complete_instances.
  • \n
  • The parent removes that date from skipped_instances if needed.
  • \n
  • The parent recalculates scheduled to the next uncompleted occurrence.
  • \n
  • If the parent policy is Create next after completion, TaskNotes creates the next occurrence note idempotently.
  • \n
\n

Uncompleting an occurrence note removes the date from the parent's complete_instances list, but it does not delete later occurrence notes that were already created.

\n

Example Behavior#

\n
# Initial state\nrecurrence: "DTSTART:20250804T090000Z;FREQ=DAILY"\nscheduled: "2025-08-04T09:00"\ncomplete_instances: []\n\n# After completing Aug 4\nrecurrence: "DTSTART:20250804T090000Z;FREQ=DAILY"\nscheduled: "2025-08-05T09:00"\ncomplete_instances: ["2025-08-04"]\n\n# After manually rescheduling next occurrence\nrecurrence: "DTSTART:20250804T090000Z;FREQ=DAILY"\nscheduled: "2025-08-05T14:30"\ncomplete_instances: ["2025-08-04"]\n

Calendar Drag and Drop#

\n

Calendar interactions follow the same model distinction: drag the concrete next item to reschedule execution, or drag a pattern instance to redefine the recurrence anchor.

\n

Recurring tasks can show:

\n
    \n
  • Next occurrence (solid border): dragging updates only scheduled
  • \n
  • Pattern instances (dashed border): dragging updates DTSTART and future pattern instances
  • \n
  • Materialized occurrence notes: dragging updates the occurrence note's own scheduled or due date like a normal task, without changing the parent's recurrence rule
  • \n
\n

\"Recurring

\n

Materialized occurrence notes keep occurrence_date as their identity. If you drag the note for the June 1 occurrence to June 2, it is still the June 1 recurrence instance, now scheduled for June 2. TaskNotes suppresses the June 1 virtual parent event and leaves the June 2 virtual occurrence alone unless that date also has its own materialized note.

\n

Completion Tracking#

\n

Each occurrence can be completed or skipped independently (task cards, calendar menus, task edit modal completion calendar).

\n

Completed instances are stored in:

\n
complete_instances: ["2025-08-04", "2025-08-06", "2025-08-08"]\n

Skipped instances are stored in:

\n
skipped_instances: ["2025-08-05"]\n

When completion changes, scheduled updates to the next uncompleted instance. If a materialized occurrence note exists for a date, that note's own status takes precedence for that occurrence, and TaskNotes reconciles the parent compatibility lists during completion, uncompletion, skip, and unskip actions.

\n

This means completion history and next-action planning stay synchronized automatically, without manually advancing recurring tasks.

\n

Flexible Scheduling#

\n

TaskNotes intentionally allows off-pattern scheduling so recurring tasks can absorb real-world disruptions without rewriting the entire recurrence rule.

\n

The next occurrence can be:

\n
    \n
  • Before DTSTART
  • \n
  • Outside the pattern day
  • \n
  • At a different time than pattern instances
  • \n
  • Far ahead while pattern continues unchanged
  • \n
\n

Examples#

\n
# Early start before DTSTART\nrecurrence: "DTSTART:20250810T090000Z;FREQ=WEEKLY;BYDAY=MO"\nscheduled: "2025-08-07T14:00"\n
# Off-pattern next occurrence\nrecurrence: "DTSTART:20250804T090000Z;FREQ=WEEKLY;BYDAY=MO"\nscheduled: "2025-08-06T15:30"\n

Timezone Handling#

\n

Recurring task logic uses a UTC anchor approach:

\n
    \n
  • Pattern generation uses UTC dates
  • \n
  • DTSTART dates are interpreted as UTC anchors
  • \n
  • Display adapts to local timezone
  • \n
  • Prevents common off-by-one date issues
  • \n
\n

In other words, calculations stay stable internally while display remains local, which avoids drift when traveling or sharing vaults across timezones.

\n

Backward Compatibility#

\n

Recurring behavior remains compatible with older task data, so upgrades do not require manual note rewrites.

\n
    \n
  • Legacy RRule strings without DTSTART continue to work using scheduled as anchor
  • \n
  • Legacy recurrence objects are converted to RRule format
  • \n
  • Existing tasks continue to function without migration steps
  • \n
  • Mixed formats are handled transparently
  • \n
\n","text":"TaskNotes recurring tasks use RFC 5545 RRule strings with DTSTART support and dynamic next-occurrence scheduling. The model separates recurrence patterns from the next planned instance, and can also create normal task notes for individual occurrences when an instance needs its own content. If you are new to recurring tasks in TaskNotes, think of the recurrence rule as the long-term plan and the scheduled field as the next concrete commitment. Most day-to-day editing affects scheduled, while recurrence editing changes the plan itself. Core Concepts# Recurring tasks operate on two independent levels: Recurring Pattern: Defines when pattern instances appear (controlled by DTSTART in the recurrence rule) Next Occurrence: The specific date/time when you plan to work on the next instance (controlled by the scheduled field) Materialized Occurrence Notes: Optional child task notes for specific occurrence dates, used when an occurrence needs its own checklist, status, time tracking, or body content This separation lets you reschedule the next occurrence without changing the pattern. Setting Up Recurring Tasks# In practice, setup is usually a two-step flow: choose a pattern, then check whether the next scheduled occurrence matches how you actually want to execute the next instance. Creating Recurrence Patterns# You can create recurring tasks through: Recurrence Context Menu in task modals for presets or custom options Preset Options such as daily, weekly, or monthly Custom Recurrence Modal with date/time pickers and RRule configuration Required Components# Recurring tasks require: Recurrence Rule: RRule string with DTSTART Scheduled Date: Next occurrence date (independent from the pattern) Materialized occurrence notes add two system fields to the occurrence note: recurrence_parent: link/path back to the recurring parent task occurrence_date: the occurrence date represented by the note DTSTART Integration# DTSTART is the anchor for pattern generation. It controls where the rule begins and, when time is included, the default time for future pattern instances. Date-only: DTSTART:20250804;FREQ=DAILY Date and time: DTSTART:20250804T090000Z;FREQ=DAILY Recurring Task Due Date# When a recurring task is completed, scheduled advances to the next occurrence. By default, due does not change. Enable Maintain due date offset in recurring tasks in Settings → TaskNotes → Features → Recurring Tasks to preserve due/scheduled spacing. Example: Scheduled: 2025-01-01 Due: 2025-01-03 Recurrence: weekly If the task advances to scheduled: 2025-01-08, the due date becomes 2025-01-10 when this setting is enabled. This setting is most useful when due dates represent a fixed lead/lag relative to scheduled work (for example, \"due two days after execution\"). If due dates are independent deadlines, leaving the setting off is usually clearer. Recurrence Pattern Examples# DTSTART:20250804T090000Z;FREQ=DAILY → Daily at 9:00 AM, starting August 4, 2025 DTSTART:20250804T140000Z;FREQ=WEEKLY;BYDAY=MO,WE,FR → Monday, Wednesday, Friday at 2:00 PM, starting August 4, 2025 DTSTART:20250815;FREQ=MONTHLY;BYMONTHDAY=15 → 15th of each month (all-day), starting August 15, 2025 DTSTART:20250831;FREQ=MONTHLY;BYMONTHDAY=-1 → Last day of each month (all-day), starting August 31, 2025 DTSTART:20250801T100000Z;FREQ=MONTHLY;BYDAY=-1FR → Last Friday of each month at 10:00 AM, starting August 1, 2025 Dynamic Scheduled Dates# The scheduled field automatically tracks the next uncompleted occurrence: Initially set to the DTSTART date Advances when occurrences are completed Recalculates when the rule changes Can be manually rescheduled independently This behavior keeps recurring tasks practical in real planning: you can preserve a stable weekly/monthly pattern while still adapting the immediate next occurrence to calendar realities. Materialized Occurrence Notes# Most recurring tasks can remain virtual: the parent task stores complete_instances and skipped_instances, and TaskNotes renders each calendar/list instance from that parent. Materialized occurrence notes are for heavier instances where the date-specific work needs its own note. Good uses include: A weekly review where each week needs a separate agenda and notes A maintenance task where each visit needs photos, links, or a checklist A recurring meeting where every occurrence should have its own time entries and completion state To create one manually, right-click a recurring task card or calendar occurrence and choose Open or create occurrence note. The Task Action Palette also exposes Open or create occurrence note for recurring tasks. If a matching note already exists for the same parent and date, TaskNotes opens it instead of creating a duplicate. An occurrence note is an ordinary TaskNotes task. It appears in views, can be edited like any other task, and shows an occurrence pill that links back to the recurring parent. On the calendar, a materialized occurrence replaces the matching virtual parent occurrence for the same parent/date pair, so you do not see both the generated instance and the note-backed instance at the same time. Its frontmatter includes: recurrence_parent: \"[[Tasks/Weekly review]]\" occurrence_date: \"2026-06-01\" scheduled: \"2026-06-01T09:30\" timeEstimate: 45 When TaskNotes creates an occurrence note, it copies the parent fields that describe how that instance should be planned: title, priority, scheduled time, due offset, contexts, projects, tags, reminders, dependencies, details, custom properties, and time estimate. Date-like fields are rebased onto the occurrence date, so a parent scheduled at 09:30 creates an occurrence scheduled at 09:30 on the selected date, and a due date one day after the parent scheduled date stays one day after the occurrence scheduled date. Occurrence notes can use a separate template from regular new tasks. Set occurrence_template on the recurring parent to point at a template note, or configure Settings → Features → Body template → Occurrence note template file as a global fallback. Parent-level occurrence_template wins over the global fallback. If neither occurrence-specific template is configured, occurrence note creation keeps the normal body template behavior. The parent task remains the source of the recurrence rule and series history. Occurrence notes do not copy the parent's recurrence, complete_instances, skipped_instances, completedDate, calendar provider IDs, or timeEntries. New time entries belong to the occurrence note once you track time there. Occurrence Filenames# By default, materialized occurrence notes use the existing filename behavior: the parent title followed by a numeric suffix. To opt in to custom filenames, set Occurrence filename template under Settings → Task Properties → Title. For example, {{title}} — {{occurrenceDate}} produces Weekly review — 2026-08-01.md. Occurrence filename templates support all regular filename variables plus these occurrence-specific variables: {{occurrenceDate}} - occurrence date, such as 2026-08-01 {{occurrenceWeek}} - ISO week, such as 2026-W31 {{occurrenceMonth}} - month, such as 2026-08 {{occurrenceYear}} - year, such as 2026 {{occurrenceMonthName}} - full month name, such as August Choose the date granularity explicitly in the template; TaskNotes does not infer it from the recurrence rule. A recurring parent can override the global template with the frontmatter property configured by Occurrence template override property (by default, occurrenceFilenameTemplate): occurrenceFilenameTemplate: \"{{title}} ({{occurrenceWeek}})\" Leaving the global template empty preserves the existing filename behavior. TaskNotes never renames existing occurrence notes, and filename collisions continue to receive a numeric suffix. Occurrence Note Policies# Each recurring parent has an Occurrence notes submenu under its recurrence menu: Create manually: occurrence notes are only created by explicit action. Create next after completion: after you complete a materialized occurrence note, TaskNotes creates the next occurrence note. Rolling window: defined by the TaskNotes spec, but not automated in the plugin yet. When Create next after completion is enabled, creating the first occurrence is still a deliberate action. After that, completing the occurrence note advances the parent recurrence state and materializes the next scheduled occurrence. HTTP API and MCP clients can create occurrence notes without using the desktop context menu. Use POST /api/tasks/:id/materialize-occurrence or the MCP tasknotes_materialize_occurrence tool with a parent task path and occurrence date. Completing a recurring instance through the API or MCP also respects existing occurrence notes and the Create next after completion policy. The same submenu also controls the next-note trigger: Completion only: create the next occurrence note only when the current occurrence is completed. Completion or skip: create the next occurrence note when the current occurrence is completed or skipped. Skip/unskip controls appear on materialized occurrence notes when a skipped status is configured. Skipping an occurrence preserves the note, updates its status, and reconciles the parent skipped_instances list. Completion Reconciliation# When a materialized occurrence note is completed, TaskNotes updates both sides of the relationship: The occurrence note is completed like a normal task. The parent adds the occurrence date to complete_instances. The parent removes that date from skipped_instances if needed. The parent recalculates scheduled to the next uncompleted occurrence. If the parent policy is Create next after completion, TaskNotes creates the next occurrence note idempotently. Uncompleting an occurrence note removes the date from the parent's complete_instances list, but it does not delete later occurrence notes that were already created. Example Behavior# # Initial state recurrence: \"DTSTART:20250804T090000Z;FREQ=DAILY\" scheduled: \"2025-08-04T09:00\" complete_instances: [] # After completing Aug 4 recurrence: \"DTSTART:20250804T090000Z;FREQ=DAILY\" scheduled: \"2025-08-05T09:00\" complete_instances: [\"2025-08-04\"] # After manually rescheduling next occurrence recurrence: \"DTSTART:20250804T090000Z;FREQ=DAILY\" scheduled: \"2025-08-05T14:30\" complete_instances: [\"2025-08-04\"] Calendar Drag and Drop# Calendar interactions follow the same model distinction: drag the concrete next item to reschedule execution, or drag a pattern instance to redefine the recurrence anchor. Recurring tasks can show: Next occurrence (solid border): dragging updates only scheduled Pattern instances (dashed border): dragging updates DTSTART and future pattern instances Materialized occurrence notes: dragging updates the occurrence note's own scheduled or due date like a normal task, without changing the parent's recurrence rule Materialized occurrence notes keep occurrence_date as their identity. If you drag the note for the June 1 occurrence to June 2, it is still the June 1 recurrence instance, now scheduled for June 2. TaskNotes suppresses the June 1 virtual parent event and leaves the June 2 virtual occurrence alone unless that date also has its own materialized note. Completion Tracking# Each occurrence can be completed or skipped independently (task cards, calendar menus, task edit modal completion calendar). Completed instances are stored in: complete_instances: [\"2025-08-04\", \"2025-08-06\", \"2025-08-08\"] Skipped instances are stored in: skipped_instances: [\"2025-08-05\"] When completion changes, scheduled updates to the next uncompleted instance. If a materialized occurrence note exists for a date, that note's own status takes precedence for that occurrence, and TaskNotes reconciles the parent compatibility lists during completion, uncompletion, skip, and unskip actions. This means completion history and next-action planning stay synchronized automatically, without manually advancing recurring tasks. Flexible Scheduling# TaskNotes intentionally allows off-pattern scheduling so recurring tasks can absorb real-world disruptions without rewriting the entire recurrence rule. The next occurrence can be: Before DTSTART Outside the pattern day At a different time than pattern instances Far ahead while pattern continues unchanged Examples# # Early start before DTSTART recurrence: \"DTSTART:20250810T090000Z;FREQ=WEEKLY;BYDAY=MO\" scheduled: \"2025-08-07T14:00\" # Off-pattern next occurrence recurrence: \"DTSTART:20250804T090000Z;FREQ=WEEKLY;BYDAY=MO\" scheduled: \"2025-08-06T15:30\" Timezone Handling# Recurring task logic uses a UTC anchor approach: Pattern generation uses UTC dates DTSTART dates are interpreted as UTC anchors Display adapts to local timezone Prevents common off-by-one date issues In other words, calculations stay stable internally while display remains local, which avoids drift when traveling or sharing vaults across timezones. Backward Compatibility# Recurring behavior remains compatible with older task data, so upgrades do not require manual note rewrites. Legacy RRule strings without DTSTART continue to work using scheduled as anchor Legacy recurrence objects are converted to RRule format Existing tasks continue to function without migration steps Mixed formats are handled transparently"},{"route":"/obsidian/features/reminders/","title":"Task Reminders","description":"TaskNotes reminders use iCalendar VALARM semantics and support both relative and absolute reminder types.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/features/reminders.md","namespace":"obsidian","relativePath":"features/reminders.md","raw":"# Task Reminders\n\n\nTaskNotes reminders use iCalendar `VALARM` semantics and support both relative and absolute reminder types.\n\nThe reminders system is designed to support both habit-like workflows (\"always remind me 15 minutes before\") and one-off commitments (\"alert me exactly at this date and time\"). Most users mix both styles depending on the task.\n\n## Reminder Types\n\n### Relative Reminders\n\nRelative reminders trigger from `due` or `scheduled` dates.\n\nUse relative reminders when you want reminder behavior to stay consistent even when task dates change.\n\nExamples:\n\n- 15 minutes before due date\n- 1 hour before scheduled date\n- 2 days before due date\n- 30 minutes after scheduled date\n\n### Absolute Reminders\n\nAbsolute reminders trigger at a fixed date/time.\n\nUse absolute reminders when the reminder itself is tied to a specific moment, independent of task rescheduling.\n\nExamples:\n\n- October 26, 2025 at 9:00 AM\n- Tomorrow at 2:30 PM\n- Next Monday at 10:00 AM\n\n## Adding Reminders\n\nYou can add reminders from:\n\n1. **Task Creation Modal**\n2. **Task Edit Modal**\n3. **Task Cards** (bell icon)\n4. **Reminder field context menu**\n\nFrom a workflow perspective, task cards and context menus are fastest for quick reminders, while task modals are better for reviewing multiple reminders on the same task.\n\n![Task edit modal](../assets/feature-task-modal-edit.png)\n\n### Quick Reminder Options\n\nCommon shortcuts are available for both due and scheduled anchors, such as:\n\n- 5 minutes before\n- 15 minutes before\n- 1 hour before\n- 1 day before\n\nQuick options appear only when the anchor date exists.\n\nThis prevents invalid reminder states and keeps the quick menu focused on options that can be applied immediately.\n\n![Task context menu](../assets/feature-task-context-menu.png)\n\n## Reminder Data Format\n\nReminders are stored in YAML frontmatter arrays.\n\nBecause reminders are stored in frontmatter, they remain portable and scriptable. You can inspect or transform reminder data with any tooling that reads Markdown + YAML.\n\n### Relative Structure\n\n```yaml\nreminders:\n - id: \"rem_1678886400000_abc123xyz\"\n type: \"relative\"\n relatedTo: \"due\"\n offset: \"-PT15M\"\n description: \"Review task details\"\n```\n\n### Absolute Structure\n\n```yaml\nreminders:\n - id: \"rem_1678886400001_def456uvw\"\n type: \"absolute\"\n absoluteTime: \"2025-10-26T09:00:00\"\n description: \"Follow up with client\"\n```\n\nField meanings:\n\n- `id`: unique identifier\n- `type`: `relative` or `absolute`\n- `relatedTo`: `due` or `scheduled` (relative only)\n- `offset`: ISO 8601 duration, negative before and positive after (relative only)\n- `absoluteTime`: ISO 8601 timestamp (absolute only)\n- `description`: optional message\n\nYou typically do not need to edit these fields manually, but understanding the structure helps when debugging automation or importing task data.\n\n## Visual Indicators\n\nTasks with reminders show a bell icon on task cards.\n\n- Solid bell indicates active reminders\n- Clicking opens quick reminder actions\n- Reminder UI shows task context (due/scheduled dates and reminder count)\n\nThese indicators are intended to make reminders discoverable in list-heavy views without opening every task.\n\n## Default Reminders\n\nDefault reminders can be configured in:\n\n`Settings -> TaskNotes -> Task Properties -> Reminders`\n\nDefaults are applied to:\n\n- Manual task creation\n- Instant conversion\n- Natural language task creation\n\nDefault reminders are useful for recurring habits, such as pre-deadline checks or day-before planning prompts.\n\n![Task properties settings](../assets/settings-task-properties.png)\n\n## Technical Notes\n\n- Reminders follow iCalendar `VALARM` concepts with ISO 8601 offsets\n- The reminder property name can be customized through field mapping\n\nFor settings-level behavior (notification channels, enable/disable state), see [Features Settings](../settings/features.md).\n","aliases":["/features/reminders/"],"toc":[{"level":2,"id":"reminder-types","text":"Reminder Types"},{"level":3,"id":"relative-reminders","text":"Relative Reminders"},{"level":3,"id":"absolute-reminders","text":"Absolute Reminders"},{"level":2,"id":"adding-reminders","text":"Adding Reminders"},{"level":3,"id":"quick-reminder-options","text":"Quick Reminder Options"},{"level":2,"id":"reminder-data-format","text":"Reminder Data Format"},{"level":3,"id":"relative-structure","text":"Relative Structure"},{"level":3,"id":"absolute-structure","text":"Absolute Structure"},{"level":2,"id":"visual-indicators","text":"Visual Indicators"},{"level":2,"id":"default-reminders","text":"Default Reminders"},{"level":2,"id":"technical-notes","text":"Technical Notes"}],"html":"

TaskNotes reminders use iCalendar VALARM semantics and support both relative and absolute reminder types.

\n

The reminders system is designed to support both habit-like workflows ("always remind me 15 minutes before") and one-off commitments ("alert me exactly at this date and time"). Most users mix both styles depending on the task.

\n

Reminder Types#

\n

Relative Reminders#

\n

Relative reminders trigger from due or scheduled dates.

\n

Use relative reminders when you want reminder behavior to stay consistent even when task dates change.

\n

Examples:

\n
    \n
  • 15 minutes before due date
  • \n
  • 1 hour before scheduled date
  • \n
  • 2 days before due date
  • \n
  • 30 minutes after scheduled date
  • \n
\n

Absolute Reminders#

\n

Absolute reminders trigger at a fixed date/time.

\n

Use absolute reminders when the reminder itself is tied to a specific moment, independent of task rescheduling.

\n

Examples:

\n
    \n
  • October 26, 2025 at 9:00 AM
  • \n
  • Tomorrow at 2:30 PM
  • \n
  • Next Monday at 10:00 AM
  • \n
\n

Adding Reminders#

\n

You can add reminders from:

\n
    \n
  1. Task Creation Modal
  2. \n
  3. Task Edit Modal
  4. \n
  5. Task Cards (bell icon)
  6. \n
  7. Reminder field context menu
  8. \n
\n

From a workflow perspective, task cards and context menus are fastest for quick reminders, while task modals are better for reviewing multiple reminders on the same task.

\n

\"Task

\n

Quick Reminder Options#

\n

Common shortcuts are available for both due and scheduled anchors, such as:

\n
    \n
  • 5 minutes before
  • \n
  • 15 minutes before
  • \n
  • 1 hour before
  • \n
  • 1 day before
  • \n
\n

Quick options appear only when the anchor date exists.

\n

This prevents invalid reminder states and keeps the quick menu focused on options that can be applied immediately.

\n

\"Task

\n

Reminder Data Format#

\n

Reminders are stored in YAML frontmatter arrays.

\n

Because reminders are stored in frontmatter, they remain portable and scriptable. You can inspect or transform reminder data with any tooling that reads Markdown + YAML.

\n

Relative Structure#

\n
reminders:\n  - id: "rem_1678886400000_abc123xyz"\n    type: "relative"\n    relatedTo: "due"\n    offset: "-PT15M"\n    description: "Review task details"\n

Absolute Structure#

\n
reminders:\n  - id: "rem_1678886400001_def456uvw"\n    type: "absolute"\n    absoluteTime: "2025-10-26T09:00:00"\n    description: "Follow up with client"\n

Field meanings:

\n
    \n
  • id: unique identifier
  • \n
  • type: relative or absolute
  • \n
  • relatedTo: due or scheduled (relative only)
  • \n
  • offset: ISO 8601 duration, negative before and positive after (relative only)
  • \n
  • absoluteTime: ISO 8601 timestamp (absolute only)
  • \n
  • description: optional message
  • \n
\n

You typically do not need to edit these fields manually, but understanding the structure helps when debugging automation or importing task data.

\n

Visual Indicators#

\n

Tasks with reminders show a bell icon on task cards.

\n
    \n
  • Solid bell indicates active reminders
  • \n
  • Clicking opens quick reminder actions
  • \n
  • Reminder UI shows task context (due/scheduled dates and reminder count)
  • \n
\n

These indicators are intended to make reminders discoverable in list-heavy views without opening every task.

\n

Default Reminders#

\n

Default reminders can be configured in:

\n

Settings -> TaskNotes -> Task Properties -> Reminders

\n

Defaults are applied to:

\n
    \n
  • Manual task creation
  • \n
  • Instant conversion
  • \n
  • Natural language task creation
  • \n
\n

Default reminders are useful for recurring habits, such as pre-deadline checks or day-before planning prompts.

\n

\"Task

\n

Technical Notes#

\n
    \n
  • Reminders follow iCalendar VALARM concepts with ISO 8601 offsets
  • \n
  • The reminder property name can be customized through field mapping
  • \n
\n

For settings-level behavior (notification channels, enable/disable state), see Features Settings.

\n","text":"TaskNotes reminders use iCalendar VALARM semantics and support both relative and absolute reminder types. The reminders system is designed to support both habit-like workflows (\"always remind me 15 minutes before\") and one-off commitments (\"alert me exactly at this date and time\"). Most users mix both styles depending on the task. Reminder Types# Relative Reminders# Relative reminders trigger from due or scheduled dates. Use relative reminders when you want reminder behavior to stay consistent even when task dates change. Examples: 15 minutes before due date 1 hour before scheduled date 2 days before due date 30 minutes after scheduled date Absolute Reminders# Absolute reminders trigger at a fixed date/time. Use absolute reminders when the reminder itself is tied to a specific moment, independent of task rescheduling. Examples: October 26, 2025 at 9:00 AM Tomorrow at 2:30 PM Next Monday at 10:00 AM Adding Reminders# You can add reminders from: Task Creation Modal Task Edit Modal Task Cards (bell icon) Reminder field context menu From a workflow perspective, task cards and context menus are fastest for quick reminders, while task modals are better for reviewing multiple reminders on the same task. Quick Reminder Options# Common shortcuts are available for both due and scheduled anchors, such as: 5 minutes before 15 minutes before 1 hour before 1 day before Quick options appear only when the anchor date exists. This prevents invalid reminder states and keeps the quick menu focused on options that can be applied immediately. Reminder Data Format# Reminders are stored in YAML frontmatter arrays. Because reminders are stored in frontmatter, they remain portable and scriptable. You can inspect or transform reminder data with any tooling that reads Markdown + YAML. Relative Structure# reminders: - id: \"rem_1678886400000_abc123xyz\" type: \"relative\" relatedTo: \"due\" offset: \"-PT15M\" description: \"Review task details\" Absolute Structure# reminders: - id: \"rem_1678886400001_def456uvw\" type: \"absolute\" absoluteTime: \"2025-10-26T09:00:00\" description: \"Follow up with client\" Field meanings: id: unique identifier type: relative or absolute relatedTo: due or scheduled (relative only) offset: ISO 8601 duration, negative before and positive after (relative only) absoluteTime: ISO 8601 timestamp (absolute only) description: optional message You typically do not need to edit these fields manually, but understanding the structure helps when debugging automation or importing task data. Visual Indicators# Tasks with reminders show a bell icon on task cards. Solid bell indicates active reminders Clicking opens quick reminder actions Reminder UI shows task context (due/scheduled dates and reminder count) These indicators are intended to make reminders discoverable in list-heavy views without opening every task. Default Reminders# Default reminders can be configured in: Settings -> TaskNotes -> Task Properties -> Reminders Defaults are applied to: Manual task creation Instant conversion Natural language task creation Default reminders are useful for recurring habits, such as pre-deadline checks or day-before planning prompts. Technical Notes# Reminders follow iCalendar VALARM concepts with ISO 8601 offsets The reminder property name can be customized through field mapping For settings-level behavior (notification channels, enable/disable state), see Features Settings."},{"route":"/obsidian/features/task-management/","title":"Task Management","description":"This page covers task creation, properties, projects, dependencies, recurring tasks, and reminders. For the underlying architecture, see Core Concepts.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/features/task-management.md","namespace":"obsidian","relativePath":"features/task-management.md","raw":"# Task Management\n\n\nThis page covers task creation, properties, projects, dependencies, recurring tasks, and reminders. For the underlying architecture, see [Core Concepts](../core-concepts.md).\n\nUse this page as the operational overview: how tasks are captured, how they are structured, and how relationships/automation behave. Detailed reference content for recurrence and reminders is split into dedicated pages linked near the end.\n\n## Creating and Editing Tasks\n\nYou can create and edit tasks in a variety of ways. The primary method is through the **Task Creation Modal**, which can be accessed via the \"Create new task\" command or by clicking on dates or time slots in the calendar views. This modal provides an interface for setting all available task properties, including title, status, priority, and due dates.\n\n![Task creation modal](../assets/feature-task-modal-filled.png)\n\nTaskNotes keeps a storage title and a filename-safe title separate. When **Store title in filename** is enabled, forbidden filename characters are removed from the filename while the task title is preserved whenever it cannot be represented exactly by that filename. With another filename format, such as timestamp or UUID, the full title is stored in frontmatter.\n\nFor existing tasks, the **Quick actions for current task** command opens a keyboard-searchable action palette. It includes status, priority, time-tracking, archive, edit, and date actions, including built-in due and scheduled date presets such as today, tomorrow, this weekend, next week, and next month.\n\nTaskNotes also supports **Natural Language Creation**, which allows you to create tasks by typing descriptions in plain English. The built-in parser can extract structured data from phrases like \"Buy groceries tomorrow at 3pm @home #errands high priority.\"\n\nIn most workflows, users combine both approaches: fast capture with natural language, then occasional structured edits in the modal when more precision is needed.\n\n### Auto-Suggestions in Natural Language Input\n\nThe natural language input field includes auto-suggestion functionality that activates when typing specific trigger characters:\n\n- **@** - Shows available contexts from existing tasks\n- **#** - Shows available tags from existing tasks\n- **+** - Shows files from your vault as project suggestions\n- **\\*** - Shows available status options (configurable trigger in Settings → Features)\n\nIn task creation and edit fields, focusing the tags or contexts input also opens the available suggestions immediately, so you can pick from the current vocabulary without typing a first character.\n\n#### Project Suggestions\n\nWhen typing `+` in the natural language input, you'll see up to 20 suggestions from your vault's markdown files. The suggestions display additional information to help identify files:\n\n```\nproject-alpha [title: Alpha Project Development | aliases: alpha, proj-alpha]\nmeeting-notes [title: Weekly Team Meeting Notes]\nsimple-project\nwork-file [aliases: work, office-tasks]\n```\n\nProject suggestions search across:\n- File names (basename without extension)\n- Frontmatter titles (using your configured field mapping)\n- Frontmatter aliases\n- Optional filtering by required tags, folders, and a specific frontmatter property/value defined in Settings → Appearance & UI → Project Autosuggest\n\nSelecting a project suggestion inserts it as `+[[filename]]`, creating a wikilink to the file while maintaining the `+` project marker that the natural language parser recognizes.\n\n\n#### Enhanced Project Auto‑suggester (configurable cards)\n\nProject suggestions can display configurable multi‑row cards and support smarter search. Configure up to 3 rows using a simple token syntax in Settings → Appearance & UI → Project Autosuggest.\n\n- Properties: file.basename, file.name, file.path, file.parent, title, aliases, and any frontmatter key\n- Flags:\n - n or n(Label) → show the field name/label before the value\n - s → include this field in + search (in addition to defaults)\n- Literals: you can mix in fixed text or emojis between tokens\n\nExamples\n\n- \"{title|n(Title)}\" → Title: Alpha Project\n- \"🔖 {aliases|n(Aliases)}\" → 🔖 Aliases: alpha, proj-alpha\n- \"{file.path|n(Path)|s}\" → include path in + search as well as display it\n\nSearch behavior\n\n- Defaults: + search always includes file basename, title (via your field mapping), and aliases\n- |s flag: add more searchable fields on top of the defaults (e.g., file.path or a custom frontmatter key like customer)\n- Fuzzy: optional fuzzy matching can be enabled in settings for broader, multi‑word matches\n\nPerformance tips\n\n- Keep rows to three or fewer for clarity and performance (the UI supports up to 3)\n- Prefer specific searchable fields with |s on large vaults\n\nDemo\n\n![Autosuggest projects with spaces](../assets/autosuggest_project_names_with_space.gif)\n\n![Enhanced project autosuggester](../assets/enhanced-project-auto-suggester.gif)\n\n\n#### Status Suggestions\n\nWhen typing the status trigger character (default `*`) in the natural language input, you'll see suggestions for all configured status options:\n\n![Status Auto-Suggestion](../assets/auto-suggest-status.gif)\n\nStatus suggestions allow quick selection of statuses when creating tasks. For example, typing `*in` shows \"In Progress\" as a suggestion if that's one of your configured statuses.\n\nClicking a task card's status indicator cycles through statuses in the order configured under **Settings → Task Properties → Status**. A status can optionally define a specific **Next status** for forward cycling; otherwise TaskNotes uses the configured order. Statuses marked **Skip when cycling** are left out of the ordered click cycle, but remain available through menus, suggestions, direct edits, and explicit next-status jumps.\n\nAdditionally, you can convert any line type in your notes to TaskNotes using the **Instant Conversion** feature. This works with checkboxes, bullet points, numbered lists, blockquotes, headers, and plain text lines.\n\n## Task Properties\n\nTasks store their data in YAML frontmatter with properties for status, priority, dates, contexts, projects, tags, time estimates, recurrence, and reminders. Custom fields can extend this structure.\n\nThis frontmatter-first design keeps task data editable and portable while supporting consistent behavior across views and widgets.\n\nFor property types and examples, see [Core Concepts](../core-concepts.md#yaml-frontmatter). For configuration options, see [Task Properties Settings](../settings/task-properties.md).\n\n## Projects\n\nTaskNotes supports organizing tasks into projects using note-based linking. Projects are represented as links to actual notes in your vault, allowing you to leverage Obsidian's linking and backlinking features for project management.\n\nThis model avoids creating a separate project database. Any note can become a project anchor, and task/project relationships remain visible through normal Obsidian link tooling.\n\n### Project Assignment\n\nTasks can be assigned to one or more projects through the task creation or editing interface. When creating or editing a task, click the \"Add Project\" button to open the project selection modal. This modal provides fuzzy search functionality to quickly find and select project notes from your vault.\n\n### Project Links\n\nProjects are stored as wikilinks in the task's frontmatter (e.g., `projects: [\"[[Project A]]\", \"[[Project B]]\"]`). These links are clickable in the task interface and will navigate directly to the project notes when clicked. Any note in your vault can serve as a project note simply by being linked from a task's projects field.\n\n### Organization and Filtering\n\nTasks can be filtered and grouped by their associated projects in all Bases-driven task views. Use the Bases filter editor to add `note.projects` conditions, and configure the grouping menu to organize Task List or Kanban boards by project. Tasks assigned to multiple projects will appear in each relevant project group, providing flexibility in project-based organization.\n\n### Project Indicators\n\nTaskCards display visual indicators when tasks are used as projects. These indicators help identify which tasks have other tasks linked to them as subtasks, making project hierarchy visible at a glance.\n\n### Subtask Creation\n\nTasks can have subtasks created directly from their context menu. When viewing a task that serves as a project, you can select \"Create subtask\" to create a new task automatically linked to the current project.\n\n## Dependencies\n\nTask dependencies capture prerequisite work using RFC 9253 terminology. Dependencies are stored in frontmatter as structured objects:\n\n```yaml\nblockedBy:\n - uid: \"[[Operations/Order hardware]]\"\n reltype: FINISHTOSTART\n gap: P1D\n```\n\n- `uid` references the blocking task, typically through an Obsidian wikilink.\n- `reltype` is stored with each dependency and defaults to `FINISHTOSTART` for dependencies created in the UI.\n- `gap` is optional and uses ISO 8601 duration syntax (for example `PT4H` or `P2D`).\n\nWhenever a dependency is added, TaskNotes updates the upstream note’s `blocking` list so the reverse relationship stays synchronized. Removing a dependency automatically clears both sides.\n\n### Selecting dependencies in the UI\n\n- The task creation and edit modals expose “Blocked by” and “Blocking” buttons that launch a fuzzy task selector. The picker only offers valid tasks, excludes the current note, and prevents duplicate entries.\n- The task context menu provides the same selector, enabling dependency management directly from the Task List, Kanban, and calendar views.\n- Task cards show a fork icon whenever a task blocks other work. Clicking it expands an inline list of downstream tasks without triggering the parent card’s modal, so you can inspect dependents in place.\n\nThese controls currently create and manage finish-to-start style blockers. Advanced `reltype` values and `gap` data are preserved in frontmatter, but blocking evaluation is currently based on whether unresolved dependencies exist rather than relationship-type-specific scheduling rules.\n\n![Task context menu](../assets/feature-task-context-menu.png)\n\n## Automation\n\n### Auto-Archiving\n\nTaskNotes can automatically archive tasks when they transition into a status that has auto-archiving enabled. This keeps completed work out of your active lists without requiring manual cleanup.\n\nConfigure auto-archiving per status from **Settings → Task Properties → Task Statuses**. Each status card includes an **Auto-archive** toggle and a **Delay (minutes)** input (1–1440). When you turn the toggle on for a status, any task moved into that status is queued for archiving once the delay elapses. Moving the task to a different status before the timer expires cancels the pending archive automatically.\n\nThe auto-archive queue runs in the background and persists across plugin restarts. If TaskNotes was closed while an archive was pending, the task will be archived shortly after the plugin loads again as long as it still matches the configured status.\n\nThis automation is intended to keep active views focused without manual cleanup, while still preserving archived task history in your vault.\n\n## File Management and Templates\n\nTaskNotes supports configurable task folder locations, filename generation patterns, archive behavior, and body templates for newly created tasks.\n\nThese settings let you align task files with existing vault conventions (for example, date-based folders, project-based routing, or template-driven task note scaffolds).\n\nFor configuration details, see [Task Defaults](../settings/task-defaults.md). \nFor template variables, see [Template Variables Reference](template-variables.md).\n\n## Recurring Tasks\n\nTaskNotes recurring tasks use RFC 5545 RRule syntax with `DTSTART`, separate pattern definition from next occurrence scheduling, and support independent instance completion. When an individual recurrence needs its own checklist, time entries, or notes, you can create a materialized occurrence note from the task or calendar context menu.\n\nFor full behavior, examples, and edge cases, see [Recurring Tasks](recurring-tasks.md).\n\n## Task Reminders\n\nTask reminders support relative offsets from due/scheduled dates and absolute date-time reminders. You can add reminders from task modals, task cards, and context menus.\n\nFor full setup, data format, defaults, and UI behavior, see [Task Reminders](reminders.md).\n","aliases":["/features/task-management/"],"toc":[{"level":2,"id":"creating-and-editing-tasks","text":"Creating and Editing Tasks"},{"level":3,"id":"auto-suggestions-in-natural-language-input","text":"Auto-Suggestions in Natural Language Input"},{"level":2,"id":"task-properties","text":"Task Properties"},{"level":2,"id":"projects","text":"Projects"},{"level":3,"id":"project-assignment","text":"Project Assignment"},{"level":3,"id":"project-links","text":"Project Links"},{"level":3,"id":"organization-and-filtering","text":"Organization and Filtering"},{"level":3,"id":"project-indicators","text":"Project Indicators"},{"level":3,"id":"subtask-creation","text":"Subtask Creation"},{"level":2,"id":"dependencies","text":"Dependencies"},{"level":3,"id":"selecting-dependencies-in-the-ui","text":"Selecting dependencies in the UI"},{"level":2,"id":"automation","text":"Automation"},{"level":3,"id":"auto-archiving","text":"Auto-Archiving"},{"level":2,"id":"file-management-and-templates","text":"File Management and Templates"},{"level":2,"id":"recurring-tasks","text":"Recurring Tasks"},{"level":2,"id":"task-reminders","text":"Task Reminders"}],"html":"

This page covers task creation, properties, projects, dependencies, recurring tasks, and reminders. For the underlying architecture, see Core Concepts.

\n

Use this page as the operational overview: how tasks are captured, how they are structured, and how relationships/automation behave. Detailed reference content for recurrence and reminders is split into dedicated pages linked near the end.

\n

Creating and Editing Tasks#

\n

You can create and edit tasks in a variety of ways. The primary method is through the Task Creation Modal, which can be accessed via the "Create new task" command or by clicking on dates or time slots in the calendar views. This modal provides an interface for setting all available task properties, including title, status, priority, and due dates.

\n

\"Task

\n

TaskNotes keeps a storage title and a filename-safe title separate. When Store title in filename is enabled, forbidden filename characters are removed from the filename while the task title is preserved whenever it cannot be represented exactly by that filename. With another filename format, such as timestamp or UUID, the full title is stored in frontmatter.

\n

For existing tasks, the Quick actions for current task command opens a keyboard-searchable action palette. It includes status, priority, time-tracking, archive, edit, and date actions, including built-in due and scheduled date presets such as today, tomorrow, this weekend, next week, and next month.

\n

TaskNotes also supports Natural Language Creation, which allows you to create tasks by typing descriptions in plain English. The built-in parser can extract structured data from phrases like "Buy groceries tomorrow at 3pm @home #errands high priority."

\n

In most workflows, users combine both approaches: fast capture with natural language, then occasional structured edits in the modal when more precision is needed.

\n

Auto-Suggestions in Natural Language Input#

\n

The natural language input field includes auto-suggestion functionality that activates when typing specific trigger characters:

\n
    \n
  • @ - Shows available contexts from existing tasks
  • \n
  • # - Shows available tags from existing tasks
  • \n
  • + - Shows files from your vault as project suggestions
  • \n
  • * - Shows available status options (configurable trigger in Settings → Features)
  • \n
\n

In task creation and edit fields, focusing the tags or contexts input also opens the available suggestions immediately, so you can pick from the current vocabulary without typing a first character.

\n

Project Suggestions#

\n

When typing + in the natural language input, you'll see up to 20 suggestions from your vault's markdown files. The suggestions display additional information to help identify files:

\n
project-alpha [title: Alpha Project Development | aliases: alpha, proj-alpha]\nmeeting-notes [title: Weekly Team Meeting Notes]\nsimple-project\nwork-file [aliases: work, office-tasks]\n

Project suggestions search across:

\n
    \n
  • File names (basename without extension)
  • \n
  • Frontmatter titles (using your configured field mapping)
  • \n
  • Frontmatter aliases
  • \n
  • Optional filtering by required tags, folders, and a specific frontmatter property/value defined in Settings → Appearance & UI → Project Autosuggest
  • \n
\n

Selecting a project suggestion inserts it as +[[filename]], creating a wikilink to the file while maintaining the + project marker that the natural language parser recognizes.

\n

Enhanced Project Auto‑suggester (configurable cards)#

\n

Project suggestions can display configurable multi‑row cards and support smarter search. Configure up to 3 rows using a simple token syntax in Settings → Appearance & UI → Project Autosuggest.

\n
    \n
  • Properties: file.basename, file.name, file.path, file.parent, title, aliases, and any frontmatter key
  • \n
  • Flags:
      \n
    • n or n(Label) → show the field name/label before the value
    • \n
    • s → include this field in + search (in addition to defaults)
    • \n
    \n
  • \n
  • Literals: you can mix in fixed text or emojis between tokens
  • \n
\n

Examples

\n
    \n
  • "{title|n(Title)}" → Title: Alpha Project
  • \n
  • "🔖 {aliases|n(Aliases)}" → 🔖 Aliases: alpha, proj-alpha
  • \n
  • "{file.path|n(Path)|s}" → include path in + search as well as display it
  • \n
\n

Search behavior

\n
    \n
  • Defaults: + search always includes file basename, title (via your field mapping), and aliases
  • \n
  • |s flag: add more searchable fields on top of the defaults (e.g., file.path or a custom frontmatter key like customer)
  • \n
  • Fuzzy: optional fuzzy matching can be enabled in settings for broader, multi‑word matches
  • \n
\n

Performance tips

\n
    \n
  • Keep rows to three or fewer for clarity and performance (the UI supports up to 3)
  • \n
  • Prefer specific searchable fields with |s on large vaults
  • \n
\n

Demo

\n

\"Autosuggest

\n

\"Enhanced

\n

Status Suggestions#

\n

When typing the status trigger character (default *) in the natural language input, you'll see suggestions for all configured status options:

\n

\"Status

\n

Status suggestions allow quick selection of statuses when creating tasks. For example, typing *in shows "In Progress" as a suggestion if that's one of your configured statuses.

\n

Clicking a task card's status indicator cycles through statuses in the order configured under Settings → Task Properties → Status. A status can optionally define a specific Next status for forward cycling; otherwise TaskNotes uses the configured order. Statuses marked Skip when cycling are left out of the ordered click cycle, but remain available through menus, suggestions, direct edits, and explicit next-status jumps.

\n

Additionally, you can convert any line type in your notes to TaskNotes using the Instant Conversion feature. This works with checkboxes, bullet points, numbered lists, blockquotes, headers, and plain text lines.

\n

Task Properties#

\n

Tasks store their data in YAML frontmatter with properties for status, priority, dates, contexts, projects, tags, time estimates, recurrence, and reminders. Custom fields can extend this structure.

\n

This frontmatter-first design keeps task data editable and portable while supporting consistent behavior across views and widgets.

\n

For property types and examples, see Core Concepts. For configuration options, see Task Properties Settings.

\n

Projects#

\n

TaskNotes supports organizing tasks into projects using note-based linking. Projects are represented as links to actual notes in your vault, allowing you to leverage Obsidian's linking and backlinking features for project management.

\n

This model avoids creating a separate project database. Any note can become a project anchor, and task/project relationships remain visible through normal Obsidian link tooling.

\n

Project Assignment#

\n

Tasks can be assigned to one or more projects through the task creation or editing interface. When creating or editing a task, click the "Add Project" button to open the project selection modal. This modal provides fuzzy search functionality to quickly find and select project notes from your vault.

\n

Project Links#

\n

Projects are stored as wikilinks in the task's frontmatter (e.g., projects: ["[[Project A]]", "[[Project B]]"]). These links are clickable in the task interface and will navigate directly to the project notes when clicked. Any note in your vault can serve as a project note simply by being linked from a task's projects field.

\n

Organization and Filtering#

\n

Tasks can be filtered and grouped by their associated projects in all Bases-driven task views. Use the Bases filter editor to add note.projects conditions, and configure the grouping menu to organize Task List or Kanban boards by project. Tasks assigned to multiple projects will appear in each relevant project group, providing flexibility in project-based organization.

\n

Project Indicators#

\n

TaskCards display visual indicators when tasks are used as projects. These indicators help identify which tasks have other tasks linked to them as subtasks, making project hierarchy visible at a glance.

\n

Subtask Creation#

\n

Tasks can have subtasks created directly from their context menu. When viewing a task that serves as a project, you can select "Create subtask" to create a new task automatically linked to the current project.

\n

Dependencies#

\n

Task dependencies capture prerequisite work using RFC 9253 terminology. Dependencies are stored in frontmatter as structured objects:

\n
blockedBy:\n  - uid: "[[Operations/Order hardware]]"\n    reltype: FINISHTOSTART\n    gap: P1D\n
    \n
  • uid references the blocking task, typically through an Obsidian wikilink.
  • \n
  • reltype is stored with each dependency and defaults to FINISHTOSTART for dependencies created in the UI.
  • \n
  • gap is optional and uses ISO 8601 duration syntax (for example PT4H or P2D).
  • \n
\n

Whenever a dependency is added, TaskNotes updates the upstream note’s blocking list so the reverse relationship stays synchronized. Removing a dependency automatically clears both sides.

\n

Selecting dependencies in the UI#

\n
    \n
  • The task creation and edit modals expose “Blocked by” and “Blocking” buttons that launch a fuzzy task selector. The picker only offers valid tasks, excludes the current note, and prevents duplicate entries.
  • \n
  • The task context menu provides the same selector, enabling dependency management directly from the Task List, Kanban, and calendar views.
  • \n
  • Task cards show a fork icon whenever a task blocks other work. Clicking it expands an inline list of downstream tasks without triggering the parent card’s modal, so you can inspect dependents in place.
  • \n
\n

These controls currently create and manage finish-to-start style blockers. Advanced reltype values and gap data are preserved in frontmatter, but blocking evaluation is currently based on whether unresolved dependencies exist rather than relationship-type-specific scheduling rules.

\n

\"Task

\n

Automation#

\n

Auto-Archiving#

\n

TaskNotes can automatically archive tasks when they transition into a status that has auto-archiving enabled. This keeps completed work out of your active lists without requiring manual cleanup.

\n

Configure auto-archiving per status from Settings → Task Properties → Task Statuses. Each status card includes an Auto-archive toggle and a Delay (minutes) input (1–1440). When you turn the toggle on for a status, any task moved into that status is queued for archiving once the delay elapses. Moving the task to a different status before the timer expires cancels the pending archive automatically.

\n

The auto-archive queue runs in the background and persists across plugin restarts. If TaskNotes was closed while an archive was pending, the task will be archived shortly after the plugin loads again as long as it still matches the configured status.

\n

This automation is intended to keep active views focused without manual cleanup, while still preserving archived task history in your vault.

\n

File Management and Templates#

\n

TaskNotes supports configurable task folder locations, filename generation patterns, archive behavior, and body templates for newly created tasks.

\n

These settings let you align task files with existing vault conventions (for example, date-based folders, project-based routing, or template-driven task note scaffolds).

\n

For configuration details, see Task Defaults.
For template variables, see Template Variables Reference.

\n

Recurring Tasks#

\n

TaskNotes recurring tasks use RFC 5545 RRule syntax with DTSTART, separate pattern definition from next occurrence scheduling, and support independent instance completion. When an individual recurrence needs its own checklist, time entries, or notes, you can create a materialized occurrence note from the task or calendar context menu.

\n

For full behavior, examples, and edge cases, see Recurring Tasks.

\n

Task Reminders#

\n

Task reminders support relative offsets from due/scheduled dates and absolute date-time reminders. You can add reminders from task modals, task cards, and context menus.

\n

For full setup, data format, defaults, and UI behavior, see Task Reminders.

\n","text":"This page covers task creation, properties, projects, dependencies, recurring tasks, and reminders. For the underlying architecture, see Core Concepts. Use this page as the operational overview: how tasks are captured, how they are structured, and how relationships/automation behave. Detailed reference content for recurrence and reminders is split into dedicated pages linked near the end. Creating and Editing Tasks# You can create and edit tasks in a variety of ways. The primary method is through the Task Creation Modal, which can be accessed via the \"Create new task\" command or by clicking on dates or time slots in the calendar views. This modal provides an interface for setting all available task properties, including title, status, priority, and due dates. TaskNotes keeps a storage title and a filename-safe title separate. When Store title in filename is enabled, forbidden filename characters are removed from the filename while the task title is preserved whenever it cannot be represented exactly by that filename. With another filename format, such as timestamp or UUID, the full title is stored in frontmatter. For existing tasks, the Quick actions for current task command opens a keyboard-searchable action palette. It includes status, priority, time-tracking, archive, edit, and date actions, including built-in due and scheduled date presets such as today, tomorrow, this weekend, next week, and next month. TaskNotes also supports Natural Language Creation, which allows you to create tasks by typing descriptions in plain English. The built-in parser can extract structured data from phrases like \"Buy groceries tomorrow at 3pm @home #errands high priority.\" In most workflows, users combine both approaches: fast capture with natural language, then occasional structured edits in the modal when more precision is needed. Auto-Suggestions in Natural Language Input# The natural language input field includes auto-suggestion functionality that activates when typing specific trigger characters: @ - Shows available contexts from existing tasks # - Shows available tags from existing tasks + - Shows files from your vault as project suggestions * - Shows available status options (configurable trigger in Settings → Features) In task creation and edit fields, focusing the tags or contexts input also opens the available suggestions immediately, so you can pick from the current vocabulary without typing a first character. Project Suggestions# When typing + in the natural language input, you'll see up to 20 suggestions from your vault's markdown files. The suggestions display additional information to help identify files: project-alpha [title: Alpha Project Development | aliases: alpha, proj-alpha] meeting-notes [title: Weekly Team Meeting Notes] simple-project work-file [aliases: work, office-tasks] Project suggestions search across: File names (basename without extension) Frontmatter titles (using your configured field mapping) Frontmatter aliases Optional filtering by required tags, folders, and a specific frontmatter property/value defined in Settings → Appearance & UI → Project Autosuggest Selecting a project suggestion inserts it as +[[filename]], creating a wikilink to the file while maintaining the + project marker that the natural language parser recognizes. Enhanced Project Auto‑suggester (configurable cards)# Project suggestions can display configurable multi‑row cards and support smarter search. Configure up to 3 rows using a simple token syntax in Settings → Appearance & UI → Project Autosuggest. Properties: file.basename, file.name, file.path, file.parent, title, aliases, and any frontmatter key Flags: n or n(Label) → show the field name/label before the value s → include this field in + search (in addition to defaults) Literals: you can mix in fixed text or emojis between tokens Examples \"{title|n(Title)}\" → Title: Alpha Project \"🔖 {aliases|n(Aliases)}\" → 🔖 Aliases: alpha, proj-alpha \"{file.path|n(Path)|s}\" → include path in + search as well as display it Search behavior Defaults: + search always includes file basename, title (via your field mapping), and aliases |s flag: add more searchable fields on top of the defaults (e.g., file.path or a custom frontmatter key like customer) Fuzzy: optional fuzzy matching can be enabled in settings for broader, multi‑word matches Performance tips Keep rows to three or fewer for clarity and performance (the UI supports up to 3) Prefer specific searchable fields with |s on large vaults Demo Status Suggestions# When typing the status trigger character (default *) in the natural language input, you'll see suggestions for all configured status options: Status suggestions allow quick selection of statuses when creating tasks. For example, typing *in shows \"In Progress\" as a suggestion if that's one of your configured statuses. Clicking a task card's status indicator cycles through statuses in the order configured under Settings → Task Properties → Status. A status can optionally define a specific Next status for forward cycling; otherwise TaskNotes uses the configured order. Statuses marked Skip when cycling are left out of the ordered click cycle, but remain available through menus, suggestions, direct edits, and explicit next-status jumps. Additionally, you can convert any line type in your notes to TaskNotes using the Instant Conversion feature. This works with checkboxes, bullet points, numbered lists, blockquotes, headers, and plain text lines. Task Properties# Tasks store their data in YAML frontmatter with properties for status, priority, dates, contexts, projects, tags, time estimates, recurrence, and reminders. Custom fields can extend this structure. This frontmatter-first design keeps task data editable and portable while supporting consistent behavior across views and widgets. For property types and examples, see Core Concepts. For configuration options, see Task Properties Settings. Projects# TaskNotes supports organizing tasks into projects using note-based linking. Projects are represented as links to actual notes in your vault, allowing you to leverage Obsidian's linking and backlinking features for project management. This model avoids creating a separate project database. Any note can become a project anchor, and task/project relationships remain visible through normal Obsidian link tooling. Project Assignment# Tasks can be assigned to one or more projects through the task creation or editing interface. When creating or editing a task, click the \"Add Project\" button to open the project selection modal. This modal provides fuzzy search functionality to quickly find and select project notes from your vault. Project Links# Projects are stored as wikilinks in the task's frontmatter (e.g., projects: [\"[[Project A]]\", \"[[Project B]]\"]). These links are clickable in the task interface and will navigate directly to the project notes when clicked. Any note in your vault can serve as a project note simply by being linked from a task's projects field. Organization and Filtering# Tasks can be filtered and grouped by their associated projects in all Bases-driven task views. Use the Bases filter editor to add note.projects conditions, and configure the grouping menu to organize Task List or Kanban boards by project. Tasks assigned to multiple projects will appear in each relevant project group, providing flexibility in project-based organization. Project Indicators# TaskCards display visual indicators when tasks are used as projects. These indicators help identify which tasks have other tasks linked to them as subtasks, making project hierarchy visible at a glance. Subtask Creation# Tasks can have subtasks created directly from their context menu. When viewing a task that serves as a project, you can select \"Create subtask\" to create a new task automatically linked to the current project. Dependencies# Task dependencies capture prerequisite work using RFC 9253 terminology. Dependencies are stored in frontmatter as structured objects: blockedBy: - uid: \"[[Operations/Order hardware]]\" reltype: FINISHTOSTART gap: P1D uid references the blocking task, typically through an Obsidian wikilink. reltype is stored with each dependency and defaults to FINISHTOSTART for dependencies created in the UI. gap is optional and uses ISO 8601 duration syntax (for example PT4H or P2D). Whenever a dependency is added, TaskNotes updates the upstream note’s blocking list so the reverse relationship stays synchronized. Removing a dependency automatically clears both sides. Selecting dependencies in the UI# The task creation and edit modals expose “Blocked by” and “Blocking” buttons that launch a fuzzy task selector. The picker only offers valid tasks, excludes the current note, and prevents duplicate entries. The task context menu provides the same selector, enabling dependency management directly from the Task List, Kanban, and calendar views. Task cards show a fork icon whenever a task blocks other work. Clicking it expands an inline list of downstream tasks without triggering the parent card’s modal, so you can inspect dependents in place. These controls currently create and manage finish-to-start style blockers. Advanced reltype values and gap data are preserved in frontmatter, but blocking evaluation is currently based on whether unresolved dependencies exist rather than relationship-type-specific scheduling rules. Automation# Auto-Archiving# TaskNotes can automatically archive tasks when they transition into a status that has auto-archiving enabled. This keeps completed work out of your active lists without requiring manual cleanup. Configure auto-archiving per status from Settings → Task Properties → Task Statuses. Each status card includes an Auto-archive toggle and a Delay (minutes) input (1–1440). When you turn the toggle on for a status, any task moved into that status is queued for archiving once the delay elapses. Moving the task to a different status before the timer expires cancels the pending archive automatically. The auto-archive queue runs in the background and persists across plugin restarts. If TaskNotes was closed while an archive was pending, the task will be archived shortly after the plugin loads again as long as it still matches the configured status. This automation is intended to keep active views focused without manual cleanup, while still preserving archived task history in your vault. File Management and Templates# TaskNotes supports configurable task folder locations, filename generation patterns, archive behavior, and body templates for newly created tasks. These settings let you align task files with existing vault conventions (for example, date-based folders, project-based routing, or template-driven task note scaffolds). For configuration details, see Task Defaults.For template variables, see Template Variables Reference. Recurring Tasks# TaskNotes recurring tasks use RFC 5545 RRule syntax with DTSTART, separate pattern definition from next occurrence scheduling, and support independent instance completion. When an individual recurrence needs its own checklist, time entries, or notes, you can create a materialized occurrence note from the task or calendar context menu. For full behavior, examples, and edge cases, see Recurring Tasks. Task Reminders# Task reminders support relative offsets from due/scheduled dates and absolute date-time reminders. You can add reminders from task modals, task cards, and context menus. For full setup, data format, defaults, and UI behavior, see Task Reminders."},{"route":"/obsidian/features/template-variables/","title":"Template Variables Reference","description":"TaskNotes supports template variables for dynamic content generation in body templates, folder paths, and filenames. Variables use the {{variableName}} syntax and are replaced w...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/features/template-variables.md","namespace":"obsidian","relativePath":"features/template-variables.md","raw":"# Template Variables Reference\n\nTaskNotes supports template variables for dynamic content generation in body templates, folder paths, and filenames. Variables use the `{{variableName}}` syntax and are replaced with actual values when content is created.\n\n## Overview\n\nTemplate variables are available in three contexts:\n\n- **Body templates** - Content templates for task and note files\n- **Folder templates** - Dynamic folder paths for file organization\n- **Filename templates** - Dynamic filename generation\n\nNot all variables are available in every context. The tables below indicate where each variable can be used.\n\n## Task Properties\n\nVariables for task-specific data.\n\n| Variable | Description | Body | Folder | Example |\n|----------|-------------|:----:|:------:|---------|\n| `{{title}}` | Task title | Yes | Yes | `My Task` |\n| `{{titleLower}}` | Title in lowercase | Yes | Yes | `my task` |\n| `{{titleUpper}}` | Title in uppercase | Yes | Yes | `MY TASK` |\n| `{{titleSnake}}` | Title in snake_case | Yes | Yes | `my_task` |\n| `{{titleKebab}}` | Title in kebab-case | Yes | Yes | `my-task` |\n| `{{titleCamel}}` | Title in camelCase | Yes | Yes | `myTask` |\n| `{{titlePascal}}` | Title in PascalCase | Yes | Yes | `MyTask` |\n| `{{priority}}` | Task priority value | Yes | Yes | `high` |\n| `{{priorityShort}}` | First character of priority (uppercase) | Yes | Yes | `H` |\n| `{{status}}` | Task status value | Yes | Yes | `active` |\n| `{{statusShort}}` | First character of status (uppercase) | Yes | Yes | `A` |\n| `{{context}}` | First context from contexts array | No | Yes | `work` |\n| `{{contexts}}` | All contexts (comma-separated in body, `/` in folder) | Yes | Yes | `work, home` or `work/home` |\n| `{{project}}` | First project from projects array | No | Yes | `ProjectA` |\n| `{{projects}}` | All projects joined by `/` | No | Yes | `ProjectA/ProjectB` |\n| `{{projectFilePath}}` | Full path of the first project, without `.md` | No | Yes | `Work/Projects/ProjectA` |\n| `{{projectFilePaths}}` | Full paths of all projects, joined by `/` | No | Yes | `Work/Alpha/Personal/Beta` |\n| `{{projectFolder}}` | Folder containing the first project note (its file path without the note's own name) | No | Yes | `Work/Projects` |\n| `{{projectFolders}}` | Folders of all projects, joined by `/` | No | Yes | `Work/Personal` |\n| `{{dueDate}}` | Task due date | Yes | Yes | `2025-01-15` |\n| `{{scheduledDate}}` | Task scheduled date | Yes | Yes | `2025-01-10` |\n\n## Body Template Only\n\nVariables available only in body templates (not folder templates).\n\n| Variable | Description | Example |\n|----------|-------------|---------|\n| `{{details}}` | User-provided details/description | `Task description text` |\n| `{{parentNote}}` | Parent note name/path where task was created | `Projects/MyNote` |\n| `{{tags}}` | Task tags (comma-separated) | `urgent, review` |\n| `{{hashtags}}` | Task tags as space-separated hashtags | `#urgent #review` |\n| `{{timeEstimate}}` | Time estimate in minutes | `30` |\n\n## Date and Time\n\nVariables for current date and time values.\n\n| Variable | Description | Format | Example |\n|----------|-------------|--------|---------|\n| `{{date}}` | Full current date | `YYYY-MM-DD` | `2025-01-07` |\n| `{{year}}` | Current year | `YYYY` | `2025` |\n| `{{shortYear}}` | Short year | `YY` | `25` |\n| `{{month}}` | Current month | `MM` | `01` |\n| `{{day}}` | Current day | `DD` | `07` |\n| `{{monthName}}` | Full month name | - | `January` |\n| `{{monthNameShort}}` | Abbreviated month name | - | `Jan` |\n| `{{dayName}}` | Full day name | - | `Tuesday` |\n| `{{dayNameShort}}` | Abbreviated day name | - | `Tue` |\n| `{{week}}` | Week number of year | `WW` | `02` |\n| `{{quarter}}` | Quarter of year | `Q` | `1` |\n| `{{shortDate}}` | Compact date | `YYMMDD` | `250107` |\n\n### Time Variables\n\n| Variable | Description | Format | Example |\n|----------|-------------|--------|---------|\n| `{{time}}` | Current time (compact) | `HHmmss` | `143052` |\n| `{{time24}}` | 24-hour time | `HH:mm` | `14:30` |\n| `{{time12}}` | 12-hour time with AM/PM | `hh:mm a` | `02:30 PM` |\n| `{{hour}}` | Current hour (24-hour) | `HH` | `14` |\n| `{{hourPadded}}` | Hour with leading zero | `HH` | `14` |\n| `{{hour12}}` | Hour in 12-hour format | `hh` | `02` |\n| `{{minute}}` | Current minute | `mm` | `30` |\n| `{{second}}` | Current second | `ss` | `52` |\n| `{{ampm}}` | AM/PM indicator | `a` | `PM` |\n\n### Timestamps\n\n| Variable | Description | Format | Example |\n|----------|-------------|--------|---------|\n| `{{timestamp}}` | Date and time combined | `YYYY-MM-DD-HHmmss` | `2025-01-07-143052` |\n| `{{dateTime}}` | Date and time (no seconds) | `YYYY-MM-DD-HHmm` | `2025-01-07-1430` |\n| `{{unix}}` | Unix timestamp (seconds) | - | `1736264852` |\n| `{{unixMs}}` | Unix timestamp (milliseconds) | - | `1736264852000` |\n| `{{milliseconds}}` | Current milliseconds | `SSS` | `123` |\n| `{{ms}}` | Milliseconds (alias) | `SSS` | `123` |\n\n### Timezone\n\n| Variable | Description | Example |\n|----------|-------------|---------|\n| `{{timezone}}` | Timezone offset | `+01:00` |\n| `{{timezoneShort}}` | Short timezone offset | `+0100` |\n| `{{utcOffset}}` | UTC offset | `+01:00` |\n| `{{utcOffsetShort}}` | Short UTC offset | `+0100` |\n| `{{utcZ}}` | UTC Z indicator | `Z` |\n\n### Unique Identifiers\n\n| Variable | Description | Example |\n|----------|-------------|---------|\n| `{{zettel}}` | Zettelkasten-style ID (date + seconds since midnight in base36) | `250107abc` |\n| `{{nano}}` | Unique nano ID (timestamp + random string) | `1736264852000x7k2m` |\n\n## ICS Calendar Event Variables\n\nVariables for content created from ICS calendar events. Available when creating notes or tasks from calendar events.\n\n### Event Information\n\n| Variable | Description | Body | Folder |\n|----------|-------------|:----:|:------:|\n| `{{icsEventTitle}}` | Event title | Yes | Yes |\n| `{{icsEventTitleLower}}` | Event title lowercase | No | Yes |\n| `{{icsEventTitleUpper}}` | Event title uppercase | No | Yes |\n| `{{icsEventTitleSnake}}` | Event title in snake_case | No | Yes |\n| `{{icsEventTitleKebab}}` | Event title in kebab-case | No | Yes |\n| `{{icsEventTitleCamel}}` | Event title in camelCase | No | Yes |\n| `{{icsEventTitlePascal}}` | Event title in PascalCase | No | Yes |\n| `{{icsEventStart}}` | Event start time (ISO format) | Yes | No |\n| `{{icsEventEnd}}` | Event end time (ISO format) | Yes | No |\n| `{{icsEventLocation}}` | Event location | Yes | Yes |\n| `{{icsEventDescription}}` | Event description | Yes | Yes |\n| `{{icsEventUrl}}` | Event URL | Yes | No |\n| `{{icsEventSubscription}}` | Calendar subscription name | Yes | No |\n| `{{icsEventId}}` | Unique event identifier (UUID) | Yes | No |\n\n## Current Note Folder Variables\n\nVariables available for inline-created tasks and the default tasks folder.\n\n| Variable | Description | Example |\n|----------|-------------|---------|\n| `{{currentNotePath}}` | Path to the current note's folder | `Projects/Notes` |\n| `{{currentNoteTitle}}` | Title/name of the current note | `Meeting Notes` |\n\n## Examples\n\n### Body Template\n\n```markdown\n---\ncreated: {{date}}\npriority: {{priority}}\nstatus: {{status}}\n---\n\n# {{title}}\n\n{{details}}\n\nCreated from: {{parentNote}}\nTags: {{hashtags}}\n```\n\n### Folder Template\n\nOrganize tasks by project and status:\n```\nTasks/{{project}}/{{status}}\n```\nResult: `Tasks/MyProject/active`\n\nOrganize by date hierarchy:\n```\nDaily/{{year}}/{{month}}/{{day}}\n```\nResult: `Daily/2025/01/07`\n\nOrganize ICS events by year and title:\n```\nEvents/{{year}}/{{icsEventTitleKebab}}\n```\nResult: `Events/2025/team-meeting`\n\n### Filename Template\n\nUsing Zettelkasten ID:\n```\n{{zettel}}-{{titleKebab}}\n```\nResult: `250107abc-my-task.md`\n\nUsing timestamp:\n```\n{{shortDate}}-{{title}}\n```\nResult: `250107-My Task.md`\n\n## Notes\n\n### YAML Safety\n\nWhen used in YAML frontmatter, values containing special characters (colons, brackets, quotes) are automatically quoted to prevent parsing errors.\n\n### Folder Path Sanitization\n\nIn folder templates, title values have filesystem-unsafe characters (`<>:\"/\\|?*`) replaced with underscores to ensure valid paths. Project file path variables preserve folder separators and sanitize unsafe characters within each path segment.\n\n### Empty Values\n\nIf a variable references data that isn't available (e.g., `{{project}}` when no project is set), it resolves to an empty string.\n\n### Case Transformations\n\nThe case transformation variables work as follows:\n\n| Transform | Input | Output |\n|-----------|-------|--------|\n| `titleLower` | `My Task Name` | `my task name` |\n| `titleUpper` | `My Task Name` | `MY TASK NAME` |\n| `titleSnake` | `My Task Name` | `my_task_name` |\n| `titleKebab` | `My Task Name` | `my-task-name` |\n| `titleCamel` | `My Task Name` | `myTaskName` |\n| `titlePascal` | `My Task Name` | `MyTaskName` |\n","aliases":["/features/template-variables/"],"toc":[{"level":2,"id":"overview","text":"Overview"},{"level":2,"id":"task-properties","text":"Task Properties"},{"level":2,"id":"body-template-only","text":"Body Template Only"},{"level":2,"id":"date-and-time","text":"Date and Time"},{"level":3,"id":"time-variables","text":"Time Variables"},{"level":3,"id":"timestamps","text":"Timestamps"},{"level":3,"id":"timezone","text":"Timezone"},{"level":3,"id":"unique-identifiers","text":"Unique Identifiers"},{"level":2,"id":"ics-calendar-event-variables","text":"ICS Calendar Event Variables"},{"level":3,"id":"event-information","text":"Event Information"},{"level":2,"id":"current-note-folder-variables","text":"Current Note Folder Variables"},{"level":2,"id":"examples","text":"Examples"},{"level":3,"id":"body-template","text":"Body Template"},{"level":3,"id":"folder-template","text":"Folder Template"},{"level":3,"id":"filename-template","text":"Filename Template"},{"level":2,"id":"notes","text":"Notes"},{"level":3,"id":"yaml-safety","text":"YAML Safety"},{"level":3,"id":"folder-path-sanitization","text":"Folder Path Sanitization"},{"level":3,"id":"empty-values","text":"Empty Values"},{"level":3,"id":"case-transformations","text":"Case Transformations"}],"html":"

TaskNotes supports template variables for dynamic content generation in body templates, folder paths, and filenames. Variables use the {{variableName}} syntax and are replaced with actual values when content is created.

\n

Overview#

\n

Template variables are available in three contexts:

\n
    \n
  • Body templates - Content templates for task and note files
  • \n
  • Folder templates - Dynamic folder paths for file organization
  • \n
  • Filename templates - Dynamic filename generation
  • \n
\n

Not all variables are available in every context. The tables below indicate where each variable can be used.

\n

Task Properties#

\n

Variables for task-specific data.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableDescriptionBodyFolderExample
{{title}}Task titleYesYesMy Task
{{titleLower}}Title in lowercaseYesYesmy task
{{titleUpper}}Title in uppercaseYesYesMY TASK
{{titleSnake}}Title in snake_caseYesYesmy_task
{{titleKebab}}Title in kebab-caseYesYesmy-task
{{titleCamel}}Title in camelCaseYesYesmyTask
{{titlePascal}}Title in PascalCaseYesYesMyTask
{{priority}}Task priority valueYesYeshigh
{{priorityShort}}First character of priority (uppercase)YesYesH
{{status}}Task status valueYesYesactive
{{statusShort}}First character of status (uppercase)YesYesA
{{context}}First context from contexts arrayNoYeswork
{{contexts}}All contexts (comma-separated in body, / in folder)YesYeswork, home or work/home
{{project}}First project from projects arrayNoYesProjectA
{{projects}}All projects joined by /NoYesProjectA/ProjectB
{{projectFilePath}}Full path of the first project, without .mdNoYesWork/Projects/ProjectA
{{projectFilePaths}}Full paths of all projects, joined by /NoYesWork/Alpha/Personal/Beta
{{projectFolder}}Folder containing the first project note (its file path without the note's own name)NoYesWork/Projects
{{projectFolders}}Folders of all projects, joined by /NoYesWork/Personal
{{dueDate}}Task due dateYesYes2025-01-15
{{scheduledDate}}Task scheduled dateYesYes2025-01-10
\n

Body Template Only#

\n

Variables available only in body templates (not folder templates).

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableDescriptionExample
{{details}}User-provided details/descriptionTask description text
{{parentNote}}Parent note name/path where task was createdProjects/MyNote
{{tags}}Task tags (comma-separated)urgent, review
{{hashtags}}Task tags as space-separated hashtags#urgent #review
{{timeEstimate}}Time estimate in minutes30
\n

Date and Time#

\n

Variables for current date and time values.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableDescriptionFormatExample
{{date}}Full current dateYYYY-MM-DD2025-01-07
{{year}}Current yearYYYY2025
{{shortYear}}Short yearYY25
{{month}}Current monthMM01
{{day}}Current dayDD07
{{monthName}}Full month name-January
{{monthNameShort}}Abbreviated month name-Jan
{{dayName}}Full day name-Tuesday
{{dayNameShort}}Abbreviated day name-Tue
{{week}}Week number of yearWW02
{{quarter}}Quarter of yearQ1
{{shortDate}}Compact dateYYMMDD250107
\n

Time Variables#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableDescriptionFormatExample
{{time}}Current time (compact)HHmmss143052
{{time24}}24-hour timeHH:mm14:30
{{time12}}12-hour time with AM/PMhh:mm a02:30 PM
{{hour}}Current hour (24-hour)HH14
{{hourPadded}}Hour with leading zeroHH14
{{hour12}}Hour in 12-hour formathh02
{{minute}}Current minutemm30
{{second}}Current secondss52
{{ampm}}AM/PM indicatoraPM
\n

Timestamps#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableDescriptionFormatExample
{{timestamp}}Date and time combinedYYYY-MM-DD-HHmmss2025-01-07-143052
{{dateTime}}Date and time (no seconds)YYYY-MM-DD-HHmm2025-01-07-1430
{{unix}}Unix timestamp (seconds)-1736264852
{{unixMs}}Unix timestamp (milliseconds)-1736264852000
{{milliseconds}}Current millisecondsSSS123
{{ms}}Milliseconds (alias)SSS123
\n

Timezone#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableDescriptionExample
{{timezone}}Timezone offset+01:00
{{timezoneShort}}Short timezone offset+0100
{{utcOffset}}UTC offset+01:00
{{utcOffsetShort}}Short UTC offset+0100
{{utcZ}}UTC Z indicatorZ
\n

Unique Identifiers#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableDescriptionExample
{{zettel}}Zettelkasten-style ID (date + seconds since midnight in base36)250107abc
{{nano}}Unique nano ID (timestamp + random string)1736264852000x7k2m
\n

ICS Calendar Event Variables#

\n

Variables for content created from ICS calendar events. Available when creating notes or tasks from calendar events.

\n

Event Information#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableDescriptionBodyFolder
{{icsEventTitle}}Event titleYesYes
{{icsEventTitleLower}}Event title lowercaseNoYes
{{icsEventTitleUpper}}Event title uppercaseNoYes
{{icsEventTitleSnake}}Event title in snake_caseNoYes
{{icsEventTitleKebab}}Event title in kebab-caseNoYes
{{icsEventTitleCamel}}Event title in camelCaseNoYes
{{icsEventTitlePascal}}Event title in PascalCaseNoYes
{{icsEventStart}}Event start time (ISO format)YesNo
{{icsEventEnd}}Event end time (ISO format)YesNo
{{icsEventLocation}}Event locationYesYes
{{icsEventDescription}}Event descriptionYesYes
{{icsEventUrl}}Event URLYesNo
{{icsEventSubscription}}Calendar subscription nameYesNo
{{icsEventId}}Unique event identifier (UUID)YesNo
\n

Current Note Folder Variables#

\n

Variables available for inline-created tasks and the default tasks folder.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
VariableDescriptionExample
{{currentNotePath}}Path to the current note's folderProjects/Notes
{{currentNoteTitle}}Title/name of the current noteMeeting Notes
\n

Examples#

\n

Body Template#

\n
---\ncreated: {{date}}\npriority: {{priority}}\nstatus: {{status}}\n---\n\n# {{title}}\n\n{{details}}\n\nCreated from: {{parentNote}}\nTags: {{hashtags}}\n

Folder Template#

\n

Organize tasks by project and status:

\n
Tasks/{{project}}/{{status}}\n

Result: Tasks/MyProject/active

\n

Organize by date hierarchy:

\n
Daily/{{year}}/{{month}}/{{day}}\n

Result: Daily/2025/01/07

\n

Organize ICS events by year and title:

\n
Events/{{year}}/{{icsEventTitleKebab}}\n

Result: Events/2025/team-meeting

\n

Filename Template#

\n

Using Zettelkasten ID:

\n
{{zettel}}-{{titleKebab}}\n

Result: 250107abc-my-task.md

\n

Using timestamp:

\n
{{shortDate}}-{{title}}\n

Result: 250107-My Task.md

\n

Notes#

\n

YAML Safety#

\n

When used in YAML frontmatter, values containing special characters (colons, brackets, quotes) are automatically quoted to prevent parsing errors.

\n

Folder Path Sanitization#

\n

In folder templates, title values have filesystem-unsafe characters (<>:"/\\|?*) replaced with underscores to ensure valid paths. Project file path variables preserve folder separators and sanitize unsafe characters within each path segment.

\n

Empty Values#

\n

If a variable references data that isn't available (e.g., {{project}} when no project is set), it resolves to an empty string.

\n

Case Transformations#

\n

The case transformation variables work as follows:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
TransformInputOutput
titleLowerMy Task Namemy task name
titleUpperMy Task NameMY TASK NAME
titleSnakeMy Task Namemy_task_name
titleKebabMy Task Namemy-task-name
titleCamelMy Task NamemyTaskName
titlePascalMy Task NameMyTaskName
\n","text":"TaskNotes supports template variables for dynamic content generation in body templates, folder paths, and filenames. Variables use the {{variableName}} syntax and are replaced with actual values when content is created. Overview# Template variables are available in three contexts: Body templates - Content templates for task and note files Folder templates - Dynamic folder paths for file organization Filename templates - Dynamic filename generation Not all variables are available in every context. The tables below indicate where each variable can be used. Task Properties# Variables for task-specific data. Variable Description Body Folder Example {{title}} Task title Yes Yes My Task {{titleLower}} Title in lowercase Yes Yes my task {{titleUpper}} Title in uppercase Yes Yes MY TASK {{titleSnake}} Title in snake_case Yes Yes my_task {{titleKebab}} Title in kebab-case Yes Yes my-task {{titleCamel}} Title in camelCase Yes Yes myTask {{titlePascal}} Title in PascalCase Yes Yes MyTask {{priority}} Task priority value Yes Yes high {{priorityShort}} First character of priority (uppercase) Yes Yes H {{status}} Task status value Yes Yes active {{statusShort}} First character of status (uppercase) Yes Yes A {{context}} First context from contexts array No Yes work {{contexts}} All contexts (comma-separated in body, / in folder) Yes Yes work, home or work/home {{project}} First project from projects array No Yes ProjectA {{projects}} All projects joined by / No Yes ProjectA/ProjectB {{projectFilePath}} Full path of the first project, without .md No Yes Work/Projects/ProjectA {{projectFilePaths}} Full paths of all projects, joined by / No Yes Work/Alpha/Personal/Beta {{projectFolder}} Folder containing the first project note (its file path without the note's own name) No Yes Work/Projects {{projectFolders}} Folders of all projects, joined by / No Yes Work/Personal {{dueDate}} Task due date Yes Yes 2025-01-15 {{scheduledDate}} Task scheduled date Yes Yes 2025-01-10 Body Template Only# Variables available only in body templates (not folder templates). Variable Description Example {{details}} User-provided details/description Task description text {{parentNote}} Parent note name/path where task was created Projects/MyNote {{tags}} Task tags (comma-separated) urgent, review {{hashtags}} Task tags as space-separated hashtags #urgent #review {{timeEstimate}} Time estimate in minutes 30 Date and Time# Variables for current date and time values. Variable Description Format Example {{date}} Full current date YYYY-MM-DD 2025-01-07 {{year}} Current year YYYY 2025 {{shortYear}} Short year YY 25 {{month}} Current month MM 01 {{day}} Current day DD 07 {{monthName}} Full month name - January {{monthNameShort}} Abbreviated month name - Jan {{dayName}} Full day name - Tuesday {{dayNameShort}} Abbreviated day name - Tue {{week}} Week number of year WW 02 {{quarter}} Quarter of year Q 1 {{shortDate}} Compact date YYMMDD 250107 Time Variables# Variable Description Format Example {{time}} Current time (compact) HHmmss 143052 {{time24}} 24-hour time HH:mm 14:30 {{time12}} 12-hour time with AM/PM hh:mm a 02:30 PM {{hour}} Current hour (24-hour) HH 14 {{hourPadded}} Hour with leading zero HH 14 {{hour12}} Hour in 12-hour format hh 02 {{minute}} Current minute mm 30 {{second}} Current second ss 52 {{ampm}} AM/PM indicator a PM Timestamps# Variable Description Format Example {{timestamp}} Date and time combined YYYY-MM-DD-HHmmss 2025-01-07-143052 {{dateTime}} Date and time (no seconds) YYYY-MM-DD-HHmm 2025-01-07-1430 {{unix}} Unix timestamp (seconds) - 1736264852 {{unixMs}} Unix timestamp (milliseconds) - 1736264852000 {{milliseconds}} Current milliseconds SSS 123 {{ms}} Milliseconds (alias) SSS 123 Timezone# Variable Description Example {{timezone}} Timezone offset +01:00 {{timezoneShort}} Short timezone offset +0100 {{utcOffset}} UTC offset +01:00 {{utcOffsetShort}} Short UTC offset +0100 {{utcZ}} UTC Z indicator Z Unique Identifiers# Variable Description Example {{zettel}} Zettelkasten-style ID (date + seconds since midnight in base36) 250107abc {{nano}} Unique nano ID (timestamp + random string) 1736264852000x7k2m ICS Calendar Event Variables# Variables for content created from ICS calendar events. Available when creating notes or tasks from calendar events. Event Information# Variable Description Body Folder {{icsEventTitle}} Event title Yes Yes {{icsEventTitleLower}} Event title lowercase No Yes {{icsEventTitleUpper}} Event title uppercase No Yes {{icsEventTitleSnake}} Event title in snake_case No Yes {{icsEventTitleKebab}} Event title in kebab-case No Yes {{icsEventTitleCamel}} Event title in camelCase No Yes {{icsEventTitlePascal}} Event title in PascalCase No Yes {{icsEventStart}} Event start time (ISO format) Yes No {{icsEventEnd}} Event end time (ISO format) Yes No {{icsEventLocation}} Event location Yes Yes {{icsEventDescription}} Event description Yes Yes {{icsEventUrl}} Event URL Yes No {{icsEventSubscription}} Calendar subscription name Yes No {{icsEventId}} Unique event identifier (UUID) Yes No Current Note Folder Variables# Variables available for inline-created tasks and the default tasks folder. Variable Description Example {{currentNotePath}} Path to the current note's folder Projects/Notes {{currentNoteTitle}} Title/name of the current note Meeting Notes Examples# Body Template# --- created: {{date}} priority: {{priority}} status: {{status}} --- # {{title}} {{details}} Created from: {{parentNote}} Tags: {{hashtags}} Folder Template# Organize tasks by project and status: Tasks/{{project}}/{{status}} Result: Tasks/MyProject/active Organize by date hierarchy: Daily/{{year}}/{{month}}/{{day}} Result: Daily/2025/01/07 Organize ICS events by year and title: Events/{{year}}/{{icsEventTitleKebab}} Result: Events/2025/team-meeting Filename Template# Using Zettelkasten ID: {{zettel}}-{{titleKebab}} Result: 250107abc-my-task.md Using timestamp: {{shortDate}}-{{title}} Result: 250107-My Task.md Notes# YAML Safety# When used in YAML frontmatter, values containing special characters (colons, brackets, quotes) are automatically quoted to prevent parsing errors. Folder Path Sanitization# In folder templates, title values have filesystem-unsafe characters (<>:\"/\\|?*) replaced with underscores to ensure valid paths. Project file path variables preserve folder separators and sanitize unsafe characters within each path segment. Empty Values# If a variable references data that isn't available (e.g., {{project}} when no project is set), it resolves to an empty string. Case Transformations# The case transformation variables work as follows: Transform Input Output titleLower My Task Name my task name titleUpper My Task Name MY TASK NAME titleSnake My Task Name my_task_name titleKebab My Task Name my-task-name titleCamel My Task Name myTaskName titlePascal My Task Name MyTaskName"},{"route":"/obsidian/features/time-management/","title":"Time Management","description":"TaskNotes includes features for time tracking and productivity, such as a time tracker and a Pomodoro timer.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/features/time-management.md","namespace":"obsidian","relativePath":"features/time-management.md","raw":"# Time Management\n\nTaskNotes includes features for time tracking and productivity, such as a time tracker and a Pomodoro timer.\n\n## Time Tracking\n\nTaskNotes has a time tracker to record the time spent on each task. Time tracking information is stored in the `timeEntries` array within each task's YAML frontmatter. Each time entry includes a start time and an end time.\n\nThe time tracking interface includes controls to start and stop tracking in task views and task cards. TaskNotes prevents duplicate active sessions on the same task. Active sessions on different tasks can exist at the same time, and total time spent on each task is calculated from completed sessions.\n\n### Auto-Stop Time Tracking\n\nTaskNotes can automatically stop time tracking when a task is marked as completed. This feature ensures that time tracking data accurately reflects work completion without requiring manual timer management.\n\nThe auto-stop feature works by monitoring task status changes across all views and interfaces. When a task's status changes from any non-completed state to a completed state (as defined by the custom status configuration), any active time tracking session for that task is automatically terminated.\n\n**Configuration Options:** Configure these under `Settings -> TaskNotes -> Features` (Time Tracking section).\n\n- **Auto-stop tracking** - Enable or disable the automatic stopping behavior (enabled by default)\n- **Completion notification** - Show a notice when auto-stop occurs (disabled by default)\n\n**Behavior:**\n\n- Monitors all task status changes in real-time\n- Stops only the specific task that was completed (other active timers continue)\n- Preserves the recorded time data in the task's time entries\n- Works with both standard and recurring task completions\n- Functions across all task views (list, kanban, calendar, etc.)\n\nThe feature integrates with the custom status system, so completion detection respects your configured workflow statuses rather than relying on hardcoded completion states.\n\n## Pomodoro Timer\n\nTaskNotes also includes a Pomodoro timer, which is a tool for time management that uses a timer to break down work into intervals, separated by short breaks. The Pomodoro timer in TaskNotes has a dedicated view with controls to start, stop, and reset the timer.\n\nWhen a task is associated with a Pomodoro session, the time is automatically recorded in the task's time tracking data upon completion of the session.\n\n## Productivity Analytics\n\nThe **Pomodoro Stats View** provides analytics and historical data about your Pomodoro sessions. This includes a history of completed sessions, as well as metrics like completion rates and total time spent on tasks. The data can be visualized to show productivity patterns over time.\n\n![Task Statistics](../assets/feature-task-statistics.png)\n","aliases":["/features/time-management/"],"toc":[{"level":2,"id":"time-tracking","text":"Time Tracking"},{"level":3,"id":"auto-stop-time-tracking","text":"Auto-Stop Time Tracking"},{"level":2,"id":"pomodoro-timer","text":"Pomodoro Timer"},{"level":2,"id":"productivity-analytics","text":"Productivity Analytics"}],"html":"

TaskNotes includes features for time tracking and productivity, such as a time tracker and a Pomodoro timer.

\n

Time Tracking#

\n

TaskNotes has a time tracker to record the time spent on each task. Time tracking information is stored in the timeEntries array within each task's YAML frontmatter. Each time entry includes a start time and an end time.

\n

The time tracking interface includes controls to start and stop tracking in task views and task cards. TaskNotes prevents duplicate active sessions on the same task. Active sessions on different tasks can exist at the same time, and total time spent on each task is calculated from completed sessions.

\n

Auto-Stop Time Tracking#

\n

TaskNotes can automatically stop time tracking when a task is marked as completed. This feature ensures that time tracking data accurately reflects work completion without requiring manual timer management.

\n

The auto-stop feature works by monitoring task status changes across all views and interfaces. When a task's status changes from any non-completed state to a completed state (as defined by the custom status configuration), any active time tracking session for that task is automatically terminated.

\n

Configuration Options: Configure these under Settings -> TaskNotes -> Features (Time Tracking section).

\n
    \n
  • Auto-stop tracking - Enable or disable the automatic stopping behavior (enabled by default)
  • \n
  • Completion notification - Show a notice when auto-stop occurs (disabled by default)
  • \n
\n

Behavior:

\n
    \n
  • Monitors all task status changes in real-time
  • \n
  • Stops only the specific task that was completed (other active timers continue)
  • \n
  • Preserves the recorded time data in the task's time entries
  • \n
  • Works with both standard and recurring task completions
  • \n
  • Functions across all task views (list, kanban, calendar, etc.)
  • \n
\n

The feature integrates with the custom status system, so completion detection respects your configured workflow statuses rather than relying on hardcoded completion states.

\n

Pomodoro Timer#

\n

TaskNotes also includes a Pomodoro timer, which is a tool for time management that uses a timer to break down work into intervals, separated by short breaks. The Pomodoro timer in TaskNotes has a dedicated view with controls to start, stop, and reset the timer.

\n

When a task is associated with a Pomodoro session, the time is automatically recorded in the task's time tracking data upon completion of the session.

\n

Productivity Analytics#

\n

The Pomodoro Stats View provides analytics and historical data about your Pomodoro sessions. This includes a history of completed sessions, as well as metrics like completion rates and total time spent on tasks. The data can be visualized to show productivity patterns over time.

\n

\"Task

\n","text":"TaskNotes includes features for time tracking and productivity, such as a time tracker and a Pomodoro timer. Time Tracking# TaskNotes has a time tracker to record the time spent on each task. Time tracking information is stored in the timeEntries array within each task's YAML frontmatter. Each time entry includes a start time and an end time. The time tracking interface includes controls to start and stop tracking in task views and task cards. TaskNotes prevents duplicate active sessions on the same task. Active sessions on different tasks can exist at the same time, and total time spent on each task is calculated from completed sessions. Auto-Stop Time Tracking# TaskNotes can automatically stop time tracking when a task is marked as completed. This feature ensures that time tracking data accurately reflects work completion without requiring manual timer management. The auto-stop feature works by monitoring task status changes across all views and interfaces. When a task's status changes from any non-completed state to a completed state (as defined by the custom status configuration), any active time tracking session for that task is automatically terminated. Configuration Options: Configure these under Settings -> TaskNotes -> Features (Time Tracking section). Auto-stop tracking - Enable or disable the automatic stopping behavior (enabled by default) Completion notification - Show a notice when auto-stop occurs (disabled by default) Behavior: Monitors all task status changes in real-time Stops only the specific task that was completed (other active timers continue) Preserves the recorded time data in the task's time entries Works with both standard and recurring task completions Functions across all task views (list, kanban, calendar, etc.) The feature integrates with the custom status system, so completion detection respects your configured workflow statuses rather than relying on hardcoded completion states. Pomodoro Timer# TaskNotes also includes a Pomodoro timer, which is a tool for time management that uses a timer to break down work into intervals, separated by short breaks. The Pomodoro timer in TaskNotes has a dedicated view with controls to start, stop, and reset the timer. When a task is associated with a Pomodoro session, the time is automatically recorded in the task's time tracking data upon completion of the session. Productivity Analytics# The Pomodoro Stats View provides analytics and historical data about your Pomodoro sessions. This includes a history of completed sessions, as well as metrics like completion rates and total time spent on tasks. The data can be visualized to show productivity patterns over time."},{"route":"/obsidian/features/user-fields/","title":"User Fields","description":"TaskNotes allows you to define your own custom fields for tasks. This feature allows you to add custom data to your tasks and use it for filtering, sorting, and grouping. User f...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/features/user-fields.md","namespace":"obsidian","relativePath":"features/user-fields.md","raw":"\n# User Fields\n\nTaskNotes allows you to define your own custom fields for tasks. This feature allows you to add custom data to your tasks and use it for filtering, sorting, and grouping.\nUser fields can store workflow-specific metadata such as owner, effort class, client, or review stage.\n\n\n## Creating User Fields\n\nUser fields are created in the TaskNotes settings, under the \"Task Properties\" tab. To create a new user field, click the \"Add new user field\" button.\nFields that are not used in filters or grouping still add frontmatter overhead, so this section focuses on fields used in views.\n\nEach user field has the following properties:\n\n- **Display Name**: The name of the field as it will be displayed in the UI.\n- **Property Name**: The name of the field as it will be stored in the frontmatter of the task note.\n- **Type**: The data type of the field. The following types are supported:\n - **Text**: A single line of text.\n - **Number**: A numeric value (supports ranges in filters and sorting).\n - **Boolean**: A true/false value stored as a checkbox in the task modal.\n - **Date**: A date.\n - **List**: A list of values.\n- **Default Value** (optional): A default value to pre-fill when creating new tasks. The input format depends on the field type:\n - **Text**: Enter the default text value.\n - **Number**: Enter the default number.\n - **Boolean**: Toggle to set the default state (checked/unchecked).\n - **Date**: Select from presets: None, Today, Tomorrow, or Next Week.\n - **List**: Enter comma-separated default values.\n\n## Link Values\n\nUse a **Text** field for one related link, such as a pull request or specification, and a **List** field for multiple related links. Task cards render wikilinks, markdown links, angle-bracket autolinks, and bare `https://` URLs as clickable links.\n\nFor internal note links, type `[[` in a text or list field to use the same file suggestions as other TaskNotes link fields. Autosuggestion filters can narrow those note suggestions without changing how the stored field value is filtered, sorted, or grouped.\n\n## File Suggestion Filtering (Advanced)\n\nWhen using text or list type custom fields, you can configure **autosuggestion filters** to control which files appear in the autocomplete dropdown when you type `[[` in the field.\n\n![Custom field autosuggestion filters for tags, folders, and property values](../assets/custom-fields-selection-filter.webp)\n\nThis is useful when you want to limit suggestions to specific types of notes. For example:\n- An \"Assignee\" field that only suggests notes tagged with `#person`\n- A \"Project\" field that only shows notes in the `Projects/` folder\n- A \"Related Document\" field filtered by a specific frontmatter property\nFiltering narrows wikilink suggestions in large vaults.\n\n### Configuring Filters\n\nTo configure filters for a custom field:\n\n1. Go to **Settings → Task Properties → Custom User Fields**\n2. Expand the custom field card you want to configure\n3. Expand the **\"Autosuggestion filters (Advanced)\"** section\n4. Configure one or more of the following filters:\n\n#### Filter Options\n\n- **Required tags**: Only show files that have ANY of these tags (comma-separated)\n - Example: `person, team` - shows files with either `#person` OR `#team` tag\n - Supports hierarchical tags: `project/active` matches `#project/active`\n\n- **Include folders**: Only show files in these folders (comma-separated)\n - Example: `People/, Teams/` - shows files in either folder\n - Supports nested folders: `Projects/Active/` matches files in that specific folder\n\n- **Required property key**: Only show files that have this frontmatter property\n - Example: `role` - shows files with a `role:` property in frontmatter\n\n- **Required property value**: Expected value for the property (optional)\n - Example: `developer` - when combined with property key `role`, shows files with `role: developer`\n - Leave empty to match any value (just checks property exists)\n\n#### Filter Indicator\n\nWhen filters are configured, a **\"Filters On\"** badge with a funnel icon appears next to the section title. This prevents you from forgetting that filters are active.\n\n### Filter Behavior\n\n- **All filters are combined with AND logic**: Files must match ALL configured filters to appear\n- **Empty filters are ignored**: If you don't configure a filter, it won't restrict results\n- **No filters = all files**: If no filters are configured, all markdown files in your vault will appear\n- **Filters only affect autocomplete**: They don't affect the actual field value or validation\nAutocomplete filtering and stored field values are handled independently.\n\n### Example Configurations\n\n#### Assignee Field (People Only)\n```\nDisplay Name: Assignee\nProperty Key: assignee\nType: List\n\nAutosuggestion filters:\n Required tags: person\n Include folders: People/\n```\n\n#### Project Field (Active Projects)\n```\nDisplay Name: Project\nProperty Key: project\nType: Text\n\nAutosuggestion filters:\n Required tags: project\n Required property key: status\n Required property value: active\n```\n\n#### Related Note (Specific Folder)\n```\nDisplay Name: Related Note\nProperty Key: related-note\nType: Text\n\nAutosuggestion filters:\n Include folders: Documentation/, Guides/\n```\n\n## Using User Fields\n\nOnce you have created a user field, it will be available in the following places:\n\n- **Task Modals**: The user field will be displayed in the task creation and edit modals.\n- **Bases Filters**: Add the field to Bases filter expressions (for example `note.effort == \"high\"`) to narrow task lists and Kanban boards.\n- **Sorting**: Use the Bases sort menu to order tasks by the user field.\n- **Grouping**: Use the Bases group menu to create swimlanes or list groupings based on the user field.\nTo verify a new field is active in workflow, add it to at least one saved view.\n\n## Frontmatter\n\nUser field data is stored in the frontmatter of the task note. The property name you define for the user field is used as the key in the frontmatter.\n\nFor example, if you create a user field with the property name \"my_field\", the data for that field will be stored in the frontmatter as follows:\n\n```yaml\n---\nmy_field: value\n---\n```\n","aliases":["/features/user-fields/"],"toc":[{"level":2,"id":"creating-user-fields","text":"Creating User Fields"},{"level":2,"id":"link-values","text":"Link Values"},{"level":2,"id":"file-suggestion-filtering-advanced","text":"File Suggestion Filtering (Advanced)"},{"level":3,"id":"configuring-filters","text":"Configuring Filters"},{"level":3,"id":"filter-behavior","text":"Filter Behavior"},{"level":3,"id":"example-configurations","text":"Example Configurations"},{"level":2,"id":"using-user-fields","text":"Using User Fields"},{"level":2,"id":"frontmatter","text":"Frontmatter"}],"html":"

TaskNotes allows you to define your own custom fields for tasks. This feature allows you to add custom data to your tasks and use it for filtering, sorting, and grouping.\nUser fields can store workflow-specific metadata such as owner, effort class, client, or review stage.

\n

Creating User Fields#

\n

User fields are created in the TaskNotes settings, under the "Task Properties" tab. To create a new user field, click the "Add new user field" button.\nFields that are not used in filters or grouping still add frontmatter overhead, so this section focuses on fields used in views.

\n

Each user field has the following properties:

\n
    \n
  • Display Name: The name of the field as it will be displayed in the UI.
  • \n
  • Property Name: The name of the field as it will be stored in the frontmatter of the task note.
  • \n
  • Type: The data type of the field. The following types are supported:
      \n
    • Text: A single line of text.
    • \n
    • Number: A numeric value (supports ranges in filters and sorting).
    • \n
    • Boolean: A true/false value stored as a checkbox in the task modal.
    • \n
    • Date: A date.
    • \n
    • List: A list of values.
    • \n
    \n
  • \n
  • Default Value (optional): A default value to pre-fill when creating new tasks. The input format depends on the field type:
      \n
    • Text: Enter the default text value.
    • \n
    • Number: Enter the default number.
    • \n
    • Boolean: Toggle to set the default state (checked/unchecked).
    • \n
    • Date: Select from presets: None, Today, Tomorrow, or Next Week.
    • \n
    • List: Enter comma-separated default values.
    • \n
    \n
  • \n
\n\n

Use a Text field for one related link, such as a pull request or specification, and a List field for multiple related links. Task cards render wikilinks, markdown links, angle-bracket autolinks, and bare https:// URLs as clickable links.

\n

For internal note links, type [[ in a text or list field to use the same file suggestions as other TaskNotes link fields. Autosuggestion filters can narrow those note suggestions without changing how the stored field value is filtered, sorted, or grouped.

\n

File Suggestion Filtering (Advanced)#

\n

When using text or list type custom fields, you can configure autosuggestion filters to control which files appear in the autocomplete dropdown when you type [[ in the field.

\n

\"Custom

\n

This is useful when you want to limit suggestions to specific types of notes. For example:

\n
    \n
  • An "Assignee" field that only suggests notes tagged with #person
  • \n
  • A "Project" field that only shows notes in the Projects/ folder
  • \n
  • A "Related Document" field filtered by a specific frontmatter property\nFiltering narrows wikilink suggestions in large vaults.
  • \n
\n

Configuring Filters#

\n

To configure filters for a custom field:

\n
    \n
  1. Go to Settings → Task Properties → Custom User Fields
  2. \n
  3. Expand the custom field card you want to configure
  4. \n
  5. Expand the "Autosuggestion filters (Advanced)" section
  6. \n
  7. Configure one or more of the following filters:
  8. \n
\n

Filter Options#

\n
    \n
  • Required tags: Only show files that have ANY of these tags (comma-separated)

    \n
      \n
    • Example: person, team - shows files with either #person OR #team tag
    • \n
    • Supports hierarchical tags: project/active matches #project/active
    • \n
    \n
  • \n
  • Include folders: Only show files in these folders (comma-separated)

    \n
      \n
    • Example: People/, Teams/ - shows files in either folder
    • \n
    • Supports nested folders: Projects/Active/ matches files in that specific folder
    • \n
    \n
  • \n
  • Required property key: Only show files that have this frontmatter property

    \n
      \n
    • Example: role - shows files with a role: property in frontmatter
    • \n
    \n
  • \n
  • Required property value: Expected value for the property (optional)

    \n
      \n
    • Example: developer - when combined with property key role, shows files with role: developer
    • \n
    • Leave empty to match any value (just checks property exists)
    • \n
    \n
  • \n
\n

Filter Indicator#

\n

When filters are configured, a "Filters On" badge with a funnel icon appears next to the section title. This prevents you from forgetting that filters are active.

\n

Filter Behavior#

\n
    \n
  • All filters are combined with AND logic: Files must match ALL configured filters to appear
  • \n
  • Empty filters are ignored: If you don't configure a filter, it won't restrict results
  • \n
  • No filters = all files: If no filters are configured, all markdown files in your vault will appear
  • \n
  • Filters only affect autocomplete: They don't affect the actual field value or validation\nAutocomplete filtering and stored field values are handled independently.
  • \n
\n

Example Configurations#

\n

Assignee Field (People Only)#

\n
Display Name: Assignee\nProperty Key: assignee\nType: List\n\nAutosuggestion filters:\n  Required tags: person\n  Include folders: People/\n

Project Field (Active Projects)#

\n
Display Name: Project\nProperty Key: project\nType: Text\n\nAutosuggestion filters:\n  Required tags: project\n  Required property key: status\n  Required property value: active\n

Related Note (Specific Folder)#

\n
Display Name: Related Note\nProperty Key: related-note\nType: Text\n\nAutosuggestion filters:\n  Include folders: Documentation/, Guides/\n

Using User Fields#

\n

Once you have created a user field, it will be available in the following places:

\n
    \n
  • Task Modals: The user field will be displayed in the task creation and edit modals.
  • \n
  • Bases Filters: Add the field to Bases filter expressions (for example note.effort == "high") to narrow task lists and Kanban boards.
  • \n
  • Sorting: Use the Bases sort menu to order tasks by the user field.
  • \n
  • Grouping: Use the Bases group menu to create swimlanes or list groupings based on the user field.\nTo verify a new field is active in workflow, add it to at least one saved view.
  • \n
\n

Frontmatter#

\n

User field data is stored in the frontmatter of the task note. The property name you define for the user field is used as the key in the frontmatter.

\n

For example, if you create a user field with the property name "my_field", the data for that field will be stored in the frontmatter as follows:

\n
---\nmy_field: value\n---\n
","text":"TaskNotes allows you to define your own custom fields for tasks. This feature allows you to add custom data to your tasks and use it for filtering, sorting, and grouping. User fields can store workflow-specific metadata such as owner, effort class, client, or review stage. Creating User Fields# User fields are created in the TaskNotes settings, under the \"Task Properties\" tab. To create a new user field, click the \"Add new user field\" button. Fields that are not used in filters or grouping still add frontmatter overhead, so this section focuses on fields used in views. Each user field has the following properties: Display Name: The name of the field as it will be displayed in the UI. Property Name: The name of the field as it will be stored in the frontmatter of the task note. Type: The data type of the field. The following types are supported: Text: A single line of text. Number: A numeric value (supports ranges in filters and sorting). Boolean: A true/false value stored as a checkbox in the task modal. Date: A date. List: A list of values. Default Value (optional): A default value to pre-fill when creating new tasks. The input format depends on the field type: Text: Enter the default text value. Number: Enter the default number. Boolean: Toggle to set the default state (checked/unchecked). Date: Select from presets: None, Today, Tomorrow, or Next Week. List: Enter comma-separated default values. Link Values# Use a Text field for one related link, such as a pull request or specification, and a List field for multiple related links. Task cards render wikilinks, markdown links, angle-bracket autolinks, and bare https:// URLs as clickable links. For internal note links, type [[ in a text or list field to use the same file suggestions as other TaskNotes link fields. Autosuggestion filters can narrow those note suggestions without changing how the stored field value is filtered, sorted, or grouped. File Suggestion Filtering (Advanced)# When using text or list type custom fields, you can configure autosuggestion filters to control which files appear in the autocomplete dropdown when you type [[ in the field. This is useful when you want to limit suggestions to specific types of notes. For example: An \"Assignee\" field that only suggests notes tagged with #person A \"Project\" field that only shows notes in the Projects/ folder A \"Related Document\" field filtered by a specific frontmatter property Filtering narrows wikilink suggestions in large vaults. Configuring Filters# To configure filters for a custom field: Go to Settings → Task Properties → Custom User Fields Expand the custom field card you want to configure Expand the \"Autosuggestion filters (Advanced)\" section Configure one or more of the following filters: Filter Options# Required tags: Only show files that have ANY of these tags (comma-separated) Example: person, team - shows files with either #person OR #team tag Supports hierarchical tags: project/active matches #project/active Include folders: Only show files in these folders (comma-separated) Example: People/, Teams/ - shows files in either folder Supports nested folders: Projects/Active/ matches files in that specific folder Required property key: Only show files that have this frontmatter property Example: role - shows files with a role: property in frontmatter Required property value: Expected value for the property (optional) Example: developer - when combined with property key role, shows files with role: developer Leave empty to match any value (just checks property exists) Filter Indicator# When filters are configured, a \"Filters On\" badge with a funnel icon appears next to the section title. This prevents you from forgetting that filters are active. Filter Behavior# All filters are combined with AND logic: Files must match ALL configured filters to appear Empty filters are ignored: If you don't configure a filter, it won't restrict results No filters = all files: If no filters are configured, all markdown files in your vault will appear Filters only affect autocomplete: They don't affect the actual field value or validation Autocomplete filtering and stored field values are handled independently. Example Configurations# Assignee Field (People Only)# Display Name: Assignee Property Key: assignee Type: List Autosuggestion filters: Required tags: person Include folders: People/ Project Field (Active Projects)# Display Name: Project Property Key: project Type: Text Autosuggestion filters: Required tags: project Required property key: status Required property value: active Related Note (Specific Folder)# Display Name: Related Note Property Key: related-note Type: Text Autosuggestion filters: Include folders: Documentation/, Guides/ Using User Fields# Once you have created a user field, it will be available in the following places: Task Modals: The user field will be displayed in the task creation and edit modals. Bases Filters: Add the field to Bases filter expressions (for example note.effort == \"high\") to narrow task lists and Kanban boards. Sorting: Use the Bases sort menu to order tasks by the user field. Grouping: Use the Bases group menu to create swimlanes or list groupings based on the user field. To verify a new field is active in workflow, add it to at least one saved view. Frontmatter# User field data is stored in the frontmatter of the task note. The property name you define for the user field is used as the key in the frontmatter. For example, if you create a user field with the property name \"my_field\", the data for that field will be stored in the frontmatter as follows: --- my_field: value ---"},{"route":"/obsidian/getting-started/existing-vault/","title":"Adopt TaskNotes in an existing vault","description":"Adopt TaskNotes in a vault that already contains tasks, tags, and custom frontmatter without rewriting everything first.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/getting-started/existing-vault.md","namespace":"obsidian","relativePath":"getting-started/existing-vault.md","raw":"---\ndescription: Adopt TaskNotes in a vault that already contains tasks, tags, and custom frontmatter without rewriting everything first.\n---\n\n# Adopt TaskNotes in an existing vault\n\nTaskNotes can use your current folders and property names. Configure identification and field mapping before creating or converting tasks so the first write follows your vault conventions.\n\n## 1. Back up the vault\n\nMake a complete vault backup, including the hidden `.obsidian` directory. The task notes themselves are Markdown, while TaskNotes settings live in `.obsidian/plugins/tasknotes/data.json`.\n\n## 2. Inspect a representative note\n\nChoose one existing task and record:\n\n- The property or tag that distinguishes tasks from ordinary notes\n- The property names used for title, status, priority, due date, and scheduled date\n- Whether contexts and tags are stored with or without display prefixes\n- The folder patterns that should be included or excluded\n\nCanonical frontmatter values do not include natural-language trigger characters. Store `office`, not `@office`, and `review`, not `#review`.\n\n```yaml\n---\ntype: task\nstatus: open\ncontexts:\n - office\ntags:\n - review\n---\n```\n\n## 3. Choose task identification\n\nOpen **Settings → TaskNotes → General**.\n\n- Choose **Tag** if every task contains one identifying tag, such as `task`.\n- Choose **Property** if a property/value pair identifies tasks, such as `type: task`.\n- Add archive, template, attachment, or other non-task locations to **Excluded folders**.\n\nTask identification controls indexing and every generated Base filter. Confirm it before regenerating Base files.\n\n## 4. Map properties\n\nOpen **Settings → TaskNotes → Task properties** and map TaskNotes fields to the names already used in your notes. Avoid creating two properties for one concept, such as both `due` and `deadline`.\n\nStart with title, status, priority, due, scheduled, projects, contexts, and recurrence. Use the [property types reference](../settings/property-types-reference.md) to check value shapes.\n\n## 5. Test one note\n\nOpen one existing note and confirm that TaskNotes recognizes it. Use **TaskNotes: Quick actions for current task** and make a reversible edit, such as changing priority. Inspect the frontmatter before testing a larger set.\n\nIf the note is not recognized, use the [troubleshooting decision tree](../troubleshooting.md#tasks-not-appearing-in-views).\n\n## 6. Generate views from the final mapping\n\nOpen **Settings → TaskNotes → General → Views & base files** and create or update the default Base files. Generated filters and columns use the current task identifier and field mapping.\n\nThe update action replaces configured default Base files. Copy any customized Base to a new filename before updating it.\n\n## 7. Convert incrementally\n\nConvert or edit a small group first. Keep normal version-control or backup checkpoints between batches. Existing notes do not need to move into the default `TaskNotes/Tasks` folder if your storage and exclusion settings already cover their location.\n","aliases":["/getting-started/existing-vault/"],"toc":[{"level":2,"id":"1-back-up-the-vault","text":"1. Back up the vault"},{"level":2,"id":"2-inspect-a-representative-note","text":"2. Inspect a representative note"},{"level":2,"id":"3-choose-task-identification","text":"3. Choose task identification"},{"level":2,"id":"4-map-properties","text":"4. Map properties"},{"level":2,"id":"5-test-one-note","text":"5. Test one note"},{"level":2,"id":"6-generate-views-from-the-final-mapping","text":"6. Generate views from the final mapping"},{"level":2,"id":"7-convert-incrementally","text":"7. Convert incrementally"}],"html":"

TaskNotes can use your current folders and property names. Configure identification and field mapping before creating or converting tasks so the first write follows your vault conventions.

\n

1. Back up the vault#

\n

Make a complete vault backup, including the hidden .obsidian directory. The task notes themselves are Markdown, while TaskNotes settings live in .obsidian/plugins/tasknotes/data.json.

\n

2. Inspect a representative note#

\n

Choose one existing task and record:

\n
    \n
  • The property or tag that distinguishes tasks from ordinary notes
  • \n
  • The property names used for title, status, priority, due date, and scheduled date
  • \n
  • Whether contexts and tags are stored with or without display prefixes
  • \n
  • The folder patterns that should be included or excluded
  • \n
\n

Canonical frontmatter values do not include natural-language trigger characters. Store office, not @office, and review, not #review.

\n
---\ntype: task\nstatus: open\ncontexts:\n  - office\ntags:\n  - review\n---\n

3. Choose task identification#

\n

Open Settings → TaskNotes → General.

\n
    \n
  • Choose Tag if every task contains one identifying tag, such as task.
  • \n
  • Choose Property if a property/value pair identifies tasks, such as type: task.
  • \n
  • Add archive, template, attachment, or other non-task locations to Excluded folders.
  • \n
\n

Task identification controls indexing and every generated Base filter. Confirm it before regenerating Base files.

\n

4. Map properties#

\n

Open Settings → TaskNotes → Task properties and map TaskNotes fields to the names already used in your notes. Avoid creating two properties for one concept, such as both due and deadline.

\n

Start with title, status, priority, due, scheduled, projects, contexts, and recurrence. Use the property types reference to check value shapes.

\n

5. Test one note#

\n

Open one existing note and confirm that TaskNotes recognizes it. Use TaskNotes: Quick actions for current task and make a reversible edit, such as changing priority. Inspect the frontmatter before testing a larger set.

\n

If the note is not recognized, use the troubleshooting decision tree.

\n

6. Generate views from the final mapping#

\n

Open Settings → TaskNotes → General → Views & base files and create or update the default Base files. Generated filters and columns use the current task identifier and field mapping.

\n

The update action replaces configured default Base files. Copy any customized Base to a new filename before updating it.

\n

7. Convert incrementally#

\n

Convert or edit a small group first. Keep normal version-control or backup checkpoints between batches. Existing notes do not need to move into the default TaskNotes/Tasks folder if your storage and exclusion settings already cover their location.

\n","text":"TaskNotes can use your current folders and property names. Configure identification and field mapping before creating or converting tasks so the first write follows your vault conventions. 1. Back up the vault# Make a complete vault backup, including the hidden .obsidian directory. The task notes themselves are Markdown, while TaskNotes settings live in .obsidian/plugins/tasknotes/data.json. 2. Inspect a representative note# Choose one existing task and record: The property or tag that distinguishes tasks from ordinary notes The property names used for title, status, priority, due date, and scheduled date Whether contexts and tags are stored with or without display prefixes The folder patterns that should be included or excluded Canonical frontmatter values do not include natural-language trigger characters. Store office, not @office, and review, not #review. --- type: task status: open contexts: - office tags: - review --- 3. Choose task identification# Open Settings → TaskNotes → General. Choose Tag if every task contains one identifying tag, such as task. Choose Property if a property/value pair identifies tasks, such as type: task. Add archive, template, attachment, or other non-task locations to Excluded folders. Task identification controls indexing and every generated Base filter. Confirm it before regenerating Base files. 4. Map properties# Open Settings → TaskNotes → Task properties and map TaskNotes fields to the names already used in your notes. Avoid creating two properties for one concept, such as both due and deadline. Start with title, status, priority, due, scheduled, projects, contexts, and recurrence. Use the property types reference to check value shapes. 5. Test one note# Open one existing note and confirm that TaskNotes recognizes it. Use TaskNotes: Quick actions for current task and make a reversible edit, such as changing priority. Inspect the frontmatter before testing a larger set. If the note is not recognized, use the troubleshooting decision tree. 6. Generate views from the final mapping# Open Settings → TaskNotes → General → Views & base files and create or update the default Base files. Generated filters and columns use the current task identifier and field mapping. The update action replaces configured default Base files. Copy any customized Base to a new filename before updating it. 7. Convert incrementally# Convert or edit a small group first. Keep normal version-control or backup checkpoints between batches. Existing notes do not need to move into the default TaskNotes/Tasks folder if your storage and exclusion settings already cover their location."},{"route":"/obsidian/getting-started/mobile/","title":"Obsidian mobile guide","description":"What is shared between TaskNotes desktop and mobile, and which integrations differ on mobile.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/getting-started/mobile.md","namespace":"obsidian","relativePath":"getting-started/mobile.md","raw":"---\ndescription: What is shared between TaskNotes desktop and mobile, and which integrations differ on mobile.\n---\n\n# Obsidian mobile guide\n\nTaskNotes task files, Base files, settings, and most commands work on Obsidian mobile. Sync the complete vault, including `.base` files and `.obsidian/plugins/tasknotes/data.json`, when you want the same configuration on every device.\n\n## Before opening TaskNotes\n\n1. Install an Obsidian mobile version compatible with the current [TaskNotes requirement](../reference/compatibility.md).\n2. Enable the **Bases** core plugin.\n3. Confirm the TaskNotes plugin and its `data.json` have finished syncing before changing settings.\n4. Open a small default Base first and allow the initial index to finish.\n\n## Mobile differences\n\n| Area | Mobile behavior |\n| --- | --- |\n| HTTP API and MCP server | Desktop only. The HTTP API settings section is hidden on mobile. |\n| Calendar integrations | Available, with an option to disable calendar integration on mobile when startup time or provider behavior is a problem. |\n| Settings layout | Uses the same six tabs. Desktop-only controls are omitted where they cannot run. |\n| Keyboard commands | Commands remain available in the command palette; desktop key bindings may not have a mobile equivalent. |\n| Wide views | Calendar, Kanban, and large tables may require horizontal scrolling or a narrower Base configuration. |\n\n## A practical mobile setup\n\n- Keep task cards compact under **Settings → Appearance and UI**.\n- Limit visible Base columns and calendar event layers.\n- Increase remote calendar refresh intervals when mobile networking or battery use matters.\n- Use the task creation modal or command palette for predictable capture.\n- Keep HTTP automation on a desktop Obsidian instance.\n\n## If mobile stops loading tasks\n\nWait for vault sync to finish, confirm Bases is enabled, and run **TaskNotes: Refresh cache**. Then reopen the affected Base. If the problem is isolated to calendar data, enable **Disable calendar integration on mobile** and restart Obsidian before investigating the provider connection on desktop.\n","aliases":["/getting-started/mobile/"],"toc":[{"level":2,"id":"before-opening-tasknotes","text":"Before opening TaskNotes"},{"level":2,"id":"mobile-differences","text":"Mobile differences"},{"level":2,"id":"a-practical-mobile-setup","text":"A practical mobile setup"},{"level":2,"id":"if-mobile-stops-loading-tasks","text":"If mobile stops loading tasks"}],"html":"

TaskNotes task files, Base files, settings, and most commands work on Obsidian mobile. Sync the complete vault, including .base files and .obsidian/plugins/tasknotes/data.json, when you want the same configuration on every device.

\n

Before opening TaskNotes#

\n
    \n
  1. Install an Obsidian mobile version compatible with the current TaskNotes requirement.
  2. \n
  3. Enable the Bases core plugin.
  4. \n
  5. Confirm the TaskNotes plugin and its data.json have finished syncing before changing settings.
  6. \n
  7. Open a small default Base first and allow the initial index to finish.
  8. \n
\n

Mobile differences#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
AreaMobile behavior
HTTP API and MCP serverDesktop only. The HTTP API settings section is hidden on mobile.
Calendar integrationsAvailable, with an option to disable calendar integration on mobile when startup time or provider behavior is a problem.
Settings layoutUses the same six tabs. Desktop-only controls are omitted where they cannot run.
Keyboard commandsCommands remain available in the command palette; desktop key bindings may not have a mobile equivalent.
Wide viewsCalendar, Kanban, and large tables may require horizontal scrolling or a narrower Base configuration.
\n

A practical mobile setup#

\n
    \n
  • Keep task cards compact under Settings → Appearance and UI.
  • \n
  • Limit visible Base columns and calendar event layers.
  • \n
  • Increase remote calendar refresh intervals when mobile networking or battery use matters.
  • \n
  • Use the task creation modal or command palette for predictable capture.
  • \n
  • Keep HTTP automation on a desktop Obsidian instance.
  • \n
\n

If mobile stops loading tasks#

\n

Wait for vault sync to finish, confirm Bases is enabled, and run TaskNotes: Refresh cache. Then reopen the affected Base. If the problem is isolated to calendar data, enable Disable calendar integration on mobile and restart Obsidian before investigating the provider connection on desktop.

\n","text":"TaskNotes task files, Base files, settings, and most commands work on Obsidian mobile. Sync the complete vault, including .base files and .obsidian/plugins/tasknotes/data.json, when you want the same configuration on every device. Before opening TaskNotes# Install an Obsidian mobile version compatible with the current TaskNotes requirement. Enable the Bases core plugin. Confirm the TaskNotes plugin and its data.json have finished syncing before changing settings. Open a small default Base first and allow the initial index to finish. Mobile differences# Area Mobile behavior HTTP API and MCP server Desktop only. The HTTP API settings section is hidden on mobile. Calendar integrations Available, with an option to disable calendar integration on mobile when startup time or provider behavior is a problem. Settings layout Uses the same six tabs. Desktop-only controls are omitted where they cannot run. Keyboard commands Commands remain available in the command palette; desktop key bindings may not have a mobile equivalent. Wide views Calendar, Kanban, and large tables may require horizontal scrolling or a narrower Base configuration. A practical mobile setup# Keep task cards compact under Settings → Appearance and UI. Limit visible Base columns and calendar event layers. Increase remote calendar refresh intervals when mobile networking or battery use matters. Use the task creation modal or command palette for predictable capture. Keep HTTP automation on a desktop Obsidian instance. If mobile stops loading tasks# Wait for vault sync to finish, confirm Bases is enabled, and run TaskNotes: Refresh cache. Then reopen the affected Base. If the problem is isolated to calendar data, enable Disable calendar integration on mobile and restart Obsidian before investigating the provider connection on desktop."},{"route":"/obsidian/guides/backup-recovery/","title":"Backup, restore, and removal","description":"Back up, restore, reset, and uninstall TaskNotes while protecting task notes, views, settings, and integration data.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/guides/backup-recovery.md","namespace":"obsidian","relativePath":"guides/backup-recovery.md","raw":"---\ndescription: Back up, restore, reset, and uninstall TaskNotes while protecting task notes, views, settings, and integration data.\n---\n\n# Backup, restore, and removal\n\nTaskNotes keeps task content in your vault and configuration in the plugin data file. A complete backup includes both.\n\n## What to back up\n\n| Data | Typical location | Why it matters |\n| --- | --- | --- |\n| Task notes | Your configured task folders | Titles, properties, details, recurrence, and time entries |\n| Base views | `TaskNotes/Views/` or custom paths | Filters, formulas, layout, and custom views |\n| Plugin settings | `.obsidian/plugins/tasknotes/data.json` | Field mapping, statuses, defaults, integrations, and view command paths |\n| Daily notes | Your daily-note folder | Pomodoro history when daily-note storage is enabled |\n| mdbase configuration | `tasknotes.yaml`, `mdbase.yaml`, or `.mdbase/` when configured | Shared collection and schema configuration |\n\nTreat `data.json` as sensitive because integration configuration can include credentials or tokens. Store backups accordingly.\n\n## Create a restorable backup\n\n1. Close Obsidian or disable TaskNotes so settings are not being written.\n2. Copy the entire vault, including hidden files.\n3. Verify the backup contains `.obsidian/plugins/tasknotes/data.json`.\n4. Keep at least one version from before a migration or bulk edit.\n\nFile-history sync is useful, but it is not a substitute for a separate tested backup.\n\n## Restore\n\n1. Close Obsidian.\n2. Restore task notes and Base files first.\n3. Restore `.obsidian/plugins/tasknotes/data.json` if you also need the previous settings.\n4. Reopen Obsidian and confirm Bases is enabled.\n5. Run **TaskNotes: Refresh cache** and open one default Base.\n\nIf provider credentials have expired or were intentionally excluded from the backup, reconnect those integrations instead of restoring stale tokens.\n\n## Reset configuration safely\n\nDo not delete `data.json` as a first troubleshooting step.\n\n1. Close Obsidian.\n2. Rename `data.json` to `data.json.backup-YYYY-MM-DD`.\n3. Reopen Obsidian and test with fresh defaults.\n4. Restore the backup while Obsidian is closed if the reset does not help.\n\nA reset affects settings, configured statuses and priorities, integration state, saved views, and plugin-stored Pomodoro history. It does not delete task Markdown files.\n\n## Uninstall\n\nDisabling or uninstalling TaskNotes leaves task notes and `.base` files in the vault. After uninstalling, remove generated folders only if you have inspected them and confirmed they contain no content you want to keep.\n\nTo remove plugin settings as well, close Obsidian and remove `.obsidian/plugins/tasknotes/` after making a backup. Task metadata remains readable YAML, but TaskNotes-specific Base view types and interactive widgets will no longer render.\n\n## Recovery checklist\n\n- Missing tasks: restore the note files, then verify task identification and excluded folders.\n- Missing settings: restore `data.json` with Obsidian closed.\n- Broken default views: regenerate them from **General → Views & base files**.\n- Broken custom views: restore the individual `.base` files from history.\n- Lost Pomodoro history: restore the configured storage source, which may be plugin data or daily-note frontmatter.\n","aliases":["/guides/backup-recovery/"],"toc":[{"level":2,"id":"what-to-back-up","text":"What to back up"},{"level":2,"id":"create-a-restorable-backup","text":"Create a restorable backup"},{"level":2,"id":"restore","text":"Restore"},{"level":2,"id":"reset-configuration-safely","text":"Reset configuration safely"},{"level":2,"id":"uninstall","text":"Uninstall"},{"level":2,"id":"recovery-checklist","text":"Recovery checklist"}],"html":"

TaskNotes keeps task content in your vault and configuration in the plugin data file. A complete backup includes both.

\n

What to back up#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
DataTypical locationWhy it matters
Task notesYour configured task foldersTitles, properties, details, recurrence, and time entries
Base viewsTaskNotes/Views/ or custom pathsFilters, formulas, layout, and custom views
Plugin settings.obsidian/plugins/tasknotes/data.jsonField mapping, statuses, defaults, integrations, and view command paths
Daily notesYour daily-note folderPomodoro history when daily-note storage is enabled
mdbase configurationtasknotes.yaml, mdbase.yaml, or .mdbase/ when configuredShared collection and schema configuration
\n

Treat data.json as sensitive because integration configuration can include credentials or tokens. Store backups accordingly.

\n

Create a restorable backup#

\n
    \n
  1. Close Obsidian or disable TaskNotes so settings are not being written.
  2. \n
  3. Copy the entire vault, including hidden files.
  4. \n
  5. Verify the backup contains .obsidian/plugins/tasknotes/data.json.
  6. \n
  7. Keep at least one version from before a migration or bulk edit.
  8. \n
\n

File-history sync is useful, but it is not a substitute for a separate tested backup.

\n

Restore#

\n
    \n
  1. Close Obsidian.
  2. \n
  3. Restore task notes and Base files first.
  4. \n
  5. Restore .obsidian/plugins/tasknotes/data.json if you also need the previous settings.
  6. \n
  7. Reopen Obsidian and confirm Bases is enabled.
  8. \n
  9. Run TaskNotes: Refresh cache and open one default Base.
  10. \n
\n

If provider credentials have expired or were intentionally excluded from the backup, reconnect those integrations instead of restoring stale tokens.

\n

Reset configuration safely#

\n

Do not delete data.json as a first troubleshooting step.

\n
    \n
  1. Close Obsidian.
  2. \n
  3. Rename data.json to data.json.backup-YYYY-MM-DD.
  4. \n
  5. Reopen Obsidian and test with fresh defaults.
  6. \n
  7. Restore the backup while Obsidian is closed if the reset does not help.
  8. \n
\n

A reset affects settings, configured statuses and priorities, integration state, saved views, and plugin-stored Pomodoro history. It does not delete task Markdown files.

\n

Uninstall#

\n

Disabling or uninstalling TaskNotes leaves task notes and .base files in the vault. After uninstalling, remove generated folders only if you have inspected them and confirmed they contain no content you want to keep.

\n

To remove plugin settings as well, close Obsidian and remove .obsidian/plugins/tasknotes/ after making a backup. Task metadata remains readable YAML, but TaskNotes-specific Base view types and interactive widgets will no longer render.

\n

Recovery checklist#

\n
    \n
  • Missing tasks: restore the note files, then verify task identification and excluded folders.
  • \n
  • Missing settings: restore data.json with Obsidian closed.
  • \n
  • Broken default views: regenerate them from General → Views & base files.
  • \n
  • Broken custom views: restore the individual .base files from history.
  • \n
  • Lost Pomodoro history: restore the configured storage source, which may be plugin data or daily-note frontmatter.
  • \n
\n","text":"TaskNotes keeps task content in your vault and configuration in the plugin data file. A complete backup includes both. What to back up# Data Typical location Why it matters Task notes Your configured task folders Titles, properties, details, recurrence, and time entries Base views TaskNotes/Views/ or custom paths Filters, formulas, layout, and custom views Plugin settings .obsidian/plugins/tasknotes/data.json Field mapping, statuses, defaults, integrations, and view command paths Daily notes Your daily-note folder Pomodoro history when daily-note storage is enabled mdbase configuration tasknotes.yaml, mdbase.yaml, or .mdbase/ when configured Shared collection and schema configuration Treat data.json as sensitive because integration configuration can include credentials or tokens. Store backups accordingly. Create a restorable backup# Close Obsidian or disable TaskNotes so settings are not being written. Copy the entire vault, including hidden files. Verify the backup contains .obsidian/plugins/tasknotes/data.json. Keep at least one version from before a migration or bulk edit. File-history sync is useful, but it is not a substitute for a separate tested backup. Restore# Close Obsidian. Restore task notes and Base files first. Restore .obsidian/plugins/tasknotes/data.json if you also need the previous settings. Reopen Obsidian and confirm Bases is enabled. Run TaskNotes: Refresh cache and open one default Base. If provider credentials have expired or were intentionally excluded from the backup, reconnect those integrations instead of restoring stale tokens. Reset configuration safely# Do not delete data.json as a first troubleshooting step. Close Obsidian. Rename data.json to data.json.backup-YYYY-MM-DD. Reopen Obsidian and test with fresh defaults. Restore the backup while Obsidian is closed if the reset does not help. A reset affects settings, configured statuses and priorities, integration state, saved views, and plugin-stored Pomodoro history. It does not delete task Markdown files. Uninstall# Disabling or uninstalling TaskNotes leaves task notes and .base files in the vault. After uninstalling, remove generated folders only if you have inspected them and confirmed they contain no content you want to keep. To remove plugin settings as well, close Obsidian and remove .obsidian/plugins/tasknotes/ after making a backup. Task metadata remains readable YAML, but TaskNotes-specific Base view types and interactive widgets will no longer render. Recovery checklist# Missing tasks: restore the note files, then verify task identification and excluded folders. Missing settings: restore data.json with Obsidian closed. Broken default views: regenerate them from General → Views & base files. Broken custom views: restore the individual .base files from history. Lost Pomodoro history: restore the configured storage source, which may be plugin data or daily-note frontmatter."},{"route":"/obsidian/guides/custom-bases/","title":"Build a custom Base","description":"Create a custom Obsidian Base for TaskNotes while keeping generated defaults safe and upgradeable.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/guides/custom-bases.md","namespace":"obsidian","relativePath":"guides/custom-bases.md","raw":"---\ndescription: Create a custom Obsidian Base for TaskNotes while keeping generated defaults safe and upgradeable.\n---\n\n# Build a custom Base\n\nTaskNotes views are ordinary Obsidian `.base` files. The safest workflow is to copy a generated Base, give it a new path, and customize the copy.\n\n## Start from a copy\n\n1. Open `TaskNotes/Views/` in the file explorer.\n2. Duplicate the closest default, such as `tasks-default.base`.\n3. Rename the copy, for example `work-tasks.base`.\n4. Open the copy and make changes with the Bases interface or source editor.\n\nAvoid editing the only copy of a generated default. **Update default base files** replaces the files configured as defaults.\n\n## Preserve task identification\n\nEvery task view needs a filter that matches the identification method in **Settings → TaskNotes → General**.\n\nFor tag identification:\n\n```yaml\nfilters:\n and:\n - file.hasTag(\"task\")\n```\n\nFor property identification:\n\n```yaml\nfilters:\n and:\n - note[\"type\"] == \"task\"\n```\n\nAlso preserve any excluded-folder conditions generated from your settings.\n\n## Add a focused view\n\nThis example starts with recognized tasks, then limits the view to the `work` context:\n\n```yaml\nfilters:\n and:\n - file.hasTag(\"task\")\n - list(contexts).contains(\"work\")\n\nviews:\n - type: tasknotesTaskList\n name: Work\n order:\n - status\n - priority\n - due\n - file.name\n sort:\n - column: due\n direction: ASC\n```\n\nUse canonical stored values in filters. Natural-language prefixes such as `@` and `#` are input syntax, not part of stored context and tag values.\n\n## Point a command at the custom Base\n\nOpen **Settings → TaskNotes → General → View commands** and change the relevant command path. Resetting that mapping returns it to the generated default path.\n\n## Upgrade safely\n\nWhen TaskNotes ships improved templates:\n\n1. Keep your custom file at its own path.\n2. Run **Update default base files**.\n3. Compare the regenerated default with your copy.\n4. Bring across only the formulas, filters, or view options you want.\n\nThe [generated template reference](../reference/default-base-templates.md) always reflects the current source and default field mapping.\n\n## Recovery\n\nIf a custom Base no longer opens, validate its YAML indentation and remove the most recent filter or formula change. You can create a fresh default from settings at any time, then copy your custom view into it one section at a time.\n","aliases":["/guides/custom-bases/"],"toc":[{"level":2,"id":"start-from-a-copy","text":"Start from a copy"},{"level":2,"id":"preserve-task-identification","text":"Preserve task identification"},{"level":2,"id":"add-a-focused-view","text":"Add a focused view"},{"level":2,"id":"point-a-command-at-the-custom-base","text":"Point a command at the custom Base"},{"level":2,"id":"upgrade-safely","text":"Upgrade safely"},{"level":2,"id":"recovery","text":"Recovery"}],"html":"

TaskNotes views are ordinary Obsidian .base files. The safest workflow is to copy a generated Base, give it a new path, and customize the copy.

\n

Start from a copy#

\n
    \n
  1. Open TaskNotes/Views/ in the file explorer.
  2. \n
  3. Duplicate the closest default, such as tasks-default.base.
  4. \n
  5. Rename the copy, for example work-tasks.base.
  6. \n
  7. Open the copy and make changes with the Bases interface or source editor.
  8. \n
\n

Avoid editing the only copy of a generated default. Update default base files replaces the files configured as defaults.

\n

Preserve task identification#

\n

Every task view needs a filter that matches the identification method in Settings → TaskNotes → General.

\n

For tag identification:

\n
filters:\n  and:\n    - file.hasTag("task")\n

For property identification:

\n
filters:\n  and:\n    - note["type"] == "task"\n

Also preserve any excluded-folder conditions generated from your settings.

\n

Add a focused view#

\n

This example starts with recognized tasks, then limits the view to the work context:

\n
filters:\n  and:\n    - file.hasTag("task")\n    - list(contexts).contains("work")\n\nviews:\n  - type: tasknotesTaskList\n    name: Work\n    order:\n      - status\n      - priority\n      - due\n      - file.name\n    sort:\n      - column: due\n        direction: ASC\n

Use canonical stored values in filters. Natural-language prefixes such as @ and # are input syntax, not part of stored context and tag values.

\n

Point a command at the custom Base#

\n

Open Settings → TaskNotes → General → View commands and change the relevant command path. Resetting that mapping returns it to the generated default path.

\n

Upgrade safely#

\n

When TaskNotes ships improved templates:

\n
    \n
  1. Keep your custom file at its own path.
  2. \n
  3. Run Update default base files.
  4. \n
  5. Compare the regenerated default with your copy.
  6. \n
  7. Bring across only the formulas, filters, or view options you want.
  8. \n
\n

The generated template reference always reflects the current source and default field mapping.

\n

Recovery#

\n

If a custom Base no longer opens, validate its YAML indentation and remove the most recent filter or formula change. You can create a fresh default from settings at any time, then copy your custom view into it one section at a time.

\n","text":"TaskNotes views are ordinary Obsidian .base files. The safest workflow is to copy a generated Base, give it a new path, and customize the copy. Start from a copy# Open TaskNotes/Views/ in the file explorer. Duplicate the closest default, such as tasks-default.base. Rename the copy, for example work-tasks.base. Open the copy and make changes with the Bases interface or source editor. Avoid editing the only copy of a generated default. Update default base files replaces the files configured as defaults. Preserve task identification# Every task view needs a filter that matches the identification method in Settings → TaskNotes → General. For tag identification: filters: and: - file.hasTag(\"task\") For property identification: filters: and: - note[\"type\"] == \"task\" Also preserve any excluded-folder conditions generated from your settings. Add a focused view# This example starts with recognized tasks, then limits the view to the work context: filters: and: - file.hasTag(\"task\") - list(contexts).contains(\"work\") views: - type: tasknotesTaskList name: Work order: - status - priority - due - file.name sort: - column: due direction: ASC Use canonical stored values in filters. Natural-language prefixes such as @ and # are input syntax, not part of stored context and tag values. Point a command at the custom Base# Open Settings → TaskNotes → General → View commands and change the relevant command path. Resetting that mapping returns it to the generated default path. Upgrade safely# When TaskNotes ships improved templates: Keep your custom file at its own path. Run Update default base files. Compare the regenerated default with your copy. Bring across only the formulas, filters, or view options you want. The generated template reference always reflects the current source and default field mapping. Recovery# If a custom Base no longer opens, validate its YAML indentation and remove the most recent filter or formula change. You can create a fresh default from settings at any time, then copy your custom view into it one section at a time."},{"route":"/obsidian/HTTP_API/","title":"TaskNotes HTTP API","description":"The TaskNotes HTTP API provides local HTTP access to tasks, time tracking, pomodoro, calendars, webhooks, and NLP parsing.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/HTTP_API.md","namespace":"obsidian","relativePath":"HTTP_API.md","raw":"# TaskNotes HTTP API\n\nThe TaskNotes HTTP API provides local HTTP access to tasks, time tracking, pomodoro, calendars, webhooks, and NLP parsing.\n\n## Availability\n\n- Desktop only\n- Disabled by default\n- Started when Obsidian starts and TaskNotes API is enabled\n- Bound to loopback (`127.0.0.1`) only, not the local network\n- Browser CORS requests are allowed only from loopback origins such as\n `localhost`, `127.0.0.1`, and `[::1]`\n- Not available on mobile\n\nEnable it in `Settings -> TaskNotes -> Integrations -> HTTP API`.\n\n## Base URL\n\n`http://localhost:{PORT}`\n\nDefault port is `8080`.\n\n## Authentication\n\nAuthentication is optional.\n\n- If `apiAuthToken` is empty, all API requests are accepted.\n- If `apiAuthToken` is set, send `Authorization: Bearer `.\n- Set a token for any workflow where local browser pages, scripts, or other\n desktop apps are not fully trusted.\n\nExample:\n\n```bash\ncurl -H \"Authorization: Bearer YOUR_TOKEN\" http://localhost:8080/api/health\n```\n\n## Response Format\n\nSuccess:\n\n```json\n{\n \"success\": true,\n \"data\": {}\n}\n```\n\nError:\n\n```json\n{\n \"success\": false,\n \"error\": \"Error message\"\n}\n```\n\n## Endpoint Index\n\n### System\n\n- `GET /api/health`\n- `GET /api/docs`\n- `GET /api/docs/ui`\n- `POST /api/nlp/parse`\n- `POST /api/nlp/create`\n\n### Tasks\n\n- `GET /api/tasks`\n- `POST /api/tasks`\n- `GET /api/tasks/:id`\n- `PUT /api/tasks/:id`\n- `DELETE /api/tasks/:id`\n- `POST /api/tasks/:id/toggle-status`\n- `POST /api/tasks/:id/archive`\n- `POST /api/tasks/:id/complete-instance`\n- `POST /api/tasks/:id/materialize-occurrence`\n- `POST /api/tasks/query`\n- `GET /api/filter-options`\n- `GET /api/stats`\n\n### Bases\n\n- `POST /api/bases/default-files/update`\n\n### Time Tracking\n\n- `POST /api/tasks/:id/time/start`\n- `POST /api/tasks/:id/time/start-with-description`\n- `POST /api/tasks/:id/time/stop`\n- `GET /api/tasks/:id/time`\n- `GET /api/time/active`\n- `GET /api/time/summary`\n\n### Pomodoro\n\n- `POST /api/pomodoro/start`\n- `POST /api/pomodoro/stop`\n- `POST /api/pomodoro/pause`\n- `POST /api/pomodoro/resume`\n- `GET /api/pomodoro/status`\n- `GET /api/pomodoro/sessions`\n- `GET /api/pomodoro/stats`\n\n### Calendars\n\n- `GET /api/calendars`\n- `GET /api/calendars/google`\n- `GET /api/calendars/microsoft`\n- `GET /api/calendars/subscriptions`\n- `GET /api/calendars/events`\n\n### Webhooks\n\n- `POST /api/webhooks`\n- `GET /api/webhooks`\n- `DELETE /api/webhooks/:id`\n- `GET /api/webhooks/deliveries`\n\nSee `docs/webhooks.md` for event and transform details.\n\n## Route Details\n\n## Health\n\n### `GET /api/health`\n\nReturns service state plus vault metadata.\n\n```bash\ncurl http://localhost:8080/api/health\n```\n\n## Tasks\n\n### `GET /api/tasks`\n\nBasic task listing with pagination only.\n\nQuery params:\n\n- `limit` (default `50`, max `200`)\n- `offset` (default `0`)\n\nImportant:\n\n- Filtering params such as `status`, `priority`, `tag`, `project`, `context`, `due_before`, `due_after`, `overdue`, `completed`, `archived`, and `sort` are rejected on this endpoint with HTTP `400`.\n- Use `POST /api/tasks/query` for filtering.\n\nExample:\n\n```bash\ncurl \"http://localhost:8080/api/tasks?limit=25&offset=0\"\n```\n\nResponse fields:\n\n- `data.tasks`\n- `data.pagination` with `total`, `offset`, `limit`, `hasMore`\n- `data.vault`\n- `data.note`\n- Task objects include configured TaskNotes user fields in `customProperties`, keyed by their frontmatter property key.\n\n### `POST /api/tasks`\n\nCreate one task.\n\nRequired:\n\n- `title`\n\nCommon optional fields:\n\n- `details`, `status`, `priority`, `due`, `scheduled`\n- `tags`, `contexts`, `projects`\n- `recurrence`, `recurrence_anchor`, `timeEstimate`, `reminders`\n- `blockedBy`\n\n`blockedBy` accepts an array of dependency objects:\n\n- `uid`: link or identifier for the blocking task, such as `[[Project setup]]`\n- `reltype`: one of `FINISHTOSTART`, `FINISHTOFINISH`, `STARTTOSTART`, or `STARTTOFINISH`\n- `gap`: optional ISO 8601 duration, such as `P1D`\n\n`blocking` is a read-only reverse relationship in API responses. To make a task block existing tasks, update those existing tasks' `blockedBy` fields.\n\n```bash\ncurl -X POST http://localhost:8080/api/tasks \\\n -H \"Content-Type: application/json\" \\\n -d '{\"title\":\"Review docs\",\"priority\":\"high\",\"blockedBy\":[{\"uid\":\"[[Draft docs]]\",\"reltype\":\"FINISHTOSTART\"}]}'\n```\n\nReturns HTTP `201` with created task data.\n\n### `GET /api/tasks/:id`\n\nGet one task by path id.\n\n- `:id` must be URL-encoded task path.\n- Single-task reads include the task body in `details`.\n- Configured TaskNotes user fields are returned in `customProperties`, keyed by their frontmatter property key.\n\n```bash\ncurl \"http://localhost:8080/api/tasks/TaskNotes%2FTasks%2FReview%20docs.md\"\n```\n\n### `PUT /api/tasks/:id`\n\nUpdate task with partial payload.\n\nConfigured TaskNotes user fields can be updated either by their frontmatter property key or via `customProperties`.\n\n```bash\ncurl -X PUT \"http://localhost:8080/api/tasks/TaskNotes%2FTasks%2FReview%20docs.md\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"status\":\"in-progress\"}'\n```\n\n### `DELETE /api/tasks/:id`\n\nDelete task file.\n\n### `POST /api/tasks/:id/toggle-status`\n\nToggle task status via configured workflow.\n\n### `POST /api/tasks/:id/archive`\n\nToggle archive state.\n\n### `POST /api/tasks/:id/complete-instance`\n\nComplete recurring instance.\n\nRequest body:\n\n- Optional `date` (ISO string). If omitted, uses current date context.\n\nWhen the recurring parent uses materialized occurrence notes, this endpoint completes the matching occurrence note if one exists. If the parent is set to **Create next after completion** and no matching occurrence note exists yet, TaskNotes creates and completes that occurrence note instead of only recording a virtual `complete_instances` entry.\n\n### `POST /api/tasks/:id/materialize-occurrence`\n\nCreate or return a materialized occurrence note for a recurring task date. This endpoint is idempotent for the same parent and date.\n\nRequest body:\n\n- Required `date` (ISO date string, for example `2026-06-01`)\n\n### `POST /api/tasks/query`\n\nAdvanced filtering.\n\nRequest body is a `FilterQuery` object. `FilterQuery` is still the supported advanced query shape for the HTTP API.\n\nThe root object is a group with:\n\n- `type: \"group\"`\n- `id`\n- `conjunction: \"and\" | \"or\"`\n- `children` (conditions or groups)\n\nOptional top-level query options:\n\n- `sortKey`, `sortDirection`\n- `groupKey`, `subgroupKey`\n\nExample:\n\n```json\n{\n \"type\": \"group\",\n \"id\": \"root\",\n \"conjunction\": \"and\",\n \"children\": [\n {\n \"type\": \"condition\",\n \"id\": \"c1\",\n \"property\": \"status\",\n \"operator\": \"is\",\n \"value\": \"open\"\n }\n ],\n \"sortKey\": \"due\",\n \"sortDirection\": \"asc\"\n}\n```\n\nFilter tasks by context:\n\n```json\n{\n \"type\": \"group\",\n \"id\": \"root\",\n \"conjunction\": \"and\",\n \"children\": [\n {\n \"type\": \"condition\",\n \"id\": \"context\",\n \"property\": \"contexts\",\n \"operator\": \"contains\",\n \"value\": \"@office\"\n }\n ],\n \"sortKey\": \"due\",\n \"sortDirection\": \"asc\"\n}\n```\n\nFilter active, unarchived tasks, similar to the default available-task view:\n\n```json\n{\n \"type\": \"group\",\n \"id\": \"root\",\n \"conjunction\": \"and\",\n \"children\": [\n {\n \"type\": \"condition\",\n \"id\": \"not-archived\",\n \"property\": \"archived\",\n \"operator\": \"is-not-checked\"\n },\n {\n \"type\": \"condition\",\n \"id\": \"not-completed\",\n \"property\": \"status.isCompleted\",\n \"operator\": \"is-not-checked\"\n }\n ],\n \"sortKey\": \"due\",\n \"sortDirection\": \"asc\",\n \"groupKey\": \"none\"\n}\n```\n\nCondition fields:\n\n- `type`: `\"condition\"`\n- `id`: any stable string for your client\n- `property`: a task property, such as `title`, `status`, `priority`, `tags`, `contexts`, `projects`, `blockedBy`, `blocking`, `due`, `scheduled`, `completedDate`, `dateCreated`, `dateModified`, `archived`, `hasSubtasks`, `dependencies.isBlocked`, `dependencies.isBlocking`, `timeEstimate`, `recurrence`, or `status.isCompleted`\n- `operator`: one of `is`, `is-not`, `contains`, `does-not-contain`, `is-before`, `is-after`, `is-on-or-before`, `is-on-or-after`, `is-empty`, `is-not-empty`, `is-checked`, `is-not-checked`, `is-greater-than`, `is-less-than`, `is-greater-than-or-equal`, or `is-less-than-or-equal`\n- `value`: required for comparison operators, omitted for empty/checked operators\n\nFor user-defined fields, use `property: \"user:\"`.\n\nResponse:\n\n- `data.tasks`\n- `data.total`\n- `data.filtered`\n- `data.vault`\n\n### `GET /api/filter-options`\n\nReturns filter options for UI builders.\n\n### `GET /api/stats`\n\nReturns summary counts:\n\n- `total`, `completed`, `active`, `overdue`, `archived`, `withTimeTracking`\n\n## Bases\n\n### `POST /api/bases/default-files/update`\n\nOverwrite the configured default TaskNotes `.base` files with templates generated from the current TaskNotes settings. This is the same write operation as **Settings -> TaskNotes -> Views & base files -> Update files** and replaces manual edits in those configured default files.\n\n```bash\ncurl -X POST http://localhost:8080/api/bases/default-files/update\n```\n\nResponse fields:\n\n- `data.created`: default files created because they were missing\n- `data.updated`: existing default files overwritten with current templates\n- `data.skipped`: configured default files skipped\n\n## Time Tracking\n\n### `POST /api/tasks/:id/time/start`\n\nStarts a new active time entry for that task.\n\n### `POST /api/tasks/:id/time/start-with-description`\n\nStarts time tracking and writes `description` on the new active entry.\n\nRequest body:\n\n```json\n{\n \"description\": \"Implementation\"\n}\n```\n\n### `POST /api/tasks/:id/time/stop`\n\nStops active time entry for that task.\n\n### `GET /api/tasks/:id/time`\n\nReturns per-task time summary and entries.\n\n### `GET /api/time/active`\n\nReturns currently active sessions across tasks.\n\nImportant:\n\n- Multiple active sessions can exist across different tasks.\n\n### `GET /api/time/summary`\n\nReturns aggregate time summary.\n\nQuery params:\n\n- `period` (for example `today`, `week`, `month`, `all`)\n- `from` (ISO date)\n- `to` (ISO date)\n\nExample:\n\n```bash\ncurl \"http://localhost:8080/api/time/summary?period=week\"\n```\n\n## Pomodoro\n\n### `POST /api/pomodoro/start`\n\nStarts a session.\n\nOptional request fields:\n\n- `taskId` (URL path of task)\n- `duration` (number)\n\n### `POST /api/pomodoro/stop`\n\nStops and resets current session.\n\n### `POST /api/pomodoro/pause`\n\nPauses running session.\n\n### `POST /api/pomodoro/resume`\n\nResumes paused session.\n\n### `GET /api/pomodoro/status`\n\nReturns current state plus computed totals (`totalPomodoros`, `currentStreak`, `totalMinutesToday`).\n\n### `GET /api/pomodoro/sessions`\n\nReturns history.\n\nQuery params:\n\n- `limit`\n- `date` (`YYYY-MM-DD`)\n\n### `GET /api/pomodoro/stats`\n\nReturns stats for today or provided date.\n\nQuery params:\n\n- `date` (`YYYY-MM-DD`)\n\n## Calendars\n\n### `GET /api/calendars`\n\nReturns provider connectivity overview and subscription counts.\n\n### `GET /api/calendars/google`\n\nReturns Google provider details.\n\n- If disconnected, returns `{ \"connected\": false }`.\n\n### `GET /api/calendars/microsoft`\n\nReturns Microsoft provider details.\n\n- If disconnected, returns `{ \"connected\": false }`.\n\n### `GET /api/calendars/subscriptions`\n\nReturns ICS subscriptions with runtime fields such as `lastFetched` and `lastError`.\n\n### `GET /api/calendars/events`\n\nReturns merged event list from connected providers and ICS subscriptions.\n\nQuery params:\n\n- `start` (ISO date/datetime)\n- `end` (ISO date/datetime)\n\nResponse includes:\n\n- `events`\n- `total`\n- `sources` (counts by provider)\n\n## Webhooks\n\n### `POST /api/webhooks`\n\nRegisters webhook.\n\nRequired fields:\n\n- `url`\n- `events` (non-empty array)\n\nOptional fields:\n\n- `id`\n- `secret`\n- `active`\n- `transformFile`\n- `corsHeaders`\n\n### `GET /api/webhooks`\n\nLists registered webhooks. Stored secrets are not returned.\n\n### `DELETE /api/webhooks/:id`\n\nDeletes webhook.\n\n### `GET /api/webhooks/deliveries`\n\nReturns last 100 delivery records.\n\n## OpenAPI Docs\n\n### `GET /api/docs`\n\nReturns OpenAPI JSON generated from registered controllers.\n\n### `GET /api/docs/ui`\n\nReturns Swagger UI.\n\n## Errors\n\nCommon status codes:\n\n- `400` invalid request or invalid state\n- `401` missing/invalid bearer token (when auth token is configured)\n- `404` missing task/webhook/resource\n- `500` internal error\n\n## Security Notes\n\nCurrent behavior:\n\n- CORS allows all origins (`*`).\n- Transport is HTTP only (no TLS).\n- Node server is started with `server.listen(port)` and does not explicitly bind to `127.0.0.1`.\n\nPractical guidance:\n\n- Set an auth token.\n- Treat API port as sensitive and keep it firewalled.\n- If you expose this port outside localhost, route through a trusted reverse proxy and TLS.\n\n## Troubleshooting\n\n### API unavailable\n\n1. Confirm API is enabled in settings.\n2. Confirm Obsidian is running.\n3. Confirm selected port is free.\n4. Reload plugin or restart Obsidian after changing API enable/port.\n\n### `401 Authentication required`\n\n1. Check token value.\n2. Check `Bearer ` prefix.\n3. Remove whitespace around token.\n\n### Unexpected task list behavior\n\nIf you pass filters to `GET /api/tasks`, the endpoint returns `400` by design. Use `POST /api/tasks/query`.\n","aliases":["/HTTP_API/"],"toc":[{"level":2,"id":"availability","text":"Availability"},{"level":2,"id":"base-url","text":"Base URL"},{"level":2,"id":"authentication","text":"Authentication"},{"level":2,"id":"response-format","text":"Response Format"},{"level":2,"id":"endpoint-index","text":"Endpoint Index"},{"level":3,"id":"system","text":"System"},{"level":3,"id":"tasks","text":"Tasks"},{"level":3,"id":"bases","text":"Bases"},{"level":3,"id":"time-tracking","text":"Time Tracking"},{"level":3,"id":"pomodoro","text":"Pomodoro"},{"level":3,"id":"calendars","text":"Calendars"},{"level":3,"id":"webhooks","text":"Webhooks"},{"level":2,"id":"route-details","text":"Route Details"},{"level":2,"id":"health","text":"Health"},{"level":3,"id":"get-apihealth","text":"GET /api/health"},{"level":2,"id":"tasks-2","text":"Tasks"},{"level":3,"id":"get-apitasks","text":"GET /api/tasks"},{"level":3,"id":"post-apitasks","text":"POST /api/tasks"},{"level":3,"id":"get-apitasksid","text":"GET /api/tasks/:id"},{"level":3,"id":"put-apitasksid","text":"PUT /api/tasks/:id"},{"level":3,"id":"delete-apitasksid","text":"DELETE /api/tasks/:id"},{"level":3,"id":"post-apitasksidtoggle-status","text":"POST /api/tasks/:id/toggle-status"},{"level":3,"id":"post-apitasksidarchive","text":"POST /api/tasks/:id/archive"},{"level":3,"id":"post-apitasksidcomplete-instance","text":"POST /api/tasks/:id/complete-instance"},{"level":3,"id":"post-apitasksidmaterialize-occurrence","text":"POST /api/tasks/:id/materialize-occurrence"},{"level":3,"id":"post-apitasksquery","text":"POST /api/tasks/query"},{"level":3,"id":"get-apifilter-options","text":"GET /api/filter-options"},{"level":3,"id":"get-apistats","text":"GET /api/stats"},{"level":2,"id":"bases-2","text":"Bases"},{"level":3,"id":"post-apibasesdefault-filesupdate","text":"POST /api/bases/default-files/update"},{"level":2,"id":"time-tracking-2","text":"Time Tracking"},{"level":3,"id":"post-apitasksidtimestart","text":"POST /api/tasks/:id/time/start"},{"level":3,"id":"post-apitasksidtimestart-with-description","text":"POST /api/tasks/:id/time/start-with-description"},{"level":3,"id":"post-apitasksidtimestop","text":"POST /api/tasks/:id/time/stop"},{"level":3,"id":"get-apitasksidtime","text":"GET /api/tasks/:id/time"},{"level":3,"id":"get-apitimeactive","text":"GET /api/time/active"},{"level":3,"id":"get-apitimesummary","text":"GET /api/time/summary"},{"level":2,"id":"pomodoro-2","text":"Pomodoro"},{"level":3,"id":"post-apipomodorostart","text":"POST /api/pomodoro/start"},{"level":3,"id":"post-apipomodorostop","text":"POST /api/pomodoro/stop"},{"level":3,"id":"post-apipomodoropause","text":"POST /api/pomodoro/pause"},{"level":3,"id":"post-apipomodororesume","text":"POST /api/pomodoro/resume"},{"level":3,"id":"get-apipomodorostatus","text":"GET /api/pomodoro/status"},{"level":3,"id":"get-apipomodorosessions","text":"GET /api/pomodoro/sessions"},{"level":3,"id":"get-apipomodorostats","text":"GET /api/pomodoro/stats"},{"level":2,"id":"calendars-2","text":"Calendars"},{"level":3,"id":"get-apicalendars","text":"GET /api/calendars"},{"level":3,"id":"get-apicalendarsgoogle","text":"GET /api/calendars/google"},{"level":3,"id":"get-apicalendarsmicrosoft","text":"GET /api/calendars/microsoft"},{"level":3,"id":"get-apicalendarssubscriptions","text":"GET /api/calendars/subscriptions"},{"level":3,"id":"get-apicalendarsevents","text":"GET /api/calendars/events"},{"level":2,"id":"webhooks-2","text":"Webhooks"},{"level":3,"id":"post-apiwebhooks","text":"POST /api/webhooks"},{"level":3,"id":"get-apiwebhooks","text":"GET /api/webhooks"},{"level":3,"id":"delete-apiwebhooksid","text":"DELETE /api/webhooks/:id"},{"level":3,"id":"get-apiwebhooksdeliveries","text":"GET /api/webhooks/deliveries"},{"level":2,"id":"openapi-docs","text":"OpenAPI Docs"},{"level":3,"id":"get-apidocs","text":"GET /api/docs"},{"level":3,"id":"get-apidocsui","text":"GET /api/docs/ui"},{"level":2,"id":"errors","text":"Errors"},{"level":2,"id":"security-notes","text":"Security Notes"},{"level":2,"id":"troubleshooting","text":"Troubleshooting"},{"level":3,"id":"api-unavailable","text":"API unavailable"},{"level":3,"id":"401-authentication-required","text":"401 Authentication required"},{"level":3,"id":"unexpected-task-list-behavior","text":"Unexpected task list behavior"}],"html":"

The TaskNotes HTTP API provides local HTTP access to tasks, time tracking, pomodoro, calendars, webhooks, and NLP parsing.

\n

Availability#

\n
    \n
  • Desktop only
  • \n
  • Disabled by default
  • \n
  • Started when Obsidian starts and TaskNotes API is enabled
  • \n
  • Bound to loopback (127.0.0.1) only, not the local network
  • \n
  • Browser CORS requests are allowed only from loopback origins such as\nlocalhost, 127.0.0.1, and [::1]
  • \n
  • Not available on mobile
  • \n
\n

Enable it in Settings -> TaskNotes -> Integrations -> HTTP API.

\n

Base URL#

\n

http://localhost:{PORT}

\n

Default port is 8080.

\n

Authentication#

\n

Authentication is optional.

\n
    \n
  • If apiAuthToken is empty, all API requests are accepted.
  • \n
  • If apiAuthToken is set, send Authorization: Bearer <token>.
  • \n
  • Set a token for any workflow where local browser pages, scripts, or other\ndesktop apps are not fully trusted.
  • \n
\n

Example:

\n
curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:8080/api/health\n

Response Format#

\n

Success:

\n
{\n  "success": true,\n  "data": {}\n}\n

Error:

\n
{\n  "success": false,\n  "error": "Error message"\n}\n

Endpoint Index#

\n

System#

\n
    \n
  • GET /api/health
  • \n
  • GET /api/docs
  • \n
  • GET /api/docs/ui
  • \n
  • POST /api/nlp/parse
  • \n
  • POST /api/nlp/create
  • \n
\n

Tasks#

\n
    \n
  • GET /api/tasks
  • \n
  • POST /api/tasks
  • \n
  • GET /api/tasks/:id
  • \n
  • PUT /api/tasks/:id
  • \n
  • DELETE /api/tasks/:id
  • \n
  • POST /api/tasks/:id/toggle-status
  • \n
  • POST /api/tasks/:id/archive
  • \n
  • POST /api/tasks/:id/complete-instance
  • \n
  • POST /api/tasks/:id/materialize-occurrence
  • \n
  • POST /api/tasks/query
  • \n
  • GET /api/filter-options
  • \n
  • GET /api/stats
  • \n
\n

Bases#

\n
    \n
  • POST /api/bases/default-files/update
  • \n
\n

Time Tracking#

\n
    \n
  • POST /api/tasks/:id/time/start
  • \n
  • POST /api/tasks/:id/time/start-with-description
  • \n
  • POST /api/tasks/:id/time/stop
  • \n
  • GET /api/tasks/:id/time
  • \n
  • GET /api/time/active
  • \n
  • GET /api/time/summary
  • \n
\n

Pomodoro#

\n
    \n
  • POST /api/pomodoro/start
  • \n
  • POST /api/pomodoro/stop
  • \n
  • POST /api/pomodoro/pause
  • \n
  • POST /api/pomodoro/resume
  • \n
  • GET /api/pomodoro/status
  • \n
  • GET /api/pomodoro/sessions
  • \n
  • GET /api/pomodoro/stats
  • \n
\n

Calendars#

\n
    \n
  • GET /api/calendars
  • \n
  • GET /api/calendars/google
  • \n
  • GET /api/calendars/microsoft
  • \n
  • GET /api/calendars/subscriptions
  • \n
  • GET /api/calendars/events
  • \n
\n

Webhooks#

\n
    \n
  • POST /api/webhooks
  • \n
  • GET /api/webhooks
  • \n
  • DELETE /api/webhooks/:id
  • \n
  • GET /api/webhooks/deliveries
  • \n
\n

See docs/webhooks.md for event and transform details.

\n

Route Details#

\n

Health#

\n

GET /api/health#

\n

Returns service state plus vault metadata.

\n
curl http://localhost:8080/api/health\n

Tasks#

\n

GET /api/tasks#

\n

Basic task listing with pagination only.

\n

Query params:

\n
    \n
  • limit (default 50, max 200)
  • \n
  • offset (default 0)
  • \n
\n

Important:

\n
    \n
  • Filtering params such as status, priority, tag, project, context, due_before, due_after, overdue, completed, archived, and sort are rejected on this endpoint with HTTP 400.
  • \n
  • Use POST /api/tasks/query for filtering.
  • \n
\n

Example:

\n
curl "http://localhost:8080/api/tasks?limit=25&offset=0"\n

Response fields:

\n
    \n
  • data.tasks
  • \n
  • data.pagination with total, offset, limit, hasMore
  • \n
  • data.vault
  • \n
  • data.note
  • \n
  • Task objects include configured TaskNotes user fields in customProperties, keyed by their frontmatter property key.
  • \n
\n

POST /api/tasks#

\n

Create one task.

\n

Required:

\n
    \n
  • title
  • \n
\n

Common optional fields:

\n
    \n
  • details, status, priority, due, scheduled
  • \n
  • tags, contexts, projects
  • \n
  • recurrence, recurrence_anchor, timeEstimate, reminders
  • \n
  • blockedBy
  • \n
\n

blockedBy accepts an array of dependency objects:

\n
    \n
  • uid: link or identifier for the blocking task, such as [[Project setup]]
  • \n
  • reltype: one of FINISHTOSTART, FINISHTOFINISH, STARTTOSTART, or STARTTOFINISH
  • \n
  • gap: optional ISO 8601 duration, such as P1D
  • \n
\n

blocking is a read-only reverse relationship in API responses. To make a task block existing tasks, update those existing tasks' blockedBy fields.

\n
curl -X POST http://localhost:8080/api/tasks \\\n  -H "Content-Type: application/json" \\\n  -d '{"title":"Review docs","priority":"high","blockedBy":[{"uid":"[[Draft docs]]","reltype":"FINISHTOSTART"}]}'\n

Returns HTTP 201 with created task data.

\n

GET /api/tasks/:id#

\n

Get one task by path id.

\n
    \n
  • :id must be URL-encoded task path.
  • \n
  • Single-task reads include the task body in details.
  • \n
  • Configured TaskNotes user fields are returned in customProperties, keyed by their frontmatter property key.
  • \n
\n
curl "http://localhost:8080/api/tasks/TaskNotes%2FTasks%2FReview%20docs.md"\n

PUT /api/tasks/:id#

\n

Update task with partial payload.

\n

Configured TaskNotes user fields can be updated either by their frontmatter property key or via customProperties.

\n
curl -X PUT "http://localhost:8080/api/tasks/TaskNotes%2FTasks%2FReview%20docs.md" \\\n  -H "Content-Type: application/json" \\\n  -d '{"status":"in-progress"}'\n

DELETE /api/tasks/:id#

\n

Delete task file.

\n

POST /api/tasks/:id/toggle-status#

\n

Toggle task status via configured workflow.

\n

POST /api/tasks/:id/archive#

\n

Toggle archive state.

\n

POST /api/tasks/:id/complete-instance#

\n

Complete recurring instance.

\n

Request body:

\n
    \n
  • Optional date (ISO string). If omitted, uses current date context.
  • \n
\n

When the recurring parent uses materialized occurrence notes, this endpoint completes the matching occurrence note if one exists. If the parent is set to Create next after completion and no matching occurrence note exists yet, TaskNotes creates and completes that occurrence note instead of only recording a virtual complete_instances entry.

\n

POST /api/tasks/:id/materialize-occurrence#

\n

Create or return a materialized occurrence note for a recurring task date. This endpoint is idempotent for the same parent and date.

\n

Request body:

\n
    \n
  • Required date (ISO date string, for example 2026-06-01)
  • \n
\n

POST /api/tasks/query#

\n

Advanced filtering.

\n

Request body is a FilterQuery object. FilterQuery is still the supported advanced query shape for the HTTP API.

\n

The root object is a group with:

\n
    \n
  • type: "group"
  • \n
  • id
  • \n
  • conjunction: "and" | "or"
  • \n
  • children (conditions or groups)
  • \n
\n

Optional top-level query options:

\n
    \n
  • sortKey, sortDirection
  • \n
  • groupKey, subgroupKey
  • \n
\n

Example:

\n
{\n  "type": "group",\n  "id": "root",\n  "conjunction": "and",\n  "children": [\n    {\n      "type": "condition",\n      "id": "c1",\n      "property": "status",\n      "operator": "is",\n      "value": "open"\n    }\n  ],\n  "sortKey": "due",\n  "sortDirection": "asc"\n}\n

Filter tasks by context:

\n
{\n  "type": "group",\n  "id": "root",\n  "conjunction": "and",\n  "children": [\n    {\n      "type": "condition",\n      "id": "context",\n      "property": "contexts",\n      "operator": "contains",\n      "value": "@office"\n    }\n  ],\n  "sortKey": "due",\n  "sortDirection": "asc"\n}\n

Filter active, unarchived tasks, similar to the default available-task view:

\n
{\n  "type": "group",\n  "id": "root",\n  "conjunction": "and",\n  "children": [\n    {\n      "type": "condition",\n      "id": "not-archived",\n      "property": "archived",\n      "operator": "is-not-checked"\n    },\n    {\n      "type": "condition",\n      "id": "not-completed",\n      "property": "status.isCompleted",\n      "operator": "is-not-checked"\n    }\n  ],\n  "sortKey": "due",\n  "sortDirection": "asc",\n  "groupKey": "none"\n}\n

Condition fields:

\n
    \n
  • type: "condition"
  • \n
  • id: any stable string for your client
  • \n
  • property: a task property, such as title, status, priority, tags, contexts, projects, blockedBy, blocking, due, scheduled, completedDate, dateCreated, dateModified, archived, hasSubtasks, dependencies.isBlocked, dependencies.isBlocking, timeEstimate, recurrence, or status.isCompleted
  • \n
  • operator: one of is, is-not, contains, does-not-contain, is-before, is-after, is-on-or-before, is-on-or-after, is-empty, is-not-empty, is-checked, is-not-checked, is-greater-than, is-less-than, is-greater-than-or-equal, or is-less-than-or-equal
  • \n
  • value: required for comparison operators, omitted for empty/checked operators
  • \n
\n

For user-defined fields, use property: "user:<fieldId>".

\n

Response:

\n
    \n
  • data.tasks
  • \n
  • data.total
  • \n
  • data.filtered
  • \n
  • data.vault
  • \n
\n

GET /api/filter-options#

\n

Returns filter options for UI builders.

\n

GET /api/stats#

\n

Returns summary counts:

\n
    \n
  • total, completed, active, overdue, archived, withTimeTracking
  • \n
\n

Bases#

\n

POST /api/bases/default-files/update#

\n

Overwrite the configured default TaskNotes .base files with templates generated from the current TaskNotes settings. This is the same write operation as Settings -> TaskNotes -> Views & base files -> Update files and replaces manual edits in those configured default files.

\n
curl -X POST http://localhost:8080/api/bases/default-files/update\n

Response fields:

\n
    \n
  • data.created: default files created because they were missing
  • \n
  • data.updated: existing default files overwritten with current templates
  • \n
  • data.skipped: configured default files skipped
  • \n
\n

Time Tracking#

\n

POST /api/tasks/:id/time/start#

\n

Starts a new active time entry for that task.

\n

POST /api/tasks/:id/time/start-with-description#

\n

Starts time tracking and writes description on the new active entry.

\n

Request body:

\n
{\n  "description": "Implementation"\n}\n

POST /api/tasks/:id/time/stop#

\n

Stops active time entry for that task.

\n

GET /api/tasks/:id/time#

\n

Returns per-task time summary and entries.

\n

GET /api/time/active#

\n

Returns currently active sessions across tasks.

\n

Important:

\n
    \n
  • Multiple active sessions can exist across different tasks.
  • \n
\n

GET /api/time/summary#

\n

Returns aggregate time summary.

\n

Query params:

\n
    \n
  • period (for example today, week, month, all)
  • \n
  • from (ISO date)
  • \n
  • to (ISO date)
  • \n
\n

Example:

\n
curl "http://localhost:8080/api/time/summary?period=week"\n

Pomodoro#

\n

POST /api/pomodoro/start#

\n

Starts a session.

\n

Optional request fields:

\n
    \n
  • taskId (URL path of task)
  • \n
  • duration (number)
  • \n
\n

POST /api/pomodoro/stop#

\n

Stops and resets current session.

\n

POST /api/pomodoro/pause#

\n

Pauses running session.

\n

POST /api/pomodoro/resume#

\n

Resumes paused session.

\n

GET /api/pomodoro/status#

\n

Returns current state plus computed totals (totalPomodoros, currentStreak, totalMinutesToday).

\n

GET /api/pomodoro/sessions#

\n

Returns history.

\n

Query params:

\n
    \n
  • limit
  • \n
  • date (YYYY-MM-DD)
  • \n
\n

GET /api/pomodoro/stats#

\n

Returns stats for today or provided date.

\n

Query params:

\n
    \n
  • date (YYYY-MM-DD)
  • \n
\n

Calendars#

\n

GET /api/calendars#

\n

Returns provider connectivity overview and subscription counts.

\n

GET /api/calendars/google#

\n

Returns Google provider details.

\n
    \n
  • If disconnected, returns { "connected": false }.
  • \n
\n

GET /api/calendars/microsoft#

\n

Returns Microsoft provider details.

\n
    \n
  • If disconnected, returns { "connected": false }.
  • \n
\n

GET /api/calendars/subscriptions#

\n

Returns ICS subscriptions with runtime fields such as lastFetched and lastError.

\n

GET /api/calendars/events#

\n

Returns merged event list from connected providers and ICS subscriptions.

\n

Query params:

\n
    \n
  • start (ISO date/datetime)
  • \n
  • end (ISO date/datetime)
  • \n
\n

Response includes:

\n
    \n
  • events
  • \n
  • total
  • \n
  • sources (counts by provider)
  • \n
\n

Webhooks#

\n

POST /api/webhooks#

\n

Registers webhook.

\n

Required fields:

\n
    \n
  • url
  • \n
  • events (non-empty array)
  • \n
\n

Optional fields:

\n
    \n
  • id
  • \n
  • secret
  • \n
  • active
  • \n
  • transformFile
  • \n
  • corsHeaders
  • \n
\n

GET /api/webhooks#

\n

Lists registered webhooks. Stored secrets are not returned.

\n

DELETE /api/webhooks/:id#

\n

Deletes webhook.

\n

GET /api/webhooks/deliveries#

\n

Returns last 100 delivery records.

\n

OpenAPI Docs#

\n

GET /api/docs#

\n

Returns OpenAPI JSON generated from registered controllers.

\n

GET /api/docs/ui#

\n

Returns Swagger UI.

\n

Errors#

\n

Common status codes:

\n
    \n
  • 400 invalid request or invalid state
  • \n
  • 401 missing/invalid bearer token (when auth token is configured)
  • \n
  • 404 missing task/webhook/resource
  • \n
  • 500 internal error
  • \n
\n

Security Notes#

\n

Current behavior:

\n
    \n
  • CORS allows all origins (*).
  • \n
  • Transport is HTTP only (no TLS).
  • \n
  • Node server is started with server.listen(port) and does not explicitly bind to 127.0.0.1.
  • \n
\n

Practical guidance:

\n
    \n
  • Set an auth token.
  • \n
  • Treat API port as sensitive and keep it firewalled.
  • \n
  • If you expose this port outside localhost, route through a trusted reverse proxy and TLS.
  • \n
\n

Troubleshooting#

\n

API unavailable#

\n
    \n
  1. Confirm API is enabled in settings.
  2. \n
  3. Confirm Obsidian is running.
  4. \n
  5. Confirm selected port is free.
  6. \n
  7. Reload plugin or restart Obsidian after changing API enable/port.
  8. \n
\n

401 Authentication required#

\n
    \n
  1. Check token value.
  2. \n
  3. Check Bearer prefix.
  4. \n
  5. Remove whitespace around token.
  6. \n
\n

Unexpected task list behavior#

\n

If you pass filters to GET /api/tasks, the endpoint returns 400 by design. Use POST /api/tasks/query.

\n","text":"The TaskNotes HTTP API provides local HTTP access to tasks, time tracking, pomodoro, calendars, webhooks, and NLP parsing. Availability# Desktop only Disabled by default Started when Obsidian starts and TaskNotes API is enabled Bound to loopback (127.0.0.1) only, not the local network Browser CORS requests are allowed only from loopback origins such as localhost, 127.0.0.1, and [::1] Not available on mobile Enable it in Settings -> TaskNotes -> Integrations -> HTTP API. Base URL# http://localhost:{PORT} Default port is 8080. Authentication# Authentication is optional. If apiAuthToken is empty, all API requests are accepted. If apiAuthToken is set, send Authorization: Bearer . Set a token for any workflow where local browser pages, scripts, or other desktop apps are not fully trusted. Example: curl -H \"Authorization: Bearer YOUR_TOKEN\" http://localhost:8080/api/health Response Format# Success: { \"success\": true, \"data\": {} } Error: { \"success\": false, \"error\": \"Error message\" } Endpoint Index# System# GET /api/health GET /api/docs GET /api/docs/ui POST /api/nlp/parse POST /api/nlp/create Tasks# GET /api/tasks POST /api/tasks GET /api/tasks/:id PUT /api/tasks/:id DELETE /api/tasks/:id POST /api/tasks/:id/toggle-status POST /api/tasks/:id/archive POST /api/tasks/:id/complete-instance POST /api/tasks/:id/materialize-occurrence POST /api/tasks/query GET /api/filter-options GET /api/stats Bases# POST /api/bases/default-files/update Time Tracking# POST /api/tasks/:id/time/start POST /api/tasks/:id/time/start-with-description POST /api/tasks/:id/time/stop GET /api/tasks/:id/time GET /api/time/active GET /api/time/summary Pomodoro# POST /api/pomodoro/start POST /api/pomodoro/stop POST /api/pomodoro/pause POST /api/pomodoro/resume GET /api/pomodoro/status GET /api/pomodoro/sessions GET /api/pomodoro/stats Calendars# GET /api/calendars GET /api/calendars/google GET /api/calendars/microsoft GET /api/calendars/subscriptions GET /api/calendars/events Webhooks# POST /api/webhooks GET /api/webhooks DELETE /api/webhooks/:id GET /api/webhooks/deliveries See docs/webhooks.md for event and transform details. Route Details# Health# GET /api/health# Returns service state plus vault metadata. curl http://localhost:8080/api/health Tasks# GET /api/tasks# Basic task listing with pagination only. Query params: limit (default 50, max 200) offset (default 0) Important: Filtering params such as status, priority, tag, project, context, due_before, due_after, overdue, completed, archived, and sort are rejected on this endpoint with HTTP 400. Use POST /api/tasks/query for filtering. Example: curl \"http://localhost:8080/api/tasks?limit=25&offset=0\" Response fields: data.tasks data.pagination with total, offset, limit, hasMore data.vault data.note Task objects include configured TaskNotes user fields in customProperties, keyed by their frontmatter property key. POST /api/tasks# Create one task. Required: title Common optional fields: details, status, priority, due, scheduled tags, contexts, projects recurrence, recurrence_anchor, timeEstimate, reminders blockedBy blockedBy accepts an array of dependency objects: uid: link or identifier for the blocking task, such as [[Project setup]] reltype: one of FINISHTOSTART, FINISHTOFINISH, STARTTOSTART, or STARTTOFINISH gap: optional ISO 8601 duration, such as P1D blocking is a read-only reverse relationship in API responses. To make a task block existing tasks, update those existing tasks' blockedBy fields. curl -X POST http://localhost:8080/api/tasks \\ -H \"Content-Type: application/json\" \\ -d '{\"title\":\"Review docs\",\"priority\":\"high\",\"blockedBy\":[{\"uid\":\"[[Draft docs]]\",\"reltype\":\"FINISHTOSTART\"}]}' Returns HTTP 201 with created task data. GET /api/tasks/:id# Get one task by path id. :id must be URL-encoded task path. Single-task reads include the task body in details. Configured TaskNotes user fields are returned in customProperties, keyed by their frontmatter property key. curl \"http://localhost:8080/api/tasks/TaskNotes%2FTasks%2FReview%20docs.md\" PUT /api/tasks/:id# Update task with partial payload. Configured TaskNotes user fields can be updated either by their frontmatter property key or via customProperties. curl -X PUT \"http://localhost:8080/api/tasks/TaskNotes%2FTasks%2FReview%20docs.md\" \\ -H \"Content-Type: application/json\" \\ -d '{\"status\":\"in-progress\"}' DELETE /api/tasks/:id# Delete task file. POST /api/tasks/:id/toggle-status# Toggle task status via configured workflow. POST /api/tasks/:id/archive# Toggle archive state. POST /api/tasks/:id/complete-instance# Complete recurring instance. Request body: Optional date (ISO string). If omitted, uses current date context. When the recurring parent uses materialized occurrence notes, this endpoint completes the matching occurrence note if one exists. If the parent is set to Create next after completion and no matching occurrence note exists yet, TaskNotes creates and completes that occurrence note instead of only recording a virtual complete_instances entry. POST /api/tasks/:id/materialize-occurrence# Create or return a materialized occurrence note for a recurring task date. This endpoint is idempotent for the same parent and date. Request body: Required date (ISO date string, for example 2026-06-01) POST /api/tasks/query# Advanced filtering. Request body is a FilterQuery object. FilterQuery is still the supported advanced query shape for the HTTP API. The root object is a group with: type: \"group\" id conjunction: \"and\" | \"or\" children (conditions or groups) Optional top-level query options: sortKey, sortDirection groupKey, subgroupKey Example: { \"type\": \"group\", \"id\": \"root\", \"conjunction\": \"and\", \"children\": [ { \"type\": \"condition\", \"id\": \"c1\", \"property\": \"status\", \"operator\": \"is\", \"value\": \"open\" } ], \"sortKey\": \"due\", \"sortDirection\": \"asc\" } Filter tasks by context: { \"type\": \"group\", \"id\": \"root\", \"conjunction\": \"and\", \"children\": [ { \"type\": \"condition\", \"id\": \"context\", \"property\": \"contexts\", \"operator\": \"contains\", \"value\": \"@office\" } ], \"sortKey\": \"due\", \"sortDirection\": \"asc\" } Filter active, unarchived tasks, similar to the default available-task view: { \"type\": \"group\", \"id\": \"root\", \"conjunction\": \"and\", \"children\": [ { \"type\": \"condition\", \"id\": \"not-archived\", \"property\": \"archived\", \"operator\": \"is-not-checked\" }, { \"type\": \"condition\", \"id\": \"not-completed\", \"property\": \"status.isCompleted\", \"operator\": \"is-not-checked\" } ], \"sortKey\": \"due\", \"sortDirection\": \"asc\", \"groupKey\": \"none\" } Condition fields: type: \"condition\" id: any stable string for your client property: a task property, such as title, status, priority, tags, contexts, projects, blockedBy, blocking, due, scheduled, completedDate, dateCreated, dateModified, archived, hasSubtasks, dependencies.isBlocked, dependencies.isBlocking, timeEstimate, recurrence, or status.isCompleted operator: one of is, is-not, contains, does-not-contain, is-before, is-after, is-on-or-before, is-on-or-after, is-empty, is-not-empty, is-checked, is-not-checked, is-greater-than, is-less-than, is-greater-than-or-equal, or is-less-than-or-equal value: required for comparison operators, omitted for empty/checked operators For user-defined fields, use property: \"user:\". Response: data.tasks data.total data.filtered data.vault GET /api/filter-options# Returns filter options for UI builders. GET /api/stats# Returns summary counts: total, completed, active, overdue, archived, withTimeTracking Bases# POST /api/bases/default-files/update# Overwrite the configured default TaskNotes .base files with templates generated from the current TaskNotes settings. This is the same write operation as Settings -> TaskNotes -> Views & base files -> Update files and replaces manual edits in those configured default files. curl -X POST http://localhost:8080/api/bases/default-files/update Response fields: data.created: default files created because they were missing data.updated: existing default files overwritten with current templates data.skipped: configured default files skipped Time Tracking# POST /api/tasks/:id/time/start# Starts a new active time entry for that task. POST /api/tasks/:id/time/start-with-description# Starts time tracking and writes description on the new active entry. Request body: { \"description\": \"Implementation\" } POST /api/tasks/:id/time/stop# Stops active time entry for that task. GET /api/tasks/:id/time# Returns per-task time summary and entries. GET /api/time/active# Returns currently active sessions across tasks. Important: Multiple active sessions can exist across different tasks. GET /api/time/summary# Returns aggregate time summary. Query params: period (for example today, week, month, all) from (ISO date) to (ISO date) Example: curl \"http://localhost:8080/api/time/summary?period=week\" Pomodoro# POST /api/pomodoro/start# Starts a session. Optional request fields: taskId (URL path of task) duration (number) POST /api/pomodoro/stop# Stops and resets current session. POST /api/pomodoro/pause# Pauses running session. POST /api/pomodoro/resume# Resumes paused session. GET /api/pomodoro/status# Returns current state plus computed totals (totalPomodoros, currentStreak, totalMinutesToday). GET /api/pomodoro/sessions# Returns history. Query params: limit date (YYYY-MM-DD) GET /api/pomodoro/stats# Returns stats for today or provided date. Query params: date (YYYY-MM-DD) Calendars# GET /api/calendars# Returns provider connectivity overview and subscription counts. GET /api/calendars/google# Returns Google provider details. If disconnected, returns { \"connected\": false }. GET /api/calendars/microsoft# Returns Microsoft provider details. If disconnected, returns { \"connected\": false }. GET /api/calendars/subscriptions# Returns ICS subscriptions with runtime fields such as lastFetched and lastError. GET /api/calendars/events# Returns merged event list from connected providers and ICS subscriptions. Query params: start (ISO date/datetime) end (ISO date/datetime) Response includes: events total sources (counts by provider) Webhooks# POST /api/webhooks# Registers webhook. Required fields: url events (non-empty array) Optional fields: id secret active transformFile corsHeaders GET /api/webhooks# Lists registered webhooks. Stored secrets are not returned. DELETE /api/webhooks/:id# Deletes webhook. GET /api/webhooks/deliveries# Returns last 100 delivery records. OpenAPI Docs# GET /api/docs# Returns OpenAPI JSON generated from registered controllers. GET /api/docs/ui# Returns Swagger UI. Errors# Common status codes: 400 invalid request or invalid state 401 missing/invalid bearer token (when auth token is configured) 404 missing task/webhook/resource 500 internal error Security Notes# Current behavior: CORS allows all origins (*). Transport is HTTP only (no TLS). Node server is started with server.listen(port) and does not explicitly bind to 127.0.0.1. Practical guidance: Set an auth token. Treat API port as sensitive and keep it firewalled. If you expose this port outside localhost, route through a trusted reverse proxy and TLS. Troubleshooting# API unavailable# Confirm API is enabled in settings. Confirm Obsidian is running. Confirm selected port is free. Reload plugin or restart Obsidian after changing API enable/port. 401 Authentication required# Check token value. Check Bearer prefix. Remove whitespace around token. Unexpected task list behavior# If you pass filters to GET /api/tasks, the endpoint returns 400 by design. Use POST /api/tasks/query."},{"route":"/obsidian/javascript-api/","title":"TaskNotes JavaScript Runtime API","description":"TaskNotes exposes an in-process runtime API on the loaded Obsidian plugin instance:","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/javascript-api.md","namespace":"obsidian","relativePath":"javascript-api.md","raw":"# TaskNotes JavaScript Runtime API\n\nTaskNotes exposes an in-process runtime API on the loaded Obsidian plugin instance:\n\n```javascript\nconst tasknotes = app.plugins.plugins.tasknotes;\nconst api = tasknotes?.api;\n```\n\nThis API is for Obsidian companion plugins and in-vault scripting tools such as Templater, QuickAdd, and MetaBind. It runs inside Obsidian and uses the same TaskNotes services, settings, cache, and vault permissions as the plugin UI.\n\nThis is separate from the [HTTP API](HTTP_API.md). The runtime API does not start a server, does not use bearer-token authentication, and is only available inside the running Obsidian app.\n\nFor user-facing extensions built on this API, see [Companion Plugins](companion-plugins.md). For a concrete automation companion plugin, see [TaskNotes Workflows](companion-plugins/tasknotes-workflows.md).\n\nThe TypeScript contract lives in `src/api/runtime-api.ts`. It is intentionally small and type-focused so it can later become a standalone `@tasknotes/runtime-api` package for companion plugins.\n\n## Version and Capabilities\n\nCheck the API version and capabilities before using methods that may not exist in older TaskNotes versions:\n\n```javascript\nconst tasknotes = app.plugins.plugins.tasknotes;\nconst api = tasknotes?.api;\n\nif (!api || api.apiVersion !== 1 || !api.hasCapability(\"tasks.write\")) {\n\tthrow new Error(\"This workflow requires TaskNotes runtime API v1 task writes\");\n}\n```\n\nCurrent capabilities:\n\n- `model.read`\n- `model.validate`\n- `catalog.read`\n- `extensions.read`\n- `extensions.register`\n- `tasks.read`\n- `tasks.write`\n- `tasks.delete`\n- `tasks.move`\n- `tasks.events`\n- `relationships.read`\n- `events.list`\n- `time.read`\n- `time.write`\n- `time.summary`\n- `pomodoro.read`\n- `pomodoro.write`\n- `pomodoro.events`\n- `recurring.write`\n- `recurring.materialize`\n- `recurring.events`\n- `settings.snapshot`\n- `bases.write`\n- `nlp.parse`\n- `ui.task-menu`\n- `query.tasks`\n- `query.validate`\n- `query.explain`\n- `query.filter-options`\n- `stats.tasks`\n- `system.health`\n- `lifecycle.events`\n- `errors.typed`\n\n## Namespaces\n\nPrefer the namespaced API for new code:\n\n```javascript\nawait api.tasks.update(\"Tasks/example.md\", { status: \"active\" });\nconst subtasks = await api.relationships.subtasks(\"Tasks/example.md\");\nawait api.time.start(\"Tasks/example.md\", { description: \"Deep work\" });\nawait api.pomodoro.start({ taskPath: \"Tasks/example.md\", duration: 25 });\n```\n\nThe older flat methods, such as `api.getTask(path)` and `api.parseNaturalLanguage(text)`, remain available as compatibility aliases.\n\n## Extension Registry\n\nCompanion plugins can publish their own runtime API namespace through `api.extensions`. This is the preferred way to extend TaskNotes without adding arbitrary properties to the core API object.\n\n```javascript\nconst tasknotes = this.app.plugins.getPlugin(\"tasknotes\");\nconst api = tasknotes?.api;\n\nif (!api?.hasCapability(\"extensions.register\")) {\n\treturn;\n}\n\nconst handle = api.extensions.register({\n\tid: this.manifest.id,\n\tnamespace: \"tasknotes-workflows\",\n\tdisplayName: \"TaskNotes Workflows\",\n\tversion: this.manifest.version,\n\tcapabilities: [\"tasknotes-workflows.run\", \"tasknotes-workflows.events\"],\n\tapi: {\n\t\trunWorkflow: async (workflowId, input) => {\n\t\t\t// companion plugin implementation\n\t\t},\n\t},\n});\n\nthis.register(() => handle.unregister());\n```\n\nOther plugins can discover and consume extension namespaces:\n\n```javascript\nconst workflows = api.extensions.get(\"tasknotes-workflows\");\n\nif (api.hasCapability(\"tasknotes-workflows.run\")) {\n\tawait workflows.runWorkflow(\"start-timer-on-active\", { taskPath: \"Tasks/example.md\" });\n}\n```\n\nExtension namespaces are normalized to lowercase and may use letters, numbers, dots, underscores, or dashes. Capability names are also normalized to lowercase. Prefix extension capabilities with the extension namespace to avoid collisions.\n\n## Companion Plugin Access\n\nCompanion plugins can read the TaskNotes plugin instance from Obsidian's plugin registry:\n\n```javascript\nconst tasknotes = this.app.plugins.getPlugin(\"tasknotes\");\nconst api = tasknotes?.api;\n\nif (!api?.hasCapability(\"tasks.events\")) {\n\treturn;\n}\n\nthis.registerEvent(\n\tapi.events.on(\"task.status.changed\", (event) => {\n\t\tconsole.log(event.taskPath, event.changes.status);\n\t})\n);\n```\n\nIf TaskNotes is disabled or has not loaded yet, `api` will be unavailable. Companion plugins should handle that case and retry after plugin load if needed.\n\n## TypeScript\n\nUse the exported runtime contract for type safety:\n\n```typescript\nimport type { TaskNotesRuntimeApiV1 } from \"tasknotes/src/api/runtime-api\";\n\ntype TaskNotesPluginInstance = {\n\tapi?: TaskNotesRuntimeApiV1;\n};\n\nconst tasknotes = app.plugins.getPlugin(\"tasknotes\") as TaskNotesPluginInstance | null;\nconst api = tasknotes?.api;\n\nif (api?.apiVersion === 1 && api.hasCapability(\"tasks.write\")) {\n\tawait api.tasks.setStatus(\"Tasks/example.md\", \"active\");\n}\n```\n\nTaskNotes is still loaded by Obsidian at runtime. The TypeScript contract only gives companion plugins compile-time checking and autocomplete.\n\n## Model\n\nThe runtime API exposes a small model namespace backed by `@tasknotes/model`:\n\n```javascript\nconst info = api.model.info();\nconst config = api.model.config();\nconst validation = api.model.validateTask(task);\n```\n\n| Method | Description |\n| -------------------------------- | ------------------------------------------------------------------------------------------------ |\n| `api.model.info()` | Returns the model package name, TaskNotes spec version, and runtime API version. |\n| `api.model.config()` | Returns a resolved, Obsidian-free model configuration snapshot derived from TaskNotes settings. |\n| `api.model.validateTask(task)` | Validates a partial or complete task against the shared model schema and TaskNotes status rules. |\n| `api.model.validatePatch(patch)` | Validates a task patch before passing it to a runtime task mutation. |\n\n## Catalog\n\nUse `api.catalog` to build companion-plugin editors without hardcoding TaskNotes values:\n\n```javascript\nconst statuses = api.catalog.statuses();\nconst writableFields = api.catalog.writableFields();\nconst operators = api.catalog.filterOperators();\n```\n\n| Method | Description |\n| ---------------------------------- | ----------------------------------------------------------------------------------------------------------------- |\n| `api.catalog.statuses()` | Returns configured TaskNotes status definitions. |\n| `api.catalog.priorities()` | Returns configured TaskNotes priority definitions. |\n| `api.catalog.userFields()` | Returns configured user-defined field mappings. |\n| `api.catalog.fields()` | Returns core, computed, and user field metadata with value type, writability, and frontmatter key when available. |\n| `api.catalog.writableFields()` | Returns only fields that runtime task mutations may write. |\n| `api.catalog.filterProperties()` | Returns canonical query fields, aliases, value types, and supported operators. |\n| `api.catalog.filterOperators()` | Returns canonical query operators, labels, value requirements, and accepted aliases. |\n| `api.catalog.relationships()` | Returns relationship categories supported by `api.relationships`. |\n| `api.catalog.dependencyRelTypes()` | Returns dependency relationship types accepted by `api.tasks.addDependency`. |\n| `api.catalog.events()` | Returns the same runtime event catalogue as `api.events.list()`. |\n\n## Tasks\n\nAll paths are vault-relative Markdown file paths.\n\n| Method | Description |\n| --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |\n| `api.tasks.get(path)` | Returns a task by path, or `null` when no task is cached at that path. |\n| `api.tasks.list(query?)` | Returns all tasks, or tasks matching a runtime task query. Prefer `api.query.tasks()` when count and grouping metadata matters. |\n| `api.tasks.create(taskData, context?)` | Creates a task using the normal TaskNotes creation service. |\n| `api.tasks.update(path, patch, context?)` | Updates one or more task fields using the normal TaskNotes update service. |\n| `api.tasks.delete(path, context?)` | Deletes the task file through TaskNotes' delete service. |\n| `api.tasks.complete(path, options?, context?)` | Marks a task complete. |\n| `api.tasks.uncomplete(path, options?, context?)` | Moves a completed task back to a non-completed status. |\n| `api.tasks.setStatus(path, status, context?)` | Sets task status. |\n| `api.tasks.setPriority(path, priority, context?)` | Sets task priority. |\n| `api.tasks.setDue(path, date, context?)` / `clearDue(path, context?)` | Sets or clears due date. |\n| `api.tasks.setScheduled(path, date, context?)` / `clearScheduled(path, context?)` | Sets or clears scheduled date. |\n| `api.tasks.archive(path, archived, context?)` | Archives or unarchives a task, including archive-folder movement when configured. |\n| `api.tasks.move(path, targetFolder, context?)` | Moves the task note and refuses to overwrite an existing file. |\n| `api.tasks.addTag/removeTag` | Mutates task tags. |\n| `api.tasks.addProject/removeProject` | Mutates project links. |\n| `api.tasks.addContext/removeContext` | Mutates contexts. |\n| `api.tasks.setReminders/addReminder/removeReminder` | Mutates reminders. |\n| `api.tasks.addDependency/removeDependency` | Mutates blocking dependencies stored in `blockedBy`. |\n\nExample:\n\n```javascript\nconst task = await api.tasks.create(\n\t{\n\t\ttitle: \"Review automation design\",\n\t\tstatus: \"open\",\n\t\tpriority: \"normal\",\n\t\tscheduled: \"2026-06-01\",\n\t\ttags: [\"tasknotes\"],\n\t},\n\t{\n\t\tsource: \"my-companion-plugin\",\n\t\tcorrelationId: crypto.randomUUID(),\n\t\treason: \"manual workflow command\",\n\t}\n);\n\nawait api.tasks.complete(task.path);\n```\n\n## Relationships\n\nRelationship methods resolve TaskNotes' project-as-parent links and `blockedBy` dependencies into task records where possible.\n\n| Method | Description |\n| -------------------------------------- | -------------------------------------------------------------------------- |\n| `api.relationships.parents(path)` | Returns parent tasks referenced from the task's projects. |\n| `api.relationships.subtasks(path)` | Returns tasks that reference this task as a project. |\n| `api.relationships.dependencies(path)` | Returns `blockedBy` dependencies with resolved task data when available. |\n| `api.relationships.blocking(path)` | Returns tasks that are blocked by this task. |\n| `api.relationships.all(path)` | Returns the task plus parents, subtasks, dependencies, and blocking tasks. |\n\nExample:\n\n```javascript\nconst relationships = await api.relationships.all(\"Tasks/example.md\");\n\nfor (const subtask of relationships.subtasks) {\n\tawait api.tasks.setPriority(subtask.path, relationships.task.priority);\n}\n```\n\n## Time Tracking\n\n| Method | Description |\n| -------------------------------------------------- | -------------------------------------------------------------------- |\n| `api.time.start(path, options?, context?)` | Starts time tracking and returns the updated task. |\n| `api.time.stop(path, context?)` | Stops the active time entry and returns the updated task. |\n| `api.time.active()` | Returns active time entries with task, path, entry, and entry index. |\n| `api.time.summary(options?)` | Returns aggregate time totals, top tasks, projects, and tags. |\n| `api.time.task(path)` | Returns one task's time summary and normalized time entries. |\n| `api.time.append(path, entry, context?)` | Appends a time entry. |\n| `api.time.deleteEntry(path, entryIndex, context?)` | Deletes a time entry through TaskNotes' service. |\n\n## Query, Stats, And System\n\nThe query, stats, and system namespaces expose HTTP/MCP-style support data without requiring companion plugins to reach into TaskNotes internals. Runtime queries use a stable DTO rather than TaskNotes' internal view state.\n\n```javascript\nconst result = await api.query.tasks({\n\twhere: {\n\t\tall: [\n\t\t\t{ field: \"task.status\", op: \"eq\", value: \"active\" },\n\t\t\t{ field: \"task.due\", op: \"lte\", value: { fn: \"today\" } },\n\t\t],\n\t},\n\tsort: [{ field: \"task.due\", direction: \"asc\" }],\n\tgroup: [{ field: \"task.status\" }],\n\tlimit: 25,\n\tscope: {\n\t\tincludeArchived: false,\n\t\tfolders: [\"Tasks\"],\n\t},\n});\n```\n\nRuntime query fields are canonical IDs such as `task.status`, `task.priority`, `task.due`, `task.projects`, `task.isBlocked`, `file.path`, and `user.`. `api.catalog.filterProperties()` returns the complete queryable field catalog, including aliases such as `status` and `user:`.\n\nCanonical operators are `eq`, `ne`, `contains`, `notContains`, `in`, `notIn`, `exists`, `missing`, `lt`, `lte`, `gt`, `gte`, `isTrue`, and `isFalse`. Legacy operator aliases such as `is`, `is-not`, `is-on-or-before`, and `is-not-empty` are accepted and normalized.\n\n`api.query.tasks()` returns explicit count semantics:\n\n- `total`: tasks in scope before filtering\n- `matched`: tasks matching `where` before `offset` and `limit`\n- `returned`: tasks returned after `offset` and `limit`\n- `tasks`: returned task records\n- `groups`: optional group details with task paths\n- `query`: the normalized canonical query\n- `warnings`: non-fatal normalization notes\n\n| Method | Description |\n| ---------------------------- | -------------------------------------------------------------------------------------------------- |\n| `api.query.tasks(query?)` | Validates, normalizes, and executes a runtime task query. |\n| `api.query.validate(query)` | Validates a query without executing it. |\n| `api.query.normalize(query)` | Returns the canonical normalized query, or throws a typed `invalid_input` API error. |\n| `api.query.explain(query)` | Returns validation, normalized query, count, grouping, and applied sort/limit details for dry run. |\n| `api.query.filterOptions()` | Returns available statuses, priorities, contexts, projects, tags, folders, and user properties. |\n| `api.stats.tasks(query?)` | Returns task counts, status/priority counts, archive/completion counts, and time-tracking totals. |\n| `api.system.health()` | Returns runtime status, API version, capabilities, vault identity, and task count. |\n\nTaskNotes compiles this DTO into its internal filter engine. Companion plugins should treat the runtime DTO and the catalog metadata as the public query contract.\n\n## Task Menu UI\n\nCompanion plugins can reuse the standard TaskNotes task context menu through `api.ui.taskMenu`. This keeps task actions, relationship actions, recurrence controls, and future menu changes behind the runtime API boundary instead of requiring companion plugins to import TaskNotes internals.\n\nThis surface is only available inside Obsidian. It is not exposed through the HTTP API.\n\n| Method | Description |\n| ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |\n| `api.ui.taskMenu.show({ taskPath, event, targetDate?, onUpdate?, promoteOccurrenceControls? })` | Shows the standard TaskNotes task context menu at a mouse event. |\n| `api.ui.taskMenu.showAtElement({ taskPath, element, targetDate?, onUpdate?, ... })` | Shows the standard TaskNotes task context menu anchored to an element. |\n| `api.ui.taskMenu.populate(menu, { taskPath, targetDate?, onUpdate?, ... })` | Adds the standard TaskNotes task context menu items to an existing Obsidian `Menu` so plugins can extend it. |\n\nAll methods resolve `taskPath` through the TaskNotes task cache and throw a typed `task_not_found` error when the path does not point to a cached task.\n\n`targetDate` defaults to today and is used by date-sensitive recurring-task menu items. `onUpdate` is called after menu actions mutate the task; when omitted, TaskNotes refreshes its own task views. `promoteOccurrenceControls` moves recurring-instance controls to the top of the menu.\n\nExample context menu:\n\n```javascript\nnodeEl.addEventListener(\"contextmenu\", async (event) => {\n\tevent.preventDefault();\n\n\tawait api.ui.taskMenu.show({\n\t\ttaskPath: task.path,\n\t\tevent,\n\t\tonUpdate: () => refreshGraph(),\n\t});\n});\n```\n\nExample composed menu:\n\n```javascript\nconst menu = new Menu();\n\nawait api.ui.taskMenu.populate(menu, {\n\ttaskPath: task.path,\n\tonUpdate: () => refreshGraph(),\n});\n\nmenu.addSeparator();\nmenu.addItem((item) =>\n\titem\n\t\t.setTitle(\"Focus in graph\")\n\t\t.setIcon(\"network\")\n\t\t.onClick(() => selectGraphNode(task.path))\n);\n\nmenu.showAtMouseEvent(event);\n```\n\n## Pomodoro\n\n| Method | Description |\n| ----------------------------------------------- | --------------------------------------------- |\n| `api.pomodoro.status()` | Returns current Pomodoro state. |\n| `api.pomodoro.start(options?, context?)` | Starts a Pomodoro session. |\n| `api.pomodoro.stop(context?)` | Stops and resets the active Pomodoro session. |\n| `api.pomodoro.pause(context?)` | Pauses the current session. |\n| `api.pomodoro.resume(context?)` | Resumes a paused session. |\n| `api.pomodoro.assignTask(pathOrNull, context?)` | Assigns or clears the current session task. |\n| `api.pomodoro.sessions(options?)` | Returns Pomodoro session history. |\n| `api.pomodoro.stats(date?)` | Returns Pomodoro stats for a date or today. |\n\n## Recurring Tasks\n\n| Method | Description |\n| ------------------------------------------------------------- | ---------------------------------------------------- |\n| `api.recurring.toggleCompleteInstance(path, date?, context?)` | Toggles completion for a recurring task instance. |\n| `api.recurring.toggleSkippedInstance(path, date?, context?)` | Toggles skipped state for a recurring task instance. |\n| `api.recurring.materializeOccurrence(path, date, context?)` | Creates or returns an occurrence note for a recurring task date. |\n\n## Natural Language Parser\n\n```javascript\nconst parsed = api.nlp.parse(\"Write draft friday 2pm #writing @desk\");\n```\n\n`api.parseNaturalLanguage(text)` remains as a compatibility alias. Parsing does not create or modify task files.\n\nSee [NLP API](nlp-api.md) for HTTP endpoint details and parser behavior.\n\n## Settings Snapshot\n\n```javascript\nconst settings = api.settings.snapshot();\nconsole.log(settings.defaultTaskStatus);\n```\n\nThe returned object is a snapshot. Mutating it does not change TaskNotes settings. `api.getSettingsSnapshot()` remains available as a compatibility alias.\n\n## Bases\n\n`api.bases.updateDefaultFiles()` regenerates the configured default TaskNotes `.base` files from the current TaskNotes settings and returns the created, updated, and skipped file paths.\n\n```javascript\nconst result = await api.bases.updateDefaultFiles();\nconsole.log(result.updated);\n```\n\n## Mutation Context\n\nMutating methods accept an optional context object:\n\n```javascript\n{\n source: \"tasknotes-workflows\",\n correlationId: \"run-2026-06-01T09-00-00\",\n reason: \"status changed to active\"\n}\n```\n\nTaskNotes attaches this context to normalized events emitted during the mutation. Use it to make workflow runs debuggable, connect multiple API calls to one run, and prevent companion plugins from responding to their own writes.\n\n## Events\n\nSubscribe with `api.events.on(eventName, handler)` and unsubscribe with `api.events.off(ref)`. In an Obsidian plugin, pass the returned `EventRef` to `this.registerEvent(ref)`.\n\nUse `api.events.list()` to discover the event catalogue for companion-plugin UIs:\n\n```javascript\nconst events = api.events.list();\n// [{ name: \"task.status.changed\", label: \"Task status changed\", category: \"task\", ... }]\n```\n\nTask events:\n\n- `task.created`\n- `task.updated`\n- `task.deleted`\n- `task.moved`\n- `task.status.changed`\n- `task.completed`\n- `task.uncompleted`\n- `task.archived`\n- `task.unarchived`\n- `task.scheduled.changed`\n- `task.due.changed`\n- `task.priority.changed`\n- `task.tags.changed`\n- `task.contexts.changed`\n- `task.projects.changed`\n- `task.reminders.changed`\n- `task.dependencies.changed`\n- `task.recurrence.changed`\n\nTime, Pomodoro, and recurring events:\n\n- `time.started`\n- `time.stopped`\n- `pomodoro.started`\n- `pomodoro.completed`\n- `pomodoro.interrupted`\n- `recurring.instance.completed`\n- `recurring.instance.skipped`\n\nSpecific events are emitted in addition to `task.updated`. For example, changing a task from `open` to `done` emits `task.updated`, `task.status.changed`, and `task.completed`.\n\nEvent payloads have this shape:\n\n```javascript\n{\n event: \"task.status.changed\",\n timestamp: \"2026-06-01T09:00:00.000Z\",\n taskPath: \"Tasks/Review automation design.md\",\n task: { /* current task */ },\n before: { /* task before change */ },\n after: { /* task after change */ },\n deletedTask: undefined,\n changes: {\n status: {\n before: \"open\",\n after: \"done\"\n }\n },\n data: undefined,\n context: {\n source: \"tasknotes-workflows\",\n correlationId: \"run-2026-06-01T09-00-00\",\n reason: \"status changed to done\"\n },\n source: \"tasknotes-workflows\",\n correlationId: \"run-2026-06-01T09-00-00\",\n reason: \"status changed to done\",\n rawEvent: \"task-updated\"\n}\n```\n\nEvents caused outside the runtime API may not include `context`, `source`, `correlationId`, or `reason`.\n\nExample automation-style listener:\n\n```javascript\nconst source = \"my-workflow-plugin\";\n\nthis.registerEvent(\n\tapi.events.on(\"task.status.changed\", async (event) => {\n\t\tif (event.source === source) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (event.after?.status !== \"active\") {\n\t\t\treturn;\n\t\t}\n\n\t\tawait api.time.start(event.after.path, undefined, {\n\t\t\tsource,\n\t\t\tcorrelationId: event.correlationId ?? crypto.randomUUID(),\n\t\t\treason: \"status changed to active\",\n\t\t});\n\t})\n);\n```\n\n## Lifecycle\n\nUse `api.lifecycle` to coordinate companion plugin startup, reload, and cache-sensitive UI state:\n\n```javascript\nawait api.lifecycle.ready();\n\nthis.registerEvent(\n\tapi.lifecycle.on(\"settings.changed\", () => {\n\t\trefreshCompanionCatalogs();\n\t})\n);\n```\n\nLifecycle events:\n\n- `ready`\n- `layout.ready`\n- `settings.changed`\n- `cache.changed`\n- `cache.rebuilt`\n- `extension.registered`\n- `extension.unregistered`\n- `unloading`\n\n`api.lifecycle.list()` returns labels, descriptions, and categories for these events.\n\n## Error Handling\n\nAPI methods throw `TaskNotesApiError` for invalid input or failed operations that the runtime API can classify. The error object includes:\n\n- `name`: always `TaskNotesApiError`\n- `code`: a stable machine-readable code\n- `message`: a human-readable message for logs\n- `status`: an HTTP-style status code for tools that mirror runtime calls over HTTP or MCP\n- `details`: optional structured context such as the task path, extension namespace, or invalid status\n\nCommon examples:\n\n- The task path is empty or invalid.\n- No task exists at the requested path.\n- A target move folder already contains a file with the same name.\n- `complete` is called with a status that is not configured as completed.\n\nCurrent error codes:\n\n- `invalid_input`\n- `invalid_task_path`\n- `invalid_status`\n- `task_not_found`\n- `task_file_not_found`\n- `file_already_exists`\n- `extension_invalid`\n- `extension_namespace_reserved`\n- `extension_namespace_conflict`\n- `extension_not_registered`\n- `operation_failed`\n\nUse `api.errors` when workflow engines or background listeners need consistent result objects instead of thrown exceptions:\n\n```javascript\nconst result = await api.errors.toResult(() =>\n\tapi.tasks.complete(\"Tasks/example.md\", { status: \"done\" })\n);\n\nif (!result.ok) {\n\tconsole.warn(result.error.code, result.error.details);\n\treturn;\n}\n\nconsole.log(result.value.path);\n```\n\n`api.errors.normalize(error)` converts unknown thrown values into a `TaskNotesApiError` payload. Unknown JavaScript errors use `operation_failed` with status `500`.\n","aliases":["/javascript-api/"],"toc":[{"level":2,"id":"version-and-capabilities","text":"Version and Capabilities"},{"level":2,"id":"namespaces","text":"Namespaces"},{"level":2,"id":"extension-registry","text":"Extension Registry"},{"level":2,"id":"companion-plugin-access","text":"Companion Plugin Access"},{"level":2,"id":"typescript","text":"TypeScript"},{"level":2,"id":"model","text":"Model"},{"level":2,"id":"catalog","text":"Catalog"},{"level":2,"id":"tasks","text":"Tasks"},{"level":2,"id":"relationships","text":"Relationships"},{"level":2,"id":"time-tracking","text":"Time Tracking"},{"level":2,"id":"query-stats-and-system","text":"Query, Stats, And System"},{"level":2,"id":"task-menu-ui","text":"Task Menu UI"},{"level":2,"id":"pomodoro","text":"Pomodoro"},{"level":2,"id":"recurring-tasks","text":"Recurring Tasks"},{"level":2,"id":"natural-language-parser","text":"Natural Language Parser"},{"level":2,"id":"settings-snapshot","text":"Settings Snapshot"},{"level":2,"id":"bases","text":"Bases"},{"level":2,"id":"mutation-context","text":"Mutation Context"},{"level":2,"id":"events","text":"Events"},{"level":2,"id":"lifecycle","text":"Lifecycle"},{"level":2,"id":"error-handling","text":"Error Handling"}],"html":"

TaskNotes exposes an in-process runtime API on the loaded Obsidian plugin instance:

\n
const tasknotes = app.plugins.plugins.tasknotes;\nconst api = tasknotes?.api;\n

This API is for Obsidian companion plugins and in-vault scripting tools such as Templater, QuickAdd, and MetaBind. It runs inside Obsidian and uses the same TaskNotes services, settings, cache, and vault permissions as the plugin UI.

\n

This is separate from the HTTP API. The runtime API does not start a server, does not use bearer-token authentication, and is only available inside the running Obsidian app.

\n

For user-facing extensions built on this API, see Companion Plugins. For a concrete automation companion plugin, see TaskNotes Workflows.

\n

The TypeScript contract lives in src/api/runtime-api.ts. It is intentionally small and type-focused so it can later become a standalone @tasknotes/runtime-api package for companion plugins.

\n

Version and Capabilities#

\n

Check the API version and capabilities before using methods that may not exist in older TaskNotes versions:

\n
const tasknotes = app.plugins.plugins.tasknotes;\nconst api = tasknotes?.api;\n\nif (!api || api.apiVersion !== 1 || !api.hasCapability("tasks.write")) {\n    throw new Error("This workflow requires TaskNotes runtime API v1 task writes");\n}\n

Current capabilities:

\n
    \n
  • model.read
  • \n
  • model.validate
  • \n
  • catalog.read
  • \n
  • extensions.read
  • \n
  • extensions.register
  • \n
  • tasks.read
  • \n
  • tasks.write
  • \n
  • tasks.delete
  • \n
  • tasks.move
  • \n
  • tasks.events
  • \n
  • relationships.read
  • \n
  • events.list
  • \n
  • time.read
  • \n
  • time.write
  • \n
  • time.summary
  • \n
  • pomodoro.read
  • \n
  • pomodoro.write
  • \n
  • pomodoro.events
  • \n
  • recurring.write
  • \n
  • recurring.materialize
  • \n
  • recurring.events
  • \n
  • settings.snapshot
  • \n
  • bases.write
  • \n
  • nlp.parse
  • \n
  • ui.task-menu
  • \n
  • query.tasks
  • \n
  • query.validate
  • \n
  • query.explain
  • \n
  • query.filter-options
  • \n
  • stats.tasks
  • \n
  • system.health
  • \n
  • lifecycle.events
  • \n
  • errors.typed
  • \n
\n

Namespaces#

\n

Prefer the namespaced API for new code:

\n
await api.tasks.update("Tasks/example.md", { status: "active" });\nconst subtasks = await api.relationships.subtasks("Tasks/example.md");\nawait api.time.start("Tasks/example.md", { description: "Deep work" });\nawait api.pomodoro.start({ taskPath: "Tasks/example.md", duration: 25 });\n

The older flat methods, such as api.getTask(path) and api.parseNaturalLanguage(text), remain available as compatibility aliases.

\n

Extension Registry#

\n

Companion plugins can publish their own runtime API namespace through api.extensions. This is the preferred way to extend TaskNotes without adding arbitrary properties to the core API object.

\n
const tasknotes = this.app.plugins.getPlugin("tasknotes");\nconst api = tasknotes?.api;\n\nif (!api?.hasCapability("extensions.register")) {\n    return;\n}\n\nconst handle = api.extensions.register({\n    id: this.manifest.id,\n    namespace: "tasknotes-workflows",\n    displayName: "TaskNotes Workflows",\n    version: this.manifest.version,\n    capabilities: ["tasknotes-workflows.run", "tasknotes-workflows.events"],\n    api: {\n        runWorkflow: async (workflowId, input) => {\n            // companion plugin implementation\n        },\n    },\n});\n\nthis.register(() => handle.unregister());\n

Other plugins can discover and consume extension namespaces:

\n
const workflows = api.extensions.get("tasknotes-workflows");\n\nif (api.hasCapability("tasknotes-workflows.run")) {\n    await workflows.runWorkflow("start-timer-on-active", { taskPath: "Tasks/example.md" });\n}\n

Extension namespaces are normalized to lowercase and may use letters, numbers, dots, underscores, or dashes. Capability names are also normalized to lowercase. Prefix extension capabilities with the extension namespace to avoid collisions.

\n

Companion Plugin Access#

\n

Companion plugins can read the TaskNotes plugin instance from Obsidian's plugin registry:

\n
const tasknotes = this.app.plugins.getPlugin("tasknotes");\nconst api = tasknotes?.api;\n\nif (!api?.hasCapability("tasks.events")) {\n    return;\n}\n\nthis.registerEvent(\n    api.events.on("task.status.changed", (event) => {\n        console.log(event.taskPath, event.changes.status);\n    })\n);\n

If TaskNotes is disabled or has not loaded yet, api will be unavailable. Companion plugins should handle that case and retry after plugin load if needed.

\n

TypeScript#

\n

Use the exported runtime contract for type safety:

\n
import type { TaskNotesRuntimeApiV1 } from "tasknotes/src/api/runtime-api";\n\ntype TaskNotesPluginInstance = {\n    api?: TaskNotesRuntimeApiV1;\n};\n\nconst tasknotes = app.plugins.getPlugin("tasknotes") as TaskNotesPluginInstance | null;\nconst api = tasknotes?.api;\n\nif (api?.apiVersion === 1 && api.hasCapability("tasks.write")) {\n    await api.tasks.setStatus("Tasks/example.md", "active");\n}\n

TaskNotes is still loaded by Obsidian at runtime. The TypeScript contract only gives companion plugins compile-time checking and autocomplete.

\n

Model#

\n

The runtime API exposes a small model namespace backed by @tasknotes/model:

\n
const info = api.model.info();\nconst config = api.model.config();\nconst validation = api.model.validateTask(task);\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
MethodDescription
api.model.info()Returns the model package name, TaskNotes spec version, and runtime API version.
api.model.config()Returns a resolved, Obsidian-free model configuration snapshot derived from TaskNotes settings.
api.model.validateTask(task)Validates a partial or complete task against the shared model schema and TaskNotes status rules.
api.model.validatePatch(patch)Validates a task patch before passing it to a runtime task mutation.
\n

Catalog#

\n

Use api.catalog to build companion-plugin editors without hardcoding TaskNotes values:

\n
const statuses = api.catalog.statuses();\nconst writableFields = api.catalog.writableFields();\nconst operators = api.catalog.filterOperators();\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
MethodDescription
api.catalog.statuses()Returns configured TaskNotes status definitions.
api.catalog.priorities()Returns configured TaskNotes priority definitions.
api.catalog.userFields()Returns configured user-defined field mappings.
api.catalog.fields()Returns core, computed, and user field metadata with value type, writability, and frontmatter key when available.
api.catalog.writableFields()Returns only fields that runtime task mutations may write.
api.catalog.filterProperties()Returns canonical query fields, aliases, value types, and supported operators.
api.catalog.filterOperators()Returns canonical query operators, labels, value requirements, and accepted aliases.
api.catalog.relationships()Returns relationship categories supported by api.relationships.
api.catalog.dependencyRelTypes()Returns dependency relationship types accepted by api.tasks.addDependency.
api.catalog.events()Returns the same runtime event catalogue as api.events.list().
\n

Tasks#

\n

All paths are vault-relative Markdown file paths.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
MethodDescription
api.tasks.get(path)Returns a task by path, or null when no task is cached at that path.
api.tasks.list(query?)Returns all tasks, or tasks matching a runtime task query. Prefer api.query.tasks() when count and grouping metadata matters.
api.tasks.create(taskData, context?)Creates a task using the normal TaskNotes creation service.
api.tasks.update(path, patch, context?)Updates one or more task fields using the normal TaskNotes update service.
api.tasks.delete(path, context?)Deletes the task file through TaskNotes' delete service.
api.tasks.complete(path, options?, context?)Marks a task complete.
api.tasks.uncomplete(path, options?, context?)Moves a completed task back to a non-completed status.
api.tasks.setStatus(path, status, context?)Sets task status.
api.tasks.setPriority(path, priority, context?)Sets task priority.
api.tasks.setDue(path, date, context?) / clearDue(path, context?)Sets or clears due date.
api.tasks.setScheduled(path, date, context?) / clearScheduled(path, context?)Sets or clears scheduled date.
api.tasks.archive(path, archived, context?)Archives or unarchives a task, including archive-folder movement when configured.
api.tasks.move(path, targetFolder, context?)Moves the task note and refuses to overwrite an existing file.
api.tasks.addTag/removeTagMutates task tags.
api.tasks.addProject/removeProjectMutates project links.
api.tasks.addContext/removeContextMutates contexts.
api.tasks.setReminders/addReminder/removeReminderMutates reminders.
api.tasks.addDependency/removeDependencyMutates blocking dependencies stored in blockedBy.
\n

Example:

\n
const task = await api.tasks.create(\n    {\n        title: "Review automation design",\n        status: "open",\n        priority: "normal",\n        scheduled: "2026-06-01",\n        tags: ["tasknotes"],\n    },\n    {\n        source: "my-companion-plugin",\n        correlationId: crypto.randomUUID(),\n        reason: "manual workflow command",\n    }\n);\n\nawait api.tasks.complete(task.path);\n

Relationships#

\n

Relationship methods resolve TaskNotes' project-as-parent links and blockedBy dependencies into task records where possible.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
MethodDescription
api.relationships.parents(path)Returns parent tasks referenced from the task's projects.
api.relationships.subtasks(path)Returns tasks that reference this task as a project.
api.relationships.dependencies(path)Returns blockedBy dependencies with resolved task data when available.
api.relationships.blocking(path)Returns tasks that are blocked by this task.
api.relationships.all(path)Returns the task plus parents, subtasks, dependencies, and blocking tasks.
\n

Example:

\n
const relationships = await api.relationships.all("Tasks/example.md");\n\nfor (const subtask of relationships.subtasks) {\n    await api.tasks.setPriority(subtask.path, relationships.task.priority);\n}\n

Time Tracking#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
MethodDescription
api.time.start(path, options?, context?)Starts time tracking and returns the updated task.
api.time.stop(path, context?)Stops the active time entry and returns the updated task.
api.time.active()Returns active time entries with task, path, entry, and entry index.
api.time.summary(options?)Returns aggregate time totals, top tasks, projects, and tags.
api.time.task(path)Returns one task's time summary and normalized time entries.
api.time.append(path, entry, context?)Appends a time entry.
api.time.deleteEntry(path, entryIndex, context?)Deletes a time entry through TaskNotes' service.
\n

Query, Stats, And System#

\n

The query, stats, and system namespaces expose HTTP/MCP-style support data without requiring companion plugins to reach into TaskNotes internals. Runtime queries use a stable DTO rather than TaskNotes' internal view state.

\n
const result = await api.query.tasks({\n    where: {\n        all: [\n            { field: "task.status", op: "eq", value: "active" },\n            { field: "task.due", op: "lte", value: { fn: "today" } },\n        ],\n    },\n    sort: [{ field: "task.due", direction: "asc" }],\n    group: [{ field: "task.status" }],\n    limit: 25,\n    scope: {\n        includeArchived: false,\n        folders: ["Tasks"],\n    },\n});\n

Runtime query fields are canonical IDs such as task.status, task.priority, task.due, task.projects, task.isBlocked, file.path, and user.<id-or-key>. api.catalog.filterProperties() returns the complete queryable field catalog, including aliases such as status and user:<id>.

\n

Canonical operators are eq, ne, contains, notContains, in, notIn, exists, missing, lt, lte, gt, gte, isTrue, and isFalse. Legacy operator aliases such as is, is-not, is-on-or-before, and is-not-empty are accepted and normalized.

\n

api.query.tasks() returns explicit count semantics:

\n
    \n
  • total: tasks in scope before filtering
  • \n
  • matched: tasks matching where before offset and limit
  • \n
  • returned: tasks returned after offset and limit
  • \n
  • tasks: returned task records
  • \n
  • groups: optional group details with task paths
  • \n
  • query: the normalized canonical query
  • \n
  • warnings: non-fatal normalization notes
  • \n
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
MethodDescription
api.query.tasks(query?)Validates, normalizes, and executes a runtime task query.
api.query.validate(query)Validates a query without executing it.
api.query.normalize(query)Returns the canonical normalized query, or throws a typed invalid_input API error.
api.query.explain(query)Returns validation, normalized query, count, grouping, and applied sort/limit details for dry run.
api.query.filterOptions()Returns available statuses, priorities, contexts, projects, tags, folders, and user properties.
api.stats.tasks(query?)Returns task counts, status/priority counts, archive/completion counts, and time-tracking totals.
api.system.health()Returns runtime status, API version, capabilities, vault identity, and task count.
\n

TaskNotes compiles this DTO into its internal filter engine. Companion plugins should treat the runtime DTO and the catalog metadata as the public query contract.

\n

Task Menu UI#

\n

Companion plugins can reuse the standard TaskNotes task context menu through api.ui.taskMenu. This keeps task actions, relationship actions, recurrence controls, and future menu changes behind the runtime API boundary instead of requiring companion plugins to import TaskNotes internals.

\n

This surface is only available inside Obsidian. It is not exposed through the HTTP API.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
MethodDescription
api.ui.taskMenu.show({ taskPath, event, targetDate?, onUpdate?, promoteOccurrenceControls? })Shows the standard TaskNotes task context menu at a mouse event.
api.ui.taskMenu.showAtElement({ taskPath, element, targetDate?, onUpdate?, ... })Shows the standard TaskNotes task context menu anchored to an element.
api.ui.taskMenu.populate(menu, { taskPath, targetDate?, onUpdate?, ... })Adds the standard TaskNotes task context menu items to an existing Obsidian Menu so plugins can extend it.
\n

All methods resolve taskPath through the TaskNotes task cache and throw a typed task_not_found error when the path does not point to a cached task.

\n

targetDate defaults to today and is used by date-sensitive recurring-task menu items. onUpdate is called after menu actions mutate the task; when omitted, TaskNotes refreshes its own task views. promoteOccurrenceControls moves recurring-instance controls to the top of the menu.

\n

Example context menu:

\n
nodeEl.addEventListener("contextmenu", async (event) => {\n    event.preventDefault();\n\n    await api.ui.taskMenu.show({\n        taskPath: task.path,\n        event,\n        onUpdate: () => refreshGraph(),\n    });\n});\n

Example composed menu:

\n
const menu = new Menu();\n\nawait api.ui.taskMenu.populate(menu, {\n    taskPath: task.path,\n    onUpdate: () => refreshGraph(),\n});\n\nmenu.addSeparator();\nmenu.addItem((item) =>\n    item\n        .setTitle("Focus in graph")\n        .setIcon("network")\n        .onClick(() => selectGraphNode(task.path))\n);\n\nmenu.showAtMouseEvent(event);\n

Pomodoro#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
MethodDescription
api.pomodoro.status()Returns current Pomodoro state.
api.pomodoro.start(options?, context?)Starts a Pomodoro session.
api.pomodoro.stop(context?)Stops and resets the active Pomodoro session.
api.pomodoro.pause(context?)Pauses the current session.
api.pomodoro.resume(context?)Resumes a paused session.
api.pomodoro.assignTask(pathOrNull, context?)Assigns or clears the current session task.
api.pomodoro.sessions(options?)Returns Pomodoro session history.
api.pomodoro.stats(date?)Returns Pomodoro stats for a date or today.
\n

Recurring Tasks#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
MethodDescription
api.recurring.toggleCompleteInstance(path, date?, context?)Toggles completion for a recurring task instance.
api.recurring.toggleSkippedInstance(path, date?, context?)Toggles skipped state for a recurring task instance.
api.recurring.materializeOccurrence(path, date, context?)Creates or returns an occurrence note for a recurring task date.
\n

Natural Language Parser#

\n
const parsed = api.nlp.parse("Write draft friday 2pm #writing @desk");\n

api.parseNaturalLanguage(text) remains as a compatibility alias. Parsing does not create or modify task files.

\n

See NLP API for HTTP endpoint details and parser behavior.

\n

Settings Snapshot#

\n
const settings = api.settings.snapshot();\nconsole.log(settings.defaultTaskStatus);\n

The returned object is a snapshot. Mutating it does not change TaskNotes settings. api.getSettingsSnapshot() remains available as a compatibility alias.

\n

Bases#

\n

api.bases.updateDefaultFiles() regenerates the configured default TaskNotes .base files from the current TaskNotes settings and returns the created, updated, and skipped file paths.

\n
const result = await api.bases.updateDefaultFiles();\nconsole.log(result.updated);\n

Mutation Context#

\n

Mutating methods accept an optional context object:

\n
{\n  source: "tasknotes-workflows",\n  correlationId: "run-2026-06-01T09-00-00",\n  reason: "status changed to active"\n}\n

TaskNotes attaches this context to normalized events emitted during the mutation. Use it to make workflow runs debuggable, connect multiple API calls to one run, and prevent companion plugins from responding to their own writes.

\n

Events#

\n

Subscribe with api.events.on(eventName, handler) and unsubscribe with api.events.off(ref). In an Obsidian plugin, pass the returned EventRef to this.registerEvent(ref).

\n

Use api.events.list() to discover the event catalogue for companion-plugin UIs:

\n
const events = api.events.list();\n// [{ name: "task.status.changed", label: "Task status changed", category: "task", ... }]\n

Task events:

\n
    \n
  • task.created
  • \n
  • task.updated
  • \n
  • task.deleted
  • \n
  • task.moved
  • \n
  • task.status.changed
  • \n
  • task.completed
  • \n
  • task.uncompleted
  • \n
  • task.archived
  • \n
  • task.unarchived
  • \n
  • task.scheduled.changed
  • \n
  • task.due.changed
  • \n
  • task.priority.changed
  • \n
  • task.tags.changed
  • \n
  • task.contexts.changed
  • \n
  • task.projects.changed
  • \n
  • task.reminders.changed
  • \n
  • task.dependencies.changed
  • \n
  • task.recurrence.changed
  • \n
\n

Time, Pomodoro, and recurring events:

\n
    \n
  • time.started
  • \n
  • time.stopped
  • \n
  • pomodoro.started
  • \n
  • pomodoro.completed
  • \n
  • pomodoro.interrupted
  • \n
  • recurring.instance.completed
  • \n
  • recurring.instance.skipped
  • \n
\n

Specific events are emitted in addition to task.updated. For example, changing a task from open to done emits task.updated, task.status.changed, and task.completed.

\n

Event payloads have this shape:

\n
{\n  event: "task.status.changed",\n  timestamp: "2026-06-01T09:00:00.000Z",\n  taskPath: "Tasks/Review automation design.md",\n  task: { /* current task */ },\n  before: { /* task before change */ },\n  after: { /* task after change */ },\n  deletedTask: undefined,\n  changes: {\n    status: {\n      before: "open",\n      after: "done"\n    }\n  },\n  data: undefined,\n  context: {\n    source: "tasknotes-workflows",\n    correlationId: "run-2026-06-01T09-00-00",\n    reason: "status changed to done"\n  },\n  source: "tasknotes-workflows",\n  correlationId: "run-2026-06-01T09-00-00",\n  reason: "status changed to done",\n  rawEvent: "task-updated"\n}\n

Events caused outside the runtime API may not include context, source, correlationId, or reason.

\n

Example automation-style listener:

\n
const source = "my-workflow-plugin";\n\nthis.registerEvent(\n    api.events.on("task.status.changed", async (event) => {\n        if (event.source === source) {\n            return;\n        }\n\n        if (event.after?.status !== "active") {\n            return;\n        }\n\n        await api.time.start(event.after.path, undefined, {\n            source,\n            correlationId: event.correlationId ?? crypto.randomUUID(),\n            reason: "status changed to active",\n        });\n    })\n);\n

Lifecycle#

\n

Use api.lifecycle to coordinate companion plugin startup, reload, and cache-sensitive UI state:

\n
await api.lifecycle.ready();\n\nthis.registerEvent(\n    api.lifecycle.on("settings.changed", () => {\n        refreshCompanionCatalogs();\n    })\n);\n

Lifecycle events:

\n
    \n
  • ready
  • \n
  • layout.ready
  • \n
  • settings.changed
  • \n
  • cache.changed
  • \n
  • cache.rebuilt
  • \n
  • extension.registered
  • \n
  • extension.unregistered
  • \n
  • unloading
  • \n
\n

api.lifecycle.list() returns labels, descriptions, and categories for these events.

\n

Error Handling#

\n

API methods throw TaskNotesApiError for invalid input or failed operations that the runtime API can classify. The error object includes:

\n
    \n
  • name: always TaskNotesApiError
  • \n
  • code: a stable machine-readable code
  • \n
  • message: a human-readable message for logs
  • \n
  • status: an HTTP-style status code for tools that mirror runtime calls over HTTP or MCP
  • \n
  • details: optional structured context such as the task path, extension namespace, or invalid status
  • \n
\n

Common examples:

\n
    \n
  • The task path is empty or invalid.
  • \n
  • No task exists at the requested path.
  • \n
  • A target move folder already contains a file with the same name.
  • \n
  • complete is called with a status that is not configured as completed.
  • \n
\n

Current error codes:

\n
    \n
  • invalid_input
  • \n
  • invalid_task_path
  • \n
  • invalid_status
  • \n
  • task_not_found
  • \n
  • task_file_not_found
  • \n
  • file_already_exists
  • \n
  • extension_invalid
  • \n
  • extension_namespace_reserved
  • \n
  • extension_namespace_conflict
  • \n
  • extension_not_registered
  • \n
  • operation_failed
  • \n
\n

Use api.errors when workflow engines or background listeners need consistent result objects instead of thrown exceptions:

\n
const result = await api.errors.toResult(() =>\n    api.tasks.complete("Tasks/example.md", { status: "done" })\n);\n\nif (!result.ok) {\n    console.warn(result.error.code, result.error.details);\n    return;\n}\n\nconsole.log(result.value.path);\n

api.errors.normalize(error) converts unknown thrown values into a TaskNotesApiError payload. Unknown JavaScript errors use operation_failed with status 500.

\n","text":"TaskNotes exposes an in-process runtime API on the loaded Obsidian plugin instance: const tasknotes = app.plugins.plugins.tasknotes; const api = tasknotes?.api; This API is for Obsidian companion plugins and in-vault scripting tools such as Templater, QuickAdd, and MetaBind. It runs inside Obsidian and uses the same TaskNotes services, settings, cache, and vault permissions as the plugin UI. This is separate from the HTTP API. The runtime API does not start a server, does not use bearer-token authentication, and is only available inside the running Obsidian app. For user-facing extensions built on this API, see Companion Plugins. For a concrete automation companion plugin, see TaskNotes Workflows. The TypeScript contract lives in src/api/runtime-api.ts. It is intentionally small and type-focused so it can later become a standalone @tasknotes/runtime-api package for companion plugins. Version and Capabilities# Check the API version and capabilities before using methods that may not exist in older TaskNotes versions: const tasknotes = app.plugins.plugins.tasknotes; const api = tasknotes?.api; if (!api || api.apiVersion !== 1 || !api.hasCapability(\"tasks.write\")) { throw new Error(\"This workflow requires TaskNotes runtime API v1 task writes\"); } Current capabilities: model.read model.validate catalog.read extensions.read extensions.register tasks.read tasks.write tasks.delete tasks.move tasks.events relationships.read events.list time.read time.write time.summary pomodoro.read pomodoro.write pomodoro.events recurring.write recurring.materialize recurring.events settings.snapshot bases.write nlp.parse ui.task-menu query.tasks query.validate query.explain query.filter-options stats.tasks system.health lifecycle.events errors.typed Namespaces# Prefer the namespaced API for new code: await api.tasks.update(\"Tasks/example.md\", { status: \"active\" }); const subtasks = await api.relationships.subtasks(\"Tasks/example.md\"); await api.time.start(\"Tasks/example.md\", { description: \"Deep work\" }); await api.pomodoro.start({ taskPath: \"Tasks/example.md\", duration: 25 }); The older flat methods, such as api.getTask(path) and api.parseNaturalLanguage(text), remain available as compatibility aliases. Extension Registry# Companion plugins can publish their own runtime API namespace through api.extensions. This is the preferred way to extend TaskNotes without adding arbitrary properties to the core API object. const tasknotes = this.app.plugins.getPlugin(\"tasknotes\"); const api = tasknotes?.api; if (!api?.hasCapability(\"extensions.register\")) { return; } const handle = api.extensions.register({ id: this.manifest.id, namespace: \"tasknotes-workflows\", displayName: \"TaskNotes Workflows\", version: this.manifest.version, capabilities: [\"tasknotes-workflows.run\", \"tasknotes-workflows.events\"], api: { runWorkflow: async (workflowId, input) => { // companion plugin implementation }, }, }); this.register(() => handle.unregister()); Other plugins can discover and consume extension namespaces: const workflows = api.extensions.get(\"tasknotes-workflows\"); if (api.hasCapability(\"tasknotes-workflows.run\")) { await workflows.runWorkflow(\"start-timer-on-active\", { taskPath: \"Tasks/example.md\" }); } Extension namespaces are normalized to lowercase and may use letters, numbers, dots, underscores, or dashes. Capability names are also normalized to lowercase. Prefix extension capabilities with the extension namespace to avoid collisions. Companion Plugin Access# Companion plugins can read the TaskNotes plugin instance from Obsidian's plugin registry: const tasknotes = this.app.plugins.getPlugin(\"tasknotes\"); const api = tasknotes?.api; if (!api?.hasCapability(\"tasks.events\")) { return; } this.registerEvent( api.events.on(\"task.status.changed\", (event) => { console.log(event.taskPath, event.changes.status); }) ); If TaskNotes is disabled or has not loaded yet, api will be unavailable. Companion plugins should handle that case and retry after plugin load if needed. TypeScript# Use the exported runtime contract for type safety: import type { TaskNotesRuntimeApiV1 } from \"tasknotes/src/api/runtime-api\"; type TaskNotesPluginInstance = { api?: TaskNotesRuntimeApiV1; }; const tasknotes = app.plugins.getPlugin(\"tasknotes\") as TaskNotesPluginInstance | null; const api = tasknotes?.api; if (api?.apiVersion === 1 && api.hasCapability(\"tasks.write\")) { await api.tasks.setStatus(\"Tasks/example.md\", \"active\"); } TaskNotes is still loaded by Obsidian at runtime. The TypeScript contract only gives companion plugins compile-time checking and autocomplete. Model# The runtime API exposes a small model namespace backed by @tasknotes/model: const info = api.model.info(); const config = api.model.config(); const validation = api.model.validateTask(task); Method Description api.model.info() Returns the model package name, TaskNotes spec version, and runtime API version. api.model.config() Returns a resolved, Obsidian-free model configuration snapshot derived from TaskNotes settings. api.model.validateTask(task) Validates a partial or complete task against the shared model schema and TaskNotes status rules. api.model.validatePatch(patch) Validates a task patch before passing it to a runtime task mutation. Catalog# Use api.catalog to build companion-plugin editors without hardcoding TaskNotes values: const statuses = api.catalog.statuses(); const writableFields = api.catalog.writableFields(); const operators = api.catalog.filterOperators(); Method Description api.catalog.statuses() Returns configured TaskNotes status definitions. api.catalog.priorities() Returns configured TaskNotes priority definitions. api.catalog.userFields() Returns configured user-defined field mappings. api.catalog.fields() Returns core, computed, and user field metadata with value type, writability, and frontmatter key when available. api.catalog.writableFields() Returns only fields that runtime task mutations may write. api.catalog.filterProperties() Returns canonical query fields, aliases, value types, and supported operators. api.catalog.filterOperators() Returns canonical query operators, labels, value requirements, and accepted aliases. api.catalog.relationships() Returns relationship categories supported by api.relationships. api.catalog.dependencyRelTypes() Returns dependency relationship types accepted by api.tasks.addDependency. api.catalog.events() Returns the same runtime event catalogue as api.events.list(). Tasks# All paths are vault-relative Markdown file paths. Method Description api.tasks.get(path) Returns a task by path, or null when no task is cached at that path. api.tasks.list(query?) Returns all tasks, or tasks matching a runtime task query. Prefer api.query.tasks() when count and grouping metadata matters. api.tasks.create(taskData, context?) Creates a task using the normal TaskNotes creation service. api.tasks.update(path, patch, context?) Updates one or more task fields using the normal TaskNotes update service. api.tasks.delete(path, context?) Deletes the task file through TaskNotes' delete service. api.tasks.complete(path, options?, context?) Marks a task complete. api.tasks.uncomplete(path, options?, context?) Moves a completed task back to a non-completed status. api.tasks.setStatus(path, status, context?) Sets task status. api.tasks.setPriority(path, priority, context?) Sets task priority. api.tasks.setDue(path, date, context?) / clearDue(path, context?) Sets or clears due date. api.tasks.setScheduled(path, date, context?) / clearScheduled(path, context?) Sets or clears scheduled date. api.tasks.archive(path, archived, context?) Archives or unarchives a task, including archive-folder movement when configured. api.tasks.move(path, targetFolder, context?) Moves the task note and refuses to overwrite an existing file. api.tasks.addTag/removeTag Mutates task tags. api.tasks.addProject/removeProject Mutates project links. api.tasks.addContext/removeContext Mutates contexts. api.tasks.setReminders/addReminder/removeReminder Mutates reminders. api.tasks.addDependency/removeDependency Mutates blocking dependencies stored in blockedBy. Example: const task = await api.tasks.create( { title: \"Review automation design\", status: \"open\", priority: \"normal\", scheduled: \"2026-06-01\", tags: [\"tasknotes\"], }, { source: \"my-companion-plugin\", correlationId: crypto.randomUUID(), reason: \"manual workflow command\", } ); await api.tasks.complete(task.path); Relationships# Relationship methods resolve TaskNotes' project-as-parent links and blockedBy dependencies into task records where possible. Method Description api.relationships.parents(path) Returns parent tasks referenced from the task's projects. api.relationships.subtasks(path) Returns tasks that reference this task as a project. api.relationships.dependencies(path) Returns blockedBy dependencies with resolved task data when available. api.relationships.blocking(path) Returns tasks that are blocked by this task. api.relationships.all(path) Returns the task plus parents, subtasks, dependencies, and blocking tasks. Example: const relationships = await api.relationships.all(\"Tasks/example.md\"); for (const subtask of relationships.subtasks) { await api.tasks.setPriority(subtask.path, relationships.task.priority); } Time Tracking# Method Description api.time.start(path, options?, context?) Starts time tracking and returns the updated task. api.time.stop(path, context?) Stops the active time entry and returns the updated task. api.time.active() Returns active time entries with task, path, entry, and entry index. api.time.summary(options?) Returns aggregate time totals, top tasks, projects, and tags. api.time.task(path) Returns one task's time summary and normalized time entries. api.time.append(path, entry, context?) Appends a time entry. api.time.deleteEntry(path, entryIndex, context?) Deletes a time entry through TaskNotes' service. Query, Stats, And System# The query, stats, and system namespaces expose HTTP/MCP-style support data without requiring companion plugins to reach into TaskNotes internals. Runtime queries use a stable DTO rather than TaskNotes' internal view state. const result = await api.query.tasks({ where: { all: [ { field: \"task.status\", op: \"eq\", value: \"active\" }, { field: \"task.due\", op: \"lte\", value: { fn: \"today\" } }, ], }, sort: [{ field: \"task.due\", direction: \"asc\" }], group: [{ field: \"task.status\" }], limit: 25, scope: { includeArchived: false, folders: [\"Tasks\"], }, }); Runtime query fields are canonical IDs such as task.status, task.priority, task.due, task.projects, task.isBlocked, file.path, and user.. api.catalog.filterProperties() returns the complete queryable field catalog, including aliases such as status and user:. Canonical operators are eq, ne, contains, notContains, in, notIn, exists, missing, lt, lte, gt, gte, isTrue, and isFalse. Legacy operator aliases such as is, is-not, is-on-or-before, and is-not-empty are accepted and normalized. api.query.tasks() returns explicit count semantics: total: tasks in scope before filtering matched: tasks matching where before offset and limit returned: tasks returned after offset and limit tasks: returned task records groups: optional group details with task paths query: the normalized canonical query warnings: non-fatal normalization notes Method Description api.query.tasks(query?) Validates, normalizes, and executes a runtime task query. api.query.validate(query) Validates a query without executing it. api.query.normalize(query) Returns the canonical normalized query, or throws a typed invalid_input API error. api.query.explain(query) Returns validation, normalized query, count, grouping, and applied sort/limit details for dry run. api.query.filterOptions() Returns available statuses, priorities, contexts, projects, tags, folders, and user properties. api.stats.tasks(query?) Returns task counts, status/priority counts, archive/completion counts, and time-tracking totals. api.system.health() Returns runtime status, API version, capabilities, vault identity, and task count. TaskNotes compiles this DTO into its internal filter engine. Companion plugins should treat the runtime DTO and the catalog metadata as the public query contract. Task Menu UI# Companion plugins can reuse the standard TaskNotes task context menu through api.ui.taskMenu. This keeps task actions, relationship actions, recurrence controls, and future menu changes behind the runtime API boundary instead of requiring companion plugins to import TaskNotes internals. This surface is only available inside Obsidian. It is not exposed through the HTTP API. Method Description api.ui.taskMenu.show({ taskPath, event, targetDate?, onUpdate?, promoteOccurrenceControls? }) Shows the standard TaskNotes task context menu at a mouse event. api.ui.taskMenu.showAtElement({ taskPath, element, targetDate?, onUpdate?, ... }) Shows the standard TaskNotes task context menu anchored to an element. api.ui.taskMenu.populate(menu, { taskPath, targetDate?, onUpdate?, ... }) Adds the standard TaskNotes task context menu items to an existing Obsidian Menu so plugins can extend it. All methods resolve taskPath through the TaskNotes task cache and throw a typed task_not_found error when the path does not point to a cached task. targetDate defaults to today and is used by date-sensitive recurring-task menu items. onUpdate is called after menu actions mutate the task; when omitted, TaskNotes refreshes its own task views. promoteOccurrenceControls moves recurring-instance controls to the top of the menu. Example context menu: nodeEl.addEventListener(\"contextmenu\", async (event) => { event.preventDefault(); await api.ui.taskMenu.show({ taskPath: task.path, event, onUpdate: () => refreshGraph(), }); }); Example composed menu: const menu = new Menu(); await api.ui.taskMenu.populate(menu, { taskPath: task.path, onUpdate: () => refreshGraph(), }); menu.addSeparator(); menu.addItem((item) => item .setTitle(\"Focus in graph\") .setIcon(\"network\") .onClick(() => selectGraphNode(task.path)) ); menu.showAtMouseEvent(event); Pomodoro# Method Description api.pomodoro.status() Returns current Pomodoro state. api.pomodoro.start(options?, context?) Starts a Pomodoro session. api.pomodoro.stop(context?) Stops and resets the active Pomodoro session. api.pomodoro.pause(context?) Pauses the current session. api.pomodoro.resume(context?) Resumes a paused session. api.pomodoro.assignTask(pathOrNull, context?) Assigns or clears the current session task. api.pomodoro.sessions(options?) Returns Pomodoro session history. api.pomodoro.stats(date?) Returns Pomodoro stats for a date or today. Recurring Tasks# Method Description api.recurring.toggleCompleteInstance(path, date?, context?) Toggles completion for a recurring task instance. api.recurring.toggleSkippedInstance(path, date?, context?) Toggles skipped state for a recurring task instance. api.recurring.materializeOccurrence(path, date, context?) Creates or returns an occurrence note for a recurring task date. Natural Language Parser# const parsed = api.nlp.parse(\"Write draft friday 2pm #writing @desk\"); api.parseNaturalLanguage(text) remains as a compatibility alias. Parsing does not create or modify task files. See NLP API for HTTP endpoint details and parser behavior. Settings Snapshot# const settings = api.settings.snapshot(); console.log(settings.defaultTaskStatus); The returned object is a snapshot. Mutating it does not change TaskNotes settings. api.getSettingsSnapshot() remains available as a compatibility alias. Bases# api.bases.updateDefaultFiles() regenerates the configured default TaskNotes .base files from the current TaskNotes settings and returns the created, updated, and skipped file paths. const result = await api.bases.updateDefaultFiles(); console.log(result.updated); Mutation Context# Mutating methods accept an optional context object: { source: \"tasknotes-workflows\", correlationId: \"run-2026-06-01T09-00-00\", reason: \"status chang"},{"route":"/obsidian/mdbase-tasknotes-cli/","title":"mdbase-tasknotes CLI","description":"mdbase-tasknotes (mtn) is a standalone command-line tool for managing TaskNotes tasks directly on markdown files. It uses mdbase to read and write task files and tasknotes-nlp-c...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/mdbase-tasknotes-cli.md","namespace":"obsidian","relativePath":"mdbase-tasknotes-cli.md","raw":"# mdbase-tasknotes CLI\n\n[mdbase-tasknotes](https://github.com/callumalpass/mdbase-tasknotes) (`mtn`) is a standalone command-line tool for managing TaskNotes tasks directly on markdown files. It uses [mdbase](https://mdbase.dev) to read and write task files and [tasknotes-nlp-core](https://github.com/callumalpass/tasknotes-nlp-core) for natural language parsing.\n\n\n## When to use this vs TaskNotes Obsidian CLI\n\nIf you are looking for the built-in `obsidian tasknotes:*` commands exposed by the plugin itself, see [TaskNotes Obsidian CLI](obsidian-cli.md).\n\nTaskNotes ships with [tasknotes-cli](https://github.com/callumalpass/tasknotes-cli) (`tn`), which communicates with the Obsidian plugin over its HTTP API. `mdbase-tasknotes` operates directly on the markdown files instead.\n\n| | `tn` (tasknotes-cli) | `mtn` (mdbase-tasknotes) |\n|---|---|---|\n| **Requires Obsidian** | Yes — plugin must be running with API enabled | No |\n| **Operates on** | HTTP API | Markdown files directly via mdbase |\n| **Use when** | Obsidian is open and you want live sync | Obsidian is closed, on a server, or in scripts |\n| **Time tracking** | Via plugin API | Via frontmatter `timeEntries` |\n| **Task creation** | NLP via API | NLP via bundled `tasknotes-nlp-core` |\n| **Install** | `npm install -g tasknotes-cli` | `npm install -g mdbase-tasknotes` |\n\nUse `mtn` when:\n\n- Obsidian isn't running or isn't available (headless servers, SSH sessions, CI pipelines)\n- You want to manage tasks from the terminal without any background process\n- You're scripting task creation or querying in shell workflows\n- You're on a machine where Obsidian isn't installed\n\nBoth tools read and write the same task files, so they can be used interchangeably on the same vault.\n\n## Install\n\n```\nnpm install -g mdbase-tasknotes\n```\n\n## Setup\n\n### Using an existing TaskNotes vault\n\nIf you already use TaskNotes with mdbase spec generation enabled (Settings → Integrations → Enable mdbase spec), point `mtn` at your vault root:\n\n```bash\nmtn config --set collectionPath=/path/to/your/vault\n```\n\nThe plugin generates `mdbase.yaml` and `_types/task.md` automatically — `mtn` reads these to understand your task schema, including your custom statuses and priorities.\n\n### Creating a standalone collection\n\nTo create a new collection without Obsidian:\n\n```bash\nmtn init ~/tasks\nmtn config --set collectionPath=~/tasks\n```\n\nThis generates `mdbase.yaml`, `_types/task.md`, and a `tasks/` folder with sensible defaults (statuses: open, in-progress, done, cancelled; priorities: low, normal, high, urgent).\n\n## Creating tasks\n\nCreate tasks using natural language. Tags, contexts, projects, dates, priorities, and recurrence are extracted automatically:\n\n```bash\nmtn create \"Buy groceries tomorrow #shopping @errands\"\nmtn create \"Write quarterly report due friday #work +quarterly-review\"\nmtn create \"Call dentist high priority @phone\"\nmtn create \"Water plants every monday #home\"\n```\n\n### Supported patterns\n\n| Pattern | Example | Extracted as |\n|---|---|---|\n| `#tag` | `#shopping` | Tag |\n| `@context` | `@errands` | Context |\n| `+project` | `+quarterly-review` | Project (stored as wikilink) |\n| Date words | `tomorrow`, `friday`, `next week` | Due date |\n| Priority words | `high priority`, `urgent` | Priority |\n| Recurrence | `every day`, `weekly`, `every monday` | Recurrence rule |\n| Estimate | `~30m`, `~2h` | Time estimate |\n\nThe NLP parser reads your collection's status and priority enum values from `_types/task.md`, so any custom values you define there are automatically recognized.\n\n## Querying tasks\n\n### List tasks\n\n```bash\n# Default: open tasks ordered by due date\nmtn list\n\n# Filter by status, priority, or tag\nmtn list --status in-progress\nmtn list --priority high\nmtn list --tag work\n\n# Show overdue tasks\nmtn list --overdue\n\n# Raw mdbase where expression\nmtn list --where 'due < \"2026-03-01\" && priority == \"urgent\"'\n\n# JSON output for scripting\nmtn list --json\n```\n\n### Show task detail\n\n```bash\nmtn show \"Buy groceries\"\nmtn show tasks/Buy\\ groceries.md\n```\n\nTasks can be referenced by title or file path. Title matching tries exact match first, then substring.\n\n### Search\n\nFull-text search across titles, body content, tags, contexts, and projects:\n\n```bash\nmtn search quarterly\n```\n\n## Updating tasks\n\n### Complete a task\n\n```bash\nmtn complete \"Buy groceries\"\n```\n\nSets status to `done` and records the completion date.\n\n### Update fields\n\n```bash\nmtn update \"Write report\" --status in-progress\nmtn update \"Write report\" --priority urgent --due 2026-03-01\nmtn update \"Write report\" --add-tag important --remove-tag draft\nmtn update \"Write report\" --add-context office\n```\n\n### Archive and delete\n\n```bash\nmtn archive \"Write report\" # Adds \"archive\" tag\nmtn delete \"Old task\" # Checks for backlinks first\nmtn delete \"Old task\" --force # Skip backlink check\n```\n\n## Time tracking\n\nTrack time spent on tasks via the `timeEntries` frontmatter field — the same format TaskNotes uses.\n\n```bash\n# Start a timer\nmtn timer start \"Write report\"\nmtn timer start \"Write report\" -d \"Drafting introduction\"\n\n# Check active timers\nmtn timer status\n\n# Stop the running timer\nmtn timer stop\n\n# View time log\nmtn timer log\nmtn timer log --period today\nmtn timer log --period week\nmtn timer log --from 2026-02-01 --to 2026-02-28\n```\n\n## Projects and statistics\n\n### Projects\n\n```bash\n# List all projects\nmtn projects list\nmtn projects list --stats # With completion percentages\n\n# Show tasks for a project\nmtn projects show quarterly-review\n```\n\n### Statistics\n\n```bash\nmtn stats\n```\n\nShows total tasks, completion rate, overdue count, breakdown by status and priority, and total time tracked.\n\n## Interactive mode\n\nLaunch a REPL with live NLP preview that updates as you type:\n\n```bash\nmtn interactive\n# or\nmtn i\n```\n\nType a task description and the preview line shows how it will be parsed (title, tags, dates, priority). Press Enter to create the task.\n\n## Configuration\n\nConfiguration is stored at `~/.config/mdbase-tasknotes/config.json`.\n\n```bash\nmtn config --list # Show all settings\nmtn config --set collectionPath=/path/to/vault # Set collection path\nmtn config --get collectionPath # Get a setting\n```\n\n### Collection path resolution\n\nThe collection path is resolved in order:\n\n1. `--path` / `-p` flag on any command\n2. `MDBASE_TASKNOTES_PATH` environment variable\n3. `collectionPath` in config file\n4. Current working directory\n\n## Command reference\n\n| Command | Alias | Description |\n|---|---|---|\n| `mtn init [path]` | | Initialize a new collection |\n| `mtn create ` | | Create a task from natural language |\n| `mtn list [options]` | `ls` | List tasks with filters |\n| `mtn show ` | | Show full task detail |\n| `mtn complete ` | `done` | Mark task as completed |\n| `mtn update [options]` | | Update task fields |\n| `mtn delete ` | `rm` | Delete a task |\n| `mtn archive ` | | Add archive tag |\n| `mtn search ` | | Full-text search |\n| `mtn timer start ` | | Start time tracking |\n| `mtn timer stop` | | Stop running timer |\n| `mtn timer status` | | Show active timers |\n| `mtn timer log` | | Show time entry log |\n| `mtn projects list` | | List projects |\n| `mtn projects show ` | | Show project tasks |\n| `mtn stats` | | Show task statistics |\n| `mtn interactive` | `i` | Interactive REPL |\n| `mtn config [options]` | | Manage configuration |\n","aliases":["/mdbase-tasknotes-cli/"],"toc":[{"level":2,"id":"when-to-use-this-vs-tasknotes-obsidian-cli","text":"When to use this vs TaskNotes Obsidian CLI"},{"level":2,"id":"install","text":"Install"},{"level":2,"id":"setup","text":"Setup"},{"level":3,"id":"using-an-existing-tasknotes-vault","text":"Using an existing TaskNotes vault"},{"level":3,"id":"creating-a-standalone-collection","text":"Creating a standalone collection"},{"level":2,"id":"creating-tasks","text":"Creating tasks"},{"level":3,"id":"supported-patterns","text":"Supported patterns"},{"level":2,"id":"querying-tasks","text":"Querying tasks"},{"level":3,"id":"list-tasks","text":"List tasks"},{"level":3,"id":"show-task-detail","text":"Show task detail"},{"level":3,"id":"search","text":"Search"},{"level":2,"id":"updating-tasks","text":"Updating tasks"},{"level":3,"id":"complete-a-task","text":"Complete a task"},{"level":3,"id":"update-fields","text":"Update fields"},{"level":3,"id":"archive-and-delete","text":"Archive and delete"},{"level":2,"id":"time-tracking","text":"Time tracking"},{"level":2,"id":"projects-and-statistics","text":"Projects and statistics"},{"level":3,"id":"projects","text":"Projects"},{"level":3,"id":"statistics","text":"Statistics"},{"level":2,"id":"interactive-mode","text":"Interactive mode"},{"level":2,"id":"configuration","text":"Configuration"},{"level":3,"id":"collection-path-resolution","text":"Collection path resolution"},{"level":2,"id":"command-reference","text":"Command reference"}],"html":"

mdbase-tasknotes (mtn) is a standalone command-line tool for managing TaskNotes tasks directly on markdown files. It uses mdbase to read and write task files and tasknotes-nlp-core for natural language parsing.

\n

When to use this vs TaskNotes Obsidian CLI#

\n

If you are looking for the built-in obsidian tasknotes:* commands exposed by the plugin itself, see TaskNotes Obsidian CLI.

\n

TaskNotes ships with tasknotes-cli (tn), which communicates with the Obsidian plugin over its HTTP API. mdbase-tasknotes operates directly on the markdown files instead.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
tn (tasknotes-cli)mtn (mdbase-tasknotes)
Requires ObsidianYes — plugin must be running with API enabledNo
Operates onHTTP APIMarkdown files directly via mdbase
Use whenObsidian is open and you want live syncObsidian is closed, on a server, or in scripts
Time trackingVia plugin APIVia frontmatter timeEntries
Task creationNLP via APINLP via bundled tasknotes-nlp-core
Installnpm install -g tasknotes-clinpm install -g mdbase-tasknotes
\n

Use mtn when:

\n
    \n
  • Obsidian isn't running or isn't available (headless servers, SSH sessions, CI pipelines)
  • \n
  • You want to manage tasks from the terminal without any background process
  • \n
  • You're scripting task creation or querying in shell workflows
  • \n
  • You're on a machine where Obsidian isn't installed
  • \n
\n

Both tools read and write the same task files, so they can be used interchangeably on the same vault.

\n

Install#

\n
npm install -g mdbase-tasknotes\n

Setup#

\n

Using an existing TaskNotes vault#

\n

If you already use TaskNotes with mdbase spec generation enabled (Settings → Integrations → Enable mdbase spec), point mtn at your vault root:

\n
mtn config --set collectionPath=/path/to/your/vault\n

The plugin generates mdbase.yaml and _types/task.md automatically — mtn reads these to understand your task schema, including your custom statuses and priorities.

\n

Creating a standalone collection#

\n

To create a new collection without Obsidian:

\n
mtn init ~/tasks\nmtn config --set collectionPath=~/tasks\n

This generates mdbase.yaml, _types/task.md, and a tasks/ folder with sensible defaults (statuses: open, in-progress, done, cancelled; priorities: low, normal, high, urgent).

\n

Creating tasks#

\n

Create tasks using natural language. Tags, contexts, projects, dates, priorities, and recurrence are extracted automatically:

\n
mtn create "Buy groceries tomorrow #shopping @errands"\nmtn create "Write quarterly report due friday #work +quarterly-review"\nmtn create "Call dentist high priority @phone"\nmtn create "Water plants every monday #home"\n

Supported patterns#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
PatternExampleExtracted as
#tag#shoppingTag
@context@errandsContext
+project+quarterly-reviewProject (stored as wikilink)
Date wordstomorrow, friday, next weekDue date
Priority wordshigh priority, urgentPriority
Recurrenceevery day, weekly, every mondayRecurrence rule
Estimate~30m, ~2hTime estimate
\n

The NLP parser reads your collection's status and priority enum values from _types/task.md, so any custom values you define there are automatically recognized.

\n

Querying tasks#

\n

List tasks#

\n
# Default: open tasks ordered by due date\nmtn list\n\n# Filter by status, priority, or tag\nmtn list --status in-progress\nmtn list --priority high\nmtn list --tag work\n\n# Show overdue tasks\nmtn list --overdue\n\n# Raw mdbase where expression\nmtn list --where 'due < "2026-03-01" && priority == "urgent"'\n\n# JSON output for scripting\nmtn list --json\n

Show task detail#

\n
mtn show "Buy groceries"\nmtn show tasks/Buy\\ groceries.md\n

Tasks can be referenced by title or file path. Title matching tries exact match first, then substring.

\n

Search#

\n

Full-text search across titles, body content, tags, contexts, and projects:

\n
mtn search quarterly\n

Updating tasks#

\n

Complete a task#

\n
mtn complete "Buy groceries"\n

Sets status to done and records the completion date.

\n

Update fields#

\n
mtn update "Write report" --status in-progress\nmtn update "Write report" --priority urgent --due 2026-03-01\nmtn update "Write report" --add-tag important --remove-tag draft\nmtn update "Write report" --add-context office\n

Archive and delete#

\n
mtn archive "Write report"     # Adds "archive" tag\nmtn delete "Old task"           # Checks for backlinks first\nmtn delete "Old task" --force   # Skip backlink check\n

Time tracking#

\n

Track time spent on tasks via the timeEntries frontmatter field — the same format TaskNotes uses.

\n
# Start a timer\nmtn timer start "Write report"\nmtn timer start "Write report" -d "Drafting introduction"\n\n# Check active timers\nmtn timer status\n\n# Stop the running timer\nmtn timer stop\n\n# View time log\nmtn timer log\nmtn timer log --period today\nmtn timer log --period week\nmtn timer log --from 2026-02-01 --to 2026-02-28\n

Projects and statistics#

\n

Projects#

\n
# List all projects\nmtn projects list\nmtn projects list --stats    # With completion percentages\n\n# Show tasks for a project\nmtn projects show quarterly-review\n

Statistics#

\n
mtn stats\n

Shows total tasks, completion rate, overdue count, breakdown by status and priority, and total time tracked.

\n

Interactive mode#

\n

Launch a REPL with live NLP preview that updates as you type:

\n
mtn interactive\n# or\nmtn i\n

Type a task description and the preview line shows how it will be parsed (title, tags, dates, priority). Press Enter to create the task.

\n

Configuration#

\n

Configuration is stored at ~/.config/mdbase-tasknotes/config.json.

\n
mtn config --list                              # Show all settings\nmtn config --set collectionPath=/path/to/vault  # Set collection path\nmtn config --get collectionPath                 # Get a setting\n

Collection path resolution#

\n

The collection path is resolved in order:

\n
    \n
  1. --path / -p flag on any command
  2. \n
  3. MDBASE_TASKNOTES_PATH environment variable
  4. \n
  5. collectionPath in config file
  6. \n
  7. Current working directory
  8. \n
\n

Command reference#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
CommandAliasDescription
mtn init [path]Initialize a new collection
mtn create <text...>Create a task from natural language
mtn list [options]lsList tasks with filters
mtn show <task>Show full task detail
mtn complete <task>doneMark task as completed
mtn update <task> [options]Update task fields
mtn delete <task>rmDelete a task
mtn archive <task>Add archive tag
mtn search <query>Full-text search
mtn timer start <task>Start time tracking
mtn timer stopStop running timer
mtn timer statusShow active timers
mtn timer logShow time entry log
mtn projects listList projects
mtn projects show <name>Show project tasks
mtn statsShow task statistics
mtn interactiveiInteractive REPL
mtn config [options]Manage configuration
\n","text":"mdbase-tasknotes (mtn) is a standalone command-line tool for managing TaskNotes tasks directly on markdown files. It uses mdbase to read and write task files and tasknotes-nlp-core for natural language parsing. When to use this vs TaskNotes Obsidian CLI# If you are looking for the built-in obsidian tasknotes:* commands exposed by the plugin itself, see TaskNotes Obsidian CLI. TaskNotes ships with tasknotes-cli (tn), which communicates with the Obsidian plugin over its HTTP API. mdbase-tasknotes operates directly on the markdown files instead. tn (tasknotes-cli) mtn (mdbase-tasknotes) Requires Obsidian Yes — plugin must be running with API enabled No Operates on HTTP API Markdown files directly via mdbase Use when Obsidian is open and you want live sync Obsidian is closed, on a server, or in scripts Time tracking Via plugin API Via frontmatter timeEntries Task creation NLP via API NLP via bundled tasknotes-nlp-core Install npm install -g tasknotes-cli npm install -g mdbase-tasknotes Use mtn when: Obsidian isn't running or isn't available (headless servers, SSH sessions, CI pipelines) You want to manage tasks from the terminal without any background process You're scripting task creation or querying in shell workflows You're on a machine where Obsidian isn't installed Both tools read and write the same task files, so they can be used interchangeably on the same vault. Install# npm install -g mdbase-tasknotes Setup# Using an existing TaskNotes vault# If you already use TaskNotes with mdbase spec generation enabled (Settings → Integrations → Enable mdbase spec), point mtn at your vault root: mtn config --set collectionPath=/path/to/your/vault The plugin generates mdbase.yaml and _types/task.md automatically — mtn reads these to understand your task schema, including your custom statuses and priorities. Creating a standalone collection# To create a new collection without Obsidian: mtn init ~/tasks mtn config --set collectionPath=~/tasks This generates mdbase.yaml, _types/task.md, and a tasks/ folder with sensible defaults (statuses: open, in-progress, done, cancelled; priorities: low, normal, high, urgent). Creating tasks# Create tasks using natural language. Tags, contexts, projects, dates, priorities, and recurrence are extracted automatically: mtn create \"Buy groceries tomorrow #shopping @errands\" mtn create \"Write quarterly report due friday #work +quarterly-review\" mtn create \"Call dentist high priority @phone\" mtn create \"Water plants every monday #home\" Supported patterns# Pattern Example Extracted as #tag #shopping Tag @context @errands Context +project +quarterly-review Project (stored as wikilink) Date words tomorrow, friday, next week Due date Priority words high priority, urgent Priority Recurrence every day, weekly, every monday Recurrence rule Estimate ~30m, ~2h Time estimate The NLP parser reads your collection's status and priority enum values from _types/task.md, so any custom values you define there are automatically recognized. Querying tasks# List tasks# # Default: open tasks ordered by due date mtn list # Filter by status, priority, or tag mtn list --status in-progress mtn list --priority high mtn list --tag work # Show overdue tasks mtn list --overdue # Raw mdbase where expression mtn list --where 'due < \"2026-03-01\" && priority == \"urgent\"' # JSON output for scripting mtn list --json Show task detail# mtn show \"Buy groceries\" mtn show tasks/Buy\\ groceries.md Tasks can be referenced by title or file path. Title matching tries exact match first, then substring. Search# Full-text search across titles, body content, tags, contexts, and projects: mtn search quarterly Updating tasks# Complete a task# mtn complete \"Buy groceries\" Sets status to done and records the completion date. Update fields# mtn update \"Write report\" --status in-progress mtn update \"Write report\" --priority urgent --due 2026-03-01 mtn update \"Write report\" --add-tag important --remove-tag draft mtn update \"Write report\" --add-context office Archive and delete# mtn archive \"Write report\" # Adds \"archive\" tag mtn delete \"Old task\" # Checks for backlinks first mtn delete \"Old task\" --force # Skip backlink check Time tracking# Track time spent on tasks via the timeEntries frontmatter field — the same format TaskNotes uses. # Start a timer mtn timer start \"Write report\" mtn timer start \"Write report\" -d \"Drafting introduction\" # Check active timers mtn timer status # Stop the running timer mtn timer stop # View time log mtn timer log mtn timer log --period today mtn timer log --period week mtn timer log --from 2026-02-01 --to 2026-02-28 Projects and statistics# Projects# # List all projects mtn projects list mtn projects list --stats # With completion percentages # Show tasks for a project mtn projects show quarterly-review Statistics# mtn stats Shows total tasks, completion rate, overdue count, breakdown by status and priority, and total time tracked. Interactive mode# Launch a REPL with live NLP preview that updates as you type: mtn interactive # or mtn i Type a task description and the preview line shows how it will be parsed (title, tags, dates, priority). Press Enter to create the task. Configuration# Configuration is stored at ~/.config/mdbase-tasknotes/config.json. mtn config --list # Show all settings mtn config --set collectionPath=/path/to/vault # Set collection path mtn config --get collectionPath # Get a setting Collection path resolution# The collection path is resolved in order: --path / -p flag on any command MDBASE_TASKNOTES_PATH environment variable collectionPath in config file Current working directory Command reference# Command Alias Description mtn init [path] Initialize a new collection mtn create Create a task from natural language mtn list [options] ls List tasks with filters mtn show Show full task detail mtn complete done Mark task as completed mtn update [options] Update task fields mtn delete rm Delete a task mtn archive Add archive tag mtn search Full-text search mtn timer start Start time tracking mtn timer stop Stop running timer mtn timer status Show active timers mtn timer log Show time entry log mtn projects list List projects mtn projects show Show project tasks mtn stats Show task statistics mtn interactive i Interactive REPL mtn config [options] Manage configuration"},{"route":"/obsidian/migration-v3-to-v4/","title":"Migrating from v3 to v4","description":"TaskNotes v4 migrates all views to the Bases system. This guide covers what changed and how to update your setup.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/migration-v3-to-v4.md","namespace":"obsidian","relativePath":"migration-v3-to-v4.md","raw":"# Migrating from v3 to v4\n\nTaskNotes v4 migrates all views to the Bases system. This guide covers what changed and how to update your setup.\n\n!!! warning \"Back up before migrating\"\n Back up the complete vault, including the hidden `.obsidian` directory, before changing views or plugin data.\n\n## Requirements\n\n- **Obsidian 1.10.1 or later** for early TaskNotes v4 releases\n- **Obsidian 1.12.2 or later** for the current TaskNotes 4.13.0 release\n- **Bases core plugin enabled** (Settings → Core Plugins → Bases)\n\n## What Changed\n\n### Views are Now Bases Files\n\nAll task views (Task List, Kanban, Calendar, Agenda) are now `.base` files stored in `TaskNotes/Views/`. This replaces the custom view system in v3.\n\n| v3 | v4 |\n|----|-----|\n| Views stored in plugin settings | Views stored as `.base` files |\n| Custom filter UI | Bases filter syntax |\n| Saved views in settings | Default views are separate files; exported v3 saved views share one multi-view file |\n\n### Automatic Migration on First Launch\n\nWhen you first open TaskNotes v4:\n\n1. Default `.base` files are created in `TaskNotes/Views/`\n2. Ribbon icons and commands now open these `.base` files\n3. Your existing task files are unchanged\n\n### Converting Saved Filter Views\n\nIf you had saved filter views in v3, you can export them to one `.base` file:\n\n1. Go to **Settings → TaskNotes → General → Views & base files**.\n2. Find **Export v3 saved views to Bases**.\n3. Run the export.\n4. TaskNotes creates `TaskNotes/Views/all-saved-views.base` with one Base view for each saved v3 view.\n\nThis is a one-way conversion. The original saved views remain in settings until you delete them.\n\n## Breaking Changes\n\n### View Configuration\n\nv3 saved views with custom filters need manual conversion to Bases filter syntax. Simple filters (status, priority, due date) convert automatically. Complex filters may need adjustment.\n\n**v3 Filter Example:**\n```\nstatus: in-progress\npriority: high\n```\n\n**v4 Bases Syntax:**\n```yaml\nfilters:\n and:\n - status == \"in-progress\"\n - priority == \"high\"\n```\n\nSee the [Obsidian Bases documentation](https://help.obsidian.md/Bases/Introduction+to+Bases) for filter syntax details.\n\n### Minimum Obsidian Version\n\nEarly v4 releases required Obsidian 1.10.1. The current release requirement is generated on the [version compatibility](reference/compatibility.md) page. Use the manifest requirement for the exact TaskNotes version you install.\n\n## New Features in v4\n\n### OAuth Calendar Integration\n\nv4 adds Google Calendar and Microsoft Outlook integration:\n\n- View external calendar events alongside tasks\n- Drag events to reschedule (syncs back to calendar provider)\n- Events sync every 15 minutes\n\nSee [Calendar Setup](calendar-setup.md) for configuration.\n\n### Kanban Swimlanes\n\nThe Kanban view now supports horizontal swimlane grouping:\n\n```yaml\nviews:\n - type: tasknotesKanban\n groupBy:\n property: status\n config:\n swimLane: priority\n```\n\n### Time Entry Editor\n\nA dedicated modal for managing time entries:\n\n- Alt-drag on calendar to create time entries\n- View total tracked time per task\n- Edit and delete time entries\n\n## Troubleshooting\n\n### Views Not Loading\n\n1. Verify Bases core plugin is enabled (Settings → Core Plugins)\n2. Check that `.base` files exist in `TaskNotes/Views/`\n3. Restart Obsidian\n\n### Missing Saved Views After Upgrade\n\nSaved views from v3 are preserved in settings. Use **Export v3 saved views to Bases** in **Settings → TaskNotes → General → Views & base files** to create the multi-view `.base` file.\n\n### Filter Syntax Errors\n\nBases uses different filter syntax than v3. Common issues:\n\n| Problem | Solution |\n|---------|----------|\n| `status: done` | Use `status == \"done\"` |\n| Multiple conditions | Wrap in `and:` or `or:` block |\n| Date comparisons | Use `date(due) < today()` |\n\n### Downgrading to v3\n\nMigration is one-way. If you need to downgrade:\n\n1. Uninstall TaskNotes v4\n2. Install TaskNotes v3 from releases\n3. Reconfigure your saved views manually\n\nYour task files are unaffected—only view configurations change.\n\n## View Templates\n\nFor complete `.base` file examples, see [Default Base Templates](views/default-base-templates.md).\n","aliases":["/migration-v3-to-v4/"],"toc":[{"level":2,"id":"requirements","text":"Requirements"},{"level":2,"id":"what-changed","text":"What Changed"},{"level":3,"id":"views-are-now-bases-files","text":"Views are Now Bases Files"},{"level":3,"id":"automatic-migration-on-first-launch","text":"Automatic Migration on First Launch"},{"level":3,"id":"converting-saved-filter-views","text":"Converting Saved Filter Views"},{"level":2,"id":"breaking-changes","text":"Breaking Changes"},{"level":3,"id":"view-configuration","text":"View Configuration"},{"level":3,"id":"minimum-obsidian-version","text":"Minimum Obsidian Version"},{"level":2,"id":"new-features-in-v4","text":"New Features in v4"},{"level":3,"id":"oauth-calendar-integration","text":"OAuth Calendar Integration"},{"level":3,"id":"kanban-swimlanes","text":"Kanban Swimlanes"},{"level":3,"id":"time-entry-editor","text":"Time Entry Editor"},{"level":2,"id":"troubleshooting","text":"Troubleshooting"},{"level":3,"id":"views-not-loading","text":"Views Not Loading"},{"level":3,"id":"missing-saved-views-after-upgrade","text":"Missing Saved Views After Upgrade"},{"level":3,"id":"filter-syntax-errors","text":"Filter Syntax Errors"},{"level":3,"id":"downgrading-to-v3","text":"Downgrading to v3"},{"level":2,"id":"view-templates","text":"View Templates"}],"html":"

TaskNotes v4 migrates all views to the Bases system. This guide covers what changed and how to update your setup.

\n\n

Requirements#

\n
    \n
  • Obsidian 1.10.1 or later for early TaskNotes v4 releases
  • \n
  • Obsidian 1.12.2 or later for the current TaskNotes 4.13.0 release
  • \n
  • Bases core plugin enabled (Settings → Core Plugins → Bases)
  • \n
\n

What Changed#

\n

Views are Now Bases Files#

\n

All task views (Task List, Kanban, Calendar, Agenda) are now .base files stored in TaskNotes/Views/. This replaces the custom view system in v3.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
v3v4
Views stored in plugin settingsViews stored as .base files
Custom filter UIBases filter syntax
Saved views in settingsDefault views are separate files; exported v3 saved views share one multi-view file
\n

Automatic Migration on First Launch#

\n

When you first open TaskNotes v4:

\n
    \n
  1. Default .base files are created in TaskNotes/Views/
  2. \n
  3. Ribbon icons and commands now open these .base files
  4. \n
  5. Your existing task files are unchanged
  6. \n
\n

Converting Saved Filter Views#

\n

If you had saved filter views in v3, you can export them to one .base file:

\n
    \n
  1. Go to Settings → TaskNotes → General → Views & base files.
  2. \n
  3. Find Export v3 saved views to Bases.
  4. \n
  5. Run the export.
  6. \n
  7. TaskNotes creates TaskNotes/Views/all-saved-views.base with one Base view for each saved v3 view.
  8. \n
\n

This is a one-way conversion. The original saved views remain in settings until you delete them.

\n

Breaking Changes#

\n

View Configuration#

\n

v3 saved views with custom filters need manual conversion to Bases filter syntax. Simple filters (status, priority, due date) convert automatically. Complex filters may need adjustment.

\n

v3 Filter Example:

\n
status: in-progress\npriority: high\n

v4 Bases Syntax:

\n
filters:\n  and:\n    - status == "in-progress"\n    - priority == "high"\n

See the Obsidian Bases documentation for filter syntax details.

\n

Minimum Obsidian Version#

\n

Early v4 releases required Obsidian 1.10.1. The current release requirement is generated on the version compatibility page. Use the manifest requirement for the exact TaskNotes version you install.

\n

New Features in v4#

\n

OAuth Calendar Integration#

\n

v4 adds Google Calendar and Microsoft Outlook integration:

\n
    \n
  • View external calendar events alongside tasks
  • \n
  • Drag events to reschedule (syncs back to calendar provider)
  • \n
  • Events sync every 15 minutes
  • \n
\n

See Calendar Setup for configuration.

\n

Kanban Swimlanes#

\n

The Kanban view now supports horizontal swimlane grouping:

\n
views:\n  - type: tasknotesKanban\n    groupBy:\n      property: status\n    config:\n      swimLane: priority\n

Time Entry Editor#

\n

A dedicated modal for managing time entries:

\n
    \n
  • Alt-drag on calendar to create time entries
  • \n
  • View total tracked time per task
  • \n
  • Edit and delete time entries
  • \n
\n

Troubleshooting#

\n

Views Not Loading#

\n
    \n
  1. Verify Bases core plugin is enabled (Settings → Core Plugins)
  2. \n
  3. Check that .base files exist in TaskNotes/Views/
  4. \n
  5. Restart Obsidian
  6. \n
\n

Missing Saved Views After Upgrade#

\n

Saved views from v3 are preserved in settings. Use Export v3 saved views to Bases in Settings → TaskNotes → General → Views & base files to create the multi-view .base file.

\n

Filter Syntax Errors#

\n

Bases uses different filter syntax than v3. Common issues:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
ProblemSolution
status: doneUse status == "done"
Multiple conditionsWrap in and: or or: block
Date comparisonsUse date(due) < today()
\n

Downgrading to v3#

\n

Migration is one-way. If you need to downgrade:

\n
    \n
  1. Uninstall TaskNotes v4
  2. \n
  3. Install TaskNotes v3 from releases
  4. \n
  5. Reconfigure your saved views manually
  6. \n
\n

Your task files are unaffected—only view configurations change.

\n

View Templates#

\n

For complete .base file examples, see Default Base Templates.

\n","text":"TaskNotes v4 migrates all views to the Bases system. This guide covers what changed and how to update your setup. Back up before migratingBack up the complete vault, including the hidden .obsidian directory, before changing views or plugin data. Requirements# Obsidian 1.10.1 or later for early TaskNotes v4 releases Obsidian 1.12.2 or later for the current TaskNotes 4.13.0 release Bases core plugin enabled (Settings → Core Plugins → Bases) What Changed# Views are Now Bases Files# All task views (Task List, Kanban, Calendar, Agenda) are now .base files stored in TaskNotes/Views/. This replaces the custom view system in v3. v3 v4 Views stored in plugin settings Views stored as .base files Custom filter UI Bases filter syntax Saved views in settings Default views are separate files; exported v3 saved views share one multi-view file Automatic Migration on First Launch# When you first open TaskNotes v4: Default .base files are created in TaskNotes/Views/ Ribbon icons and commands now open these .base files Your existing task files are unchanged Converting Saved Filter Views# If you had saved filter views in v3, you can export them to one .base file: Go to Settings → TaskNotes → General → Views & base files. Find Export v3 saved views to Bases. Run the export. TaskNotes creates TaskNotes/Views/all-saved-views.base with one Base view for each saved v3 view. This is a one-way conversion. The original saved views remain in settings until you delete them. Breaking Changes# View Configuration# v3 saved views with custom filters need manual conversion to Bases filter syntax. Simple filters (status, priority, due date) convert automatically. Complex filters may need adjustment. v3 Filter Example: status: in-progress priority: high v4 Bases Syntax: filters: and: - status == \"in-progress\" - priority == \"high\" See the Obsidian Bases documentation for filter syntax details. Minimum Obsidian Version# Early v4 releases required Obsidian 1.10.1. The current release requirement is generated on the version compatibility page. Use the manifest requirement for the exact TaskNotes version you install. New Features in v4# OAuth Calendar Integration# v4 adds Google Calendar and Microsoft Outlook integration: View external calendar events alongside tasks Drag events to reschedule (syncs back to calendar provider) Events sync every 15 minutes See Calendar Setup for configuration. Kanban Swimlanes# The Kanban view now supports horizontal swimlane grouping: views: - type: tasknotesKanban groupBy: property: status config: swimLane: priority Time Entry Editor# A dedicated modal for managing time entries: Alt-drag on calendar to create time entries View total tracked time per task Edit and delete time entries Troubleshooting# Views Not Loading# Verify Bases core plugin is enabled (Settings → Core Plugins) Check that .base files exist in TaskNotes/Views/ Restart Obsidian Missing Saved Views After Upgrade# Saved views from v3 are preserved in settings. Use Export v3 saved views to Bases in Settings → TaskNotes → General → Views & base files to create the multi-view .base file. Filter Syntax Errors# Bases uses different filter syntax than v3. Common issues: Problem Solution status: done Use status == \"done\" Multiple conditions Wrap in and: or or: block Date comparisons Use date(due) < today() Downgrading to v3# Migration is one-way. If you need to downgrade: Uninstall TaskNotes v4 Install TaskNotes v3 from releases Reconfigure your saved views manually Your task files are unaffected—only view configurations change. View Templates# For complete .base file examples, see Default Base Templates."},{"route":"/obsidian/nlp-api/","title":"TaskNotes NLP API","description":"The NLP API parses natural-language task text and optionally creates a task.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/nlp-api.md","namespace":"obsidian","relativePath":"nlp-api.md","raw":"# TaskNotes NLP API\n\nThe NLP API parses natural-language task text and optionally creates a task.\n\nIn-vault scripts can also call the parser directly from the loaded plugin:\n\n```javascript\nconst tasknotes = app.plugins.plugins.tasknotes;\nconst parsed = tasknotes.api.parseNaturalLanguage(\"Review PR tomorrow #code @work\");\n```\n\nFor the full in-process API exposed at `tasknotes.api`, including task updates, time tracking, settings snapshots, and events, see [TaskNotes JavaScript API](javascript-api.md).\n\n## Endpoints\n\n- `POST /api/nlp/parse`\n- `POST /api/nlp/create`\n\nBoth endpoints require a JSON body with `text`.\n\n## Request Format\n\n```json\n{\n \"text\": \"Review PR #123 tomorrow high priority @work\"\n}\n```\n\nNotes:\n\n- `text` is required and must be a string.\n- Per-request `locale` is not currently supported.\n- Parser language comes from TaskNotes settings (`nlpLanguage`).\n\n## `POST /api/nlp/parse`\n\nParses text and returns two objects:\n\n- `parsed`: direct parser output\n- `taskData`: normalized task payload that would be used for creation\n\nExample response (shape):\n\n```json\n{\n \"success\": true,\n \"data\": {\n \"parsed\": {\n \"title\": \"Review PR\",\n \"tags\": [\"123\"],\n \"contexts\": [\"work\"],\n \"projects\": [],\n \"priority\": \"high\",\n \"status\": null,\n \"dueDate\": \"2026-02-22\",\n \"scheduledDate\": null,\n \"dueTime\": null,\n \"scheduledTime\": null,\n \"recurrence\": null,\n \"estimate\": null,\n \"isCompleted\": false\n },\n \"taskData\": {\n \"title\": \"Review PR\",\n \"priority\": \"high\",\n \"status\": \"open\",\n \"tags\": [\"123\"],\n \"contexts\": [\"work\"],\n \"due\": \"2026-02-22\",\n \"dateCreated\": \"2026-02-22T09:00:00.000Z\",\n \"dateModified\": \"2026-02-22T09:00:00.000Z\"\n }\n }\n}\n```\n\nIf parser does not detect status, `taskData.status` falls back to your configured default task status. Parsed due and scheduled date-times in `taskData` use the same `YYYY-MM-DDTHH:mm` format as created tasks, and NLP trigger values for user-defined fields are returned under `customFrontmatter`.\n\n## `POST /api/nlp/create`\n\nParses text and creates a task in one call.\n\nReturns HTTP `201` on success.\n\nExample:\n\n```bash\ncurl -X POST http://localhost:8080/api/nlp/create \\\n -H \"Content-Type: application/json\" \\\n -d '{\"text\":\"Call mom due friday 2pm #personal\"}'\n```\n\nResponse fields:\n\n- `data.task` (created task)\n- `data.parsed` (parser output)\n\n## What the Parser Extracts\n\nThe parser can extract:\n\n- Dates and times (`tomorrow`, `friday 2pm`, ISO dates)\n- Priority terms (`high priority`, `urgent`, symbol patterns)\n- Status terms (mapped to your configured statuses)\n- Tags (`#tag`)\n- Contexts (`@context`)\n- Projects (`+project`)\n- Time estimates (`2h`, `30min`, `estimate 45m`)\n- Recurrence (`daily`, `weekly`, `every monday`)\n\nExact parsing behavior depends on your TaskNotes NLP settings and trigger configuration.\n\n## In-Vault Parser Method\n\nTemplater, QuickAdd, MetaBind, and other in-vault scripts can use the loaded plugin instance directly:\n\n```javascript\nconst tasknotes = app.plugins.plugins.tasknotes;\nconst parsed = tasknotes.api.parseNaturalLanguage(\"Write draft friday 2pm #writing @desk\");\n```\n\n`parseNaturalLanguage(text)` returns the same parser output shape as `data.parsed` from `POST /api/nlp/parse`. It uses your current TaskNotes settings, including custom status values, priority values, NLP language, NLP trigger configuration, user fields, and calendar locale.\n\nThis method only parses text. It does not create or modify task files.\n\nFor task creation and updates from in-vault scripts or companion plugins, use the broader [TaskNotes JavaScript API](javascript-api.md).\n\nExample Templater use:\n\n```javascript\n<%*\nconst tasknotes = app.plugins.plugins.tasknotes;\nconst text = await tp.system.prompt(\"Task\");\nconst parsed = tasknotes.api.parseNaturalLanguage(text);\ntR += `title: ${parsed.title}`;\n%>\n```\n\n## Error Responses\n\nCommon errors:\n\n- `400`: missing/invalid `text`\n- `401`: auth required (if API token is enabled)\n- `500`: parse/processing error\n\nError shape:\n\n```json\n{\n \"success\": false,\n \"error\": \"Text field is required and must be a string\"\n}\n```\n\n## Client Examples\n\n### JavaScript\n\n```javascript\nasync function parseTask(text) {\n const response = await fetch(\"http://localhost:8080/api/nlp/parse\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ text })\n });\n return response.json();\n}\n\nasync function createTaskFromText(text) {\n const response = await fetch(\"http://localhost:8080/api/nlp/create\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ text })\n });\n return response.json();\n}\n```\n\n### Python\n\n```python\nimport requests\n\n\ndef parse_task(text):\n response = requests.post(\n \"http://localhost:8080/api/nlp/parse\",\n json={\"text\": text},\n )\n return response.json()\n\n\ndef create_task_from_text(text):\n response = requests.post(\n \"http://localhost:8080/api/nlp/create\",\n json={\"text\": text},\n )\n return response.json()\n```\n\n## Authentication\n\nIf API auth token is enabled, include bearer token:\n\n```http\nAuthorization: Bearer YOUR_TOKEN\n```\n","aliases":["/nlp-api/"],"toc":[{"level":2,"id":"endpoints","text":"Endpoints"},{"level":2,"id":"request-format","text":"Request Format"},{"level":2,"id":"post-apinlpparse","text":"POST /api/nlp/parse"},{"level":2,"id":"post-apinlpcreate","text":"POST /api/nlp/create"},{"level":2,"id":"what-the-parser-extracts","text":"What the Parser Extracts"},{"level":2,"id":"in-vault-parser-method","text":"In-Vault Parser Method"},{"level":2,"id":"error-responses","text":"Error Responses"},{"level":2,"id":"client-examples","text":"Client Examples"},{"level":3,"id":"javascript","text":"JavaScript"},{"level":3,"id":"python","text":"Python"},{"level":2,"id":"authentication","text":"Authentication"}],"html":"

The NLP API parses natural-language task text and optionally creates a task.

\n

In-vault scripts can also call the parser directly from the loaded plugin:

\n
const tasknotes = app.plugins.plugins.tasknotes;\nconst parsed = tasknotes.api.parseNaturalLanguage("Review PR tomorrow #code @work");\n

For the full in-process API exposed at tasknotes.api, including task updates, time tracking, settings snapshots, and events, see TaskNotes JavaScript API.

\n

Endpoints#

\n
    \n
  • POST /api/nlp/parse
  • \n
  • POST /api/nlp/create
  • \n
\n

Both endpoints require a JSON body with text.

\n

Request Format#

\n
{\n  "text": "Review PR #123 tomorrow high priority @work"\n}\n

Notes:

\n
    \n
  • text is required and must be a string.
  • \n
  • Per-request locale is not currently supported.
  • \n
  • Parser language comes from TaskNotes settings (nlpLanguage).
  • \n
\n

POST /api/nlp/parse#

\n

Parses text and returns two objects:

\n
    \n
  • parsed: direct parser output
  • \n
  • taskData: normalized task payload that would be used for creation
  • \n
\n

Example response (shape):

\n
{\n  "success": true,\n  "data": {\n    "parsed": {\n      "title": "Review PR",\n      "tags": ["123"],\n      "contexts": ["work"],\n      "projects": [],\n      "priority": "high",\n      "status": null,\n      "dueDate": "2026-02-22",\n      "scheduledDate": null,\n      "dueTime": null,\n      "scheduledTime": null,\n      "recurrence": null,\n      "estimate": null,\n      "isCompleted": false\n    },\n    "taskData": {\n      "title": "Review PR",\n      "priority": "high",\n      "status": "open",\n      "tags": ["123"],\n      "contexts": ["work"],\n      "due": "2026-02-22",\n      "dateCreated": "2026-02-22T09:00:00.000Z",\n      "dateModified": "2026-02-22T09:00:00.000Z"\n    }\n  }\n}\n

If parser does not detect status, taskData.status falls back to your configured default task status. Parsed due and scheduled date-times in taskData use the same YYYY-MM-DDTHH:mm format as created tasks, and NLP trigger values for user-defined fields are returned under customFrontmatter.

\n

POST /api/nlp/create#

\n

Parses text and creates a task in one call.

\n

Returns HTTP 201 on success.

\n

Example:

\n
curl -X POST http://localhost:8080/api/nlp/create \\\n  -H "Content-Type: application/json" \\\n  -d '{"text":"Call mom due friday 2pm #personal"}'\n

Response fields:

\n
    \n
  • data.task (created task)
  • \n
  • data.parsed (parser output)
  • \n
\n

What the Parser Extracts#

\n

The parser can extract:

\n
    \n
  • Dates and times (tomorrow, friday 2pm, ISO dates)
  • \n
  • Priority terms (high priority, urgent, symbol patterns)
  • \n
  • Status terms (mapped to your configured statuses)
  • \n
  • Tags (#tag)
  • \n
  • Contexts (@context)
  • \n
  • Projects (+project)
  • \n
  • Time estimates (2h, 30min, estimate 45m)
  • \n
  • Recurrence (daily, weekly, every monday)
  • \n
\n

Exact parsing behavior depends on your TaskNotes NLP settings and trigger configuration.

\n

In-Vault Parser Method#

\n

Templater, QuickAdd, MetaBind, and other in-vault scripts can use the loaded plugin instance directly:

\n
const tasknotes = app.plugins.plugins.tasknotes;\nconst parsed = tasknotes.api.parseNaturalLanguage("Write draft friday 2pm #writing @desk");\n

parseNaturalLanguage(text) returns the same parser output shape as data.parsed from POST /api/nlp/parse. It uses your current TaskNotes settings, including custom status values, priority values, NLP language, NLP trigger configuration, user fields, and calendar locale.

\n

This method only parses text. It does not create or modify task files.

\n

For task creation and updates from in-vault scripts or companion plugins, use the broader TaskNotes JavaScript API.

\n

Example Templater use:

\n
<%*\nconst tasknotes = app.plugins.plugins.tasknotes;\nconst text = await tp.system.prompt("Task");\nconst parsed = tasknotes.api.parseNaturalLanguage(text);\ntR += `title: ${parsed.title}`;\n%>\n

Error Responses#

\n

Common errors:

\n
    \n
  • 400: missing/invalid text
  • \n
  • 401: auth required (if API token is enabled)
  • \n
  • 500: parse/processing error
  • \n
\n

Error shape:

\n
{\n  "success": false,\n  "error": "Text field is required and must be a string"\n}\n

Client Examples#

\n

JavaScript#

\n
async function parseTask(text) {\n  const response = await fetch("http://localhost:8080/api/nlp/parse", {\n    method: "POST",\n    headers: { "Content-Type": "application/json" },\n    body: JSON.stringify({ text })\n  });\n  return response.json();\n}\n\nasync function createTaskFromText(text) {\n  const response = await fetch("http://localhost:8080/api/nlp/create", {\n    method: "POST",\n    headers: { "Content-Type": "application/json" },\n    body: JSON.stringify({ text })\n  });\n  return response.json();\n}\n

Python#

\n
import requests\n\n\ndef parse_task(text):\n    response = requests.post(\n        "http://localhost:8080/api/nlp/parse",\n        json={"text": text},\n    )\n    return response.json()\n\n\ndef create_task_from_text(text):\n    response = requests.post(\n        "http://localhost:8080/api/nlp/create",\n        json={"text": text},\n    )\n    return response.json()\n

Authentication#

\n

If API auth token is enabled, include bearer token:

\n
Authorization: Bearer YOUR_TOKEN\n
","text":"The NLP API parses natural-language task text and optionally creates a task. In-vault scripts can also call the parser directly from the loaded plugin: const tasknotes = app.plugins.plugins.tasknotes; const parsed = tasknotes.api.parseNaturalLanguage(\"Review PR tomorrow #code @work\"); For the full in-process API exposed at tasknotes.api, including task updates, time tracking, settings snapshots, and events, see TaskNotes JavaScript API. Endpoints# POST /api/nlp/parse POST /api/nlp/create Both endpoints require a JSON body with text. Request Format# { \"text\": \"Review PR #123 tomorrow high priority @work\" } Notes: text is required and must be a string. Per-request locale is not currently supported. Parser language comes from TaskNotes settings (nlpLanguage). POST /api/nlp/parse# Parses text and returns two objects: parsed: direct parser output taskData: normalized task payload that would be used for creation Example response (shape): { \"success\": true, \"data\": { \"parsed\": { \"title\": \"Review PR\", \"tags\": [\"123\"], \"contexts\": [\"work\"], \"projects\": [], \"priority\": \"high\", \"status\": null, \"dueDate\": \"2026-02-22\", \"scheduledDate\": null, \"dueTime\": null, \"scheduledTime\": null, \"recurrence\": null, \"estimate\": null, \"isCompleted\": false }, \"taskData\": { \"title\": \"Review PR\", \"priority\": \"high\", \"status\": \"open\", \"tags\": [\"123\"], \"contexts\": [\"work\"], \"due\": \"2026-02-22\", \"dateCreated\": \"2026-02-22T09:00:00.000Z\", \"dateModified\": \"2026-02-22T09:00:00.000Z\" } } } If parser does not detect status, taskData.status falls back to your configured default task status. Parsed due and scheduled date-times in taskData use the same YYYY-MM-DDTHH:mm format as created tasks, and NLP trigger values for user-defined fields are returned under customFrontmatter. POST /api/nlp/create# Parses text and creates a task in one call. Returns HTTP 201 on success. Example: curl -X POST http://localhost:8080/api/nlp/create \\ -H \"Content-Type: application/json\" \\ -d '{\"text\":\"Call mom due friday 2pm #personal\"}' Response fields: data.task (created task) data.parsed (parser output) What the Parser Extracts# The parser can extract: Dates and times (tomorrow, friday 2pm, ISO dates) Priority terms (high priority, urgent, symbol patterns) Status terms (mapped to your configured statuses) Tags (#tag) Contexts (@context) Projects (+project) Time estimates (2h, 30min, estimate 45m) Recurrence (daily, weekly, every monday) Exact parsing behavior depends on your TaskNotes NLP settings and trigger configuration. In-Vault Parser Method# Templater, QuickAdd, MetaBind, and other in-vault scripts can use the loaded plugin instance directly: const tasknotes = app.plugins.plugins.tasknotes; const parsed = tasknotes.api.parseNaturalLanguage(\"Write draft friday 2pm #writing @desk\"); parseNaturalLanguage(text) returns the same parser output shape as data.parsed from POST /api/nlp/parse. It uses your current TaskNotes settings, including custom status values, priority values, NLP language, NLP trigger configuration, user fields, and calendar locale. This method only parses text. It does not create or modify task files. For task creation and updates from in-vault scripts or companion plugins, use the broader TaskNotes JavaScript API. Example Templater use: <%* const tasknotes = app.plugins.plugins.tasknotes; const text = await tp.system.prompt(\"Task\"); const parsed = tasknotes.api.parseNaturalLanguage(text); tR += `title: ${parsed.title}`; %> Error Responses# Common errors: 400: missing/invalid text 401: auth required (if API token is enabled) 500: parse/processing error Error shape: { \"success\": false, \"error\": \"Text field is required and must be a string\" } Client Examples# JavaScript# async function parseTask(text) { const response = await fetch(\"http://localhost:8080/api/nlp/parse\", { method: \"POST\", headers: { \"Content-Type\": \"application/json\" }, body: JSON.stringify({ text }) }); return response.json(); } async function createTaskFromText(text) { const response = await fetch(\"http://localhost:8080/api/nlp/create\", { method: \"POST\", headers: { \"Content-Type\": \"application/json\" }, body: JSON.stringify({ text }) }); return response.json(); } Python# import requests def parse_task(text): response = requests.post( \"http://localhost:8080/api/nlp/parse\", json={\"text\": text}, ) return response.json() def create_task_from_text(text): response = requests.post( \"http://localhost:8080/api/nlp/create\", json={\"text\": text}, ) return response.json() Authentication# If API auth token is enabled, include bearer token: Authorization: Bearer YOUR_TOKEN"},{"route":"/obsidian/obsidian-cli/","title":"TaskNotes Obsidian CLI","description":"TaskNotes can register commands directly with the Obsidian desktop CLI. This is useful when Obsidian is already running and you want shell access to task creation, time tracking...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/obsidian-cli.md","namespace":"obsidian","relativePath":"obsidian-cli.md","raw":"# TaskNotes Obsidian CLI\n\nTaskNotes can register commands directly with the Obsidian desktop CLI. This is useful when Obsidian is already running and you want shell access to task creation, time tracking, or Pomodoro control without going through the HTTP API.\n\nUse this page for the built-in `obsidian ...` commands exposed by the plugin itself. If you want a standalone terminal tool that works directly on Markdown files without Obsidian running, see [mdbase-tasknotes CLI](mdbase-tasknotes-cli.md).\n\n## Requirements\n\n- Obsidian desktop `1.12.2` or newer\n- TaskNotes installed and enabled in the target vault\n- Obsidian running when you invoke the CLI\n\nThe Obsidian CLI resolves commands against a vault context. In practice, it is safer to pass `vault=` explicitly instead of relying on the default vault.\n\n## Discovering commands\n\nList available TaskNotes commands:\n\n```bash\nobsidian help | rg 'tasknotes:'\n```\n\nYou should see:\n\n- `tasknotes:capture`\n- `tasknotes:start-time`\n- `tasknotes:stop-time`\n- `tasknotes:time-status`\n- `tasknotes:pomodoro`\n\n## `tasknotes:capture`\n\nCreate a task from free text, explicit flags, or both.\n\n```bash\nobsidian tasknotes:capture vault=test text=\"Review PR tomorrow #work @desk\"\n```\n\nBy default, `text=` is parsed with TaskNotes NLP. Explicit flags override parsed values.\n\n### Literal title mode\n\nUse `literal` when you want the text treated as an exact title instead of being parsed.\n\n```bash\nobsidian tasknotes:capture vault=test text=\"Fix parser edge case\" literal\n```\n\n### Explicit fields\n\nSupported override flags:\n\n- `title`\n- `details`\n- `status`\n- `priority`\n- `due`\n- `scheduled`\n- `tags`\n- `contexts`\n- `projects`\n- `recurrence`\n- `recurrence-anchor`\n- `reminders`\n- `estimate`\n\nExample:\n\n```bash\nobsidian tasknotes:capture vault=test \\\n text=\"Write release notes tomorrow #docs\" \\\n priority=high \\\n status=in-progress \\\n reminders='due:-PT1H'\n```\n\n### Reminder format\n\n`reminders=` accepts either:\n\n- a semicolon-separated shorthand such as `due:-PT1H;scheduled:-PT30M;at:2026-04-02T09:00`\n- a JSON array in the same shape TaskNotes stores internally\n\n### Recurrence anchor\n\nUse `recurrence-anchor=scheduled` or `recurrence-anchor=completion` to control how recurring tasks advance.\n\n## `tasknotes:start-time`\n\nStart time tracking for a task.\n\nYou can target a task by:\n\n- `path`\n- exact `title`\n- fuzzy `query`\n\nExamples:\n\n```bash\nobsidian tasknotes:start-time vault=test title=\"Write release notes\"\nobsidian tasknotes:start-time vault=test query=\"release notes\" description=\"Drafting first pass\"\nobsidian tasknotes:start-time vault=test path=\"TaskNotes/Write release notes.md\"\n```\n\n## `tasknotes:stop-time`\n\nStop time tracking for a task.\n\nExamples:\n\n```bash\nobsidian tasknotes:stop-time vault=test title=\"Write release notes\"\nobsidian tasknotes:stop-time vault=test path=\"TaskNotes/Write release notes.md\"\n```\n\nIf you omit task lookup flags, TaskNotes will stop the only active session when that is unambiguous.\n\n## `tasknotes:time-status`\n\nShow time-tracking status for either:\n\n- all active sessions\n- one resolved task\n\nExamples:\n\n```bash\nobsidian tasknotes:time-status vault=test\nobsidian tasknotes:time-status vault=test title=\"Write release notes\"\nobsidian tasknotes:time-status vault=test path=\"TaskNotes/Write release notes.md\"\n```\n\nWhen a task is targeted, the command returns that task's summary, active session, and time entries. With no lookup flags, it returns the currently active sessions across the vault.\n\n## `tasknotes:pomodoro`\n\nControl Pomodoro state from the CLI.\n\nSupported actions:\n\n- `status`\n- `start`\n- `pause`\n- `resume`\n- `stop`\n- `short-break`\n- `long-break`\n\n### Inspect state\n\n```bash\nobsidian tasknotes:pomodoro vault=test action=status\n```\n\n### Start a work session\n\nYou can start a Pomodoro with or without a linked task.\n\n```bash\nobsidian tasknotes:pomodoro vault=test action=start duration=25\nobsidian tasknotes:pomodoro vault=test action=start title=\"Write release notes\" duration=25\n```\n\nTask lookup for `action=start` supports the same selectors as time tracking:\n\n- `path`\n- exact `title`\n- fuzzy `query`\n\n### Pause, resume, and stop\n\n```bash\nobsidian tasknotes:pomodoro vault=test action=pause\nobsidian tasknotes:pomodoro vault=test action=resume\nobsidian tasknotes:pomodoro vault=test action=stop\n```\n\n### Breaks\n\n```bash\nobsidian tasknotes:pomodoro vault=test action=short-break\nobsidian tasknotes:pomodoro vault=test action=long-break\n```\n\n## Choosing between CLI surfaces\n\nUse the built-in Obsidian CLI when:\n\n- Obsidian is already open\n- you want plugin-aware behavior, including current cache, defaults, templates, time tracking, and Pomodoro state\n- you are scripting on the same machine as the running vault\n\nUse [mdbase-tasknotes CLI](mdbase-tasknotes-cli.md) when:\n\n- Obsidian is not running\n- you need headless/server workflows\n- you want direct file-level automation over a task collection\n\n## Notes\n\n- `path` is the most reliable task selector for automation.\n- Immediately after creating a task, exact title lookup can lag briefly until the in-memory cache catches up.\n- These commands are desktop-only because they depend on the Obsidian desktop CLI.\n","aliases":["/obsidian-cli/"],"toc":[{"level":2,"id":"requirements","text":"Requirements"},{"level":2,"id":"discovering-commands","text":"Discovering commands"},{"level":2,"id":"tasknotescapture","text":"tasknotes:capture"},{"level":3,"id":"literal-title-mode","text":"Literal title mode"},{"level":3,"id":"explicit-fields","text":"Explicit fields"},{"level":3,"id":"reminder-format","text":"Reminder format"},{"level":3,"id":"recurrence-anchor","text":"Recurrence anchor"},{"level":2,"id":"tasknotesstart-time","text":"tasknotes:start-time"},{"level":2,"id":"tasknotesstop-time","text":"tasknotes:stop-time"},{"level":2,"id":"tasknotestime-status","text":"tasknotes:time-status"},{"level":2,"id":"tasknotespomodoro","text":"tasknotes:pomodoro"},{"level":3,"id":"inspect-state","text":"Inspect state"},{"level":3,"id":"start-a-work-session","text":"Start a work session"},{"level":3,"id":"pause-resume-and-stop","text":"Pause, resume, and stop"},{"level":3,"id":"breaks","text":"Breaks"},{"level":2,"id":"choosing-between-cli-surfaces","text":"Choosing between CLI surfaces"},{"level":2,"id":"notes","text":"Notes"}],"html":"

TaskNotes can register commands directly with the Obsidian desktop CLI. This is useful when Obsidian is already running and you want shell access to task creation, time tracking, or Pomodoro control without going through the HTTP API.

\n

Use this page for the built-in obsidian ... commands exposed by the plugin itself. If you want a standalone terminal tool that works directly on Markdown files without Obsidian running, see mdbase-tasknotes CLI.

\n

Requirements#

\n
    \n
  • Obsidian desktop 1.12.2 or newer
  • \n
  • TaskNotes installed and enabled in the target vault
  • \n
  • Obsidian running when you invoke the CLI
  • \n
\n

The Obsidian CLI resolves commands against a vault context. In practice, it is safer to pass vault=<name> explicitly instead of relying on the default vault.

\n

Discovering commands#

\n

List available TaskNotes commands:

\n
obsidian help | rg 'tasknotes:'\n

You should see:

\n
    \n
  • tasknotes:capture
  • \n
  • tasknotes:start-time
  • \n
  • tasknotes:stop-time
  • \n
  • tasknotes:time-status
  • \n
  • tasknotes:pomodoro
  • \n
\n

tasknotes:capture#

\n

Create a task from free text, explicit flags, or both.

\n
obsidian tasknotes:capture vault=test text="Review PR tomorrow #work @desk"\n

By default, text= is parsed with TaskNotes NLP. Explicit flags override parsed values.

\n

Literal title mode#

\n

Use literal when you want the text treated as an exact title instead of being parsed.

\n
obsidian tasknotes:capture vault=test text="Fix parser edge case" literal\n

Explicit fields#

\n

Supported override flags:

\n
    \n
  • title
  • \n
  • details
  • \n
  • status
  • \n
  • priority
  • \n
  • due
  • \n
  • scheduled
  • \n
  • tags
  • \n
  • contexts
  • \n
  • projects
  • \n
  • recurrence
  • \n
  • recurrence-anchor
  • \n
  • reminders
  • \n
  • estimate
  • \n
\n

Example:

\n
obsidian tasknotes:capture vault=test \\\n  text="Write release notes tomorrow #docs" \\\n  priority=high \\\n  status=in-progress \\\n  reminders='due:-PT1H'\n

Reminder format#

\n

reminders= accepts either:

\n
    \n
  • a semicolon-separated shorthand such as due:-PT1H;scheduled:-PT30M;at:2026-04-02T09:00
  • \n
  • a JSON array in the same shape TaskNotes stores internally
  • \n
\n

Recurrence anchor#

\n

Use recurrence-anchor=scheduled or recurrence-anchor=completion to control how recurring tasks advance.

\n

tasknotes:start-time#

\n

Start time tracking for a task.

\n

You can target a task by:

\n
    \n
  • path
  • \n
  • exact title
  • \n
  • fuzzy query
  • \n
\n

Examples:

\n
obsidian tasknotes:start-time vault=test title="Write release notes"\nobsidian tasknotes:start-time vault=test query="release notes" description="Drafting first pass"\nobsidian tasknotes:start-time vault=test path="TaskNotes/Write release notes.md"\n

tasknotes:stop-time#

\n

Stop time tracking for a task.

\n

Examples:

\n
obsidian tasknotes:stop-time vault=test title="Write release notes"\nobsidian tasknotes:stop-time vault=test path="TaskNotes/Write release notes.md"\n

If you omit task lookup flags, TaskNotes will stop the only active session when that is unambiguous.

\n

tasknotes:time-status#

\n

Show time-tracking status for either:

\n
    \n
  • all active sessions
  • \n
  • one resolved task
  • \n
\n

Examples:

\n
obsidian tasknotes:time-status vault=test\nobsidian tasknotes:time-status vault=test title="Write release notes"\nobsidian tasknotes:time-status vault=test path="TaskNotes/Write release notes.md"\n

When a task is targeted, the command returns that task's summary, active session, and time entries. With no lookup flags, it returns the currently active sessions across the vault.

\n

tasknotes:pomodoro#

\n

Control Pomodoro state from the CLI.

\n

Supported actions:

\n
    \n
  • status
  • \n
  • start
  • \n
  • pause
  • \n
  • resume
  • \n
  • stop
  • \n
  • short-break
  • \n
  • long-break
  • \n
\n

Inspect state#

\n
obsidian tasknotes:pomodoro vault=test action=status\n

Start a work session#

\n

You can start a Pomodoro with or without a linked task.

\n
obsidian tasknotes:pomodoro vault=test action=start duration=25\nobsidian tasknotes:pomodoro vault=test action=start title="Write release notes" duration=25\n

Task lookup for action=start supports the same selectors as time tracking:

\n
    \n
  • path
  • \n
  • exact title
  • \n
  • fuzzy query
  • \n
\n

Pause, resume, and stop#

\n
obsidian tasknotes:pomodoro vault=test action=pause\nobsidian tasknotes:pomodoro vault=test action=resume\nobsidian tasknotes:pomodoro vault=test action=stop\n

Breaks#

\n
obsidian tasknotes:pomodoro vault=test action=short-break\nobsidian tasknotes:pomodoro vault=test action=long-break\n

Choosing between CLI surfaces#

\n

Use the built-in Obsidian CLI when:

\n
    \n
  • Obsidian is already open
  • \n
  • you want plugin-aware behavior, including current cache, defaults, templates, time tracking, and Pomodoro state
  • \n
  • you are scripting on the same machine as the running vault
  • \n
\n

Use mdbase-tasknotes CLI when:

\n
    \n
  • Obsidian is not running
  • \n
  • you need headless/server workflows
  • \n
  • you want direct file-level automation over a task collection
  • \n
\n

Notes#

\n
    \n
  • path is the most reliable task selector for automation.
  • \n
  • Immediately after creating a task, exact title lookup can lag briefly until the in-memory cache catches up.
  • \n
  • These commands are desktop-only because they depend on the Obsidian desktop CLI.
  • \n
\n","text":"TaskNotes can register commands directly with the Obsidian desktop CLI. This is useful when Obsidian is already running and you want shell access to task creation, time tracking, or Pomodoro control without going through the HTTP API. Use this page for the built-in obsidian ... commands exposed by the plugin itself. If you want a standalone terminal tool that works directly on Markdown files without Obsidian running, see mdbase-tasknotes CLI. Requirements# Obsidian desktop 1.12.2 or newer TaskNotes installed and enabled in the target vault Obsidian running when you invoke the CLI The Obsidian CLI resolves commands against a vault context. In practice, it is safer to pass vault= explicitly instead of relying on the default vault. Discovering commands# List available TaskNotes commands: obsidian help | rg 'tasknotes:' You should see: tasknotes:capture tasknotes:start-time tasknotes:stop-time tasknotes:time-status tasknotes:pomodoro tasknotes:capture# Create a task from free text, explicit flags, or both. obsidian tasknotes:capture vault=test text=\"Review PR tomorrow #work @desk\" By default, text= is parsed with TaskNotes NLP. Explicit flags override parsed values. Literal title mode# Use literal when you want the text treated as an exact title instead of being parsed. obsidian tasknotes:capture vault=test text=\"Fix parser edge case\" literal Explicit fields# Supported override flags: title details status priority due scheduled tags contexts projects recurrence recurrence-anchor reminders estimate Example: obsidian tasknotes:capture vault=test \\ text=\"Write release notes tomorrow #docs\" \\ priority=high \\ status=in-progress \\ reminders='due:-PT1H' Reminder format# reminders= accepts either: a semicolon-separated shorthand such as due:-PT1H;scheduled:-PT30M;at:2026-04-02T09:00 a JSON array in the same shape TaskNotes stores internally Recurrence anchor# Use recurrence-anchor=scheduled or recurrence-anchor=completion to control how recurring tasks advance. tasknotes:start-time# Start time tracking for a task. You can target a task by: path exact title fuzzy query Examples: obsidian tasknotes:start-time vault=test title=\"Write release notes\" obsidian tasknotes:start-time vault=test query=\"release notes\" description=\"Drafting first pass\" obsidian tasknotes:start-time vault=test path=\"TaskNotes/Write release notes.md\" tasknotes:stop-time# Stop time tracking for a task. Examples: obsidian tasknotes:stop-time vault=test title=\"Write release notes\" obsidian tasknotes:stop-time vault=test path=\"TaskNotes/Write release notes.md\" If you omit task lookup flags, TaskNotes will stop the only active session when that is unambiguous. tasknotes:time-status# Show time-tracking status for either: all active sessions one resolved task Examples: obsidian tasknotes:time-status vault=test obsidian tasknotes:time-status vault=test title=\"Write release notes\" obsidian tasknotes:time-status vault=test path=\"TaskNotes/Write release notes.md\" When a task is targeted, the command returns that task's summary, active session, and time entries. With no lookup flags, it returns the currently active sessions across the vault. tasknotes:pomodoro# Control Pomodoro state from the CLI. Supported actions: status start pause resume stop short-break long-break Inspect state# obsidian tasknotes:pomodoro vault=test action=status Start a work session# You can start a Pomodoro with or without a linked task. obsidian tasknotes:pomodoro vault=test action=start duration=25 obsidian tasknotes:pomodoro vault=test action=start title=\"Write release notes\" duration=25 Task lookup for action=start supports the same selectors as time tracking: path exact title fuzzy query Pause, resume, and stop# obsidian tasknotes:pomodoro vault=test action=pause obsidian tasknotes:pomodoro vault=test action=resume obsidian tasknotes:pomodoro vault=test action=stop Breaks# obsidian tasknotes:pomodoro vault=test action=short-break obsidian tasknotes:pomodoro vault=test action=long-break Choosing between CLI surfaces# Use the built-in Obsidian CLI when: Obsidian is already open you want plugin-aware behavior, including current cache, defaults, templates, time tracking, and Pomodoro state you are scripting on the same machine as the running vault Use mdbase-tasknotes CLI when: Obsidian is not running you need headless/server workflows you want direct file-level automation over a task collection Notes# path is the most reliable task selector for automation. Immediately after creating a task, exact title lookup can lag briefly until the in-memory cache catches up. These commands are desktop-only because they depend on the Obsidian desktop CLI."},{"route":"/obsidian/reference/commands/","title":"Command reference","description":"Every TaskNotes command registered with Obsidian, generated from the plugin command definitions.","product":"obsidian","platforms":[],"version":"4.13.0","generated":true,"noIndex":false,"hideToc":false,"source":"tasknotes:docs-builder/src/generated-pages.js","namespace":"obsidian","relativePath":"reference/commands.md","raw":"---\ntitle: \"Command reference\"\ndescription: \"Every TaskNotes command registered with Obsidian, generated from the plugin command definitions.\"\ngenerated: true\nsource: [\"src/commands/taskNotesCommands.ts\",\"src/i18n/resources/en.ts\"]\n---\n# Command reference\n\nThis page is generated from the commands registered by TaskNotes. Command IDs are stable integration identifiers; names are the English labels shown in Obsidian.\n\n| Command | ID | Available in |\n| --- | --- | --- |\n| Open mini calendar view | `open-calendar-view` | Global |\n| Open calendar view | `open-advanced-calendar-view` | Global |\n| Open tasks view | `open-tasks-view` | Global |\n| Open agenda view | `open-agenda-view` | Global |\n| Open Pomodoro timer | `open-pomodoro-view` | Global |\n| Open Kanban board | `open-kanban-view` | Global |\n| Update default base files | `update-default-base-files` | Global |\n| Open Pomodoro statistics | `open-pomodoro-stats` | Global |\n| Open task & project statistics | `open-statistics` | Global |\n| Create new task | `create-new-task` | Global |\n| Convert current note to task | `convert-current-note-to-task` | Global |\n| Convert checkbox task to TaskNote | `convert-to-tasknote` | Editor |\n| Convert all tasks in note | `batch-convert-all-tasks` | Editor |\n| Insert tasknote link | `insert-tasknote-link` | Editor |\n| Create new inline task | `create-inline-task` | Editor |\n| Quick actions for current task | `quick-actions-current-task` | Global |\n| Quick actions for task under cursor | `quick-actions-task-under-cursor` | Editor |\n| Edit current task | `edit-current-task` | Global |\n| Cycle current task status | `cycle-current-task-status` | Global |\n| Cycle current task priority | `cycle-current-task-priority` | Global |\n| Add project to current task | `add-project-to-current-task` | Global |\n| Add subtask to current note | `add-subtask-to-current-note` | Global |\n| Go to today's note | `go-to-today` | Global |\n| Start Pomodoro timer | `start-pomodoro` | Global |\n| Stop Pomodoro timer | `stop-pomodoro` | Global |\n| Pause/resume Pomodoro timer | `pause-pomodoro` | Global |\n| Refresh cache | `refresh-cache` | Global |\n| Export all tasks as ICS file | `export-all-tasks-ics` | Global |\n| Sync all tasks to Google Calendar | `sync-all-tasks-google-calendar` | Global |\n| Sync current task to Google Calendar | `sync-current-task-google-calendar` | Global |\n| View release notes | `view-release-notes` | Global |\n| Start time tracking (select task) | `start-time-tracking-with-selector` | Global |\n| Edit time entries (select task) | `edit-time-entries` | Global |\n| Create or open task | `create-or-open-task` | Global |\n| Create or open task and start time tracking | `create-or-open-task-with-time-tracking` | Global |\n| Postpone overdue scheduled tasks to today | `rollover-overdue-scheduled-tasks` | Global |\n\n_Generated from 36 registered commands._\n","aliases":["/reference/commands/","/reference/commands/"],"toc":[],"html":"

This page is generated from the commands registered by TaskNotes. Command IDs are stable integration identifiers; names are the English labels shown in Obsidian.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
CommandIDAvailable in
Open mini calendar viewopen-calendar-viewGlobal
Open calendar viewopen-advanced-calendar-viewGlobal
Open tasks viewopen-tasks-viewGlobal
Open agenda viewopen-agenda-viewGlobal
Open Pomodoro timeropen-pomodoro-viewGlobal
Open Kanban boardopen-kanban-viewGlobal
Update default base filesupdate-default-base-filesGlobal
Open Pomodoro statisticsopen-pomodoro-statsGlobal
Open task & project statisticsopen-statisticsGlobal
Create new taskcreate-new-taskGlobal
Convert current note to taskconvert-current-note-to-taskGlobal
Convert checkbox task to TaskNoteconvert-to-tasknoteEditor
Convert all tasks in notebatch-convert-all-tasksEditor
Insert tasknote linkinsert-tasknote-linkEditor
Create new inline taskcreate-inline-taskEditor
Quick actions for current taskquick-actions-current-taskGlobal
Quick actions for task under cursorquick-actions-task-under-cursorEditor
Edit current taskedit-current-taskGlobal
Cycle current task statuscycle-current-task-statusGlobal
Cycle current task prioritycycle-current-task-priorityGlobal
Add project to current taskadd-project-to-current-taskGlobal
Add subtask to current noteadd-subtask-to-current-noteGlobal
Go to today's notego-to-todayGlobal
Start Pomodoro timerstart-pomodoroGlobal
Stop Pomodoro timerstop-pomodoroGlobal
Pause/resume Pomodoro timerpause-pomodoroGlobal
Refresh cacherefresh-cacheGlobal
Export all tasks as ICS fileexport-all-tasks-icsGlobal
Sync all tasks to Google Calendarsync-all-tasks-google-calendarGlobal
Sync current task to Google Calendarsync-current-task-google-calendarGlobal
View release notesview-release-notesGlobal
Start time tracking (select task)start-time-tracking-with-selectorGlobal
Edit time entries (select task)edit-time-entriesGlobal
Create or open taskcreate-or-open-taskGlobal
Create or open task and start time trackingcreate-or-open-task-with-time-trackingGlobal
Postpone overdue scheduled tasks to todayrollover-overdue-scheduled-tasksGlobal
\n

Generated from 36 registered commands.

\n","text":"This page is generated from the commands registered by TaskNotes. Command IDs are stable integration identifiers; names are the English labels shown in Obsidian. Command ID Available in Open mini calendar view open-calendar-view Global Open calendar view open-advanced-calendar-view Global Open tasks view open-tasks-view Global Open agenda view open-agenda-view Global Open Pomodoro timer open-pomodoro-view Global Open Kanban board open-kanban-view Global Update default base files update-default-base-files Global Open Pomodoro statistics open-pomodoro-stats Global Open task & project statistics open-statistics Global Create new task create-new-task Global Convert current note to task convert-current-note-to-task Global Convert checkbox task to TaskNote convert-to-tasknote Editor Convert all tasks in note batch-convert-all-tasks Editor Insert tasknote link insert-tasknote-link Editor Create new inline task create-inline-task Editor Quick actions for current task quick-actions-current-task Global Quick actions for task under cursor quick-actions-task-under-cursor Editor Edit current task edit-current-task Global Cycle current task status cycle-current-task-status Global Cycle current task priority cycle-current-task-priority Global Add project to current task add-project-to-current-task Global Add subtask to current note add-subtask-to-current-note Global Go to today's note go-to-today Global Start Pomodoro timer start-pomodoro Global Stop Pomodoro timer stop-pomodoro Global Pause/resume Pomodoro timer pause-pomodoro Global Refresh cache refresh-cache Global Export all tasks as ICS file export-all-tasks-ics Global Sync all tasks to Google Calendar sync-all-tasks-google-calendar Global Sync current task to Google Calendar sync-current-task-google-calendar Global View release notes view-release-notes Global Start time tracking (select task) start-time-tracking-with-selector Global Edit time entries (select task) edit-time-entries Global Create or open task create-or-open-task Global Create or open task and start time tracking create-or-open-task-with-time-tracking Global Postpone overdue scheduled tasks to today rollover-overdue-scheduled-tasks Global Generated from 36 registered commands."},{"route":"/obsidian/reference/compatibility/","title":"Version compatibility","description":"Current TaskNotes and Obsidian compatibility requirements, generated from the plugin manifest.","product":"obsidian","platforms":[],"version":"4.13.0","generated":true,"noIndex":false,"hideToc":false,"source":"tasknotes:docs-builder/src/generated-pages.js","namespace":"obsidian","relativePath":"reference/compatibility.md","raw":"---\ntitle: \"Version compatibility\"\ndescription: \"Current TaskNotes and Obsidian compatibility requirements, generated from the plugin manifest.\"\ngenerated: true\nsource: [\"manifest.json\",\"versions.json\"]\n---\n# Version compatibility\n\n## Current release\n\n| Item | Value |\n| --- | --- |\n| TaskNotes | `4.13.0` |\n| Minimum Obsidian version | `1.12.2` |\n| Desktop only | No |\n| Bases core plugin | Required |\n\nThe minimum version above applies to the current TaskNotes release. Older releases had different requirements; consult `versions.json` or the relevant [release note](/releases/) when maintaining an older installation.\n","aliases":["/reference/compatibility/","/reference/compatibility/"],"toc":[{"level":2,"id":"current-release","text":"Current release"}],"html":"

Current release#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
ItemValue
TaskNotes4.13.0
Minimum Obsidian version1.12.2
Desktop onlyNo
Bases core pluginRequired
\n

The minimum version above applies to the current TaskNotes release. Older releases had different requirements; consult versions.json or the relevant release note when maintaining an older installation.

\n","text":"Current release# Item Value TaskNotes 4.13.0 Minimum Obsidian version 1.12.2 Desktop only No Bases core plugin Required The minimum version above applies to the current TaskNotes release. Older releases had different requirements; consult versions.json or the relevant release note when maintaining an older installation."},{"route":"/obsidian/reference/default-base-templates/","title":"Generated default Base templates","description":"Exact default Obsidian Base files generated by the current TaskNotes source and default settings.","product":"obsidian","platforms":[],"version":"4.13.0","generated":true,"noIndex":false,"hideToc":false,"source":"tasknotes:docs-builder/src/generated-pages.js","namespace":"obsidian","relativePath":"reference/default-base-templates.md","raw":"---\ntitle: \"Generated default Base templates\"\ndescription: \"Exact default Obsidian Base files generated by the current TaskNotes source and default settings.\"\ngenerated: true\nsource: [\"src/templates/defaultBasesFiles.ts\",\"src/settings/defaults.ts\",\"src/core/FieldMapper.ts\"]\n---\n# Generated default Base templates\n\nThese are the exact templates TaskNotes 4.13.0 produces with default settings. Your generated files reflect your own field mapping and other settings, so customized output can differ.\n\nRegenerating with **Update files** overwrites configured default Base files. Copy a customized file to a new path before updating it.\n\n## mini-calendar-default.base\n\nCommand/template ID: `open-calendar-view`\n\n```yaml\n# Mini Calendar\n# Generated with your TaskNotes settings\n\nfilters:\n and:\n - file.hasTag(\"task\")\n\nformulas:\n priorityWeight: 'if(priority==\"none\",0,if(priority==\"low\",1,if(priority==\"normal\",2,if(priority==\"high\",3,999))))'\n daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n dueIn: 'if(due.isEmpty(), \"\", if(formula.daysUntilDue == 0, \"Today\", if(formula.daysUntilDue == 1, \"1 day\", if(formula.daysUntilDue > 1, formula.daysUntilDue + \" days\", if(formula.daysUntilDue == -1, \"1 day overdue\", formula.daysUntilDue * -1 + \" days overdue\")))))'\n daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != \"done\"'\n isDueToday: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isDueThisWeek: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")'\n isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isRecurring: 'recurrence && !recurrence.isEmpty()'\n hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - \"7d\").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n dueMonth: 'if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), \"No due date\")'\n dueWeek: 'if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), \"No due date\")'\n scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"Not scheduled\")'\n scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"Not scheduled\")'\n dueDateCategory: 'if(due.isEmpty(), \"No due date\", if(date(due) < today(), \"Overdue\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), \"This week\", \"Later\")))))'\n timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(timeEstimate < 30, \"Quick (<30m)\", if(timeEstimate <= 120, \"Medium (30m-2h)\", \"Long (>2h)\")))'\n ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, \"Today\", if(((number(now()) - number(file.ctime)) / 86400000) < 7, \"This week\", if(((number(now()) - number(file.ctime)) / 86400000) < 30, \"This month\", \"Older\")))'\n createdMonth: 'file.ctime.format(\"YYYY-MM\")'\n modifiedMonth: 'file.mtime.format(\"YYYY-MM\")'\n priorityCategory: 'if(priority==\"none\",\"None\",if(priority==\"low\",\"Low\",if(priority==\"normal\",\"Normal\",if(priority==\"high\",\"High\",\"No priority\"))))'\n projectCount: 'if(!projects || list(projects).length == 0, \"No projects\", if(list(projects).length == 1, \"Single project\", \"Multiple projects\"))'\n contextCount: 'if(!contexts || list(contexts).length == 0, \"No contexts\", if(list(contexts).length == 1, \"Single context\", \"Multiple contexts\"))'\n trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(!timeEntries || list(timeEntries).length == 0, \"Not started\", if(formula.efficiencyRatio < 100, \"Under estimate\", \"Over estimate\")))'\n nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n isToday: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"))'\n isThisWeek: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"))'\n nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), \"No date\", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), \"Overdue/Past\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")), \"Today\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")), \"Tomorrow\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")), \"This week\", \"Later\")))))'\n nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-MM\"), date(scheduled).format(\"YYYY-MM\")), if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"No date\")))'\n nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-[W]WW\"), date(scheduled).format(\"YYYY-[W]WW\")), if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"No date\")))'\n urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format(\"YYYY-MM-DD\")))) / 86400000)))'\n timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + \"h \" + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + \"m\", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + \"m\"), \"0m\")'\n dueDateDisplay: 'if(due.isEmpty(), \"\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") == (today() - \"1 day\").format(\"YYYY-MM-DD\"), \"Yesterday\", if(date(due) < today(), formula.daysUntilDue * -1 + \"d ago\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), date(due).format(\"ddd\"), date(due).format(\"MMM D\")))))))'\n\nviews:\n - type: tasknotesMiniCalendar\n name: \"Due\"\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - property: due\n direction: ASC\n dateProperty: due\n - type: tasknotesMiniCalendar\n name: \"Scheduled\"\n order: []\n dateProperty: scheduled\n - type: tasknotesMiniCalendar\n name: \"Created\"\n dateProperty: file.ctime\n - type: tasknotesMiniCalendar\n name: \"Modified\"\n dateProperty: file.mtime\n```\n\n## kanban-default.base\n\nCommand/template ID: `open-kanban-view`\n\n```yaml\n# Kanban Board\n\nfilters:\n and:\n - file.hasTag(\"task\")\n\nformulas:\n priorityWeight: 'if(priority==\"none\",0,if(priority==\"low\",1,if(priority==\"normal\",2,if(priority==\"high\",3,999))))'\n daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n dueIn: 'if(due.isEmpty(), \"\", if(formula.daysUntilDue == 0, \"Today\", if(formula.daysUntilDue == 1, \"1 day\", if(formula.daysUntilDue > 1, formula.daysUntilDue + \" days\", if(formula.daysUntilDue == -1, \"1 day overdue\", formula.daysUntilDue * -1 + \" days overdue\")))))'\n daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != \"done\"'\n isDueToday: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isDueThisWeek: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")'\n isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isRecurring: 'recurrence && !recurrence.isEmpty()'\n hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - \"7d\").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n dueMonth: 'if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), \"No due date\")'\n dueWeek: 'if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), \"No due date\")'\n scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"Not scheduled\")'\n scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"Not scheduled\")'\n dueDateCategory: 'if(due.isEmpty(), \"No due date\", if(date(due) < today(), \"Overdue\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), \"This week\", \"Later\")))))'\n timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(timeEstimate < 30, \"Quick (<30m)\", if(timeEstimate <= 120, \"Medium (30m-2h)\", \"Long (>2h)\")))'\n ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, \"Today\", if(((number(now()) - number(file.ctime)) / 86400000) < 7, \"This week\", if(((number(now()) - number(file.ctime)) / 86400000) < 30, \"This month\", \"Older\")))'\n createdMonth: 'file.ctime.format(\"YYYY-MM\")'\n modifiedMonth: 'file.mtime.format(\"YYYY-MM\")'\n priorityCategory: 'if(priority==\"none\",\"None\",if(priority==\"low\",\"Low\",if(priority==\"normal\",\"Normal\",if(priority==\"high\",\"High\",\"No priority\"))))'\n projectCount: 'if(!projects || list(projects).length == 0, \"No projects\", if(list(projects).length == 1, \"Single project\", \"Multiple projects\"))'\n contextCount: 'if(!contexts || list(contexts).length == 0, \"No contexts\", if(list(contexts).length == 1, \"Single context\", \"Multiple contexts\"))'\n trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(!timeEntries || list(timeEntries).length == 0, \"Not started\", if(formula.efficiencyRatio < 100, \"Under estimate\", \"Over estimate\")))'\n nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n isToday: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"))'\n isThisWeek: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"))'\n nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), \"No date\", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), \"Overdue/Past\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")), \"Today\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")), \"Tomorrow\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")), \"This week\", \"Later\")))))'\n nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-MM\"), date(scheduled).format(\"YYYY-MM\")), if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"No date\")))'\n nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-[W]WW\"), date(scheduled).format(\"YYYY-[W]WW\")), if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"No date\")))'\n urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format(\"YYYY-MM-DD\")))) / 86400000)))'\n timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + \"h \" + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + \"m\", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + \"m\"), \"0m\")'\n dueDateDisplay: 'if(due.isEmpty(), \"\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") == (today() - \"1 day\").format(\"YYYY-MM-DD\"), \"Yesterday\", if(date(due) < today(), formula.daysUntilDue * -1 + \"d ago\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), date(due).format(\"ddd\"), date(due).format(\"MMM D\")))))))'\n\nviews:\n - type: tasknotesKanban\n name: \"Kanban Board\"\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: tasknotes_manual_order\n direction: DESC\n groupBy:\n property: status\n direction: ASC\n config:\n columnWidth: 280\n hideEmptyColumns: false\n```\n\n## tasks-default.base\n\nCommand/template ID: `open-tasks-view`\n\n```yaml\n# All Tasks\n\nfilters:\n and:\n - file.hasTag(\"task\")\n\nformulas:\n priorityWeight: 'if(priority==\"none\",0,if(priority==\"low\",1,if(priority==\"normal\",2,if(priority==\"high\",3,999))))'\n daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n dueIn: 'if(due.isEmpty(), \"\", if(formula.daysUntilDue == 0, \"Today\", if(formula.daysUntilDue == 1, \"1 day\", if(formula.daysUntilDue > 1, formula.daysUntilDue + \" days\", if(formula.daysUntilDue == -1, \"1 day overdue\", formula.daysUntilDue * -1 + \" days overdue\")))))'\n daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != \"done\"'\n isDueToday: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isDueThisWeek: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")'\n isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isRecurring: 'recurrence && !recurrence.isEmpty()'\n hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - \"7d\").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n dueMonth: 'if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), \"No due date\")'\n dueWeek: 'if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), \"No due date\")'\n scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"Not scheduled\")'\n scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"Not scheduled\")'\n dueDateCategory: 'if(due.isEmpty(), \"No due date\", if(date(due) < today(), \"Overdue\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), \"This week\", \"Later\")))))'\n timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(timeEstimate < 30, \"Quick (<30m)\", if(timeEstimate <= 120, \"Medium (30m-2h)\", \"Long (>2h)\")))'\n ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, \"Today\", if(((number(now()) - number(file.ctime)) / 86400000) < 7, \"This week\", if(((number(now()) - number(file.ctime)) / 86400000) < 30, \"This month\", \"Older\")))'\n createdMonth: 'file.ctime.format(\"YYYY-MM\")'\n modifiedMonth: 'file.mtime.format(\"YYYY-MM\")'\n priorityCategory: 'if(priority==\"none\",\"None\",if(priority==\"low\",\"Low\",if(priority==\"normal\",\"Normal\",if(priority==\"high\",\"High\",\"No priority\"))))'\n projectCount: 'if(!projects || list(projects).length == 0, \"No projects\", if(list(projects).length == 1, \"Single project\", \"Multiple projects\"))'\n contextCount: 'if(!contexts || list(contexts).length == 0, \"No contexts\", if(list(contexts).length == 1, \"Single context\", \"Multiple contexts\"))'\n trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(!timeEntries || list(timeEntries).length == 0, \"Not started\", if(formula.efficiencyRatio < 100, \"Under estimate\", \"Over estimate\")))'\n nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n isToday: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"))'\n isThisWeek: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"))'\n nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), \"No date\", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), \"Overdue/Past\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")), \"Today\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")), \"Tomorrow\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")), \"This week\", \"Later\")))))'\n nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-MM\"), date(scheduled).format(\"YYYY-MM\")), if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"No date\")))'\n nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-[W]WW\"), date(scheduled).format(\"YYYY-[W]WW\")), if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"No date\")))'\n urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format(\"YYYY-MM-DD\")))) / 86400000)))'\n timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + \"h \" + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + \"m\", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + \"m\"), \"0m\")'\n dueDateDisplay: 'if(due.isEmpty(), \"\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") == (today() - \"1 day\").format(\"YYYY-MM-DD\"), \"Yesterday\", if(date(due) < today(), formula.daysUntilDue * -1 + \"d ago\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), date(due).format(\"ddd\"), date(due).format(\"MMM D\")))))))'\n\nviews:\n - type: tasknotesTaskList\n name: \"Manual Order\"\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: tasknotes_manual_order\n direction: DESC\n groupBy:\n property: status\n direction: ASC\n - type: tasknotesTaskList\n name: \"All Tasks\"\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: due\n direction: ASC\n - type: tasknotesTaskList\n name: \"Not Blocked\"\n filters:\n and:\n # Incomplete tasks\n - or:\n # Non-recurring task that's not in any completed status\n - and:\n - recurrence.isEmpty()\n - status != \"done\"\n # Recurring task where today is not in complete_instances\n - and:\n - recurrence.isEmpty() == false\n - complete_instances.map(date(value).format(\"YYYY-MM-DD\")).contains(today().format(\"YYYY-MM-DD\")) != true\n # Not blocked by any incomplete tasks\n - or:\n # No blocking dependencies at all\n - blockedBy.isEmpty()\n # All blocking tasks are completed (filter returns only incomplete, then check if empty)\n - 'list(blockedBy).filter(file(if(value.isType(\"object\"), value.uid, value)).properties.status != \"done\").isEmpty()'\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: formula.urgencyScore\n direction: DESC\n - type: tasknotesTaskList\n name: \"Today\"\n filters:\n and:\n # Incomplete tasks (handles both recurring and non-recurring)\n - or:\n # Non-recurring task that's not in any completed status\n - and:\n - recurrence.isEmpty()\n - status != \"done\"\n # Recurring task where today is not in complete_instances\n - and:\n - recurrence.isEmpty() == false\n - complete_instances.map(date(value).format(\"YYYY-MM-DD\")).contains(today().format(\"YYYY-MM-DD\")) != true\n # Due or scheduled today\n - or:\n - and:\n - due.isEmpty() == false\n - date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")\n - and:\n - scheduled.isEmpty() == false\n - date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: formula.urgencyScore\n direction: DESC\n - type: tasknotesTaskList\n name: \"Overdue\"\n filters:\n and:\n # Incomplete tasks\n - or:\n # Non-recurring task that's not in any completed status\n - and:\n - recurrence.isEmpty()\n - status != \"done\"\n # Recurring task where today is not in complete_instances\n - and:\n - recurrence.isEmpty() == false\n - complete_instances.map(date(value).format(\"YYYY-MM-DD\")).contains(today().format(\"YYYY-MM-DD\")) != true\n # Due or scheduled in the past\n - or:\n - and:\n - due.isEmpty() == false\n - date(due) < today()\n - and:\n - scheduled.isEmpty() == false\n - date(scheduled) < today()\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: formula.urgencyScore\n direction: DESC\n - type: tasknotesTaskList\n name: \"This Week\"\n filters:\n and:\n # Incomplete tasks\n - or:\n # Non-recurring task that's not in any completed status\n - and:\n - recurrence.isEmpty()\n - status != \"done\"\n # Recurring task where today is not in complete_instances\n - and:\n - recurrence.isEmpty() == false\n - complete_instances.map(date(value).format(\"YYYY-MM-DD\")).contains(today().format(\"YYYY-MM-DD\")) != true\n # Due or scheduled this week\n - or:\n - and:\n - due.isEmpty() == false\n - date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\")\n - date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")\n - and:\n - scheduled.isEmpty() == false\n - date(scheduled).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\")\n - date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: formula.urgencyScore\n direction: DESC\n - type: tasknotesTaskList\n name: \"Unscheduled\"\n filters:\n and:\n # Incomplete tasks\n - or:\n # Non-recurring task that's not in any completed status\n - and:\n - recurrence.isEmpty()\n - status != \"done\"\n # Recurring task where today is not in complete_instances\n - and:\n - recurrence.isEmpty() == false\n - complete_instances.map(date(value).format(\"YYYY-MM-DD\")).contains(today().format(\"YYYY-MM-DD\")) != true\n # No due date and no scheduled date\n - date(due).isEmpty()\n - date(scheduled).isEmpty()\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: status\n direction: ASC\n```\n\n## calendar-default.base\n\nCommand/template ID: `open-advanced-calendar-view`\n\n```yaml\n# Calendar\n\nfilters:\n and:\n - file.hasTag(\"task\")\n\nformulas:\n priorityWeight: 'if(priority==\"none\",0,if(priority==\"low\",1,if(priority==\"normal\",2,if(priority==\"high\",3,999))))'\n daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n dueIn: 'if(due.isEmpty(), \"\", if(formula.daysUntilDue == 0, \"Today\", if(formula.daysUntilDue == 1, \"1 day\", if(formula.daysUntilDue > 1, formula.daysUntilDue + \" days\", if(formula.daysUntilDue == -1, \"1 day overdue\", formula.daysUntilDue * -1 + \" days overdue\")))))'\n daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != \"done\"'\n isDueToday: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isDueThisWeek: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")'\n isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isRecurring: 'recurrence && !recurrence.isEmpty()'\n hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - \"7d\").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n dueMonth: 'if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), \"No due date\")'\n dueWeek: 'if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), \"No due date\")'\n scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"Not scheduled\")'\n scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"Not scheduled\")'\n dueDateCategory: 'if(due.isEmpty(), \"No due date\", if(date(due) < today(), \"Overdue\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), \"This week\", \"Later\")))))'\n timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(timeEstimate < 30, \"Quick (<30m)\", if(timeEstimate <= 120, \"Medium (30m-2h)\", \"Long (>2h)\")))'\n ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, \"Today\", if(((number(now()) - number(file.ctime)) / 86400000) < 7, \"This week\", if(((number(now()) - number(file.ctime)) / 86400000) < 30, \"This month\", \"Older\")))'\n createdMonth: 'file.ctime.format(\"YYYY-MM\")'\n modifiedMonth: 'file.mtime.format(\"YYYY-MM\")'\n priorityCategory: 'if(priority==\"none\",\"None\",if(priority==\"low\",\"Low\",if(priority==\"normal\",\"Normal\",if(priority==\"high\",\"High\",\"No priority\"))))'\n projectCount: 'if(!projects || list(projects).length == 0, \"No projects\", if(list(projects).length == 1, \"Single project\", \"Multiple projects\"))'\n contextCount: 'if(!contexts || list(contexts).length == 0, \"No contexts\", if(list(contexts).length == 1, \"Single context\", \"Multiple contexts\"))'\n trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(!timeEntries || list(timeEntries).length == 0, \"Not started\", if(formula.efficiencyRatio < 100, \"Under estimate\", \"Over estimate\")))'\n nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n isToday: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"))'\n isThisWeek: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"))'\n nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), \"No date\", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), \"Overdue/Past\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")), \"Today\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")), \"Tomorrow\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")), \"This week\", \"Later\")))))'\n nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-MM\"), date(scheduled).format(\"YYYY-MM\")), if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"No date\")))'\n nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-[W]WW\"), date(scheduled).format(\"YYYY-[W]WW\")), if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"No date\")))'\n urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format(\"YYYY-MM-DD\")))) / 86400000)))'\n timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + \"h \" + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + \"m\", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + \"m\"), \"0m\")'\n dueDateDisplay: 'if(due.isEmpty(), \"\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") == (today() - \"1 day\").format(\"YYYY-MM-DD\"), \"Yesterday\", if(date(due) < today(), formula.daysUntilDue * -1 + \"d ago\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), date(due).format(\"ddd\"), date(due).format(\"MMM D\")))))))'\n\nviews:\n - type: tasknotesCalendar\n name: \"Calendar\"\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n options:\n showScheduled: true\n showDue: true\n showRecurring: true\n showTimeEntries: true\n showTimeblocks: true\n showPropertyBasedEvents: true\n createDailyNotesFromDateLinks: true\n calendarView: \"timeGridWeek\"\n customDayCount: 3\n firstDay: 1\n```\n\n## agenda-default.base\n\nCommand/template ID: `open-agenda-view`\n\n```yaml\n# Agenda\n\nfilters:\n and:\n - file.hasTag(\"task\")\n\nformulas:\n priorityWeight: 'if(priority==\"none\",0,if(priority==\"low\",1,if(priority==\"normal\",2,if(priority==\"high\",3,999))))'\n daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n dueIn: 'if(due.isEmpty(), \"\", if(formula.daysUntilDue == 0, \"Today\", if(formula.daysUntilDue == 1, \"1 day\", if(formula.daysUntilDue > 1, formula.daysUntilDue + \" days\", if(formula.daysUntilDue == -1, \"1 day overdue\", formula.daysUntilDue * -1 + \" days overdue\")))))'\n daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != \"done\"'\n isDueToday: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isDueThisWeek: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")'\n isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isRecurring: 'recurrence && !recurrence.isEmpty()'\n hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - \"7d\").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n dueMonth: 'if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), \"No due date\")'\n dueWeek: 'if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), \"No due date\")'\n scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"Not scheduled\")'\n scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"Not scheduled\")'\n dueDateCategory: 'if(due.isEmpty(), \"No due date\", if(date(due) < today(), \"Overdue\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), \"This week\", \"Later\")))))'\n timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(timeEstimate < 30, \"Quick (<30m)\", if(timeEstimate <= 120, \"Medium (30m-2h)\", \"Long (>2h)\")))'\n ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, \"Today\", if(((number(now()) - number(file.ctime)) / 86400000) < 7, \"This week\", if(((number(now()) - number(file.ctime)) / 86400000) < 30, \"This month\", \"Older\")))'\n createdMonth: 'file.ctime.format(\"YYYY-MM\")'\n modifiedMonth: 'file.mtime.format(\"YYYY-MM\")'\n priorityCategory: 'if(priority==\"none\",\"None\",if(priority==\"low\",\"Low\",if(priority==\"normal\",\"Normal\",if(priority==\"high\",\"High\",\"No priority\"))))'\n projectCount: 'if(!projects || list(projects).length == 0, \"No projects\", if(list(projects).length == 1, \"Single project\", \"Multiple projects\"))'\n contextCount: 'if(!contexts || list(contexts).length == 0, \"No contexts\", if(list(contexts).length == 1, \"Single context\", \"Multiple contexts\"))'\n trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(!timeEntries || list(timeEntries).length == 0, \"Not started\", if(formula.efficiencyRatio < 100, \"Under estimate\", \"Over estimate\")))'\n nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n isToday: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"))'\n isThisWeek: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"))'\n nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), \"No date\", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), \"Overdue/Past\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")), \"Today\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")), \"Tomorrow\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")), \"This week\", \"Later\")))))'\n nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-MM\"), date(scheduled).format(\"YYYY-MM\")), if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"No date\")))'\n nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-[W]WW\"), date(scheduled).format(\"YYYY-[W]WW\")), if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"No date\")))'\n urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format(\"YYYY-MM-DD\")))) / 86400000)))'\n timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + \"h \" + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + \"m\", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + \"m\"), \"0m\")'\n dueDateDisplay: 'if(due.isEmpty(), \"\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") == (today() - \"1 day\").format(\"YYYY-MM-DD\"), \"Yesterday\", if(date(due) < today(), formula.daysUntilDue * -1 + \"d ago\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), date(due).format(\"ddd\"), date(due).format(\"MMM D\")))))))'\n\nproperties:\n formula.dueIn:\n displayName: Due in\n\n\nviews:\n - type: tasknotesCalendar\n name: \"Agenda\"\n order:\n - status\n - priority\n - due\n - formula.dueIn\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n options:\n showPropertyBasedEvents: false\n showOverdueOnToday: true\n createDailyNotesFromDateLinks: true\n calendarView: \"listWeek\"\n startDateProperty: file.ctime\n listDayCount: 7\n titleProperty: file.basename\n```\n\n## pomodoro-stats.base\n\nCommand/template ID: `pomodoro-stats-base`\n\n```yaml\n# Pomodoro statistics\n# Generated with your TaskNotes settings\n# Requires Pomodoro data storage to be set to Daily notes.\n\nfilters:\n and:\n - file.hasProperty(\"pomodoros\")\n - list(note[\"pomodoros\"]).filter(value.startTime).isEmpty() == false\n\nformulas:\n pomodoroDate: 'if(note[\"pomodoros\"], list(note[\"pomodoros\"]).filter(value.startTime).map(date(value.startTime).format(\"YYYY-MM-DD\")).unique().join(\", \"), file.basename)'\n pomodoroMonth: 'if(note[\"pomodoros\"], list(note[\"pomodoros\"]).filter(value.startTime).map(date(value.startTime).format(\"YYYY-MM\")).unique().join(\", \"), \"\")'\n completedPomos: 'if(note[\"pomodoros\"], list(note[\"pomodoros\"]).filter(value.type == \"work\" && value.completed == true).length, 0)'\n attemptedPomos: 'if(note[\"pomodoros\"], list(note[\"pomodoros\"]).filter(value.type == \"work\").length, 0)'\n interruptedPomos: 'if(note[\"pomodoros\"], list(note[\"pomodoros\"]).filter(value.type == \"work\" && value.completed == false).length, 0)'\n focusMinutes: 'if(note[\"pomodoros\"], list(note[\"pomodoros\"]).filter(value.type == \"work\" && value.completed == true).map(if(value.plannedDuration && value.plannedDuration > 0, value.plannedDuration, if(value.startTime && value.endTime, ((number(date(value.endTime)) - number(date(value.startTime))) / 60000).round(), 0))).reduce(acc + value, 0).round(), 0)'\n focusTime: 'if(formula.focusMinutes >= 60, (formula.focusMinutes / 60).floor() + \"h \" + (formula.focusMinutes % 60).round() + \"m\", formula.focusMinutes + \"m\")'\n completionRate: 'if(formula.attemptedPomos > 0, (formula.completedPomos / formula.attemptedPomos * 100).round() + \"%\", \"0%\")'\n shortBreaks: 'if(note[\"pomodoros\"], list(note[\"pomodoros\"]).filter(value.type == \"short-break\").length, 0)'\n longBreaks: 'if(note[\"pomodoros\"], list(note[\"pomodoros\"]).filter(value.type == \"long-break\").length, 0)'\n\nproperties:\n formula.pomodoroDate:\n displayName: Date\n formula.pomodoroMonth:\n displayName: Month\n formula.completedPomos:\n displayName: Completed\n formula.attemptedPomos:\n displayName: Attempted\n formula.interruptedPomos:\n displayName: Interrupted\n formula.focusMinutes:\n displayName: Focus minutes\n formula.focusTime:\n displayName: Focus time\n formula.completionRate:\n displayName: Completion\n formula.shortBreaks:\n displayName: Short breaks\n formula.longBreaks:\n displayName: Long breaks\n\nviews:\n - type: table\n name: \"Daily\"\n order:\n - formula.pomodoroDate\n - formula.completedPomos\n - formula.focusTime\n - formula.attemptedPomos\n - formula.completionRate\n - formula.interruptedPomos\n - formula.shortBreaks\n - formula.longBreaks\n - file.name\n sort:\n - column: formula.pomodoroDate\n direction: DESC\n - type: table\n name: \"Monthly\"\n groupBy:\n property: formula.pomodoroMonth\n direction: DESC\n order:\n - formula.pomodoroDate\n - formula.completedPomos\n - formula.focusMinutes\n - formula.focusTime\n - formula.attemptedPomos\n - formula.completionRate\n - formula.interruptedPomos\n - formula.shortBreaks\n - formula.longBreaks\n - file.name\n summaries:\n formula.completedPomos: Sum\n formula.focusMinutes: Sum\n formula.attemptedPomos: Sum\n formula.interruptedPomos: Sum\n formula.shortBreaks: Sum\n formula.longBreaks: Sum\n sort:\n - column: formula.pomodoroDate\n direction: DESC\n```\n\n## relationships.base\n\nCommand/template ID: `relationships`\n\n```yaml\n# Relationships\n# This view shows all relationships for the current file\n# Dynamically shows/hides tabs based on available data\n\nformulas:\n priorityWeight: 'if(priority==\"none\",0,if(priority==\"low\",1,if(priority==\"normal\",2,if(priority==\"high\",3,999))))'\n daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n dueIn: 'if(due.isEmpty(), \"\", if(formula.daysUntilDue == 0, \"Today\", if(formula.daysUntilDue == 1, \"1 day\", if(formula.daysUntilDue > 1, formula.daysUntilDue + \" days\", if(formula.daysUntilDue == -1, \"1 day overdue\", formula.daysUntilDue * -1 + \" days overdue\")))))'\n daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != \"done\"'\n isDueToday: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isDueThisWeek: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")'\n isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")'\n isRecurring: 'recurrence && !recurrence.isEmpty()'\n hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - \"7d\").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n dueMonth: 'if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), \"No due date\")'\n dueWeek: 'if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), \"No due date\")'\n scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"Not scheduled\")'\n scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"Not scheduled\")'\n dueDateCategory: 'if(due.isEmpty(), \"No due date\", if(date(due) < today(), \"Overdue\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), \"This week\", \"Later\")))))'\n timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(timeEstimate < 30, \"Quick (<30m)\", if(timeEstimate <= 120, \"Medium (30m-2h)\", \"Long (>2h)\")))'\n ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, \"Today\", if(((number(now()) - number(file.ctime)) / 86400000) < 7, \"This week\", if(((number(now()) - number(file.ctime)) / 86400000) < 30, \"This month\", \"Older\")))'\n createdMonth: 'file.ctime.format(\"YYYY-MM\")'\n modifiedMonth: 'file.mtime.format(\"YYYY-MM\")'\n priorityCategory: 'if(priority==\"none\",\"None\",if(priority==\"low\",\"Low\",if(priority==\"normal\",\"Normal\",if(priority==\"high\",\"High\",\"No priority\"))))'\n projectCount: 'if(!projects || list(projects).length == 0, \"No projects\", if(list(projects).length == 1, \"Single project\", \"Multiple projects\"))'\n contextCount: 'if(!contexts || list(contexts).length == 0, \"No contexts\", if(list(contexts).length == 1, \"Single context\", \"Multiple contexts\"))'\n trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(!timeEntries || list(timeEntries).length == 0, \"Not started\", if(formula.efficiencyRatio < 100, \"Under estimate\", \"Over estimate\")))'\n nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n isToday: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"))'\n isThisWeek: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"))'\n nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), \"No date\", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), \"Overdue/Past\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")), \"Today\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")), \"Tomorrow\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")), \"This week\", \"Later\")))))'\n nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-MM\"), date(scheduled).format(\"YYYY-MM\")), if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"No date\")))'\n nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-[W]WW\"), date(scheduled).format(\"YYYY-[W]WW\")), if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"No date\")))'\n urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format(\"YYYY-MM-DD\")))) / 86400000)))'\n timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + \"h \" + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + \"m\", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + \"m\"), \"0m\")'\n dueDateDisplay: 'if(due.isEmpty(), \"\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") == (today() - \"1 day\").format(\"YYYY-MM-DD\"), \"Yesterday\", if(date(due) < today(), formula.daysUntilDue * -1 + \"d ago\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), date(due).format(\"ddd\"), date(due).format(\"MMM D\")))))))'\n\nviews:\n - type: tasknotesKanban\n name: \"Subtasks\"\n filters:\n and:\n - file.hasTag(\"task\")\n - file.hasLink(this.file) && list(note.projects).map(file(value.replace(/^\\[[^\\]]+\\]\\((.*)\\)$/, \"$1\").replace(/%20/g, \" \")).asLink()).contains(this.file.asLink())\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: tasknotes_manual_order\n direction: DESC\n groupBy:\n property: status\n direction: ASC\n - type: tasknotesTaskList\n name: \"Occurrences\"\n filters:\n and:\n - file.hasTag(\"task\")\n - file.hasLink(this.file) && note.recurrence_parent && file(note.recurrence_parent.replace(/^\\[[^\\]]+\\]\\((.*)\\)$/, \"$1\").replace(/%20/g, \" \")).asLink() == this.file.asLink()\n order:\n - status\n - priority\n - due\n - scheduled\n - occurrence_date\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: occurrence_date\n direction: ASC\n - type: tasknotesTaskList\n name: \"Projects\"\n filters:\n and:\n - list(this.projects).map(file(value.replace(/^\\[[^\\]]+\\]\\((.*)\\)$/, \"$1\").replace(/%20/g, \" \")).asLink()).contains(file.asLink())\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n - type: tasknotesTaskList\n name: \"Blocked By\"\n filters:\n and:\n - file.hasTag(\"task\")\n - list(this.note.blockedBy).map(file(if(value.isType(\"object\"), value.uid, value)).asLink()).contains(file.asLink())\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: tasknotes_manual_order\n direction: DESC\n - type: tasknotesKanban\n name: \"Blocking\"\n filters:\n and:\n - file.hasTag(\"task\")\n - list(note.blockedBy).map(file(if(value.isType(\"object\"), value.uid, value)).asLink()).contains(this.file.asLink())\n order:\n - status\n - priority\n - due\n - scheduled\n - projects\n - contexts\n - file.tags\n - blockedBy\n - file.name\n - recurrence\n - complete_instances\n - file.tasks\n sort:\n - column: tasknotes_manual_order\n direction: DESC\n groupBy:\n property: status\n direction: ASC\n```\n","aliases":["/reference/default-base-templates/","/reference/default-base-templates/"],"toc":[{"level":2,"id":"mini-calendar-defaultbase","text":"mini-calendar-default.base"},{"level":2,"id":"kanban-defaultbase","text":"kanban-default.base"},{"level":2,"id":"tasks-defaultbase","text":"tasks-default.base"},{"level":2,"id":"calendar-defaultbase","text":"calendar-default.base"},{"level":2,"id":"agenda-defaultbase","text":"agenda-default.base"},{"level":2,"id":"pomodoro-statsbase","text":"pomodoro-stats.base"},{"level":2,"id":"relationshipsbase","text":"relationships.base"}],"html":"

These are the exact templates TaskNotes 4.13.0 produces with default settings. Your generated files reflect your own field mapping and other settings, so customized output can differ.

\n

Regenerating with Update files overwrites configured default Base files. Copy a customized file to a new path before updating it.

\n

mini-calendar-default.base#

\n

Command/template ID: open-calendar-view

\n
# Mini Calendar\n# Generated with your TaskNotes settings\n\nfilters:\n  and:\n    - file.hasTag("task")\n\nformulas:\n  priorityWeight: 'if(priority=="none",0,if(priority=="low",1,if(priority=="normal",2,if(priority=="high",3,999))))'\n  daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n  dueIn: 'if(due.isEmpty(), "", if(formula.daysUntilDue == 0, "Today", if(formula.daysUntilDue == 1, "1 day", if(formula.daysUntilDue > 1, formula.daysUntilDue + " days", if(formula.daysUntilDue == -1, "1 day overdue", formula.daysUntilDue * -1 + " days overdue")))))'\n  daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n  daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n  daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n  isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != "done"'\n  isDueToday: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isDueThisWeek: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")'\n  isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isRecurring: 'recurrence && !recurrence.isEmpty()'\n  hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n  timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n  efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n  timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - "7d").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  dueMonth: 'if((due.isEmpty() == false), date(due).format("YYYY-MM"), "No due date")'\n  dueWeek: 'if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), "No due date")'\n  scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "Not scheduled")'\n  scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "Not scheduled")'\n  dueDateCategory: 'if(due.isEmpty(), "No due date", if(date(due) < today(), "Overdue", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), "This week", "Later")))))'\n  timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(timeEstimate < 30, "Quick (<30m)", if(timeEstimate <= 120, "Medium (30m-2h)", "Long (>2h)")))'\n  ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, "Today", if(((number(now()) - number(file.ctime)) / 86400000) < 7, "This week", if(((number(now()) - number(file.ctime)) / 86400000) < 30, "This month", "Older")))'\n  createdMonth: 'file.ctime.format("YYYY-MM")'\n  modifiedMonth: 'file.mtime.format("YYYY-MM")'\n  priorityCategory: 'if(priority=="none","None",if(priority=="low","Low",if(priority=="normal","Normal",if(priority=="high","High","No priority"))))'\n  projectCount: 'if(!projects || list(projects).length == 0, "No projects", if(list(projects).length == 1, "Single project", "Multiple projects"))'\n  contextCount: 'if(!contexts || list(contexts).length == 0, "No contexts", if(list(contexts).length == 1, "Single context", "Multiple contexts"))'\n  trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(!timeEntries || list(timeEntries).length == 0, "Not started", if(formula.efficiencyRatio < 100, "Under estimate", "Over estimate")))'\n  nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n  daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n  hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n  isToday: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"))'\n  isThisWeek: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"))'\n  nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), "No date", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), "Overdue/Past", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")), "Today", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")), "Tomorrow", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")), "This week", "Later")))))'\n  nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-MM"), date(scheduled).format("YYYY-MM")), if((due.isEmpty() == false), date(due).format("YYYY-MM"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "No date")))'\n  nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-[W]WW"), date(scheduled).format("YYYY-[W]WW")), if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "No date")))'\n  urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format("YYYY-MM-DD")))) / 86400000)))'\n  timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + "h " + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + "m", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + "m"), "0m")'\n  dueDateDisplay: 'if(due.isEmpty(), "", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") == (today() - "1 day").format("YYYY-MM-DD"), "Yesterday", if(date(due) < today(), formula.daysUntilDue * -1 + "d ago", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), date(due).format("ddd"), date(due).format("MMM D")))))))'\n\nviews:\n  - type: tasknotesMiniCalendar\n    name: "Due"\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - property: due\n        direction: ASC\n    dateProperty: due\n  - type: tasknotesMiniCalendar\n    name: "Scheduled"\n    order: []\n    dateProperty: scheduled\n  - type: tasknotesMiniCalendar\n    name: "Created"\n    dateProperty: file.ctime\n  - type: tasknotesMiniCalendar\n    name: "Modified"\n    dateProperty: file.mtime\n

kanban-default.base#

\n

Command/template ID: open-kanban-view

\n
# Kanban Board\n\nfilters:\n  and:\n    - file.hasTag("task")\n\nformulas:\n  priorityWeight: 'if(priority=="none",0,if(priority=="low",1,if(priority=="normal",2,if(priority=="high",3,999))))'\n  daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n  dueIn: 'if(due.isEmpty(), "", if(formula.daysUntilDue == 0, "Today", if(formula.daysUntilDue == 1, "1 day", if(formula.daysUntilDue > 1, formula.daysUntilDue + " days", if(formula.daysUntilDue == -1, "1 day overdue", formula.daysUntilDue * -1 + " days overdue")))))'\n  daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n  daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n  daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n  isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != "done"'\n  isDueToday: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isDueThisWeek: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")'\n  isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isRecurring: 'recurrence && !recurrence.isEmpty()'\n  hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n  timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n  efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n  timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - "7d").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  dueMonth: 'if((due.isEmpty() == false), date(due).format("YYYY-MM"), "No due date")'\n  dueWeek: 'if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), "No due date")'\n  scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "Not scheduled")'\n  scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "Not scheduled")'\n  dueDateCategory: 'if(due.isEmpty(), "No due date", if(date(due) < today(), "Overdue", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), "This week", "Later")))))'\n  timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(timeEstimate < 30, "Quick (<30m)", if(timeEstimate <= 120, "Medium (30m-2h)", "Long (>2h)")))'\n  ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, "Today", if(((number(now()) - number(file.ctime)) / 86400000) < 7, "This week", if(((number(now()) - number(file.ctime)) / 86400000) < 30, "This month", "Older")))'\n  createdMonth: 'file.ctime.format("YYYY-MM")'\n  modifiedMonth: 'file.mtime.format("YYYY-MM")'\n  priorityCategory: 'if(priority=="none","None",if(priority=="low","Low",if(priority=="normal","Normal",if(priority=="high","High","No priority"))))'\n  projectCount: 'if(!projects || list(projects).length == 0, "No projects", if(list(projects).length == 1, "Single project", "Multiple projects"))'\n  contextCount: 'if(!contexts || list(contexts).length == 0, "No contexts", if(list(contexts).length == 1, "Single context", "Multiple contexts"))'\n  trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(!timeEntries || list(timeEntries).length == 0, "Not started", if(formula.efficiencyRatio < 100, "Under estimate", "Over estimate")))'\n  nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n  daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n  hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n  isToday: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"))'\n  isThisWeek: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"))'\n  nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), "No date", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), "Overdue/Past", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")), "Today", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")), "Tomorrow", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")), "This week", "Later")))))'\n  nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-MM"), date(scheduled).format("YYYY-MM")), if((due.isEmpty() == false), date(due).format("YYYY-MM"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "No date")))'\n  nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-[W]WW"), date(scheduled).format("YYYY-[W]WW")), if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "No date")))'\n  urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format("YYYY-MM-DD")))) / 86400000)))'\n  timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + "h " + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + "m", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + "m"), "0m")'\n  dueDateDisplay: 'if(due.isEmpty(), "", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") == (today() - "1 day").format("YYYY-MM-DD"), "Yesterday", if(date(due) < today(), formula.daysUntilDue * -1 + "d ago", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), date(due).format("ddd"), date(due).format("MMM D")))))))'\n\nviews:\n  - type: tasknotesKanban\n    name: "Kanban Board"\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: tasknotes_manual_order\n        direction: DESC\n    groupBy:\n      property: status\n      direction: ASC\n    config:\n      columnWidth: 280\n      hideEmptyColumns: false\n

tasks-default.base#

\n

Command/template ID: open-tasks-view

\n
# All Tasks\n\nfilters:\n  and:\n    - file.hasTag("task")\n\nformulas:\n  priorityWeight: 'if(priority=="none",0,if(priority=="low",1,if(priority=="normal",2,if(priority=="high",3,999))))'\n  daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n  dueIn: 'if(due.isEmpty(), "", if(formula.daysUntilDue == 0, "Today", if(formula.daysUntilDue == 1, "1 day", if(formula.daysUntilDue > 1, formula.daysUntilDue + " days", if(formula.daysUntilDue == -1, "1 day overdue", formula.daysUntilDue * -1 + " days overdue")))))'\n  daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n  daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n  daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n  isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != "done"'\n  isDueToday: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isDueThisWeek: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")'\n  isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isRecurring: 'recurrence && !recurrence.isEmpty()'\n  hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n  timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n  efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n  timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - "7d").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  dueMonth: 'if((due.isEmpty() == false), date(due).format("YYYY-MM"), "No due date")'\n  dueWeek: 'if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), "No due date")'\n  scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "Not scheduled")'\n  scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "Not scheduled")'\n  dueDateCategory: 'if(due.isEmpty(), "No due date", if(date(due) < today(), "Overdue", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), "This week", "Later")))))'\n  timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(timeEstimate < 30, "Quick (<30m)", if(timeEstimate <= 120, "Medium (30m-2h)", "Long (>2h)")))'\n  ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, "Today", if(((number(now()) - number(file.ctime)) / 86400000) < 7, "This week", if(((number(now()) - number(file.ctime)) / 86400000) < 30, "This month", "Older")))'\n  createdMonth: 'file.ctime.format("YYYY-MM")'\n  modifiedMonth: 'file.mtime.format("YYYY-MM")'\n  priorityCategory: 'if(priority=="none","None",if(priority=="low","Low",if(priority=="normal","Normal",if(priority=="high","High","No priority"))))'\n  projectCount: 'if(!projects || list(projects).length == 0, "No projects", if(list(projects).length == 1, "Single project", "Multiple projects"))'\n  contextCount: 'if(!contexts || list(contexts).length == 0, "No contexts", if(list(contexts).length == 1, "Single context", "Multiple contexts"))'\n  trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(!timeEntries || list(timeEntries).length == 0, "Not started", if(formula.efficiencyRatio < 100, "Under estimate", "Over estimate")))'\n  nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n  daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n  hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n  isToday: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"))'\n  isThisWeek: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"))'\n  nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), "No date", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), "Overdue/Past", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")), "Today", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")), "Tomorrow", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")), "This week", "Later")))))'\n  nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-MM"), date(scheduled).format("YYYY-MM")), if((due.isEmpty() == false), date(due).format("YYYY-MM"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "No date")))'\n  nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-[W]WW"), date(scheduled).format("YYYY-[W]WW")), if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "No date")))'\n  urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format("YYYY-MM-DD")))) / 86400000)))'\n  timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + "h " + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + "m", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + "m"), "0m")'\n  dueDateDisplay: 'if(due.isEmpty(), "", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") == (today() - "1 day").format("YYYY-MM-DD"), "Yesterday", if(date(due) < today(), formula.daysUntilDue * -1 + "d ago", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), date(due).format("ddd"), date(due).format("MMM D")))))))'\n\nviews:\n  - type: tasknotesTaskList\n    name: "Manual Order"\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: tasknotes_manual_order\n        direction: DESC\n    groupBy:\n      property: status\n      direction: ASC\n  - type: tasknotesTaskList\n    name: "All Tasks"\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: due\n        direction: ASC\n  - type: tasknotesTaskList\n    name: "Not Blocked"\n    filters:\n      and:\n        # Incomplete tasks\n        - or:\n          # Non-recurring task that's not in any completed status\n          - and:\n            - recurrence.isEmpty()\n            - status != "done"\n          # Recurring task where today is not in complete_instances\n          - and:\n            - recurrence.isEmpty() == false\n            - complete_instances.map(date(value).format("YYYY-MM-DD")).contains(today().format("YYYY-MM-DD")) != true\n        # Not blocked by any incomplete tasks\n        - or:\n          # No blocking dependencies at all\n          - blockedBy.isEmpty()\n          # All blocking tasks are completed (filter returns only incomplete, then check if empty)\n          - 'list(blockedBy).filter(file(if(value.isType("object"), value.uid, value)).properties.status != "done").isEmpty()'\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: formula.urgencyScore\n        direction: DESC\n  - type: tasknotesTaskList\n    name: "Today"\n    filters:\n      and:\n        # Incomplete tasks (handles both recurring and non-recurring)\n        - or:\n          # Non-recurring task that's not in any completed status\n          - and:\n            - recurrence.isEmpty()\n            - status != "done"\n          # Recurring task where today is not in complete_instances\n          - and:\n            - recurrence.isEmpty() == false\n            - complete_instances.map(date(value).format("YYYY-MM-DD")).contains(today().format("YYYY-MM-DD")) != true\n        # Due or scheduled today\n        - or:\n          - and:\n            - due.isEmpty() == false\n            - date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")\n          - and:\n            - scheduled.isEmpty() == false\n            - date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: formula.urgencyScore\n        direction: DESC\n  - type: tasknotesTaskList\n    name: "Overdue"\n    filters:\n      and:\n        # Incomplete tasks\n        - or:\n          # Non-recurring task that's not in any completed status\n          - and:\n            - recurrence.isEmpty()\n            - status != "done"\n          # Recurring task where today is not in complete_instances\n          - and:\n            - recurrence.isEmpty() == false\n            - complete_instances.map(date(value).format("YYYY-MM-DD")).contains(today().format("YYYY-MM-DD")) != true\n        # Due or scheduled in the past\n        - or:\n          - and:\n            - due.isEmpty() == false\n            - date(due) < today()\n          - and:\n            - scheduled.isEmpty() == false\n            - date(scheduled) < today()\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: formula.urgencyScore\n        direction: DESC\n  - type: tasknotesTaskList\n    name: "This Week"\n    filters:\n      and:\n        # Incomplete tasks\n        - or:\n          # Non-recurring task that's not in any completed status\n          - and:\n            - recurrence.isEmpty()\n            - status != "done"\n          # Recurring task where today is not in complete_instances\n          - and:\n            - recurrence.isEmpty() == false\n            - complete_instances.map(date(value).format("YYYY-MM-DD")).contains(today().format("YYYY-MM-DD")) != true\n        # Due or scheduled this week\n        - or:\n          - and:\n            - due.isEmpty() == false\n            - date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD")\n            - date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")\n          - and:\n            - scheduled.isEmpty() == false\n            - date(scheduled).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD")\n            - date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: formula.urgencyScore\n        direction: DESC\n  - type: tasknotesTaskList\n    name: "Unscheduled"\n    filters:\n      and:\n        # Incomplete tasks\n        - or:\n          # Non-recurring task that's not in any completed status\n          - and:\n            - recurrence.isEmpty()\n            - status != "done"\n          # Recurring task where today is not in complete_instances\n          - and:\n            - recurrence.isEmpty() == false\n            - complete_instances.map(date(value).format("YYYY-MM-DD")).contains(today().format("YYYY-MM-DD")) != true\n        # No due date and no scheduled date\n        - date(due).isEmpty()\n        - date(scheduled).isEmpty()\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: status\n        direction: ASC\n

calendar-default.base#

\n

Command/template ID: open-advanced-calendar-view

\n
# Calendar\n\nfilters:\n  and:\n    - file.hasTag("task")\n\nformulas:\n  priorityWeight: 'if(priority=="none",0,if(priority=="low",1,if(priority=="normal",2,if(priority=="high",3,999))))'\n  daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n  dueIn: 'if(due.isEmpty(), "", if(formula.daysUntilDue == 0, "Today", if(formula.daysUntilDue == 1, "1 day", if(formula.daysUntilDue > 1, formula.daysUntilDue + " days", if(formula.daysUntilDue == -1, "1 day overdue", formula.daysUntilDue * -1 + " days overdue")))))'\n  daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n  daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n  daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n  isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != "done"'\n  isDueToday: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isDueThisWeek: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")'\n  isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isRecurring: 'recurrence && !recurrence.isEmpty()'\n  hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n  timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n  efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n  timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - "7d").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  dueMonth: 'if((due.isEmpty() == false), date(due).format("YYYY-MM"), "No due date")'\n  dueWeek: 'if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), "No due date")'\n  scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "Not scheduled")'\n  scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "Not scheduled")'\n  dueDateCategory: 'if(due.isEmpty(), "No due date", if(date(due) < today(), "Overdue", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), "This week", "Later")))))'\n  timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(timeEstimate < 30, "Quick (<30m)", if(timeEstimate <= 120, "Medium (30m-2h)", "Long (>2h)")))'\n  ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, "Today", if(((number(now()) - number(file.ctime)) / 86400000) < 7, "This week", if(((number(now()) - number(file.ctime)) / 86400000) < 30, "This month", "Older")))'\n  createdMonth: 'file.ctime.format("YYYY-MM")'\n  modifiedMonth: 'file.mtime.format("YYYY-MM")'\n  priorityCategory: 'if(priority=="none","None",if(priority=="low","Low",if(priority=="normal","Normal",if(priority=="high","High","No priority"))))'\n  projectCount: 'if(!projects || list(projects).length == 0, "No projects", if(list(projects).length == 1, "Single project", "Multiple projects"))'\n  contextCount: 'if(!contexts || list(contexts).length == 0, "No contexts", if(list(contexts).length == 1, "Single context", "Multiple contexts"))'\n  trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(!timeEntries || list(timeEntries).length == 0, "Not started", if(formula.efficiencyRatio < 100, "Under estimate", "Over estimate")))'\n  nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n  daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n  hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n  isToday: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"))'\n  isThisWeek: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"))'\n  nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), "No date", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), "Overdue/Past", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")), "Today", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")), "Tomorrow", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")), "This week", "Later")))))'\n  nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-MM"), date(scheduled).format("YYYY-MM")), if((due.isEmpty() == false), date(due).format("YYYY-MM"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "No date")))'\n  nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-[W]WW"), date(scheduled).format("YYYY-[W]WW")), if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "No date")))'\n  urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format("YYYY-MM-DD")))) / 86400000)))'\n  timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + "h " + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + "m", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + "m"), "0m")'\n  dueDateDisplay: 'if(due.isEmpty(), "", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") == (today() - "1 day").format("YYYY-MM-DD"), "Yesterday", if(date(due) < today(), formula.daysUntilDue * -1 + "d ago", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), date(due).format("ddd"), date(due).format("MMM D")))))))'\n\nviews:\n  - type: tasknotesCalendar\n    name: "Calendar"\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    options:\n      showScheduled: true\n      showDue: true\n      showRecurring: true\n      showTimeEntries: true\n      showTimeblocks: true\n      showPropertyBasedEvents: true\n      createDailyNotesFromDateLinks: true\n      calendarView: "timeGridWeek"\n      customDayCount: 3\n      firstDay: 1\n

agenda-default.base#

\n

Command/template ID: open-agenda-view

\n
# Agenda\n\nfilters:\n  and:\n    - file.hasTag("task")\n\nformulas:\n  priorityWeight: 'if(priority=="none",0,if(priority=="low",1,if(priority=="normal",2,if(priority=="high",3,999))))'\n  daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n  dueIn: 'if(due.isEmpty(), "", if(formula.daysUntilDue == 0, "Today", if(formula.daysUntilDue == 1, "1 day", if(formula.daysUntilDue > 1, formula.daysUntilDue + " days", if(formula.daysUntilDue == -1, "1 day overdue", formula.daysUntilDue * -1 + " days overdue")))))'\n  daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n  daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n  daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n  isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != "done"'\n  isDueToday: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isDueThisWeek: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")'\n  isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isRecurring: 'recurrence && !recurrence.isEmpty()'\n  hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n  timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n  efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n  timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - "7d").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  dueMonth: 'if((due.isEmpty() == false), date(due).format("YYYY-MM"), "No due date")'\n  dueWeek: 'if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), "No due date")'\n  scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "Not scheduled")'\n  scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "Not scheduled")'\n  dueDateCategory: 'if(due.isEmpty(), "No due date", if(date(due) < today(), "Overdue", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), "This week", "Later")))))'\n  timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(timeEstimate < 30, "Quick (<30m)", if(timeEstimate <= 120, "Medium (30m-2h)", "Long (>2h)")))'\n  ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, "Today", if(((number(now()) - number(file.ctime)) / 86400000) < 7, "This week", if(((number(now()) - number(file.ctime)) / 86400000) < 30, "This month", "Older")))'\n  createdMonth: 'file.ctime.format("YYYY-MM")'\n  modifiedMonth: 'file.mtime.format("YYYY-MM")'\n  priorityCategory: 'if(priority=="none","None",if(priority=="low","Low",if(priority=="normal","Normal",if(priority=="high","High","No priority"))))'\n  projectCount: 'if(!projects || list(projects).length == 0, "No projects", if(list(projects).length == 1, "Single project", "Multiple projects"))'\n  contextCount: 'if(!contexts || list(contexts).length == 0, "No contexts", if(list(contexts).length == 1, "Single context", "Multiple contexts"))'\n  trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(!timeEntries || list(timeEntries).length == 0, "Not started", if(formula.efficiencyRatio < 100, "Under estimate", "Over estimate")))'\n  nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n  daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n  hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n  isToday: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"))'\n  isThisWeek: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"))'\n  nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), "No date", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), "Overdue/Past", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")), "Today", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")), "Tomorrow", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")), "This week", "Later")))))'\n  nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-MM"), date(scheduled).format("YYYY-MM")), if((due.isEmpty() == false), date(due).format("YYYY-MM"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "No date")))'\n  nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-[W]WW"), date(scheduled).format("YYYY-[W]WW")), if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "No date")))'\n  urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format("YYYY-MM-DD")))) / 86400000)))'\n  timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + "h " + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + "m", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + "m"), "0m")'\n  dueDateDisplay: 'if(due.isEmpty(), "", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") == (today() - "1 day").format("YYYY-MM-DD"), "Yesterday", if(date(due) < today(), formula.daysUntilDue * -1 + "d ago", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), date(due).format("ddd"), date(due).format("MMM D")))))))'\n\nproperties:\n  formula.dueIn:\n    displayName: Due in\n\n\nviews:\n  - type: tasknotesCalendar\n    name: "Agenda"\n    order:\n      - status\n      - priority\n      - due\n      - formula.dueIn\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    options:\n      showPropertyBasedEvents: false\n      showOverdueOnToday: true\n      createDailyNotesFromDateLinks: true\n    calendarView: "listWeek"\n    startDateProperty: file.ctime\n    listDayCount: 7\n    titleProperty: file.basename\n

pomodoro-stats.base#

\n

Command/template ID: pomodoro-stats-base

\n
# Pomodoro statistics\n# Generated with your TaskNotes settings\n# Requires Pomodoro data storage to be set to Daily notes.\n\nfilters:\n  and:\n    - file.hasProperty("pomodoros")\n    - list(note["pomodoros"]).filter(value.startTime).isEmpty() == false\n\nformulas:\n  pomodoroDate: 'if(note["pomodoros"], list(note["pomodoros"]).filter(value.startTime).map(date(value.startTime).format("YYYY-MM-DD")).unique().join(", "), file.basename)'\n  pomodoroMonth: 'if(note["pomodoros"], list(note["pomodoros"]).filter(value.startTime).map(date(value.startTime).format("YYYY-MM")).unique().join(", "), "")'\n  completedPomos: 'if(note["pomodoros"], list(note["pomodoros"]).filter(value.type == "work" && value.completed == true).length, 0)'\n  attemptedPomos: 'if(note["pomodoros"], list(note["pomodoros"]).filter(value.type == "work").length, 0)'\n  interruptedPomos: 'if(note["pomodoros"], list(note["pomodoros"]).filter(value.type == "work" && value.completed == false).length, 0)'\n  focusMinutes: 'if(note["pomodoros"], list(note["pomodoros"]).filter(value.type == "work" && value.completed == true).map(if(value.plannedDuration && value.plannedDuration > 0, value.plannedDuration, if(value.startTime && value.endTime, ((number(date(value.endTime)) - number(date(value.startTime))) / 60000).round(), 0))).reduce(acc + value, 0).round(), 0)'\n  focusTime: 'if(formula.focusMinutes >= 60, (formula.focusMinutes / 60).floor() + "h " + (formula.focusMinutes % 60).round() + "m", formula.focusMinutes + "m")'\n  completionRate: 'if(formula.attemptedPomos > 0, (formula.completedPomos / formula.attemptedPomos * 100).round() + "%", "0%")'\n  shortBreaks: 'if(note["pomodoros"], list(note["pomodoros"]).filter(value.type == "short-break").length, 0)'\n  longBreaks: 'if(note["pomodoros"], list(note["pomodoros"]).filter(value.type == "long-break").length, 0)'\n\nproperties:\n  formula.pomodoroDate:\n    displayName: Date\n  formula.pomodoroMonth:\n    displayName: Month\n  formula.completedPomos:\n    displayName: Completed\n  formula.attemptedPomos:\n    displayName: Attempted\n  formula.interruptedPomos:\n    displayName: Interrupted\n  formula.focusMinutes:\n    displayName: Focus minutes\n  formula.focusTime:\n    displayName: Focus time\n  formula.completionRate:\n    displayName: Completion\n  formula.shortBreaks:\n    displayName: Short breaks\n  formula.longBreaks:\n    displayName: Long breaks\n\nviews:\n  - type: table\n    name: "Daily"\n    order:\n      - formula.pomodoroDate\n      - formula.completedPomos\n      - formula.focusTime\n      - formula.attemptedPomos\n      - formula.completionRate\n      - formula.interruptedPomos\n      - formula.shortBreaks\n      - formula.longBreaks\n      - file.name\n    sort:\n      - column: formula.pomodoroDate\n        direction: DESC\n  - type: table\n    name: "Monthly"\n    groupBy:\n      property: formula.pomodoroMonth\n      direction: DESC\n    order:\n      - formula.pomodoroDate\n      - formula.completedPomos\n      - formula.focusMinutes\n      - formula.focusTime\n      - formula.attemptedPomos\n      - formula.completionRate\n      - formula.interruptedPomos\n      - formula.shortBreaks\n      - formula.longBreaks\n      - file.name\n    summaries:\n      formula.completedPomos: Sum\n      formula.focusMinutes: Sum\n      formula.attemptedPomos: Sum\n      formula.interruptedPomos: Sum\n      formula.shortBreaks: Sum\n      formula.longBreaks: Sum\n    sort:\n      - column: formula.pomodoroDate\n        direction: DESC\n

relationships.base#

\n

Command/template ID: relationships

\n
# Relationships\n# This view shows all relationships for the current file\n# Dynamically shows/hides tabs based on available data\n\nformulas:\n  priorityWeight: 'if(priority=="none",0,if(priority=="low",1,if(priority=="normal",2,if(priority=="high",3,999))))'\n  daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)'\n  dueIn: 'if(due.isEmpty(), "", if(formula.daysUntilDue == 0, "Today", if(formula.daysUntilDue == 1, "1 day", if(formula.daysUntilDue > 1, formula.daysUntilDue + " days", if(formula.daysUntilDue == -1, "1 day overdue", formula.daysUntilDue * -1 + " days overdue")))))'\n  daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)'\n  daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()'\n  daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()'\n  isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != "done"'\n  isDueToday: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isDueThisWeek: '(due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")'\n  isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")'\n  isRecurring: 'recurrence && !recurrence.isEmpty()'\n  hasTimeEstimate: 'timeEstimate && timeEstimate > 0'\n  timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)'\n  efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)'\n  timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - "7d").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)'\n  dueMonth: 'if((due.isEmpty() == false), date(due).format("YYYY-MM"), "No due date")'\n  dueWeek: 'if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), "No due date")'\n  scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "Not scheduled")'\n  scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "Not scheduled")'\n  dueDateCategory: 'if(due.isEmpty(), "No due date", if(date(due) < today(), "Overdue", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), "This week", "Later")))))'\n  timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(timeEstimate < 30, "Quick (<30m)", if(timeEstimate <= 120, "Medium (30m-2h)", "Long (>2h)")))'\n  ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, "Today", if(((number(now()) - number(file.ctime)) / 86400000) < 7, "This week", if(((number(now()) - number(file.ctime)) / 86400000) < 30, "This month", "Older")))'\n  createdMonth: 'file.ctime.format("YYYY-MM")'\n  modifiedMonth: 'file.mtime.format("YYYY-MM")'\n  priorityCategory: 'if(priority=="none","None",if(priority=="low","Low",if(priority=="normal","Normal",if(priority=="high","High","No priority"))))'\n  projectCount: 'if(!projects || list(projects).length == 0, "No projects", if(list(projects).length == 1, "Single project", "Multiple projects"))'\n  contextCount: 'if(!contexts || list(contexts).length == 0, "No contexts", if(list(contexts).length == 1, "Single context", "Multiple contexts"))'\n  trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, "No estimate", if(!timeEntries || list(timeEntries).length == 0, "Not started", if(formula.efficiencyRatio < 100, "Under estimate", "Over estimate")))'\n  nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))'\n  daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))'\n  hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)'\n  isToday: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"))'\n  isThisWeek: '((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") >= today().format("YYYY-MM-DD") && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"))'\n  nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), "No date", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), "Overdue/Past", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == today().format("YYYY-MM-DD")), "Today", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD")), "Tomorrow", if(((due.isEmpty() == false) && date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")) || ((scheduled.isEmpty() == false) && date(scheduled).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD")), "This week", "Later")))))'\n  nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-MM"), date(scheduled).format("YYYY-MM")), if((due.isEmpty() == false), date(due).format("YYYY-MM"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-MM"), "No date")))'\n  nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format("YYYY-[W]WW"), date(scheduled).format("YYYY-[W]WW")), if((due.isEmpty() == false), date(due).format("YYYY-[W]WW"), if((scheduled.isEmpty() == false), date(scheduled).format("YYYY-[W]WW"), "No date")))'\n  urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format("YYYY-MM-DD")))) / 86400000)))'\n  timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + "h " + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + "m", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + "m"), "0m")'\n  dueDateDisplay: 'if(due.isEmpty(), "", if(date(due).format("YYYY-MM-DD") == today().format("YYYY-MM-DD"), "Today", if(date(due).format("YYYY-MM-DD") == (today() + "1 day").format("YYYY-MM-DD"), "Tomorrow", if(date(due).format("YYYY-MM-DD") == (today() - "1 day").format("YYYY-MM-DD"), "Yesterday", if(date(due) < today(), formula.daysUntilDue * -1 + "d ago", if(date(due).format("YYYY-MM-DD") <= (today() + "7 days").format("YYYY-MM-DD"), date(due).format("ddd"), date(due).format("MMM D")))))))'\n\nviews:\n  - type: tasknotesKanban\n    name: "Subtasks"\n    filters:\n      and:\n        - file.hasTag("task")\n        - file.hasLink(this.file) && list(note.projects).map(file(value.replace(/^\\[[^\\]]+\\]\\((.*)\\)$/, "$1").replace(/%20/g, " ")).asLink()).contains(this.file.asLink())\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: tasknotes_manual_order\n        direction: DESC\n    groupBy:\n      property: status\n      direction: ASC\n  - type: tasknotesTaskList\n    name: "Occurrences"\n    filters:\n      and:\n        - file.hasTag("task")\n        - file.hasLink(this.file) && note.recurrence_parent && file(note.recurrence_parent.replace(/^\\[[^\\]]+\\]\\((.*)\\)$/, "$1").replace(/%20/g, " ")).asLink() == this.file.asLink()\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - occurrence_date\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: occurrence_date\n        direction: ASC\n  - type: tasknotesTaskList\n    name: "Projects"\n    filters:\n      and:\n        - list(this.projects).map(file(value.replace(/^\\[[^\\]]+\\]\\((.*)\\)$/, "$1").replace(/%20/g, " ")).asLink()).contains(file.asLink())\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n  - type: tasknotesTaskList\n    name: "Blocked By"\n    filters:\n      and:\n        - file.hasTag("task")\n        - list(this.note.blockedBy).map(file(if(value.isType("object"), value.uid, value)).asLink()).contains(file.asLink())\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: tasknotes_manual_order\n        direction: DESC\n  - type: tasknotesKanban\n    name: "Blocking"\n    filters:\n      and:\n        - file.hasTag("task")\n        - list(note.blockedBy).map(file(if(value.isType("object"), value.uid, value)).asLink()).contains(this.file.asLink())\n    order:\n      - status\n      - priority\n      - due\n      - scheduled\n      - projects\n      - contexts\n      - file.tags\n      - blockedBy\n      - file.name\n      - recurrence\n      - complete_instances\n      - file.tasks\n    sort:\n      - column: tasknotes_manual_order\n        direction: DESC\n    groupBy:\n      property: status\n      direction: ASC\n
","text":"These are the exact templates TaskNotes 4.13.0 produces with default settings. Your generated files reflect your own field mapping and other settings, so customized output can differ. Regenerating with Update files overwrites configured default Base files. Copy a customized file to a new path before updating it. mini-calendar-default.base# Command/template ID: open-calendar-view # Mini Calendar # Generated with your TaskNotes settings filters: and: - file.hasTag(\"task\") formulas: priorityWeight: 'if(priority==\"none\",0,if(priority==\"low\",1,if(priority==\"normal\",2,if(priority==\"high\",3,999))))' daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)' dueIn: 'if(due.isEmpty(), \"\", if(formula.daysUntilDue == 0, \"Today\", if(formula.daysUntilDue == 1, \"1 day\", if(formula.daysUntilDue > 1, formula.daysUntilDue + \" days\", if(formula.daysUntilDue == -1, \"1 day overdue\", formula.daysUntilDue * -1 + \" days overdue\")))))' daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)' daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()' daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()' isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != \"done\"' isDueToday: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")' isDueThisWeek: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")' isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")' isRecurring: 'recurrence && !recurrence.isEmpty()' hasTimeEstimate: 'timeEstimate && timeEstimate > 0' timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)' efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)' timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - \"7d\").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)' timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)' dueMonth: 'if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), \"No due date\")' dueWeek: 'if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), \"No due date\")' scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"Not scheduled\")' scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"Not scheduled\")' dueDateCategory: 'if(due.isEmpty(), \"No due date\", if(date(due) < today(), \"Overdue\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), \"This week\", \"Later\")))))' timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(timeEstimate < 30, \"Quick (<30m)\", if(timeEstimate <= 120, \"Medium (30m-2h)\", \"Long (>2h)\")))' ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, \"Today\", if(((number(now()) - number(file.ctime)) / 86400000) < 7, \"This week\", if(((number(now()) - number(file.ctime)) / 86400000) < 30, \"This month\", \"Older\")))' createdMonth: 'file.ctime.format(\"YYYY-MM\")' modifiedMonth: 'file.mtime.format(\"YYYY-MM\")' priorityCategory: 'if(priority==\"none\",\"None\",if(priority==\"low\",\"Low\",if(priority==\"normal\",\"Normal\",if(priority==\"high\",\"High\",\"No priority\"))))' projectCount: 'if(!projects || list(projects).length == 0, \"No projects\", if(list(projects).length == 1, \"Single project\", \"Multiple projects\"))' contextCount: 'if(!contexts || list(contexts).length == 0, \"No contexts\", if(list(contexts).length == 1, \"Single context\", \"Multiple contexts\"))' trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(!timeEntries || list(timeEntries).length == 0, \"Not started\", if(formula.efficiencyRatio < 100, \"Under estimate\", \"Over estimate\")))' nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))' daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))' hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)' isToday: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"))' isThisWeek: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"))' nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), \"No date\", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), \"Overdue/Past\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")), \"Today\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")), \"Tomorrow\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")), \"This week\", \"Later\")))))' nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-MM\"), date(scheduled).format(\"YYYY-MM\")), if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"No date\")))' nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-[W]WW\"), date(scheduled).format(\"YYYY-[W]WW\")), if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"No date\")))' urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format(\"YYYY-MM-DD\")))) / 86400000)))' timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + \"h \" + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + \"m\", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + \"m\"), \"0m\")' dueDateDisplay: 'if(due.isEmpty(), \"\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") == (today() - \"1 day\").format(\"YYYY-MM-DD\"), \"Yesterday\", if(date(due) < today(), formula.daysUntilDue * -1 + \"d ago\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), date(due).format(\"ddd\"), date(due).format(\"MMM D\")))))))' views: - type: tasknotesMiniCalendar name: \"Due\" order: - status - priority - due - scheduled - projects - contexts - file.tags - blockedBy - file.name - recurrence - complete_instances - file.tasks sort: - property: due direction: ASC dateProperty: due - type: tasknotesMiniCalendar name: \"Scheduled\" order: [] dateProperty: scheduled - type: tasknotesMiniCalendar name: \"Created\" dateProperty: file.ctime - type: tasknotesMiniCalendar name: \"Modified\" dateProperty: file.mtime kanban-default.base# Command/template ID: open-kanban-view # Kanban Board filters: and: - file.hasTag(\"task\") formulas: priorityWeight: 'if(priority==\"none\",0,if(priority==\"low\",1,if(priority==\"normal\",2,if(priority==\"high\",3,999))))' daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)' dueIn: 'if(due.isEmpty(), \"\", if(formula.daysUntilDue == 0, \"Today\", if(formula.daysUntilDue == 1, \"1 day\", if(formula.daysUntilDue > 1, formula.daysUntilDue + \" days\", if(formula.daysUntilDue == -1, \"1 day overdue\", formula.daysUntilDue * -1 + \" days overdue\")))))' daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)' daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()' daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()' isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != \"done\"' isDueToday: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")' isDueThisWeek: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")' isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")' isRecurring: 'recurrence && !recurrence.isEmpty()' hasTimeEstimate: 'timeEstimate && timeEstimate > 0' timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)' efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)' timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - \"7d\").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)' timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)' dueMonth: 'if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), \"No due date\")' dueWeek: 'if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), \"No due date\")' scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"Not scheduled\")' scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"Not scheduled\")' dueDateCategory: 'if(due.isEmpty(), \"No due date\", if(date(due) < today(), \"Overdue\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), \"This week\", \"Later\")))))' timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(timeEstimate < 30, \"Quick (<30m)\", if(timeEstimate <= 120, \"Medium (30m-2h)\", \"Long (>2h)\")))' ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, \"Today\", if(((number(now()) - number(file.ctime)) / 86400000) < 7, \"This week\", if(((number(now()) - number(file.ctime)) / 86400000) < 30, \"This month\", \"Older\")))' createdMonth: 'file.ctime.format(\"YYYY-MM\")' modifiedMonth: 'file.mtime.format(\"YYYY-MM\")' priorityCategory: 'if(priority==\"none\",\"None\",if(priority==\"low\",\"Low\",if(priority==\"normal\",\"Normal\",if(priority==\"high\",\"High\",\"No priority\"))))' projectCount: 'if(!projects || list(projects).length == 0, \"No projects\", if(list(projects).length == 1, \"Single project\", \"Multiple projects\"))' contextCount: 'if(!contexts || list(contexts).length == 0, \"No contexts\", if(list(contexts).length == 1, \"Single context\", \"Multiple contexts\"))' trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(!timeEntries || list(timeEntries).length == 0, \"Not started\", if(formula.efficiencyRatio < 100, \"Under estimate\", \"Over estimate\")))' nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))' daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))' hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)' isToday: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"))' isThisWeek: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"))' nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), \"No date\", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), \"Overdue/Past\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")), \"Today\", if(((due.isEmpty() == false) && date(due).fo"},{"route":"/obsidian/reference/http-routes/","title":"HTTP route index","description":"Implemented TaskNotes HTTP API routes generated from controller decorators.","product":"obsidian","platforms":[],"version":"4.13.0","generated":true,"noIndex":false,"hideToc":false,"source":"tasknotes:docs-builder/src/generated-pages.js","namespace":"obsidian","relativePath":"reference/http-routes.md","raw":"---\ntitle: \"HTTP route index\"\ndescription: \"Implemented TaskNotes HTTP API routes generated from controller decorators.\"\ngenerated: true\nsource: [\"src/api/*Controller.ts\",\"docs/HTTP_API.md\",\"docs/nlp-api.md\"]\n---\n# HTTP route index\n\nThis index is generated from controller route decorators. The build fails if an implemented route is absent from the narrative [HTTP API guide](/HTTP_API/) or [NLP API guide](/nlp-api/).\n\n| Method | Path | Controller |\n| --- | --- | --- |\n| `POST` | `/api/bases/default-files/update` | `BasesController` |\n| `GET` | `/api/calendars` | `CalendarsController` |\n| `GET` | `/api/calendars/events` | `CalendarsController` |\n| `GET` | `/api/calendars/google` | `CalendarsController` |\n| `GET` | `/api/calendars/microsoft` | `CalendarsController` |\n| `GET` | `/api/calendars/subscriptions` | `CalendarsController` |\n| `GET` | `/api/docs` | `SystemController` |\n| `GET` | `/api/docs/ui` | `SystemController` |\n| `GET` | `/api/filter-options` | `TasksController` |\n| `GET` | `/api/health` | `SystemController` |\n| `POST` | `/api/nlp/create` | `SystemController` |\n| `POST` | `/api/nlp/parse` | `SystemController` |\n| `POST` | `/api/pomodoro/pause` | `PomodoroController` |\n| `POST` | `/api/pomodoro/resume` | `PomodoroController` |\n| `GET` | `/api/pomodoro/sessions` | `PomodoroController` |\n| `POST` | `/api/pomodoro/start` | `PomodoroController` |\n| `GET` | `/api/pomodoro/stats` | `PomodoroController` |\n| `GET` | `/api/pomodoro/status` | `PomodoroController` |\n| `POST` | `/api/pomodoro/stop` | `PomodoroController` |\n| `GET` | `/api/stats` | `TasksController` |\n| `GET` | `/api/tasks` | `TasksController` |\n| `POST` | `/api/tasks` | `TasksController` |\n| `DELETE` | `/api/tasks/:id` | `TasksController` |\n| `GET` | `/api/tasks/:id` | `TasksController` |\n| `PUT` | `/api/tasks/:id` | `TasksController` |\n| `POST` | `/api/tasks/:id/archive` | `TasksController` |\n| `POST` | `/api/tasks/:id/complete-instance` | `TasksController` |\n| `POST` | `/api/tasks/:id/materialize-occurrence` | `TasksController` |\n| `GET` | `/api/tasks/:id/time` | `TimeTrackingController` |\n| `POST` | `/api/tasks/:id/time/start` | `TimeTrackingController` |\n| `POST` | `/api/tasks/:id/time/start-with-description` | `TimeTrackingController` |\n| `POST` | `/api/tasks/:id/time/stop` | `TimeTrackingController` |\n| `POST` | `/api/tasks/:id/toggle-status` | `TasksController` |\n| `POST` | `/api/tasks/query` | `TasksController` |\n| `GET` | `/api/time/active` | `TimeTrackingController` |\n| `GET` | `/api/time/summary` | `TimeTrackingController` |\n| `GET` | `/api/webhooks` | `WebhookController` |\n| `POST` | `/api/webhooks` | `WebhookController` |\n| `DELETE` | `/api/webhooks/:id` | `WebhookController` |\n| `GET` | `/api/webhooks/deliveries` | `WebhookController` |\n\n_Generated from 40 implemented routes._\n","aliases":["/reference/http-routes/","/reference/http-routes/"],"toc":[],"html":"

This index is generated from controller route decorators. The build fails if an implemented route is absent from the narrative HTTP API guide or NLP API guide.

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
MethodPathController
POST/api/bases/default-files/updateBasesController
GET/api/calendarsCalendarsController
GET/api/calendars/eventsCalendarsController
GET/api/calendars/googleCalendarsController
GET/api/calendars/microsoftCalendarsController
GET/api/calendars/subscriptionsCalendarsController
GET/api/docsSystemController
GET/api/docs/uiSystemController
GET/api/filter-optionsTasksController
GET/api/healthSystemController
POST/api/nlp/createSystemController
POST/api/nlp/parseSystemController
POST/api/pomodoro/pausePomodoroController
POST/api/pomodoro/resumePomodoroController
GET/api/pomodoro/sessionsPomodoroController
POST/api/pomodoro/startPomodoroController
GET/api/pomodoro/statsPomodoroController
GET/api/pomodoro/statusPomodoroController
POST/api/pomodoro/stopPomodoroController
GET/api/statsTasksController
GET/api/tasksTasksController
POST/api/tasksTasksController
DELETE/api/tasks/:idTasksController
GET/api/tasks/:idTasksController
PUT/api/tasks/:idTasksController
POST/api/tasks/:id/archiveTasksController
POST/api/tasks/:id/complete-instanceTasksController
POST/api/tasks/:id/materialize-occurrenceTasksController
GET/api/tasks/:id/timeTimeTrackingController
POST/api/tasks/:id/time/startTimeTrackingController
POST/api/tasks/:id/time/start-with-descriptionTimeTrackingController
POST/api/tasks/:id/time/stopTimeTrackingController
POST/api/tasks/:id/toggle-statusTasksController
POST/api/tasks/queryTasksController
GET/api/time/activeTimeTrackingController
GET/api/time/summaryTimeTrackingController
GET/api/webhooksWebhookController
POST/api/webhooksWebhookController
DELETE/api/webhooks/:idWebhookController
GET/api/webhooks/deliveriesWebhookController
\n

Generated from 40 implemented routes.

\n","text":"This index is generated from controller route decorators. The build fails if an implemented route is absent from the narrative HTTP API guide or NLP API guide. Method Path Controller POST /api/bases/default-files/update BasesController GET /api/calendars CalendarsController GET /api/calendars/events CalendarsController GET /api/calendars/google CalendarsController GET /api/calendars/microsoft CalendarsController GET /api/calendars/subscriptions CalendarsController GET /api/docs SystemController GET /api/docs/ui SystemController GET /api/filter-options TasksController GET /api/health SystemController POST /api/nlp/create SystemController POST /api/nlp/parse SystemController POST /api/pomodoro/pause PomodoroController POST /api/pomodoro/resume PomodoroController GET /api/pomodoro/sessions PomodoroController POST /api/pomodoro/start PomodoroController GET /api/pomodoro/stats PomodoroController GET /api/pomodoro/status PomodoroController POST /api/pomodoro/stop PomodoroController GET /api/stats TasksController GET /api/tasks TasksController POST /api/tasks TasksController DELETE /api/tasks/:id TasksController GET /api/tasks/:id TasksController PUT /api/tasks/:id TasksController POST /api/tasks/:id/archive TasksController POST /api/tasks/:id/complete-instance TasksController POST /api/tasks/:id/materialize-occurrence TasksController GET /api/tasks/:id/time TimeTrackingController POST /api/tasks/:id/time/start TimeTrackingController POST /api/tasks/:id/time/start-with-description TimeTrackingController POST /api/tasks/:id/time/stop TimeTrackingController POST /api/tasks/:id/toggle-status TasksController POST /api/tasks/query TasksController GET /api/time/active TimeTrackingController GET /api/time/summary TimeTrackingController GET /api/webhooks WebhookController POST /api/webhooks WebhookController DELETE /api/webhooks/:id WebhookController GET /api/webhooks/deliveries WebhookController Generated from 40 implemented routes."},{"route":"/obsidian/reference/settings-source/","title":"Settings source reference","description":"The six TaskNotes settings tabs, their controls, and the complete default settings snapshot generated from source.","product":"obsidian","platforms":[],"version":"4.13.0","generated":true,"noIndex":false,"hideToc":false,"source":"tasknotes:docs-builder/src/generated-pages.js","namespace":"obsidian","relativePath":"reference/settings-source.md","raw":"---\ntitle: \"Settings source reference\"\ndescription: \"The six TaskNotes settings tabs, their controls, and the complete default settings snapshot generated from source.\"\ngenerated: true\nsource: [\"src/settings/TaskNotesSettingTab.ts\",\"src/settings/tabs/*.ts\",\"src/settings/defaults.ts\",\"src/i18n/resources/en.ts\"]\n---\n# Settings source reference\n\nTaskNotes currently exposes 6 settings tabs. This inventory is generated from the tab renderer and English translation source so additions cannot silently disappear from the documentation.\n\n## General\n\nSource: `src/settings/tabs/generalTab.ts`\n\n| Setting | Purpose |\n| --- | --- |\n| Default tasks folder | Default location for new tasks. Supports folder template variables like {{currentNotePath}}, {{currentNoteTitle}}, and {{projectFilePath}}, plus Daily Notes-style date tokens like YYYY/MM/DD. |\n| Folder for inline-created tasks | Folder where tasks created from inline commands or checkbox conversion will be created. Leave empty to use the default tasks folder. Use {{currentNotePath}} for the current note's folder, or {{currentNoteTitle}} for a subfolder named after the current note. |\n| Move archived tasks to folder | Automatically move archived tasks to an archive folder |\n| Archive folder | Folder to move tasks to when archived. Supports template variables like {{year}}, {{month}}, {{priority}}, etc. |\n| Identify tasks by | Choose whether to identify tasks by tag or by a frontmatter property |\n| Task tag | Tag that identifies notes as tasks (without #). Existing .base view filters keep their old tag when this changes; update default Base files or edit those filters. |\n| Hide identification tags in task cards | When enabled, tags matching the task identification tag (including hierarchical matches like 'task/project') will be hidden from task card displays |\n| Hidden tag scope | Choose whether hiding identification tags also hides nested tags. |\n| Task property name | The frontmatter property name (e.g., \"category\") |\n| Task property value | The value that identifies a note as a task (e.g., \"task\") |\n| Auto-create default files | Automatically create missing default base view files on startup. Disable to prevent deleted sample files from being recreated. |\n| Create default files | Create the default .base files in TaskNotes/Views/ directory. Existing files will not be overwritten. |\n| Update default files | Overwrite the configured default .base files with templates generated from your current TaskNotes settings. |\n| Export v3 saved views to Bases | Convert all your saved views from TaskNotes v3 into a single .base file with multiple views. This helps migrate your v3 filter configurations to the new Bases system. |\n| Excluded folders | Comma-separated list of folders to exclude from task indexing and project suggestions |\n| UI language | Select the language used for TaskNotes interface text |\n| Use Markdown links in frontmatter | Generate markdown links (`[text](path)`) instead of wikilinks ([[link]]) in frontmatter properties. ⚠️ Requires the 'obsidian-frontmatter-markdown-links' plugin to work correctly. |\n| Show release notes after update | Automatically open release notes when TaskNotes is updated to a new version |\n| Check for new releases on startup | Check GitHub once when TaskNotes starts and show a notice when a newer compatible release is available |\n| View release notes | See what's new in the latest version of TaskNotes |\n\n## Task properties\n\nSource: `src/settings/tabs/taskPropertiesTab.ts`\n\n| Setting | Purpose |\n| --- | --- |\n| No static controls detected | This tab is assembled dynamically. |\n\n## Modal fields\n\nSource: `src/settings/tabs/modalFieldsTab.ts`\n\n| Setting | Purpose |\n| --- | --- |\n| No static controls detected | This tab is assembled dynamically. |\n\n## Appearance & UI\n\nSource: `src/settings/tabs/appearanceTab.ts`\n\n| Setting | Purpose |\n| --- | --- |\n| Default visible properties | Choose which properties appear on task cards by default. |\n| Group complete and skip actions in a submenu | Nest the complete and skip actions under a submenu in the task context menu. Turn off to show them directly in the menu. |\n| Time format | Display time in 12-hour or 24-hour format throughout the plugin |\n| Default view | The calendar view shown when opening the calendar tab |\n| Custom view day count | Number of days to show in custom multi-day view |\n| First day of week | Which day should be the first column in week views |\n| Show weekends | Display weekends in calendar views |\n| Show week numbers | Display week numbers in calendar views |\n| Show today highlight | Highlight the current day in calendar views |\n| Show current time indicator | Display a line showing the current time in timeline views |\n| Selection mirror | Show a visual preview while dragging to select time ranges |\n| Calendar locale | Calendar locale for date formatting and calendar system (e.g., \"en\", \"fa\" for Farsi/Persian, \"de\" for German). Leave empty to auto-detect from browser. |\n| Show scheduled tasks | Display tasks with scheduled dates by default |\n| Show due dates | Display task due dates by default |\n| Show due dates when scheduled | Display due dates even for tasks that already have scheduled dates |\n| Show time entries | Display completed time tracking entries by default |\n| Show recurring tasks | Display recurring task instances by default |\n| Show ICS events | Display events from ICS subscriptions by default |\n| Time slot duration | Duration of each time slot in timeline views |\n| Start time | Earliest time shown in timeline views (HH:MM format) |\n| End time | Latest time shown in timeline views (HH:MM format). Use values above 24:00 to show early next-day hours, such as 26:00 for 2 AM. |\n| Initial scroll time | Time to scroll to when opening timeline views (HH:MM format) |\n| Event minimum height | Minimum height for events in timeline views (pixels) |\n| Show tracked tasks in status bar | Display currently tracked tasks in Obsidian's status bar |\n| Show relationships widget | Display a widget showing all relationships for the current note (subtasks, projects, dependencies) |\n| Relationships position | Where to position the relationships widget |\n| Show task card in note | Display a task card widget at the top of task notes showing the task details and actions |\n| Strike through completed task titles | Draw a line through completed task card titles. Turn off to keep completed tasks easier to read |\n| Show expandable subtasks | Allow expanding/collapsing subtask sections in task cards |\n| Expand subtasks by default | Show project subtasks expanded when task cards are rendered |\n| Subtask chevron position | Position of expand/collapse chevrons in task cards |\n| Views button alignment | Alignment of the views/filters button in the task interface |\n| Single-click action | Action performed when single-clicking a task card |\n| Double-click action | Action performed when double-clicking a task card |\n\n## Features\n\nSource: `src/settings/tabs/featuresTab.ts`\n\n| Setting | Purpose |\n| --- | --- |\n| Task link overlay | Show interactive overlays when hovering over task links |\n| Disable overlay for aliased links | Do not show the task widget if the link contains an alias (e.g. [[Task\\|Alias]]). |\n| Show convert button next to checkboxes | Display an inline button next to Markdown checkboxes that converts them to TaskNotes |\n| Keep checkbox when converting | Leave the original Markdown checkbox marker in place when converting a checkbox to a TaskNote link |\n| Enable natural language task input | Parse due dates, priorities, and contexts from natural language when creating tasks |\n| Default to scheduled | When NLP detects a date without context, treat it as scheduled rather than due |\n| NLP language | Language for natural language processing patterns and date parsing |\n| Open task after creation | Choose whether the task creation modal opens the new task note after saving. |\n| Use body template | Use a template file for task body content |\n| Body template file | Path to template file for task body content. Supports template variables like {{title}}, {{date}}, {{time}}, {{priority}}, {{status}}, etc. |\n| Use occurrence note template | Use a separate fallback template for materialized occurrence notes when the recurring task has no occurrence_template |\n| Occurrence note template file | Path to template file for materialized occurrence notes. A recurring task's occurrence_template field takes priority over this fallback. |\n| Template variables: | See the setting in Obsidian for contextual details. |\n| Use task defaults on instant convert | Apply default task settings when converting text to tasks instantly |\n| Work duration | Duration of work intervals in minutes |\n| Short break duration | Duration of short breaks in minutes |\n| Long break duration | Duration of long breaks in minutes |\n| Long break interval | Number of work sessions before a long break |\n| Auto-start breaks | Automatically start break timers after work sessions |\n| Auto-start work | Automatically start work sessions after breaks |\n| Pomodoro notifications | Show notifications when Pomodoro sessions end |\n| Show Pomodoro in status bar | Display the active Pomodoro countdown in Obsidian's status bar |\n| Sound enabled | Play sound when Pomodoro sessions end |\n| Sound volume | Volume for Pomodoro sounds (0-100) |\n| Pomodoro data storage | Configure where Pomodoro session data is stored and how it's managed. |\n| Mobile sidebar | Where to open the Pomodoro timer on mobile devices |\n| Enable notifications | Enable task reminder notifications |\n| Notification type | Type of notifications to show |\n| Send test reminder | Send a test reminder using the current notification type and sound settings. |\n| Notification sound | Play a sound when task reminders trigger |\n| Sound volume | Volume for task reminder sounds (0-100) |\n| Preview notification sound | Play the configured task reminder sound |\n| Hide completed tasks from overdue | Exclude completed tasks from overdue task calculations |\n| Disable note indexing | Disable automatic indexing of note content for better performance |\n| Suggestion debounce | Delay in milliseconds before showing suggestions |\n| Auto-stop time tracking | Automatically stop time tracking when a task is marked complete |\n| Time tracking stop notification | Show notification when time tracking is automatically stopped |\n| Maintain due date offset in recurring tasks | Keep the offset between due date and scheduled date when recurring tasks are completed |\n| Reset checkboxes on recurrence | Reset all Markdown checkboxes in the task body when a recurring task is completed and rescheduled |\n| Enable timeblocking | Enable timeblocking feature for lightweight scheduling in daily notes. When enabled, 'Timeblock' option appears in the calendar drag context menu. |\n| Show timeblocks | Display timeblocks from daily notes by default |\n| Default timeblock color | The default color used when creating new timeblocks |\n| Enable debug logging | Log detailed drag-and-drop and view diagnostics to the developer console. Useful for troubleshooting. |\n\n## Integrations\n\nSource: `src/settings/tabs/integrationsTab.ts`\n\n| Setting | Purpose |\n| --- | --- |\n| Generate mdbase type definitions | See the setting in Obsidian for contextual details. |\n| Disable calendar integrations on mobile | Skip Google, Microsoft, and ICS calendar loading on Obsidian mobile. Desktop calendar integrations are unchanged. |\n| Calendar integrations are disabled on this mobile device | See the setting in Obsidian for contextual details. |\n| Enable task export | When enabled, tasks with dates will be automatically synced to Google Calendar as events. |\n| Target calendar | See the setting in Obsidian for contextual details. |\n| Sync trigger | Which task date should trigger calendar event creation. |\n| Create as all-day events | When enabled, tasks are created as all-day events. When disabled, uses time estimate for duration. |\n| Default event duration | Duration in minutes for timed events (used when task has no time estimate). |\n| Event title template | Template for event titles. Available variables: {{title}}, {{status}}, {{priority}} |\n| Include task details in description | Add task metadata (priority, status, tags, etc.) to the event description. |\n| Include Obsidian link | Add a link back to the task in Obsidian in the event description. |\n| Default reminder | Add popup reminders to timed Google Calendar events. Enter minutes before the event, separated by commas. Leave empty to use calendar defaults. Common values: 15, 30, 60, 1440. |\n| Automatic sync behavior | See the setting in Obsidian for contextual details. |\n| Sync on task create | Automatically create calendar event when a new task is created. |\n| Sync on task update | Automatically update calendar event when a task is modified. |\n| Sync on task complete | Update calendar event when a task is completed (adds checkmark to title). |\n| Delete event on task delete | Remove calendar event when the corresponding task is deleted. |\n| Manual sync actions | See the setting in Obsidian for contextual details. |\n| Sync all tasks | Sync all existing tasks to Google Calendar. This will create events for tasks that haven't been synced yet. |\n| Unlink all tasks | Remove all task-event links without deleting calendar events. |\n| Default note template | Path to template file for notes created from ICS events |\n| Default note folder | Folder for notes created from ICS events |\n| ICS note filename format | How filenames are generated for notes created from ICS events |\n| Custom ICS filename template | Template for custom ICS event filenames |\n| Use ICS event end time as task due date | When enabled, tasks created from calendar events will have their due date set to the event's end time. For all-day events, the due date will be set to the event date. For timed events, the due date will include the end time. |\n| Recurring event related notes | Choose whether notes linked to one recurrence of an external calendar event appear across the loaded series or only on the selected instance. |\n| Add calendar subscription | Add a new calendar subscription from ICS/iCal URL or local file |\n| New calendar | See the setting in Obsidian for contextual details. |\n| Refresh all subscriptions | Manually refresh all enabled calendar subscriptions |\n| Enable automatic export | Automatically keep an ICS file updated with all your tasks |\n| Export file path | Path where the ICS file will be saved (relative to vault root) |\n| Update interval (between 5 and 1440 minutes) | How often to update the export file |\n| Use task duration for event length | When enabled, uses the task's time estimate (duration) instead of due date for the calendar event end time. This is useful for GTD workflows where scheduled + duration represents work planning, while due date represents deadlines. |\n| Exclude completed tasks | When enabled, completed tasks are omitted from ICS exports. Completed statuses are taken from your task statuses settings. |\n| Exclude archived tasks | When enabled, archived tasks are omitted from ICS exports. |\n| Require due date | When enabled, only tasks with a due date are included in ICS exports. |\n| Require scheduled date | When enabled, only tasks with a scheduled date are included in ICS exports. |\n| Export now | Manually trigger an immediate export |\n| Export status: | See the setting in Obsidian for contextual details. |\n| Enable HTTP API | Start local HTTP server for API access |\n| API port | Port number for the HTTP API server |\n| API authentication token | Required for API authentication. If empty, a token is generated when the server starts. |\n| Enable MCP server | Expose TaskNotes tools via Model Context Protocol at /mcp endpoint. Requires HTTP API to be enabled. |\n| Add webhook | Register a new webhook endpoint |\n\n## Complete default settings snapshot\n\nThe following JSON is generated from `DEFAULT_SETTINGS`. Empty strings and disabled flags are intentional defaults.\n\n```json\n{\n \"tasksFolder\": \"TaskNotes/Tasks\",\n \"moveArchivedTasks\": false,\n \"archiveFolder\": \"TaskNotes/Archive\",\n \"taskTag\": \"task\",\n \"taskIdentificationMethod\": \"tag\",\n \"hideIdentifyingTagsInCards\": false,\n \"hideIdentifyingTagsMode\": \"all\",\n \"taskPropertyName\": \"\",\n \"taskPropertyValue\": \"\",\n \"excludedFolders\": \"\",\n \"defaultTaskPriority\": \"normal\",\n \"defaultTaskStatus\": \"open\",\n \"taskOrgFiltersCollapsed\": false,\n \"taskFilenameFormat\": \"zettel\",\n \"storeTitleInFilename\": true,\n \"customFilenameTemplate\": \"{{title}}\",\n \"occurrenceFilenameTemplate\": \"\",\n \"occurrenceFilenameTemplateProperty\": \"occurrenceFilenameTemplate\",\n \"taskCreationDefaults\": {\n \"defaultContexts\": \"\",\n \"defaultTags\": \"\",\n \"defaultProjects\": \"\",\n \"useParentNoteForTaskCreation\": false,\n \"useParentNoteAsProject\": false,\n \"useParentHeaderAsProject\": false,\n \"inheritParentTaskProperties\": false,\n \"defaultTimeEstimate\": 0,\n \"defaultRecurrence\": \"none\",\n \"defaultDueDate\": \"none\",\n \"defaultDueTime\": \"none\",\n \"defaultScheduledDate\": \"today\",\n \"defaultScheduledTime\": \"none\",\n \"bodyTemplate\": \"\",\n \"useBodyTemplate\": false,\n \"occurrenceBodyTemplate\": \"\",\n \"useOccurrenceBodyTemplate\": false,\n \"defaultReminders\": []\n },\n \"openTaskAfterCreation\": \"none\",\n \"calendarViewSettings\": {\n \"defaultView\": \"dayGridMonth\",\n \"customDayCount\": 3,\n \"slotDuration\": \"00:30:00\",\n \"slotMinTime\": \"00:00:00\",\n \"slotMaxTime\": \"24:00:00\",\n \"scrollTime\": \"08:00:00\",\n \"firstDay\": 1,\n \"timeFormat\": \"24\",\n \"showWeekends\": true,\n \"locale\": \"\",\n \"defaultShowScheduled\": true,\n \"defaultShowDue\": true,\n \"defaultShowDueWhenScheduled\": true,\n \"defaultShowScheduledToDueSpan\": false,\n \"defaultShowTimeEntries\": false,\n \"defaultShowRecurring\": true,\n \"defaultShowICSEvents\": true,\n \"enableTimeblocking\": false,\n \"defaultShowTimeblocks\": true,\n \"defaultTimeblockColor\": \"#6366f1\",\n \"timeblockAttachmentSearchOrder\": \"name-asc\",\n \"nowIndicator\": true,\n \"selectMirror\": true,\n \"weekNumbers\": false,\n \"showTodayHighlight\": true,\n \"eventMinHeight\": 15,\n \"slotEventOverlap\": true,\n \"eventMaxStack\": null,\n \"dayMaxEvents\": true,\n \"dayMaxEventRows\": false\n },\n \"pomodoroWorkDuration\": 25,\n \"pomodoroShortBreakDuration\": 5,\n \"pomodoroLongBreakDuration\": 15,\n \"pomodoroLongBreakInterval\": 4,\n \"pomodoroAutoStartBreaks\": true,\n \"pomodoroAutoStartWork\": false,\n \"pomodoroNotifications\": true,\n \"pomodoroSoundEnabled\": true,\n \"pomodoroSoundVolume\": 50,\n \"pomodoroStorageLocation\": \"plugin\",\n \"pomodoroMobileSidebar\": \"tab\",\n \"showPomodoroInStatusBar\": true,\n \"enableTaskLinkOverlay\": true,\n \"disableOverlayOnAlias\": false,\n \"enableInstantTaskConvert\": true,\n \"useDefaultsOnInstantConvert\": true,\n \"preserveCheckboxOnConvert\": false,\n \"taskModalTabMovesFocus\": true,\n \"enableNaturalLanguageInput\": true,\n \"nlpDefaultToScheduled\": true,\n \"nlpLanguage\": \"en\",\n \"uiLanguage\": \"system\",\n \"statusSuggestionTrigger\": \"*\",\n \"nlpTriggers\": {\n \"triggers\": [\n {\n \"propertyId\": \"tags\",\n \"trigger\": \"#\",\n \"enabled\": true\n },\n {\n \"propertyId\": \"contexts\",\n \"trigger\": \"@\",\n \"enabled\": true\n },\n {\n \"propertyId\": \"projects\",\n \"trigger\": \"+\",\n \"enabled\": true\n },\n {\n \"propertyId\": \"status\",\n \"trigger\": \"*\",\n \"enabled\": true\n },\n {\n \"propertyId\": \"priority\",\n \"trigger\": \"!\",\n \"enabled\": false\n }\n ]\n },\n \"singleClickAction\": \"edit\",\n \"doubleClickAction\": \"openNote\",\n \"projectAutosuggest\": {\n \"enableFuzzy\": false,\n \"rows\": [\n \"{title|n(Title)}\",\n \"{aliases|n(Aliases)}\",\n \"{file.path|n(Path)}\"\n ],\n \"showAdvanced\": false,\n \"requiredTags\": [],\n \"includeFolders\": [],\n \"propertyKey\": \"\",\n \"propertyValue\": \"\"\n },\n \"inlineTaskConvertFolder\": \"{{currentNotePath}}\",\n \"disableNoteIndexing\": false,\n \"suggestionDebounceMs\": 0,\n \"fieldMapping\": {\n \"title\": \"title\",\n \"status\": \"status\",\n \"priority\": \"priority\",\n \"due\": \"due\",\n \"scheduled\": \"scheduled\",\n \"contexts\": \"contexts\",\n \"projects\": \"projects\",\n \"attachments\": \"attachments\",\n \"timeEstimate\": \"timeEstimate\",\n \"completedDate\": \"completedDate\",\n \"dateCreated\": \"dateCreated\",\n \"dateModified\": \"dateModified\",\n \"recurrence\": \"recurrence\",\n \"recurrenceAnchor\": \"recurrence_anchor\",\n \"recurrenceParent\": \"recurrence_parent\",\n \"occurrenceDate\": \"occurrence_date\",\n \"occurrenceMaterialization\": \"occurrence_materialization\",\n \"occurrenceNextTrigger\": \"occurrence_next_trigger\",\n \"occurrenceTemplate\": \"occurrence_template\",\n \"occurrencePastHorizon\": \"occurrence_past_horizon\",\n \"occurrenceFutureHorizon\": \"occurrence_future_horizon\",\n \"archiveTag\": \"archived\",\n \"timeEntries\": \"timeEntries\",\n \"completeInstances\": \"complete_instances\",\n \"skippedInstances\": \"skipped_instances\",\n \"blockedBy\": \"blockedBy\",\n \"pomodoros\": \"pomodoros\",\n \"icsEventId\": \"icsEventId\",\n \"icsEventTag\": \"ics_event\",\n \"googleCalendarEventId\": \"googleCalendarEventId\",\n \"googleCalendarExceptionEventId\": \"googleCalendarExceptionEventId\",\n \"googleCalendarExceptionOriginalScheduled\": \"googleCalendarExceptionOriginalScheduled\",\n \"googleCalendarMovedOriginalDates\": \"googleCalendarMovedOriginalDates\",\n \"reminders\": \"reminders\",\n \"sortOrder\": \"tasknotes_manual_order\"\n },\n \"customStatuses\": [\n {\n \"id\": \"none\",\n \"value\": \"none\",\n \"label\": \"None\",\n \"color\": \"#cccccc\",\n \"isCompleted\": false,\n \"excludeFromCycle\": false,\n \"order\": 0,\n \"autoArchive\": false,\n \"autoArchiveDelay\": 5\n },\n {\n \"id\": \"open\",\n \"value\": \"open\",\n \"label\": \"Open\",\n \"color\": \"#808080\",\n \"isCompleted\": false,\n \"excludeFromCycle\": false,\n \"order\": 1,\n \"autoArchive\": false,\n \"autoArchiveDelay\": 5\n },\n {\n \"id\": \"in-progress\",\n \"value\": \"in-progress\",\n \"label\": \"In progress\",\n \"color\": \"#0066cc\",\n \"isCompleted\": false,\n \"excludeFromCycle\": false,\n \"order\": 2,\n \"autoArchive\": false,\n \"autoArchiveDelay\": 5\n },\n {\n \"id\": \"done\",\n \"value\": \"done\",\n \"label\": \"Done\",\n \"color\": \"#00aa00\",\n \"isCompleted\": true,\n \"excludeFromCycle\": false,\n \"order\": 3,\n \"autoArchive\": false,\n \"autoArchiveDelay\": 5\n }\n ],\n \"customPriorities\": [\n {\n \"id\": \"none\",\n \"value\": \"none\",\n \"label\": \"None\",\n \"color\": \"#cccccc\",\n \"weight\": 0\n },\n {\n \"id\": \"low\",\n \"value\": \"low\",\n \"label\": \"Low\",\n \"color\": \"#00aa00\",\n \"weight\": 1\n },\n {\n \"id\": \"normal\",\n \"value\": \"normal\",\n \"label\": \"Normal\",\n \"color\": \"#ffaa00\",\n \"weight\": 2\n },\n {\n \"id\": \"high\",\n \"value\": \"high\",\n \"label\": \"High\",\n \"color\": \"#ff0000\",\n \"weight\": 3\n }\n ],\n \"recurrenceMigrated\": false,\n \"showReleaseNotesOnUpdate\": true,\n \"checkForUpdatesOnStartup\": true,\n \"starterNoteCreated\": false,\n \"showTrackedTasksInStatusBar\": false,\n \"autoStopTimeTrackingOnComplete\": true,\n \"autoStopTimeTrackingNotification\": false,\n \"showRelationships\": true,\n \"relationshipsPosition\": \"bottom\",\n \"showTaskCardInNote\": true,\n \"showCompletedTaskStrikethrough\": true,\n \"completionMenuAsSubmenu\": true,\n \"showExpandableSubtasks\": true,\n \"expandSubtasksByDefault\": false,\n \"subtaskChevronPosition\": \"right\",\n \"viewsButtonAlignment\": \"right\",\n \"hideCompletedFromOverdue\": true,\n \"icsIntegration\": {\n \"defaultNoteTemplate\": \"\",\n \"defaultNoteFolder\": \"\",\n \"icsNoteFilenameFormat\": \"title\",\n \"customICSNoteFilenameTemplate\": \"{title}\",\n \"enableAutoExport\": false,\n \"autoExportPath\": \"tasknotes-calendar.ics\",\n \"autoExportInterval\": 60,\n \"useDurationForExport\": false,\n \"excludeArchivedFromExport\": false,\n \"excludeCompletedFromExport\": false,\n \"requireDueDateForExport\": false,\n \"requireScheduledDateForExport\": false,\n \"useICSEndAsDue\": false,\n \"recurringEventRelatedNotesMode\": \"series\"\n },\n \"savedViews\": [],\n \"enableNotifications\": true,\n \"notificationType\": \"system\",\n \"notificationSoundEnabled\": false,\n \"notificationSoundVolume\": 50,\n \"enableAPI\": false,\n \"apiPort\": 8080,\n \"apiAuthToken\": \"\",\n \"enableMCP\": false,\n \"webhooks\": [],\n \"userFields\": [],\n \"enableModalSplitLayout\": true,\n \"defaultVisibleProperties\": [\n \"status\",\n \"priority\",\n \"due\",\n \"scheduled\",\n \"projects\",\n \"contexts\",\n \"tags\",\n \"blocked\",\n \"blocking\"\n ],\n \"inlineVisibleProperties\": [\n \"status\",\n \"priority\",\n \"due\",\n \"scheduled\",\n \"recurrence\"\n ],\n \"enableBases\": true,\n \"enableMdbaseSpec\": false,\n \"autoCreateDefaultBasesFiles\": true,\n \"commandFileMapping\": {\n \"open-calendar-view\": \"TaskNotes/Views/mini-calendar-default.base\",\n \"open-kanban-view\": \"TaskNotes/Views/kanban-default.base\",\n \"open-tasks-view\": \"TaskNotes/Views/tasks-default.base\",\n \"open-advanced-calendar-view\": \"TaskNotes/Views/calendar-default.base\",\n \"open-agenda-view\": \"TaskNotes/Views/agenda-default.base\",\n \"pomodoro-stats-base\": \"TaskNotes/Views/pomodoro-stats.base\",\n \"relationships\": \"TaskNotes/Views/relationships.base\"\n },\n \"maintainDueDateOffsetInRecurring\": false,\n \"resetCheckboxesOnRecurrence\": false,\n \"useFrontmatterMarkdownLinks\": false,\n \"enableGoogleCalendar\": false,\n \"enableMicrosoftCalendar\": false,\n \"disableCalendarOnMobile\": false,\n \"enabledGoogleCalendars\": [],\n \"googleCalendarSyncTokens\": {},\n \"enabledMicrosoftCalendars\": [],\n \"microsoftCalendarSyncTokens\": {},\n \"googleCalendarExport\": {\n \"enabled\": false,\n \"targetCalendarId\": \"\",\n \"syncOnTaskCreate\": true,\n \"syncOnTaskUpdate\": true,\n \"syncOnTaskComplete\": true,\n \"syncOnTaskDelete\": true,\n \"eventTitleTemplate\": \"{{title}}\",\n \"includeDescription\": true,\n \"eventColorId\": null,\n \"syncTrigger\": \"scheduled\",\n \"createAsAllDay\": true,\n \"defaultEventDuration\": 60,\n \"includeObsidianLink\": true,\n \"defaultReminderMinutes\": null\n },\n \"enableDebugLogging\": false\n}\n```\n","aliases":["/reference/settings-source/","/reference/settings-source/"],"toc":[{"level":2,"id":"general","text":"General"},{"level":2,"id":"task-properties","text":"Task properties"},{"level":2,"id":"modal-fields","text":"Modal fields"},{"level":2,"id":"appearance-ui","text":"Appearance & UI"},{"level":2,"id":"features","text":"Features"},{"level":2,"id":"integrations","text":"Integrations"},{"level":2,"id":"complete-default-settings-snapshot","text":"Complete default settings snapshot"}],"html":"

TaskNotes currently exposes 6 settings tabs. This inventory is generated from the tab renderer and English translation source so additions cannot silently disappear from the documentation.

\n

General#

\n

Source: src/settings/tabs/generalTab.ts

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
SettingPurpose
Default tasks folderDefault location for new tasks. Supports folder template variables like {{currentNotePath}}, {{currentNoteTitle}}, and {{projectFilePath}}, plus Daily Notes-style date tokens like YYYY/MM/DD.
Folder for inline-created tasksFolder where tasks created from inline commands or checkbox conversion will be created. Leave empty to use the default tasks folder. Use {{currentNotePath}} for the current note's folder, or {{currentNoteTitle}} for a subfolder named after the current note.
Move archived tasks to folderAutomatically move archived tasks to an archive folder
Archive folderFolder to move tasks to when archived. Supports template variables like {{year}}, {{month}}, {{priority}}, etc.
Identify tasks byChoose whether to identify tasks by tag or by a frontmatter property
Task tagTag that identifies notes as tasks (without #). Existing .base view filters keep their old tag when this changes; update default Base files or edit those filters.
Hide identification tags in task cardsWhen enabled, tags matching the task identification tag (including hierarchical matches like 'task/project') will be hidden from task card displays
Hidden tag scopeChoose whether hiding identification tags also hides nested tags.
Task property nameThe frontmatter property name (e.g., "category")
Task property valueThe value that identifies a note as a task (e.g., "task")
Auto-create default filesAutomatically create missing default base view files on startup. Disable to prevent deleted sample files from being recreated.
Create default filesCreate the default .base files in TaskNotes/Views/ directory. Existing files will not be overwritten.
Update default filesOverwrite the configured default .base files with templates generated from your current TaskNotes settings.
Export v3 saved views to BasesConvert all your saved views from TaskNotes v3 into a single .base file with multiple views. This helps migrate your v3 filter configurations to the new Bases system.
Excluded foldersComma-separated list of folders to exclude from task indexing and project suggestions
UI languageSelect the language used for TaskNotes interface text
Use Markdown links in frontmatterGenerate markdown links ([text](path)) instead of wikilinks ([[link]]) in frontmatter properties. ⚠️ Requires the 'obsidian-frontmatter-markdown-links' plugin to work correctly.
Show release notes after updateAutomatically open release notes when TaskNotes is updated to a new version
Check for new releases on startupCheck GitHub once when TaskNotes starts and show a notice when a newer compatible release is available
View release notesSee what's new in the latest version of TaskNotes
\n

Task properties#

\n

Source: src/settings/tabs/taskPropertiesTab.ts

\n
\n\n\n\n\n\n\n\n\n\n\n
SettingPurpose
No static controls detectedThis tab is assembled dynamically.
\n

Modal fields#

\n

Source: src/settings/tabs/modalFieldsTab.ts

\n
\n\n\n\n\n\n\n\n\n\n\n
SettingPurpose
No static controls detectedThis tab is assembled dynamically.
\n

Appearance & UI#

\n

Source: src/settings/tabs/appearanceTab.ts

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
SettingPurpose
Default visible propertiesChoose which properties appear on task cards by default.
Group complete and skip actions in a submenuNest the complete and skip actions under a submenu in the task context menu. Turn off to show them directly in the menu.
Time formatDisplay time in 12-hour or 24-hour format throughout the plugin
Default viewThe calendar view shown when opening the calendar tab
Custom view day countNumber of days to show in custom multi-day view
First day of weekWhich day should be the first column in week views
Show weekendsDisplay weekends in calendar views
Show week numbersDisplay week numbers in calendar views
Show today highlightHighlight the current day in calendar views
Show current time indicatorDisplay a line showing the current time in timeline views
Selection mirrorShow a visual preview while dragging to select time ranges
Calendar localeCalendar locale for date formatting and calendar system (e.g., "en", "fa" for Farsi/Persian, "de" for German). Leave empty to auto-detect from browser.
Show scheduled tasksDisplay tasks with scheduled dates by default
Show due datesDisplay task due dates by default
Show due dates when scheduledDisplay due dates even for tasks that already have scheduled dates
Show time entriesDisplay completed time tracking entries by default
Show recurring tasksDisplay recurring task instances by default
Show ICS eventsDisplay events from ICS subscriptions by default
Time slot durationDuration of each time slot in timeline views
Start timeEarliest time shown in timeline views (HH:MM format)
End timeLatest time shown in timeline views (HH:MM format). Use values above 24:00 to show early next-day hours, such as 26:00 for 2 AM.
Initial scroll timeTime to scroll to when opening timeline views (HH:MM format)
Event minimum heightMinimum height for events in timeline views (pixels)
Show tracked tasks in status barDisplay currently tracked tasks in Obsidian's status bar
Show relationships widgetDisplay a widget showing all relationships for the current note (subtasks, projects, dependencies)
Relationships positionWhere to position the relationships widget
Show task card in noteDisplay a task card widget at the top of task notes showing the task details and actions
Strike through completed task titlesDraw a line through completed task card titles. Turn off to keep completed tasks easier to read
Show expandable subtasksAllow expanding/collapsing subtask sections in task cards
Expand subtasks by defaultShow project subtasks expanded when task cards are rendered
Subtask chevron positionPosition of expand/collapse chevrons in task cards
Views button alignmentAlignment of the views/filters button in the task interface
Single-click actionAction performed when single-clicking a task card
Double-click actionAction performed when double-clicking a task card
\n

Features#

\n

Source: src/settings/tabs/featuresTab.ts

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
SettingPurpose
Task link overlayShow interactive overlays when hovering over task links
Disable overlay for aliased linksDo not show the task widget if the link contains an alias (e.g. [[Task|Alias]]).
Show convert button next to checkboxesDisplay an inline button next to Markdown checkboxes that converts them to TaskNotes
Keep checkbox when convertingLeave the original Markdown checkbox marker in place when converting a checkbox to a TaskNote link
Enable natural language task inputParse due dates, priorities, and contexts from natural language when creating tasks
Default to scheduledWhen NLP detects a date without context, treat it as scheduled rather than due
NLP languageLanguage for natural language processing patterns and date parsing
Open task after creationChoose whether the task creation modal opens the new task note after saving.
Use body templateUse a template file for task body content
Body template filePath to template file for task body content. Supports template variables like {{title}}, {{date}}, {{time}}, {{priority}}, {{status}}, etc.
Use occurrence note templateUse a separate fallback template for materialized occurrence notes when the recurring task has no occurrence_template
Occurrence note template filePath to template file for materialized occurrence notes. A recurring task's occurrence_template field takes priority over this fallback.
Template variables:See the setting in Obsidian for contextual details.
Use task defaults on instant convertApply default task settings when converting text to tasks instantly
Work durationDuration of work intervals in minutes
Short break durationDuration of short breaks in minutes
Long break durationDuration of long breaks in minutes
Long break intervalNumber of work sessions before a long break
Auto-start breaksAutomatically start break timers after work sessions
Auto-start workAutomatically start work sessions after breaks
Pomodoro notificationsShow notifications when Pomodoro sessions end
Show Pomodoro in status barDisplay the active Pomodoro countdown in Obsidian's status bar
Sound enabledPlay sound when Pomodoro sessions end
Sound volumeVolume for Pomodoro sounds (0-100)
Pomodoro data storageConfigure where Pomodoro session data is stored and how it's managed.
Mobile sidebarWhere to open the Pomodoro timer on mobile devices
Enable notificationsEnable task reminder notifications
Notification typeType of notifications to show
Send test reminderSend a test reminder using the current notification type and sound settings.
Notification soundPlay a sound when task reminders trigger
Sound volumeVolume for task reminder sounds (0-100)
Preview notification soundPlay the configured task reminder sound
Hide completed tasks from overdueExclude completed tasks from overdue task calculations
Disable note indexingDisable automatic indexing of note content for better performance
Suggestion debounceDelay in milliseconds before showing suggestions
Auto-stop time trackingAutomatically stop time tracking when a task is marked complete
Time tracking stop notificationShow notification when time tracking is automatically stopped
Maintain due date offset in recurring tasksKeep the offset between due date and scheduled date when recurring tasks are completed
Reset checkboxes on recurrenceReset all Markdown checkboxes in the task body when a recurring task is completed and rescheduled
Enable timeblockingEnable timeblocking feature for lightweight scheduling in daily notes. When enabled, 'Timeblock' option appears in the calendar drag context menu.
Show timeblocksDisplay timeblocks from daily notes by default
Default timeblock colorThe default color used when creating new timeblocks
Enable debug loggingLog detailed drag-and-drop and view diagnostics to the developer console. Useful for troubleshooting.
\n

Integrations#

\n

Source: src/settings/tabs/integrationsTab.ts

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
SettingPurpose
Generate mdbase type definitionsSee the setting in Obsidian for contextual details.
Disable calendar integrations on mobileSkip Google, Microsoft, and ICS calendar loading on Obsidian mobile. Desktop calendar integrations are unchanged.
Calendar integrations are disabled on this mobile deviceSee the setting in Obsidian for contextual details.
Enable task exportWhen enabled, tasks with dates will be automatically synced to Google Calendar as events.
Target calendarSee the setting in Obsidian for contextual details.
Sync triggerWhich task date should trigger calendar event creation.
Create as all-day eventsWhen enabled, tasks are created as all-day events. When disabled, uses time estimate for duration.
Default event durationDuration in minutes for timed events (used when task has no time estimate).
Event title templateTemplate for event titles. Available variables: {{title}}, {{status}}, {{priority}}
Include task details in descriptionAdd task metadata (priority, status, tags, etc.) to the event description.
Include Obsidian linkAdd a link back to the task in Obsidian in the event description.
Default reminderAdd popup reminders to timed Google Calendar events. Enter minutes before the event, separated by commas. Leave empty to use calendar defaults. Common values: 15, 30, 60, 1440.
Automatic sync behaviorSee the setting in Obsidian for contextual details.
Sync on task createAutomatically create calendar event when a new task is created.
Sync on task updateAutomatically update calendar event when a task is modified.
Sync on task completeUpdate calendar event when a task is completed (adds checkmark to title).
Delete event on task deleteRemove calendar event when the corresponding task is deleted.
Manual sync actionsSee the setting in Obsidian for contextual details.
Sync all tasksSync all existing tasks to Google Calendar. This will create events for tasks that haven't been synced yet.
Unlink all tasksRemove all task-event links without deleting calendar events.
Default note templatePath to template file for notes created from ICS events
Default note folderFolder for notes created from ICS events
ICS note filename formatHow filenames are generated for notes created from ICS events
Custom ICS filename templateTemplate for custom ICS event filenames
Use ICS event end time as task due dateWhen enabled, tasks created from calendar events will have their due date set to the event's end time. For all-day events, the due date will be set to the event date. For timed events, the due date will include the end time.
Recurring event related notesChoose whether notes linked to one recurrence of an external calendar event appear across the loaded series or only on the selected instance.
Add calendar subscriptionAdd a new calendar subscription from ICS/iCal URL or local file
New calendarSee the setting in Obsidian for contextual details.
Refresh all subscriptionsManually refresh all enabled calendar subscriptions
Enable automatic exportAutomatically keep an ICS file updated with all your tasks
Export file pathPath where the ICS file will be saved (relative to vault root)
Update interval (between 5 and 1440 minutes)How often to update the export file
Use task duration for event lengthWhen enabled, uses the task's time estimate (duration) instead of due date for the calendar event end time. This is useful for GTD workflows where scheduled + duration represents work planning, while due date represents deadlines.
Exclude completed tasksWhen enabled, completed tasks are omitted from ICS exports. Completed statuses are taken from your task statuses settings.
Exclude archived tasksWhen enabled, archived tasks are omitted from ICS exports.
Require due dateWhen enabled, only tasks with a due date are included in ICS exports.
Require scheduled dateWhen enabled, only tasks with a scheduled date are included in ICS exports.
Export nowManually trigger an immediate export
Export status:See the setting in Obsidian for contextual details.
Enable HTTP APIStart local HTTP server for API access
API portPort number for the HTTP API server
API authentication tokenRequired for API authentication. If empty, a token is generated when the server starts.
Enable MCP serverExpose TaskNotes tools via Model Context Protocol at /mcp endpoint. Requires HTTP API to be enabled.
Add webhookRegister a new webhook endpoint
\n

Complete default settings snapshot#

\n

The following JSON is generated from DEFAULT_SETTINGS. Empty strings and disabled flags are intentional defaults.

\n
{\n  "tasksFolder": "TaskNotes/Tasks",\n  "moveArchivedTasks": false,\n  "archiveFolder": "TaskNotes/Archive",\n  "taskTag": "task",\n  "taskIdentificationMethod": "tag",\n  "hideIdentifyingTagsInCards": false,\n  "hideIdentifyingTagsMode": "all",\n  "taskPropertyName": "",\n  "taskPropertyValue": "",\n  "excludedFolders": "",\n  "defaultTaskPriority": "normal",\n  "defaultTaskStatus": "open",\n  "taskOrgFiltersCollapsed": false,\n  "taskFilenameFormat": "zettel",\n  "storeTitleInFilename": true,\n  "customFilenameTemplate": "{{title}}",\n  "occurrenceFilenameTemplate": "",\n  "occurrenceFilenameTemplateProperty": "occurrenceFilenameTemplate",\n  "taskCreationDefaults": {\n    "defaultContexts": "",\n    "defaultTags": "",\n    "defaultProjects": "",\n    "useParentNoteForTaskCreation": false,\n    "useParentNoteAsProject": false,\n    "useParentHeaderAsProject": false,\n    "inheritParentTaskProperties": false,\n    "defaultTimeEstimate": 0,\n    "defaultRecurrence": "none",\n    "defaultDueDate": "none",\n    "defaultDueTime": "none",\n    "defaultScheduledDate": "today",\n    "defaultScheduledTime": "none",\n    "bodyTemplate": "",\n    "useBodyTemplate": false,\n    "occurrenceBodyTemplate": "",\n    "useOccurrenceBodyTemplate": false,\n    "defaultReminders": []\n  },\n  "openTaskAfterCreation": "none",\n  "calendarViewSettings": {\n    "defaultView": "dayGridMonth",\n    "customDayCount": 3,\n    "slotDuration": "00:30:00",\n    "slotMinTime": "00:00:00",\n    "slotMaxTime": "24:00:00",\n    "scrollTime": "08:00:00",\n    "firstDay": 1,\n    "timeFormat": "24",\n    "showWeekends": true,\n    "locale": "",\n    "defaultShowScheduled": true,\n    "defaultShowDue": true,\n    "defaultShowDueWhenScheduled": true,\n    "defaultShowScheduledToDueSpan": false,\n    "defaultShowTimeEntries": false,\n    "defaultShowRecurring": true,\n    "defaultShowICSEvents": true,\n    "enableTimeblocking": false,\n    "defaultShowTimeblocks": true,\n    "defaultTimeblockColor": "#6366f1",\n    "timeblockAttachmentSearchOrder": "name-asc",\n    "nowIndicator": true,\n    "selectMirror": true,\n    "weekNumbers": false,\n    "showTodayHighlight": true,\n    "eventMinHeight": 15,\n    "slotEventOverlap": true,\n    "eventMaxStack": null,\n    "dayMaxEvents": true,\n    "dayMaxEventRows": false\n  },\n  "pomodoroWorkDuration": 25,\n  "pomodoroShortBreakDuration": 5,\n  "pomodoroLongBreakDuration": 15,\n  "pomodoroLongBreakInterval": 4,\n  "pomodoroAutoStartBreaks": true,\n  "pomodoroAutoStartWork": false,\n  "pomodoroNotifications": true,\n  "pomodoroSoundEnabled": true,\n  "pomodoroSoundVolume": 50,\n  "pomodoroStorageLocation": "plugin",\n  "pomodoroMobileSidebar": "tab",\n  "showPomodoroInStatusBar": true,\n  "enableTaskLinkOverlay": true,\n  "disableOverlayOnAlias": false,\n  "enableInstantTaskConvert": true,\n  "useDefaultsOnInstantConvert": true,\n  "preserveCheckboxOnConvert": false,\n  "taskModalTabMovesFocus": true,\n  "enableNaturalLanguageInput": true,\n  "nlpDefaultToScheduled": true,\n  "nlpLanguage": "en",\n  "uiLanguage": "system",\n  "statusSuggestionTrigger": "*",\n  "nlpTriggers": {\n    "triggers": [\n      {\n        "propertyId": "tags",\n        "trigger": "#",\n        "enabled": true\n      },\n      {\n        "propertyId": "contexts",\n        "trigger": "@",\n        "enabled": true\n      },\n      {\n        "propertyId": "projects",\n        "trigger": "+",\n        "enabled": true\n      },\n      {\n        "propertyId": "status",\n        "trigger": "*",\n        "enabled": true\n      },\n      {\n        "propertyId": "priority",\n        "trigger": "!",\n        "enabled": false\n      }\n    ]\n  },\n  "singleClickAction": "edit",\n  "doubleClickAction": "openNote",\n  "projectAutosuggest": {\n    "enableFuzzy": false,\n    "rows": [\n      "{title|n(Title)}",\n      "{aliases|n(Aliases)}",\n      "{file.path|n(Path)}"\n    ],\n    "showAdvanced": false,\n    "requiredTags": [],\n    "includeFolders": [],\n    "propertyKey": "",\n    "propertyValue": ""\n  },\n  "inlineTaskConvertFolder": "{{currentNotePath}}",\n  "disableNoteIndexing": false,\n  "suggestionDebounceMs": 0,\n  "fieldMapping": {\n    "title": "title",\n    "status": "status",\n    "priority": "priority",\n    "due": "due",\n    "scheduled": "scheduled",\n    "contexts": "contexts",\n    "projects": "projects",\n    "attachments": "attachments",\n    "timeEstimate": "timeEstimate",\n    "completedDate": "completedDate",\n    "dateCreated": "dateCreated",\n    "dateModified": "dateModified",\n    "recurrence": "recurrence",\n    "recurrenceAnchor": "recurrence_anchor",\n    "recurrenceParent": "recurrence_parent",\n    "occurrenceDate": "occurrence_date",\n    "occurrenceMaterialization": "occurrence_materialization",\n    "occurrenceNextTrigger": "occurrence_next_trigger",\n    "occurrenceTemplate": "occurrence_template",\n    "occurrencePastHorizon": "occurrence_past_horizon",\n    "occurrenceFutureHorizon": "occurrence_future_horizon",\n    "archiveTag": "archived",\n    "timeEntries": "timeEntries",\n    "completeInstances": "complete_instances",\n    "skippedInstances": "skipped_instances",\n    "blockedBy": "blockedBy",\n    "pomodoros": "pomodoros",\n    "icsEventId": "icsEventId",\n    "icsEventTag": "ics_event",\n    "googleCalendarEventId": "googleCalendarEventId",\n    "googleCalendarExceptionEventId": "googleCalendarExceptionEventId",\n    "googleCalendarExceptionOriginalScheduled": "googleCalendarExceptionOriginalScheduled",\n    "googleCalendarMovedOriginalDates": "googleCalendarMovedOriginalDates",\n    "reminders": "reminders",\n    "sortOrder": "tasknotes_manual_order"\n  },\n  "customStatuses": [\n    {\n      "id": "none",\n      "value": "none",\n      "label": "None",\n      "color": "#cccccc",\n      "isCompleted": false,\n      "excludeFromCycle": false,\n      "order": 0,\n      "autoArchive": false,\n      "autoArchiveDelay": 5\n    },\n    {\n      "id": "open",\n      "value": "open",\n      "label": "Open",\n      "color": "#808080",\n      "isCompleted": false,\n      "excludeFromCycle": false,\n      "order": 1,\n      "autoArchive": false,\n      "autoArchiveDelay": 5\n    },\n    {\n      "id": "in-progress",\n      "value": "in-progress",\n      "label": "In progress",\n      "color": "#0066cc",\n      "isCompleted": false,\n      "excludeFromCycle": false,\n      "order": 2,\n      "autoArchive": false,\n      "autoArchiveDelay": 5\n    },\n    {\n      "id": "done",\n      "value": "done",\n      "label": "Done",\n      "color": "#00aa00",\n      "isCompleted": true,\n      "excludeFromCycle": false,\n      "order": 3,\n      "autoArchive": false,\n      "autoArchiveDelay": 5\n    }\n  ],\n  "customPriorities": [\n    {\n      "id": "none",\n      "value": "none",\n      "label": "None",\n      "color": "#cccccc",\n      "weight": 0\n    },\n    {\n      "id": "low",\n      "value": "low",\n      "label": "Low",\n      "color": "#00aa00",\n      "weight": 1\n    },\n    {\n      "id": "normal",\n      "value": "normal",\n      "label": "Normal",\n      "color": "#ffaa00",\n      "weight": 2\n    },\n    {\n      "id": "high",\n      "value": "high",\n      "label": "High",\n      "color": "#ff0000",\n      "weight": 3\n    }\n  ],\n  "recurrenceMigrated": false,\n  "showReleaseNotesOnUpdate": true,\n  "checkForUpdatesOnStartup": true,\n  "starterNoteCreated": false,\n  "showTrackedTasksInStatusBar": false,\n  "autoStopTimeTrackingOnComplete": true,\n  "autoStopTimeTrackingNotification": false,\n  "showRelationships": true,\n  "relationshipsPosition": "bottom",\n  "showTaskCardInNote": true,\n  "showCompletedTaskStrikethrough": true,\n  "completionMenuAsSubmenu": true,\n  "showExpandableSubtasks": true,\n  "expandSubtasksByDefault": false,\n  "subtaskChevronPosition": "right",\n  "viewsButtonAlignment": "right",\n  "hideCompletedFromOverdue": true,\n  "icsIntegration": {\n    "defaultNoteTemplate": "",\n    "defaultNoteFolder": "",\n    "icsNoteFilenameFormat": "title",\n    "customICSNoteFilenameTemplate": "{title}",\n    "enableAutoExport": false,\n    "autoExportPath": "tasknotes-calendar.ics",\n    "autoExportInterval": 60,\n    "useDurationForExport": false,\n    "excludeArchivedFromExport": false,\n    "excludeCompletedFromExport": false,\n    "requireDueDateForExport": false,\n    "requireScheduledDateForExport": false,\n    "useICSEndAsDue": false,\n    "recurringEventRelatedNotesMode": "series"\n  },\n  "savedViews": [],\n  "enableNotifications": true,\n  "notificationType": "system",\n  "notificationSoundEnabled": false,\n  "notificationSoundVolume": 50,\n  "enableAPI": false,\n  "apiPort": 8080,\n  "apiAuthToken": "",\n  "enableMCP": false,\n  "webhooks": [],\n  "userFields": [],\n  "enableModalSplitLayout": true,\n  "defaultVisibleProperties": [\n    "status",\n    "priority",\n    "due",\n    "scheduled",\n    "projects",\n    "contexts",\n    "tags",\n    "blocked",\n    "blocking"\n  ],\n  "inlineVisibleProperties": [\n    "status",\n    "priority",\n    "due",\n    "scheduled",\n    "recurrence"\n  ],\n  "enableBases": true,\n  "enableMdbaseSpec": false,\n  "autoCreateDefaultBasesFiles": true,\n  "commandFileMapping": {\n    "open-calendar-view": "TaskNotes/Views/mini-calendar-default.base",\n    "open-kanban-view": "TaskNotes/Views/kanban-default.base",\n    "open-tasks-view": "TaskNotes/Views/tasks-default.base",\n    "open-advanced-calendar-view": "TaskNotes/Views/calendar-default.base",\n    "open-agenda-view": "TaskNotes/Views/agenda-default.base",\n    "pomodoro-stats-base": "TaskNotes/Views/pomodoro-stats.base",\n    "relationships": "TaskNotes/Views/relationships.base"\n  },\n  "maintainDueDateOffsetInRecurring": false,\n  "resetCheckboxesOnRecurrence": false,\n  "useFrontmatterMarkdownLinks": false,\n  "enableGoogleCalendar": false,\n  "enableMicrosoftCalendar": false,\n  "disableCalendarOnMobile": false,\n  "enabledGoogleCalendars": [],\n  "googleCalendarSyncTokens": {},\n  "enabledMicrosoftCalendars": [],\n  "microsoftCalendarSyncTokens": {},\n  "googleCalendarExport": {\n    "enabled": false,\n    "targetCalendarId": "",\n    "syncOnTaskCreate": true,\n    "syncOnTaskUpdate": true,\n    "syncOnTaskComplete": true,\n    "syncOnTaskDelete": true,\n    "eventTitleTemplate": "{{title}}",\n    "includeDescription": true,\n    "eventColorId": null,\n    "syncTrigger": "scheduled",\n    "createAsAllDay": true,\n    "defaultEventDuration": 60,\n    "includeObsidianLink": true,\n    "defaultReminderMinutes": null\n  },\n  "enableDebugLogging": false\n}\n
","text":"TaskNotes currently exposes 6 settings tabs. This inventory is generated from the tab renderer and English translation source so additions cannot silently disappear from the documentation. General# Source: src/settings/tabs/generalTab.ts Setting Purpose Default tasks folder Default location for new tasks. Supports folder template variables like {{currentNotePath}}, {{currentNoteTitle}}, and {{projectFilePath}}, plus Daily Notes-style date tokens like YYYY/MM/DD. Folder for inline-created tasks Folder where tasks created from inline commands or checkbox conversion will be created. Leave empty to use the default tasks folder. Use {{currentNotePath}} for the current note's folder, or {{currentNoteTitle}} for a subfolder named after the current note. Move archived tasks to folder Automatically move archived tasks to an archive folder Archive folder Folder to move tasks to when archived. Supports template variables like {{year}}, {{month}}, {{priority}}, etc. Identify tasks by Choose whether to identify tasks by tag or by a frontmatter property Task tag Tag that identifies notes as tasks (without #). Existing .base view filters keep their old tag when this changes; update default Base files or edit those filters. Hide identification tags in task cards When enabled, tags matching the task identification tag (including hierarchical matches like 'task/project') will be hidden from task card displays Hidden tag scope Choose whether hiding identification tags also hides nested tags. Task property name The frontmatter property name (e.g., \"category\") Task property value The value that identifies a note as a task (e.g., \"task\") Auto-create default files Automatically create missing default base view files on startup. Disable to prevent deleted sample files from being recreated. Create default files Create the default .base files in TaskNotes/Views/ directory. Existing files will not be overwritten. Update default files Overwrite the configured default .base files with templates generated from your current TaskNotes settings. Export v3 saved views to Bases Convert all your saved views from TaskNotes v3 into a single .base file with multiple views. This helps migrate your v3 filter configurations to the new Bases system. Excluded folders Comma-separated list of folders to exclude from task indexing and project suggestions UI language Select the language used for TaskNotes interface text Use Markdown links in frontmatter Generate markdown links ([text](path)) instead of wikilinks ([[link]]) in frontmatter properties. ⚠️ Requires the 'obsidian-frontmatter-markdown-links' plugin to work correctly. Show release notes after update Automatically open release notes when TaskNotes is updated to a new version Check for new releases on startup Check GitHub once when TaskNotes starts and show a notice when a newer compatible release is available View release notes See what's new in the latest version of TaskNotes Task properties# Source: src/settings/tabs/taskPropertiesTab.ts Setting Purpose No static controls detected This tab is assembled dynamically. Modal fields# Source: src/settings/tabs/modalFieldsTab.ts Setting Purpose No static controls detected This tab is assembled dynamically. Appearance & UI# Source: src/settings/tabs/appearanceTab.ts Setting Purpose Default visible properties Choose which properties appear on task cards by default. Group complete and skip actions in a submenu Nest the complete and skip actions under a submenu in the task context menu. Turn off to show them directly in the menu. Time format Display time in 12-hour or 24-hour format throughout the plugin Default view The calendar view shown when opening the calendar tab Custom view day count Number of days to show in custom multi-day view First day of week Which day should be the first column in week views Show weekends Display weekends in calendar views Show week numbers Display week numbers in calendar views Show today highlight Highlight the current day in calendar views Show current time indicator Display a line showing the current time in timeline views Selection mirror Show a visual preview while dragging to select time ranges Calendar locale Calendar locale for date formatting and calendar system (e.g., \"en\", \"fa\" for Farsi/Persian, \"de\" for German). Leave empty to auto-detect from browser. Show scheduled tasks Display tasks with scheduled dates by default Show due dates Display task due dates by default Show due dates when scheduled Display due dates even for tasks that already have scheduled dates Show time entries Display completed time tracking entries by default Show recurring tasks Display recurring task instances by default Show ICS events Display events from ICS subscriptions by default Time slot duration Duration of each time slot in timeline views Start time Earliest time shown in timeline views (HH:MM format) End time Latest time shown in timeline views (HH:MM format). Use values above 24:00 to show early next-day hours, such as 26:00 for 2 AM. Initial scroll time Time to scroll to when opening timeline views (HH:MM format) Event minimum height Minimum height for events in timeline views (pixels) Show tracked tasks in status bar Display currently tracked tasks in Obsidian's status bar Show relationships widget Display a widget showing all relationships for the current note (subtasks, projects, dependencies) Relationships position Where to position the relationships widget Show task card in note Display a task card widget at the top of task notes showing the task details and actions Strike through completed task titles Draw a line through completed task card titles. Turn off to keep completed tasks easier to read Show expandable subtasks Allow expanding/collapsing subtask sections in task cards Expand subtasks by default Show project subtasks expanded when task cards are rendered Subtask chevron position Position of expand/collapse chevrons in task cards Views button alignment Alignment of the views/filters button in the task interface Single-click action Action performed when single-clicking a task card Double-click action Action performed when double-clicking a task card Features# Source: src/settings/tabs/featuresTab.ts Setting Purpose Task link overlay Show interactive overlays when hovering over task links Disable overlay for aliased links Do not show the task widget if the link contains an alias (e.g. [[Task|Alias]]). Show convert button next to checkboxes Display an inline button next to Markdown checkboxes that converts them to TaskNotes Keep checkbox when converting Leave the original Markdown checkbox marker in place when converting a checkbox to a TaskNote link Enable natural language task input Parse due dates, priorities, and contexts from natural language when creating tasks Default to scheduled When NLP detects a date without context, treat it as scheduled rather than due NLP language Language for natural language processing patterns and date parsing Open task after creation Choose whether the task creation modal opens the new task note after saving. Use body template Use a template file for task body content Body template file Path to template file for task body content. Supports template variables like {{title}}, {{date}}, {{time}}, {{priority}}, {{status}}, etc. Use occurrence note template Use a separate fallback template for materialized occurrence notes when the recurring task has no occurrence_template Occurrence note template file Path to template file for materialized occurrence notes. A recurring task's occurrence_template field takes priority over this fallback. Template variables: See the setting in Obsidian for contextual details. Use task defaults on instant convert Apply default task settings when converting text to tasks instantly Work duration Duration of work intervals in minutes Short break duration Duration of short breaks in minutes Long break duration Duration of long breaks in minutes Long break interval Number of work sessions before a long break Auto-start breaks Automatically start break timers after work sessions Auto-start work Automatically start work sessions after breaks Pomodoro notifications Show notifications when Pomodoro sessions end Show Pomodoro in status bar Display the active Pomodoro countdown in Obsidian's status bar Sound enabled Play sound when Pomodoro sessions end Sound volume Volume for Pomodoro sounds (0-100) Pomodoro data storage Configure where Pomodoro session data is stored and how it's managed. Mobile sidebar Where to open the Pomodoro timer on mobile devices Enable notifications Enable task reminder notifications Notification type Type of notifications to show Send test reminder Send a test reminder using the current notification type and sound settings. Notification sound Play a sound when task reminders trigger Sound volume Volume for task reminder sounds (0-100) Preview notification sound Play the configured task reminder sound Hide completed tasks from overdue Exclude completed tasks from overdue task calculations Disable note indexing Disable automatic indexing of note content for better performance Suggestion debounce Delay in milliseconds before showing suggestions Auto-stop time tracking Automatically stop time tracking when a task is marked complete Time tracking stop notification Show notification when time tracking is automatically stopped Maintain due date offset in recurring tasks Keep the offset between due date and scheduled date when recurring tasks are completed Reset checkboxes on recurrence Reset all Markdown checkboxes in the task body when a recurring task is completed and rescheduled Enable timeblocking Enable timeblocking feature for lightweight scheduling in daily notes. When enabled, 'Timeblock' option appears in the calendar drag context menu. Show timeblocks Display timeblocks from daily notes by default Default timeblock color The default color used when creating new timeblocks Enable debug logging Log detailed drag-and-drop and view diagnostics to the developer console. Useful for troubleshooting. Integrations# Source: src/settings/tabs/integrationsTab.ts Setting Purpose Generate mdbase type definitions See the setting in Obsidian for contextual details. Disable calendar integrations on mobile Skip Google, Microsoft, and ICS calendar loading on Obsidian mobile. Desktop calendar integrations are unchanged. Calendar integrations are disabled on this mobile device See the setting in Obsidian for contextual details. Enable task export When enabled, tasks with dates will be automatically synced to Google Calendar as events. Target calendar See the setting in Obsidian for contextual details. Sync trigger Which task date should trigger calendar event creation. Create as all-day events When enabled, tasks are created as all-day events. When disabled, uses time estimate for duration. Default event duration Duration in minutes for timed events (used when task has no time estimate). Event title template Template for event titles. Available variables: {{title}}, {{status}}, {{priority}} Include task details in description Add task metadata (priority, status, tags, etc.) to the event description. Include Obsidian link Add a link back to the task in Obsidian in the event description. Default reminder Add popup reminders to timed Google Calendar events. Enter minutes before the event, separated by commas. Leave empty to use calendar defaults. Common values: 15, 30, 60, 1440. Automatic sync behavior See the setting in Obsidian for contextual details. Sync on task create Automatically create calendar event when a new task is created. Sync on task update Automatically update calendar event when a task is modified. Sync on task complete Update calendar event when a task is completed (adds checkmark to title). Delete event on task delete Remove calendar event when the corresponding task is deleted. Manual sync actions See the setting in Obsidian for contextual details. Sync all tasks Sync all existing tasks to Google Calendar. This will create events for tasks that haven't been synced yet. Unlink all tasks Remove all task-event links without deleting calendar events. Default note template Path to template file for notes created from ICS events Default note folder Folder for notes created from ICS events ICS note filename format How filenames are generated for notes created from ICS events Custom ICS filename template Template for custom ICS event filenames Use ICS event end time as task due date When enabled, tasks created from calendar events will have their due date set to the event's end time. For all-day events, the due date will be set to the event date. For timed events, the due date will include the end time. Recurring event related notes Choose whether notes linked to one recurrence of an external calendar event appear across the loaded series or only on the selected instance. Add calendar subscription Add a new calendar subscription from ICS/iCal URL or local file New calendar See the setting in Obsidian for contextual details. Refresh all subscriptions Manually refresh all enabled calendar subscriptions Enable automatic export Automatically keep an ICS file updated with all your tasks Export file path Path where the ICS file will be saved (relative to vault root) Update interval (between 5 and 1440 minutes) How often to update the export file Use task duration for event length When enabled, uses the task's time estimate (duration) instead of due date for the calendar event end time. This is useful for GTD workflows where scheduled + duration represents work planning, while due date represents deadlines. Exclude completed tasks When enabled, completed tasks are omitted from ICS exports. Completed statuses are taken from your task statuses settings. Exclude archived tasks When enabled, archived tasks are omitted from ICS exports. Require due date When enabled, only tasks with a due date are included in ICS exports. Require scheduled date When enabled, only tasks with a scheduled date are included in ICS exports. Export now Manually trigger an immediate export Export status: See the setting in Obsidian for contextual details. Enable HTTP API Start local HTTP server for API access API port Port number for the HTTP API server API authentication token Required for API authentication. If empty, a token is generated when the server starts. Enable MCP server Expose TaskNotes tools via Model Context Protocol at /mcp endpoint. Requires HTTP API to be enabled. Add webhook Register a new webhook endpoint Complete default settings snapshot# The following JSON is generated from DEFAULT_SETTINGS. Empty strings and disabled flags are intentional defaults. { \"tasksFolder\": \"TaskNotes/Tasks\", \"moveArchivedTasks\": false, \"archiveFolder\": \"TaskNotes/Archive\", \"taskTag\": \"task\", \"taskIdentificationMethod\": \"tag\", \"hideIdentifyingTagsInCards\": false, \"hideIdentifyingTagsMode\": \"all\", \"taskPropertyName\": \"\", \"taskPropertyValue\": \"\", \"excludedFolders\": \"\", \"defaultTaskPriority\": \"normal\", \"defaultTaskStatus\": \"open\", \"taskOrgFiltersCollapsed\": false, \"taskFilenameFormat\": \"zettel\", \"storeTitleInFilename\": true, \"customFilenameTemplate\": \"{{title}}\", \"occurrenceFilenameTemplate\": \"\", \"occurrenceFilenameTemplateProperty\": \"occurrenceFilenameTemplate\", \"taskCreationDefaults\": { \"defaultContexts\": \"\", \"defaultTags\": \"\", \"defaultProjects\": \"\", \"useParentNoteForTaskCreation\": false, \"useParentNoteAsProject\": false, \"useParentHeaderAsProject\": false, \"inheritParentTaskProperties\": false, \"defaultTimeEstimate\": 0, \"defaultRecurrence\": \"none\", \"defaultDueDate\": \"none\", \"defaultDueTime\": \"none\", \"defaultScheduledDate\": \"today\", \"defaultScheduledTime\": \"none\", \"bodyTemplate\": \"\", \"useBodyTemplate\": false, \"occurrenceBodyTemplate\": \"\", \"useOccurrenceBodyTemplate\": false, \"defaultReminders\": [] }, \"openTaskAfterCreation\": \"none\", \"calendarViewSettings\": { \"defaultView\": \"dayGridMonth\", \"customDayCount\": 3, \"slotDu"},{"route":"/obsidian/releases/","title":"Release Notes","description":"Welcome to the TaskNotes release notes. Here you can find detailed information about each version, including new features, bug fixes, and improvements.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases.md","namespace":"obsidian","relativePath":"releases.md","raw":"# Release Notes\n\nWelcome to the TaskNotes release notes. Here you can find detailed information about each version, including new features, bug fixes, and improvements.\n\n## Latest Releases\n\n### Version 4.x (Current)\n\n- [4.13.0](releases/4.13.0.md)\n- [4.12.5](releases/4.12.5.md)\n- [4.12.4](releases/4.12.4.md)\n- [4.12.3](releases/4.12.3.md)\n- [4.12.2](releases/4.12.2.md)\n- [4.12.1](releases/4.12.1.md)\n- [4.12.0](releases/4.12.0.md)\n- [4.11.1](releases/4.11.1.md)\n- [4.11.0](releases/4.11.0.md)\n- [4.10.2](releases/4.10.2.md)\n- [4.10.1](releases/4.10.1.md)\n- [4.10.0](releases/4.10.0.md)\n- [4.9.2](releases/4.9.2.md)\n- [4.9.1](releases/4.9.1.md)\n- [4.9.0](releases/4.9.0.md)\n- [4.8.1](releases/4.8.1.md)\n- [4.8.0](releases/4.8.0.md)\n- [4.7.2](releases/4.7.2.md)\n- [4.7.1](releases/4.7.1.md)\n- [4.7.0](releases/4.7.0.md)\n- [4.6.0](releases/4.6.0.md)\n- [4.5.3](releases/4.5.3.md)\n- [4.5.2](releases/4.5.2.md)\n- [4.5.1](releases/4.5.1.md)\n- [4.5.0](releases/4.5.0.md)\n- [4.4.0](releases/4.4.0.md)\n- [4.3.3](releases/4.3.3.md)\n- [4.3.2](releases/4.3.2.md)\n- [4.3.1](releases/4.3.1.md)\n- [4.3.0](releases/4.3.0.md)\n- [4.2.1](releases/4.2.1.md)\n- [4.2.0](releases/4.2.0.md)\n- [4.1.3](releases/4.1.3.md)\n- [4.1.2](releases/4.1.2.md)\n- [4.1.1](releases/4.1.1.md)\n- [4.1.0](releases/4.1.0.md)\n- [4.0.5](releases/4.0.5.md)\n- [4.0.4](releases/4.0.4.md)\n- [4.0.3](releases/4.0.3.md)\n- [4.0.2](releases/4.0.2.md)\n- [4.0.1](releases/4.0.1.md)\n- [4.0.0-beta.3](releases/4.0.0-beta.3.md)\n- [4.0.0-beta.2](releases/4.0.0-beta.2.md)\n- [4.0.0-beta.1](releases/4.0.0-beta.1.md)\n- [4.0.0-beta.0](releases/4.0.0-beta.0.md)\n\n### Version 3.x\n\n- [3.25.6](releases/3.25.6.md)\n- [3.25.4](releases/3.25.4.md)\n- [3.25.3](releases/3.25.3.md)\n- [3.25.2](releases/3.25.2.md)\n- [3.25.1](releases/3.25.1.md)\n- [3.25.0](releases/3.25.0.md)\n- [3.24.6](releases/3.24.6.md)\n- [3.24.5](releases/3.24.5.md)\n- [3.24.4](releases/3.24.4.md)\n- [3.24.3](releases/3.24.3.md)\n- [3.24.2](releases/3.24.2.md)\n- [3.24.1](releases/3.24.1.md)\n- [3.24.0](releases/3.24.0.md)\n- [3.23.4](releases/3.23.4.md)\n- [3.23.3](releases/3.23.3.md)\n- [3.23.2](releases/3.23.2.md)\n- [3.23.1](releases/3.23.1.md)\n- [3.23.0](releases/3.23.0.md)\n- [3.22.1](releases/3.22.1.md)\n- [3.22.0](releases/3.22.0.md)\n- [3.21.0](releases/3.21.0.md)\n- [3.20.1](releases/3.20.1.md)\n- [3.20.0](releases/3.20.0.md)\n- [3.19.1](releases/3.19.1.md)\n- [3.19.0](releases/3.19.0.md)\n- [3.18.2](releases/3.18.2.md)\n- [3.18.1](releases/3.18.1.md)\n- [3.18.0](releases/3.18.0.md)\n- [3.17.1](releases/3.17.1.md)\n- [3.17.0](releases/3.17.0.md)\n- [3.16.4](releases/3.16.4.md)\n- [3.16.3](releases/3.16.3.md)\n- [3.16.2](releases/3.16.2.md)\n- [3.16.1](releases/3.16.1.md)\n- [3.16.0](releases/3.16.0.md)\n- [3.15.1](releases/3.15.1.md)\n- [3.15.0](releases/3.15.0.md)\n- [3.14.0](releases/3.14.0.md)\n- [3.13.4](releases/3.13.4.md)\n- [3.13.3](releases/3.13.3.md)\n- [3.13.2](releases/3.13.2.md)\n- [3.13.1](releases/3.13.1.md)\n- [3.13.0](releases/3.13.0.md)\n- [3.12.2](releases/3.12.2.md)\n- [3.12.1](releases/3.12.1.md)\n- [3.12.0](releases/3.12.0.md)\n- [3.11.2](releases/3.11.2.md)\n- [3.11.1](releases/3.11.1.md)\n- [3.11.0](releases/3.11.0.md)\n- [3.10.0](releases/3.10.0.md)\n- [3.9.1](releases/3.9.1.md)\n- [3.9.0](releases/3.9.0.md)\n- [3.8.7](releases/3.8.7.md)\n- [3.8.6](releases/3.8.6.md)\n- [3.8.5](releases/3.8.5.md)\n- [3.8.1](releases/3.8.1.md)\n- [3.7.1](releases/3.7.1.md)\n- [3.7.0](releases/3.7.0.md)\n- [3.6.0](releases/3.6.0.md)\n- [3.5.1](releases/3.5.1.md)\n- [3.4.2](releases/3.4.2.md)\n- [3.4.1](releases/3.4.1.md)\n- [3.4.0](releases/3.4.0.md)\n- [3.3.0](releases/3.3.0.md)\n- [3.1.1](releases/3.1.1.md)\n- [3.1.0](releases/3.1.0.md)\n- [3.0.1](releases/3.0.1.md)\n- [3.0.0](releases/3.0.0.md)\n\n### Version 2.x\n\n- [2.2.3](releases/2.2.3.md)\n- [2.2.2](releases/2.2.2.md)\n- [2.2.1](releases/2.2.1.md)\n- [2.2.0](releases/2.2.0.md)\n- [2.1.0](releases/2.1.0.md)\n- [2.0.4](releases/2.0.4.md)\n- [2.0.3](releases/2.0.3.md)\n- [2.0.2](releases/2.0.2.md)\n- [2.0.1](releases/2.0.1.md)\n- [2.0.0](releases/2.0.0.md)\n\n### Version 1.x\n\n- [1.2.0](releases/1.2.0.md)\n- [1.1.0](releases/1.1.0.md)\n- [1.0.0](releases/1.0.0.md)\n\n### Early Versions (0.x)\n\n- [0.8.0](releases/0.8.0.md)\n- [0.7.0](releases/0.7.0.md)\n- [0.6.3](releases/0.6.3.md)\n- [0.6.2](releases/0.6.2.md)\n- [0.6.1](releases/0.6.1.md)\n- [0.6.0](releases/0.6.0.md)\n- [0.4.2](releases/0.4.2.md)\n- [0.4.1](releases/0.4.1.md)\n- [0.4.0](releases/0.4.0.md)\n- [0.3.0](releases/0.3.0.md)\n- [0.2.4](releases/0.2.4.md)\n- [0.2.3](releases/0.2.3.md)\n- [0.2.2](releases/0.2.2.md)\n\n## Getting Updates\n\nTo update TaskNotes:\n1. Open Obsidian\n2. Go to Settings → Community Plugins\n3. Find TaskNotes and click \"Update\"\n4. Restart Obsidian if prompted\n\n## Feedback\n\nFound a bug or have a feature request? Please:\n\n- Check existing [GitHub Issues](https://github.com/callumalpass/tasknotes/issues)\n- Create a new issue with details\n","aliases":["/releases/","/releases/"],"toc":[{"level":2,"id":"latest-releases","text":"Latest Releases"},{"level":3,"id":"version-4x-current","text":"Version 4.x (Current)"},{"level":3,"id":"version-3x","text":"Version 3.x"},{"level":3,"id":"version-2x","text":"Version 2.x"},{"level":3,"id":"version-1x","text":"Version 1.x"},{"level":3,"id":"early-versions-0x","text":"Early Versions (0.x)"},{"level":2,"id":"getting-updates","text":"Getting Updates"},{"level":2,"id":"feedback","text":"Feedback"}],"html":"

Welcome to the TaskNotes release notes. Here you can find detailed information about each version, including new features, bug fixes, and improvements.

\n

Latest Releases#

\n

Version 4.x (Current)#

\n\n

Version 3.x#

\n\n

Version 2.x#

\n\n

Version 1.x#

\n\n

Early Versions (0.x)#

\n\n

Getting Updates#

\n

To update TaskNotes:

\n
    \n
  1. Open Obsidian
  2. \n
  3. Go to Settings → Community Plugins
  4. \n
  5. Find TaskNotes and click "Update"
  6. \n
  7. Restart Obsidian if prompted
  8. \n
\n

Feedback#

\n

Found a bug or have a feature request? Please:

\n
    \n
  • Check existing GitHub Issues
  • \n
  • Create a new issue with details
  • \n
\n","text":"Welcome to the TaskNotes release notes. Here you can find detailed information about each version, including new features, bug fixes, and improvements. Latest Releases# Version 4.x (Current)# 4.13.0 4.12.5 4.12.4 4.12.3 4.12.2 4.12.1 4.12.0 4.11.1 4.11.0 4.10.2 4.10.1 4.10.0 4.9.2 4.9.1 4.9.0 4.8.1 4.8.0 4.7.2 4.7.1 4.7.0 4.6.0 4.5.3 4.5.2 4.5.1 4.5.0 4.4.0 4.3.3 4.3.2 4.3.1 4.3.0 4.2.1 4.2.0 4.1.3 4.1.2 4.1.1 4.1.0 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 4.0.0-beta.3 4.0.0-beta.2 4.0.0-beta.1 4.0.0-beta.0 Version 3.x# 3.25.6 3.25.4 3.25.3 3.25.2 3.25.1 3.25.0 3.24.6 3.24.5 3.24.4 3.24.3 3.24.2 3.24.1 3.24.0 3.23.4 3.23.3 3.23.2 3.23.1 3.23.0 3.22.1 3.22.0 3.21.0 3.20.1 3.20.0 3.19.1 3.19.0 3.18.2 3.18.1 3.18.0 3.17.1 3.17.0 3.16.4 3.16.3 3.16.2 3.16.1 3.16.0 3.15.1 3.15.0 3.14.0 3.13.4 3.13.3 3.13.2 3.13.1 3.13.0 3.12.2 3.12.1 3.12.0 3.11.2 3.11.1 3.11.0 3.10.0 3.9.1 3.9.0 3.8.7 3.8.6 3.8.5 3.8.1 3.7.1 3.7.0 3.6.0 3.5.1 3.4.2 3.4.1 3.4.0 3.3.0 3.1.1 3.1.0 3.0.1 3.0.0 Version 2.x# 2.2.3 2.2.2 2.2.1 2.2.0 2.1.0 2.0.4 2.0.3 2.0.2 2.0.1 2.0.0 Version 1.x# 1.2.0 1.1.0 1.0.0 Early Versions (0.x)# 0.8.0 0.7.0 0.6.3 0.6.2 0.6.1 0.6.0 0.4.2 0.4.1 0.4.0 0.3.0 0.2.4 0.2.3 0.2.2 Getting Updates# To update TaskNotes: Open Obsidian Go to Settings → Community Plugins Find TaskNotes and click \"Update\" Restart Obsidian if prompted Feedback# Found a bug or have a feature request? Please: Check existing GitHub Issues Create a new issue with details"},{"route":"/obsidian/releases/0.2.2/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.1...0.2.2","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.2.2.md","namespace":"obsidian","relativePath":"releases/0.2.2.md","raw":"**Full Changelog**: https://github.com/callumalpass/chronosync/compare/0.2.1...0.2.2\n","aliases":["/releases/0.2.2/","/releases/0.2.2/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.1...0.2.2

\n","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.1...0.2.2"},{"route":"/obsidian/releases/0.2.3/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.2...0.2.3","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.2.3.md","namespace":"obsidian","relativePath":"releases/0.2.3.md","raw":"**Full Changelog**: https://github.com/callumalpass/chronosync/compare/0.2.2...0.2.3\n","aliases":["/releases/0.2.3/","/releases/0.2.3/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.2...0.2.3

\n","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.2...0.2.3"},{"route":"/obsidian/releases/0.2.4/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.3...0.2.4","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.2.4.md","namespace":"obsidian","relativePath":"releases/0.2.4.md","raw":"**Full Changelog**: https://github.com/callumalpass/chronosync/compare/0.2.3...0.2.4\n","aliases":["/releases/0.2.4/","/releases/0.2.4/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.3...0.2.4

\n","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.3...0.2.4"},{"route":"/obsidian/releases/0.3.0/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.4...0.3.0","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.3.0.md","namespace":"obsidian","relativePath":"releases/0.3.0.md","raw":"**Full Changelog**: https://github.com/callumalpass/chronosync/compare/0.2.4...0.3.0\n","aliases":["/releases/0.3.0/","/releases/0.3.0/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.4...0.3.0

\n","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.4...0.3.0"},{"route":"/obsidian/releases/0.4.0/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.3.0...0.4.0","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.4.0.md","namespace":"obsidian","relativePath":"releases/0.4.0.md","raw":"**Full Changelog**: https://github.com/callumalpass/chronosync/compare/0.3.0...0.4.0\n","aliases":["/releases/0.4.0/","/releases/0.4.0/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/chronosync/compare/0.3.0...0.4.0

\n","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.3.0...0.4.0"},{"route":"/obsidian/releases/0.4.1/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.1","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.4.1.md","namespace":"obsidian","relativePath":"releases/0.4.1.md","raw":"**Full Changelog**: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.1\n","aliases":["/releases/0.4.1/","/releases/0.4.1/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.1

\n","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.1"},{"route":"/obsidian/releases/0.4.2/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.2","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.4.2.md","namespace":"obsidian","relativePath":"releases/0.4.2.md","raw":"**Full Changelog**: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.2\n","aliases":["/releases/0.4.2/","/releases/0.4.2/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.2

\n","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.2"},{"route":"/obsidian/releases/0.6.0/","title":"Untitled","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.6.0.md","namespace":"obsidian","relativePath":"releases/0.6.0.md","raw":"\n","aliases":["/releases/0.6.0/","/releases/0.6.0/"],"toc":[],"html":"","text":""},{"route":"/obsidian/releases/0.6.1/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.0...0.6.1","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.6.1.md","namespace":"obsidian","relativePath":"releases/0.6.1.md","raw":"**Full Changelog**: https://github.com/callumalpass/chronosync/compare/0.6.0...0.6.1\n","aliases":["/releases/0.6.1/","/releases/0.6.1/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.0...0.6.1

\n","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.0...0.6.1"},{"route":"/obsidian/releases/0.6.2/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.1...0.6.2","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.6.2.md","namespace":"obsidian","relativePath":"releases/0.6.2.md","raw":"**Full Changelog**: https://github.com/callumalpass/chronosync/compare/0.6.1...0.6.2\n","aliases":["/releases/0.6.2/","/releases/0.6.2/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.1...0.6.2

\n","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.1...0.6.2"},{"route":"/obsidian/releases/0.6.3/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.2...0.6.3","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.6.3.md","namespace":"obsidian","relativePath":"releases/0.6.3.md","raw":"**Full Changelog**: https://github.com/callumalpass/chronosync/compare/0.6.2...0.6.3\n","aliases":["/releases/0.6.3/","/releases/0.6.3/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.2...0.6.3

\n","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.2...0.6.3"},{"route":"/obsidian/releases/0.7.0/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.7.0","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.7.0.md","namespace":"obsidian","relativePath":"releases/0.7.0.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.7.0\n","aliases":["/releases/0.7.0/","/releases/0.7.0/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.7.0

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.7.0"},{"route":"/obsidian/releases/0.8.0/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.8.0","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/0.8.0.md","namespace":"obsidian","relativePath":"releases/0.8.0.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.8.0\n","aliases":["/releases/0.8.0/","/releases/0.8.0/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.8.0

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.8.0"},{"route":"/obsidian/releases/1.0.0/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.8.0...1.0.0","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/1.0.0.md","namespace":"obsidian","relativePath":"releases/1.0.0.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/0.8.0...1.0.0\n","aliases":["/releases/1.0.0/","/releases/1.0.0/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.8.0...1.0.0

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.8.0...1.0.0"},{"route":"/obsidian/releases/1.1.0/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/1.0.0...1.1.0","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/1.1.0.md","namespace":"obsidian","relativePath":"releases/1.1.0.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/1.0.0...1.1.0\n","aliases":["/releases/1.1.0/","/releases/1.1.0/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/1.0.0...1.1.0

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/1.0.0...1.1.0"},{"route":"/obsidian/releases/1.2.0/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/1.1.0...1.2.0","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/1.2.0.md","namespace":"obsidian","relativePath":"releases/1.2.0.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/1.1.0...1.2.0\n","aliases":["/releases/1.2.0/","/releases/1.2.0/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/1.1.0...1.2.0

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/1.1.0...1.2.0"},{"route":"/obsidian/releases/2.0.0/","title":"Untitled","description":"TaskNotes 2.0.0 - Major Feature Release","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/2.0.0.md","namespace":"obsidian","relativePath":"releases/2.0.0.md","raw":"TaskNotes 2.0.0 - Major Feature Release\n\nMajor New Features:\n\n**Kanban Board View**\n\n- Visual task management with drag-and-drop functionality\n- Dynamic grouping by status, priority, or context\n- Search filtering across all columns\n- Real-time updates and collapsible columns\n\n**Enhanced Pomodoro System**\n\n- SVG progress circle with refined visual timer\n- Persistent session history and statistics tracking\n- Dedicated Pomodoro Statistics view with completion metrics\n- Enhanced UI with improved controls and display\n\n**Advanced Task Filtering & Grouping**\n\n- Unified filtering system with search, status, context, priority filters\n- Date range filtering with overdue task support\n- Flexible grouping options (status, priority, context, due date)\n- Performance-optimized filtering using cache indexes\n\n**Enhanced Recurring Tasks**\n\n- Visual distinction with special styling and indicators\n- Per-date completion tracking with smart UI controls\n- Context menus filtered to prevent status conflicts\n- Clear completion status display for selected dates\n\nUI/UX Improvements:\n\n**Task Management**\n\n- Enhanced task edit modal with improved form layout\n- Context menu (right-click) for quick property changes\n- Autocomplete for contexts and tags in task forms\n- Optimistic UI updates for better responsiveness\n\n**View Enhancements**\n\n- Agenda view with improved layout and timeline organization\n- Enhanced note cards with consistent styling across views\n- Improved calendar integration with better visual indicators\n- Unified card styling system across all views\n\n**Performance & Reliability**\n\n- Migrated to unified CacheManager from legacy FileIndexer\n- DOM reconciliation system for efficient UI updates\n- Enhanced async handling and error management\n- Improved cache update handling and race condition prevention\n\nAdditional Improvements:\n\n- Enhanced due date modal with better styling\n- Improved time tracking UX with visual feedback\n- Better task archival feedback and UI consistency\n- Refined keyboard navigation and accessibility\n- Updated README with comprehensive feature documentation\n\nBug Fixes:\n\n- Fixed 'No due date' group positioning in task list\n- Resolved various UI spacing and alignment issues\n- Improved handling of edge cases in recurring task logic\n- Enhanced stability of cache operations and file handling\n\nThis major release significantly expands TaskNotes capabilities with new views, enhanced filtering, and improved user experience while maintaining data compatibility with previous versions.\n","aliases":["/releases/2.0.0/","/releases/2.0.0/"],"toc":[],"html":"

TaskNotes 2.0.0 - Major Feature Release

\n

Major New Features:

\n

Kanban Board View

\n
    \n
  • Visual task management with drag-and-drop functionality
  • \n
  • Dynamic grouping by status, priority, or context
  • \n
  • Search filtering across all columns
  • \n
  • Real-time updates and collapsible columns
  • \n
\n

Enhanced Pomodoro System

\n
    \n
  • SVG progress circle with refined visual timer
  • \n
  • Persistent session history and statistics tracking
  • \n
  • Dedicated Pomodoro Statistics view with completion metrics
  • \n
  • Enhanced UI with improved controls and display
  • \n
\n

Advanced Task Filtering & Grouping

\n
    \n
  • Unified filtering system with search, status, context, priority filters
  • \n
  • Date range filtering with overdue task support
  • \n
  • Flexible grouping options (status, priority, context, due date)
  • \n
  • Performance-optimized filtering using cache indexes
  • \n
\n

Enhanced Recurring Tasks

\n
    \n
  • Visual distinction with special styling and indicators
  • \n
  • Per-date completion tracking with smart UI controls
  • \n
  • Context menus filtered to prevent status conflicts
  • \n
  • Clear completion status display for selected dates
  • \n
\n

UI/UX Improvements:

\n

Task Management

\n
    \n
  • Enhanced task edit modal with improved form layout
  • \n
  • Context menu (right-click) for quick property changes
  • \n
  • Autocomplete for contexts and tags in task forms
  • \n
  • Optimistic UI updates for better responsiveness
  • \n
\n

View Enhancements

\n
    \n
  • Agenda view with improved layout and timeline organization
  • \n
  • Enhanced note cards with consistent styling across views
  • \n
  • Improved calendar integration with better visual indicators
  • \n
  • Unified card styling system across all views
  • \n
\n

Performance & Reliability

\n
    \n
  • Migrated to unified CacheManager from legacy FileIndexer
  • \n
  • DOM reconciliation system for efficient UI updates
  • \n
  • Enhanced async handling and error management
  • \n
  • Improved cache update handling and race condition prevention
  • \n
\n

Additional Improvements:

\n
    \n
  • Enhanced due date modal with better styling
  • \n
  • Improved time tracking UX with visual feedback
  • \n
  • Better task archival feedback and UI consistency
  • \n
  • Refined keyboard navigation and accessibility
  • \n
  • Updated README with comprehensive feature documentation
  • \n
\n

Bug Fixes:

\n
    \n
  • Fixed 'No due date' group positioning in task list
  • \n
  • Resolved various UI spacing and alignment issues
  • \n
  • Improved handling of edge cases in recurring task logic
  • \n
  • Enhanced stability of cache operations and file handling
  • \n
\n

This major release significantly expands TaskNotes capabilities with new views, enhanced filtering, and improved user experience while maintaining data compatibility with previous versions.

\n","text":"TaskNotes 2.0.0 - Major Feature Release Major New Features: Kanban Board View Visual task management with drag-and-drop functionality Dynamic grouping by status, priority, or context Search filtering across all columns Real-time updates and collapsible columns Enhanced Pomodoro System SVG progress circle with refined visual timer Persistent session history and statistics tracking Dedicated Pomodoro Statistics view with completion metrics Enhanced UI with improved controls and display Advanced Task Filtering & Grouping Unified filtering system with search, status, context, priority filters Date range filtering with overdue task support Flexible grouping options (status, priority, context, due date) Performance-optimized filtering using cache indexes Enhanced Recurring Tasks Visual distinction with special styling and indicators Per-date completion tracking with smart UI controls Context menus filtered to prevent status conflicts Clear completion status display for selected dates UI/UX Improvements: Task Management Enhanced task edit modal with improved form layout Context menu (right-click) for quick property changes Autocomplete for contexts and tags in task forms Optimistic UI updates for better responsiveness View Enhancements Agenda view with improved layout and timeline organization Enhanced note cards with consistent styling across views Improved calendar integration with better visual indicators Unified card styling system across all views Performance & Reliability Migrated to unified CacheManager from legacy FileIndexer DOM reconciliation system for efficient UI updates Enhanced async handling and error management Improved cache update handling and race condition prevention Additional Improvements: Enhanced due date modal with better styling Improved time tracking UX with visual feedback Better task archival feedback and UI consistency Refined keyboard navigation and accessibility Updated README with comprehensive feature documentation Bug Fixes: Fixed 'No due date' group positioning in task list Resolved various UI spacing and alignment issues Improved handling of edge cases in recurring task logic Enhanced stability of cache operations and file handling This major release significantly expands TaskNotes capabilities with new views, enhanced filtering, and improved user experience while maintaining data compatibility with previous versions."},{"route":"/obsidian/releases/2.0.1/","title":"Untitled","description":"Bug Fixes and Enhancements:","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/2.0.1.md","namespace":"obsidian","relativePath":"releases/2.0.1.md","raw":" ## TaskNotes 2.0.1 - Recurring Tasks and Filtering Improvements\r\n\r\n Bug Fixes and Enhancements:\r\n\r\n Recurring Task Improvements:\r\n - Fixed recurring tasks not appearing in correct due date groups (Today, Tomorrow, etc.)\r\n - Recurring tasks now properly appear in 'Today' group when selected date matches recurrence pattern\r\n - Enhanced recurring task visual styling with distinctive indicators and backgrounds\r\n - Smart context menus for recurring tasks that prevent conflicting status changes\r\n - Fixed recurrence values not loading properly in task edit modal\r\n\r\n Task Filtering and Grouping:\r\n - Improved 'No due date' group positioning to appear at bottom of task list\r\n - Enhanced FilterService with target date awareness for intelligent recurring task grouping\r\n - Fixed cache integration issues where recurrence changes didn't trigger proper view updates\r\n - All views now properly refresh and regroup tasks when recurrence properties change\r\n\r\n UI and Data Consistency:\r\n - Fixed data format mismatch between stored abbreviations and UI display for day names\r\n - Improved task edit modal to properly convert between storage format and UI format\r\n - Enhanced cache workflow integration for seamless task property updates\r\n - Better synchronization between task edits and view refreshes\r\n\r\n Technical Improvements:\r\n - Added conversion helper methods for consistent day name handling\r\n - Enhanced cache manager with proper recurring task support\r\n - Improved event emission and handling for task updates\r\n - Better error handling and data validation in task modals\r\n\r\n This release focuses on making recurring tasks work seamlessly with the filtering and grouping system while maintaining data consistency and improving\r\n the overall user experience.\r\n\r\n","aliases":["/releases/2.0.1/","/releases/2.0.1/"],"toc":[{"level":2,"id":"tasknotes-201-recurring-tasks-and-filtering-improvements","text":"TaskNotes 2.0.1 - Recurring Tasks and Filtering Improvements"}],"html":"

TaskNotes 2.0.1 - Recurring Tasks and Filtering Improvements#

\n

Bug Fixes and Enhancements:

\n

Recurring Task Improvements:

\n
    \n
  • Fixed recurring tasks not appearing in correct due date groups (Today, Tomorrow, etc.)
  • \n
  • Recurring tasks now properly appear in 'Today' group when selected date matches recurrence pattern
  • \n
  • Enhanced recurring task visual styling with distinctive indicators and backgrounds
  • \n
  • Smart context menus for recurring tasks that prevent conflicting status changes
  • \n
  • Fixed recurrence values not loading properly in task edit modal
  • \n
\n

Task Filtering and Grouping:

\n
    \n
  • Improved 'No due date' group positioning to appear at bottom of task list
  • \n
  • Enhanced FilterService with target date awareness for intelligent recurring task grouping
  • \n
  • Fixed cache integration issues where recurrence changes didn't trigger proper view updates
  • \n
  • All views now properly refresh and regroup tasks when recurrence properties change
  • \n
\n

UI and Data Consistency:

\n
    \n
  • Fixed data format mismatch between stored abbreviations and UI display for day names
  • \n
  • Improved task edit modal to properly convert between storage format and UI format
  • \n
  • Enhanced cache workflow integration for seamless task property updates
  • \n
  • Better synchronization between task edits and view refreshes
  • \n
\n

Technical Improvements:

\n
    \n
  • Added conversion helper methods for consistent day name handling
  • \n
  • Enhanced cache manager with proper recurring task support
  • \n
  • Improved event emission and handling for task updates
  • \n
  • Better error handling and data validation in task modals
  • \n
\n

This release focuses on making recurring tasks work seamlessly with the filtering and grouping system while maintaining data consistency and improving\n the overall user experience.

\n","text":"TaskNotes 2.0.1 - Recurring Tasks and Filtering Improvements# Bug Fixes and Enhancements: Recurring Task Improvements: Fixed recurring tasks not appearing in correct due date groups (Today, Tomorrow, etc.) Recurring tasks now properly appear in 'Today' group when selected date matches recurrence pattern Enhanced recurring task visual styling with distinctive indicators and backgrounds Smart context menus for recurring tasks that prevent conflicting status changes Fixed recurrence values not loading properly in task edit modal Task Filtering and Grouping: Improved 'No due date' group positioning to appear at bottom of task list Enhanced FilterService with target date awareness for intelligent recurring task grouping Fixed cache integration issues where recurrence changes didn't trigger proper view updates All views now properly refresh and regroup tasks when recurrence properties change UI and Data Consistency: Fixed data format mismatch between stored abbreviations and UI display for day names Improved task edit modal to properly convert between storage format and UI format Enhanced cache workflow integration for seamless task property updates Better synchronization between task edits and view refreshes Technical Improvements: Added conversion helper methods for consistent day name handling Enhanced cache manager with proper recurring task support Improved event emission and handling for task updates Better error handling and data validation in task modals This release focuses on making recurring tasks work seamlessly with the filtering and grouping system while maintaining data consistency and improving the overall user experience."},{"route":"/obsidian/releases/2.0.2/","title":"Untitled","description":"Bug Fixes:","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/2.0.2.md","namespace":"obsidian","relativePath":"releases/2.0.2.md","raw":"## TaskNotes v2.0.2\r\n\r\nBug Fixes:\r\n- Fixed recurring tasks without due dates not appearing in agenda view\r\n- Recurring tasks now properly show on their scheduled days in agenda view\r\n\r\nSettings Improvements:\r\n- Enhanced Priorities settings tab with comprehensive usability improvements\r\n- Added detailed descriptions, help sections, and column headers\r\n- Added input validation and better visual organization\r\n- Matches the improved usability of the Statuses settings tab\r\n\r\nTechnical Details:\r\n- Modified FilterService date range filtering to properly handle recurring tasks without due dates\r\n- Added logic to check if recurring tasks should appear on any date within the specified range\r\n- Uses existing isRecurringTaskDueOn helper for accurate recurrence calculations\r\n- Maintains full backward compatibility for all existing functionality\n","aliases":["/releases/2.0.2/","/releases/2.0.2/"],"toc":[{"level":2,"id":"tasknotes-v202","text":"TaskNotes v2.0.2"}],"html":"

TaskNotes v2.0.2#

\n

Bug Fixes:

\n
    \n
  • Fixed recurring tasks without due dates not appearing in agenda view
  • \n
  • Recurring tasks now properly show on their scheduled days in agenda view
  • \n
\n

Settings Improvements:

\n
    \n
  • Enhanced Priorities settings tab with comprehensive usability improvements
  • \n
  • Added detailed descriptions, help sections, and column headers
  • \n
  • Added input validation and better visual organization
  • \n
  • Matches the improved usability of the Statuses settings tab
  • \n
\n

Technical Details:

\n
    \n
  • Modified FilterService date range filtering to properly handle recurring tasks without due dates
  • \n
  • Added logic to check if recurring tasks should appear on any date within the specified range
  • \n
  • Uses existing isRecurringTaskDueOn helper for accurate recurrence calculations
  • \n
  • Maintains full backward compatibility for all existing functionality
  • \n
\n","text":"TaskNotes v2.0.2# Bug Fixes: Fixed recurring tasks without due dates not appearing in agenda view Recurring tasks now properly show on their scheduled days in agenda view Settings Improvements: Enhanced Priorities settings tab with comprehensive usability improvements Added detailed descriptions, help sections, and column headers Added input validation and better visual organization Matches the improved usability of the Statuses settings tab Technical Details: Modified FilterService date range filtering to properly handle recurring tasks without due dates Added logic to check if recurring tasks should appear on any date within the specified range Uses existing isRecurringTaskDueOn helper for accurate recurrence calculations Maintains full backward compatibility for all existing functionality"},{"route":"/obsidian/releases/2.0.3/","title":"Untitled","description":"Bug Fixes:","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/2.0.3.md","namespace":"obsidian","relativePath":"releases/2.0.3.md","raw":"\r\nBug Fixes:\r\n- Fixed recurring tasks without due dates not appearing in agenda view\r\n- Recurring tasks now properly show on their scheduled days in agenda view\r\n\r\nCommand Improvements:\r\n- Removed layout-specific commands (open-linked-views, open-grid-layout, open-tabs-layout)\r\n- Removed popout window commands for cleaner command palette\r\n- Added 'Refresh TaskNotes cache' command for troubleshooting\r\n- Simplified ribbon icons to focus on core functionality\r\n\r\nTechnical Details:\r\n- Enhanced FilterService initial task set logic to include recurring tasks without due dates\r\n- Modified getTaskPathsInDateRange() to check all recurring tasks for date range inclusion\r\n- Added async processing with batched performance optimizations\r\n- Maintained backward compatibility and existing performance characteristics\r\n- Root cause: CacheManager only indexed tasks by actual due dates, excluding recurring tasks without due dates from date-based queries\r\n\r\nThe agenda view now correctly displays recurring tasks without due dates on their appropriate scheduled days.\n","aliases":["/releases/2.0.3/","/releases/2.0.3/"],"toc":[],"html":"

Bug Fixes:

\n
    \n
  • Fixed recurring tasks without due dates not appearing in agenda view
  • \n
  • Recurring tasks now properly show on their scheduled days in agenda view
  • \n
\n

Command Improvements:

\n
    \n
  • Removed layout-specific commands (open-linked-views, open-grid-layout, open-tabs-layout)
  • \n
  • Removed popout window commands for cleaner command palette
  • \n
  • Added 'Refresh TaskNotes cache' command for troubleshooting
  • \n
  • Simplified ribbon icons to focus on core functionality
  • \n
\n

Technical Details:

\n
    \n
  • Enhanced FilterService initial task set logic to include recurring tasks without due dates
  • \n
  • Modified getTaskPathsInDateRange() to check all recurring tasks for date range inclusion
  • \n
  • Added async processing with batched performance optimizations
  • \n
  • Maintained backward compatibility and existing performance characteristics
  • \n
  • Root cause: CacheManager only indexed tasks by actual due dates, excluding recurring tasks without due dates from date-based queries
  • \n
\n

The agenda view now correctly displays recurring tasks without due dates on their appropriate scheduled days.

\n","text":"Bug Fixes: Fixed recurring tasks without due dates not appearing in agenda view Recurring tasks now properly show on their scheduled days in agenda view Command Improvements: Removed layout-specific commands (open-linked-views, open-grid-layout, open-tabs-layout) Removed popout window commands for cleaner command palette Added 'Refresh TaskNotes cache' command for troubleshooting Simplified ribbon icons to focus on core functionality Technical Details: Enhanced FilterService initial task set logic to include recurring tasks without due dates Modified getTaskPathsInDateRange() to check all recurring tasks for date range inclusion Added async processing with batched performance optimizations Maintained backward compatibility and existing performance characteristics Root cause: CacheManager only indexed tasks by actual due dates, excluding recurring tasks without due dates from date-based queries The agenda view now correctly displays recurring tasks without due dates on their appropriate scheduled days."},{"route":"/obsidian/releases/2.0.4/","title":"TaskNotes v2.0.4","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.0.3...2.0.4","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/2.0.4.md","namespace":"obsidian","relativePath":"releases/2.0.4.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/2.0.3...2.0.4\r\n\r\n# TaskNotes v2.0.4\r\n\r\n- Allow multiple statuses to be filtered for at the same time, bringing\r\nstatus filtering in line with context and priority filtering\r\n- Fix flickering during kanban drag and drop\n","aliases":["/releases/2.0.4/","/releases/2.0.4/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.0.3...2.0.4

\n
    \n
  • Allow multiple statuses to be filtered for at the same time, bringing\nstatus filtering in line with context and priority filtering
  • \n
  • Fix flickering during kanban drag and drop
  • \n
\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.0.3...2.0.4 Allow multiple statuses to be filtered for at the same time, bringing status filtering in line with context and priority filtering Fix flickering during kanban drag and drop"},{"route":"/obsidian/releases/2.1.0/","title":"TaskNotes v2.1.0 - Major Feature Release","description":"This release introduces significant workflow enhancements and editor integration features that streamline task management directly within the Obsidian editing experience.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/2.1.0.md","namespace":"obsidian","relativePath":"releases/2.1.0.md","raw":"# TaskNotes v2.1.0 - Major Feature Release\r\n\r\nThis release introduces significant workflow enhancements and editor integration features that streamline task management directly within the Obsidian editing experience.\r\n\r\n## NEW FEATURES:\r\n\r\n**Instant Task Conversion**\r\n- One-click conversion of checkbox tasks to dedicated TaskNotes with inline convert buttons\r\n- Streamlined workflow for transforming simple tasks into structured task files\r\n- Configurable via settings to enable/disable the feature\r\n\r\n**Interactive Task Link Overlays**\r\n- Live task previews displayed on wikilinks in live preview mode\r\n- Hover and click interactions for editing tasks without leaving the current note\r\n- Context menus and inline task information display\r\n- Smart detection of task-related wikilinks with automatic enhancement\r\n\r\n**Enhanced Date Handling**\r\n- Improved overdue task detection that considers both due and scheduled dates\r\n- Better date consistency across all views and components\r\n- Expanded field mapping support for time tracking and completion data\r\n\r\n## IMPROVEMENTS:\r\n\r\n**Performance & Reliability**\r\n- Comprehensive resource cleanup to prevent memory leaks\r\n- Enhanced error handling with better user feedback\r\n- Performance optimizations in calendar view and task rendering\r\n- Improved DOM reconciliation and widget management\r\n\r\n**Accessibility & UX**\r\n- Enhanced accessibility with ARIA attributes and keyboard navigation\r\n- Consistent BEM CSS naming across all components\r\n- Better input validation and security measures\r\n- Improved visual consistency throughout the interface\r\n\r\n**Technical Enhancements**\r\n- Fixed deprecated Obsidian API usage for better compatibility\r\n- Standardized date handling using date-fns library\r\n- Configurable pomodoro field mapping\r\n- Better separation of concerns in component architecture\r\n\r\nThis release maintains full backward compatibility while adding new features that enhance the daily task management workflow.\n","aliases":["/releases/2.1.0/","/releases/2.1.0/"],"toc":[{"level":2,"id":"new-features","text":"NEW FEATURES:"},{"level":2,"id":"improvements","text":"IMPROVEMENTS:"}],"html":"

This release introduces significant workflow enhancements and editor integration features that streamline task management directly within the Obsidian editing experience.

\n

NEW FEATURES:#

\n

Instant Task Conversion

\n
    \n
  • One-click conversion of checkbox tasks to dedicated TaskNotes with inline convert buttons
  • \n
  • Streamlined workflow for transforming simple tasks into structured task files
  • \n
  • Configurable via settings to enable/disable the feature
  • \n
\n

Interactive Task Link Overlays

\n
    \n
  • Live task previews displayed on wikilinks in live preview mode
  • \n
  • Hover and click interactions for editing tasks without leaving the current note
  • \n
  • Context menus and inline task information display
  • \n
  • Smart detection of task-related wikilinks with automatic enhancement
  • \n
\n

Enhanced Date Handling

\n
    \n
  • Improved overdue task detection that considers both due and scheduled dates
  • \n
  • Better date consistency across all views and components
  • \n
  • Expanded field mapping support for time tracking and completion data
  • \n
\n

IMPROVEMENTS:#

\n

Performance & Reliability

\n
    \n
  • Comprehensive resource cleanup to prevent memory leaks
  • \n
  • Enhanced error handling with better user feedback
  • \n
  • Performance optimizations in calendar view and task rendering
  • \n
  • Improved DOM reconciliation and widget management
  • \n
\n

Accessibility & UX

\n
    \n
  • Enhanced accessibility with ARIA attributes and keyboard navigation
  • \n
  • Consistent BEM CSS naming across all components
  • \n
  • Better input validation and security measures
  • \n
  • Improved visual consistency throughout the interface
  • \n
\n

Technical Enhancements

\n
    \n
  • Fixed deprecated Obsidian API usage for better compatibility
  • \n
  • Standardized date handling using date-fns library
  • \n
  • Configurable pomodoro field mapping
  • \n
  • Better separation of concerns in component architecture
  • \n
\n

This release maintains full backward compatibility while adding new features that enhance the daily task management workflow.

\n","text":"This release introduces significant workflow enhancements and editor integration features that streamline task management directly within the Obsidian editing experience. NEW FEATURES:# Instant Task Conversion One-click conversion of checkbox tasks to dedicated TaskNotes with inline convert buttons Streamlined workflow for transforming simple tasks into structured task files Configurable via settings to enable/disable the feature Interactive Task Link Overlays Live task previews displayed on wikilinks in live preview mode Hover and click interactions for editing tasks without leaving the current note Context menus and inline task information display Smart detection of task-related wikilinks with automatic enhancement Enhanced Date Handling Improved overdue task detection that considers both due and scheduled dates Better date consistency across all views and components Expanded field mapping support for time tracking and completion data IMPROVEMENTS:# Performance & Reliability Comprehensive resource cleanup to prevent memory leaks Enhanced error handling with better user feedback Performance optimizations in calendar view and task rendering Improved DOM reconciliation and widget management Accessibility & UX Enhanced accessibility with ARIA attributes and keyboard navigation Consistent BEM CSS naming across all components Better input validation and security measures Improved visual consistency throughout the interface Technical Enhancements Fixed deprecated Obsidian API usage for better compatibility Standardized date handling using date-fns library Configurable pomodoro field mapping Better separation of concerns in component architecture This release maintains full backward compatibility while adding new features that enhance the daily task management workflow."},{"route":"/obsidian/releases/2.2.0/","title":"TaskNotes v2.2.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/2.2.0.md","namespace":"obsidian","relativePath":"releases/2.2.0.md","raw":"# TaskNotes v2.2.0\r\n\r\n## Major Features\r\n\r\n- Task Deletion: Added task deletion functionality with confirmation modal and proper event handling\r\n- Pomodoro Data Migration: Implemented migration utility for backward compatibility with existing Pomodoro session data\r\n- Enhanced Calendar Navigation: Improved CalendarView date navigation and refresh logic\r\n\r\n## Core Improvements\r\n\r\n- Timezone-Safe Date Handling: Complete overhaul of date utilities to ensure consistent timezone handling across the codebase\r\n- Centralized Task Management: Refactored task creation and editing to use centralized TaskService architecture\r\n- Improved Date Filtering: Enhanced FilterService with better date comparison logic for due and scheduled tasks\r\n- Pomodoro Session Tracking: Refactored session tracking and duration calculations for better accuracy\r\n\r\n## UI/UX Enhancements\r\n\r\n- Visual Consistency: Updated font sizes and UI element widths for better readability\r\n- Pomodoro Button Styling: Enhanced button styles with consistent visual feedback\r\n- Inline Widget Cleanup: Improved task update handling and cleaned up inline widget styles\r\n\r\n## Technical Improvements\r\n\r\n- Safer Date Parsing: Replaced parseISO with parseDate utilities for more robust date handling\r\n- ISO Timestamp Support: Updated timestamp generation to return ISO format with local timezone offset\r\n- Performance Optimizations: Various refactoring improvements for better code maintainability and performance\r\n\r\n","aliases":["/releases/2.2.0/","/releases/2.2.0/"],"toc":[{"level":2,"id":"major-features","text":"Major Features"},{"level":2,"id":"core-improvements","text":"Core Improvements"},{"level":2,"id":"uiux-enhancements","text":"UI/UX Enhancements"},{"level":2,"id":"technical-improvements","text":"Technical Improvements"}],"html":"

Major Features#

\n
    \n
  • Task Deletion: Added task deletion functionality with confirmation modal and proper event handling
  • \n
  • Pomodoro Data Migration: Implemented migration utility for backward compatibility with existing Pomodoro session data
  • \n
  • Enhanced Calendar Navigation: Improved CalendarView date navigation and refresh logic
  • \n
\n

Core Improvements#

\n
    \n
  • Timezone-Safe Date Handling: Complete overhaul of date utilities to ensure consistent timezone handling across the codebase
  • \n
  • Centralized Task Management: Refactored task creation and editing to use centralized TaskService architecture
  • \n
  • Improved Date Filtering: Enhanced FilterService with better date comparison logic for due and scheduled tasks
  • \n
  • Pomodoro Session Tracking: Refactored session tracking and duration calculations for better accuracy
  • \n
\n

UI/UX Enhancements#

\n
    \n
  • Visual Consistency: Updated font sizes and UI element widths for better readability
  • \n
  • Pomodoro Button Styling: Enhanced button styles with consistent visual feedback
  • \n
  • Inline Widget Cleanup: Improved task update handling and cleaned up inline widget styles
  • \n
\n

Technical Improvements#

\n
    \n
  • Safer Date Parsing: Replaced parseISO with parseDate utilities for more robust date handling
  • \n
  • ISO Timestamp Support: Updated timestamp generation to return ISO format with local timezone offset
  • \n
  • Performance Optimizations: Various refactoring improvements for better code maintainability and performance
  • \n
\n","text":"Major Features# Task Deletion: Added task deletion functionality with confirmation modal and proper event handling Pomodoro Data Migration: Implemented migration utility for backward compatibility with existing Pomodoro session data Enhanced Calendar Navigation: Improved CalendarView date navigation and refresh logic Core Improvements# Timezone-Safe Date Handling: Complete overhaul of date utilities to ensure consistent timezone handling across the codebase Centralized Task Management: Refactored task creation and editing to use centralized TaskService architecture Improved Date Filtering: Enhanced FilterService with better date comparison logic for due and scheduled tasks Pomodoro Session Tracking: Refactored session tracking and duration calculations for better accuracy UI/UX Enhancements# Visual Consistency: Updated font sizes and UI element widths for better readability Pomodoro Button Styling: Enhanced button styles with consistent visual feedback Inline Widget Cleanup: Improved task update handling and cleaned up inline widget styles Technical Improvements# Safer Date Parsing: Replaced parseISO with parseDate utilities for more robust date handling ISO Timestamp Support: Updated timestamp generation to return ISO format with local timezone offset Performance Optimizations: Various refactoring improvements for better code maintainability and performance"},{"route":"/obsidian/releases/2.2.1/","title":"Untitled","description":"Fix #22 and #24","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/2.2.1.md","namespace":"obsidian","relativePath":"releases/2.2.1.md","raw":"Fix #22 and #24 \n","aliases":["/releases/2.2.1/","/releases/2.2.1/"],"toc":[],"html":"

Fix #22 and #24

\n","text":"Fix #22 and #24"},{"route":"/obsidian/releases/2.2.2/","title":"Untitled","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/2.2.2.md","namespace":"obsidian","relativePath":"releases/2.2.2.md","raw":"\n","aliases":["/releases/2.2.2/","/releases/2.2.2/"],"toc":[],"html":"","text":""},{"route":"/obsidian/releases/2.2.3/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.2.2...2.2.3","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/2.2.3.md","namespace":"obsidian","relativePath":"releases/2.2.3.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/2.2.2...2.2.3\n","aliases":["/releases/2.2.3/","/releases/2.2.3/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.2.2...2.2.3

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.2.2...2.2.3"},{"route":"/obsidian/releases/3.0.0/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.3.0...3.0.0","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.0.0.md","namespace":"obsidian","relativePath":"releases/3.0.0.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/2.3.0...3.0.0\n","aliases":["/releases/3.0.0/","/releases/3.0.0/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.3.0...3.0.0

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.3.0...3.0.0"},{"route":"/obsidian/releases/3.0.1/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.0.0...3.0.1","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.0.1.md","namespace":"obsidian","relativePath":"releases/3.0.1.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.0.0...3.0.1\n","aliases":["/releases/3.0.1/","/releases/3.0.1/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.0.0...3.0.1

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.0.0...3.0.1"},{"route":"/obsidian/releases/3.1.0/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.0.1...3.1.0","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.1.0.md","namespace":"obsidian","relativePath":"releases/3.1.0.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.0.1...3.1.0\n","aliases":["/releases/3.1.0/","/releases/3.1.0/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.0.1...3.1.0

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.0.1...3.1.0"},{"route":"/obsidian/releases/3.1.1/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.1.0...3.1.1","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.1.1.md","namespace":"obsidian","relativePath":"releases/3.1.1.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.1.0...3.1.1\n","aliases":["/releases/3.1.1/","/releases/3.1.1/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.1.0...3.1.1

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.1.0...3.1.1"},{"route":"/obsidian/releases/3.10.0/","title":"Release Notes: 3.10.0","description":"This version introduces a new data storage option for tasks, adds a status bar component for time tracking, and includes several bug fixes and internal improvements.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.10.0.md","namespace":"obsidian","relativePath":"releases/3.10.0.md","raw":"# Release Notes: 3.10.0\r\n\r\n This version introduces a new data storage option for tasks, adds a status bar component for time tracking, and includes several bug fixes and internal improvements.\r\n\r\n## New Features\r\n\r\n### Option to Store Task Title in Filename\r\n\r\nA new setting, storeTitleInFilename, is available under \"Task Filenames\" in the settings tab. This feature changes how task titles are stored.\r\n\r\n**Implementation Details:**\r\n\r\n- When this setting is enabled, creating a new task will use its title to generate the filename (e.g., My New Task.md). The title field will be omitted from the task's frontmatter.\r\n- For reading tasks, the application will first look for a title field in the frontmatter. If it is not found, the system will use the filename as the task's title. This ensures backward compatibility with existing tasks.\r\n- When a task's title is updated, and this setting is active, the file itself is automatically renamed to match the new title. The file's frontmatter is updated before the rename operation occurs to ensure data integrity.\r\n- Enabling this setting disables and hides the other filename format options (Zettelkasten, timestamp, custom).\r\n- This setting is disabled by default.\r\n\r\n### Status Bar Component for Tracked Tasks\r\n\r\nA new UI component has been added to the app's status bar to display tasks with active time-tracking sessions.\r\n\r\n**Functionality:**\r\n\r\n- When a single task is being tracked, its title (truncated if necessary) is displayed in the status bar. The full title is visible in a tooltip.\r\n- When multiple tasks are being tracked, a count of these tasks is displayed. The tooltip lists the titles of the tracked tasks.\r\n- The status bar item is hidden when no tasks are being tracked.\r\n- This feature is controlled by the \"Show tracked tasks in status bar\" setting and is disabled by default.\r\n\r\n### Customizable First Day of Week for Mini Calendar\r\n\r\nThe mini calendar view now respects the \"First day of the week\" setting in Obsidian's general settings. The calendar grid will adjust to start the week on the day you have configured (e.g., Sunday or Monday).\r\n\r\n## Bug Fixes\r\n\r\n- Search Functionality: Resolved a type error in the search filter that occurred when a task's title or context field was null. The code now handles null values gracefully during search operations.\r\n- File Renaming: Corrected the order of operations when storeTitleInFilename is enabled. The previous implementation could rename the file before its frontmatter was updated, which has now been fixed.\r\n\r\n## Internal Improvements & Documentation\r\n\r\n- Service Refactoring: The TaskService, FieldMapper, and MinimalNativeCache have been updated to handle the new logic for storing and retrieving task titles from filenames.\r\n- `StatusBarService`: A new StatusBarService was implemented to encapsulate the logic for the new status bar component, including its creation, updates, and event handling.\r\n- Issue Templates: The GitHub issue templates for bug reports and questions have been updated to be more structured and improve the quality of submitted reports.\r\n- Documentation: Added a new section to the documentation explaining the storeTitleInFilename feature in detail.\r\n","aliases":["/releases/3.10.0/","/releases/3.10.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"option-to-store-task-title-in-filename","text":"Option to Store Task Title in Filename"},{"level":3,"id":"status-bar-component-for-tracked-tasks","text":"Status Bar Component for Tracked Tasks"},{"level":3,"id":"customizable-first-day-of-week-for-mini-calendar","text":"Customizable First Day of Week for Mini Calendar"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":2,"id":"internal-improvements-documentation","text":"Internal Improvements & Documentation"}],"html":"

This version introduces a new data storage option for tasks, adds a status bar component for time tracking, and includes several bug fixes and internal improvements.

\n

New Features#

\n

Option to Store Task Title in Filename#

\n

A new setting, storeTitleInFilename, is available under "Task Filenames" in the settings tab. This feature changes how task titles are stored.

\n

Implementation Details:

\n
    \n
  • When this setting is enabled, creating a new task will use its title to generate the filename (e.g., My New Task.md). The title field will be omitted from the task's frontmatter.
  • \n
  • For reading tasks, the application will first look for a title field in the frontmatter. If it is not found, the system will use the filename as the task's title. This ensures backward compatibility with existing tasks.
  • \n
  • When a task's title is updated, and this setting is active, the file itself is automatically renamed to match the new title. The file's frontmatter is updated before the rename operation occurs to ensure data integrity.
  • \n
  • Enabling this setting disables and hides the other filename format options (Zettelkasten, timestamp, custom).
  • \n
  • This setting is disabled by default.
  • \n
\n

Status Bar Component for Tracked Tasks#

\n

A new UI component has been added to the app's status bar to display tasks with active time-tracking sessions.

\n

Functionality:

\n
    \n
  • When a single task is being tracked, its title (truncated if necessary) is displayed in the status bar. The full title is visible in a tooltip.
  • \n
  • When multiple tasks are being tracked, a count of these tasks is displayed. The tooltip lists the titles of the tracked tasks.
  • \n
  • The status bar item is hidden when no tasks are being tracked.
  • \n
  • This feature is controlled by the "Show tracked tasks in status bar" setting and is disabled by default.
  • \n
\n

Customizable First Day of Week for Mini Calendar#

\n

The mini calendar view now respects the "First day of the week" setting in Obsidian's general settings. The calendar grid will adjust to start the week on the day you have configured (e.g., Sunday or Monday).

\n

Bug Fixes#

\n
    \n
  • Search Functionality: Resolved a type error in the search filter that occurred when a task's title or context field was null. The code now handles null values gracefully during search operations.
  • \n
  • File Renaming: Corrected the order of operations when storeTitleInFilename is enabled. The previous implementation could rename the file before its frontmatter was updated, which has now been fixed.
  • \n
\n

Internal Improvements & Documentation#

\n
    \n
  • Service Refactoring: The TaskService, FieldMapper, and MinimalNativeCache have been updated to handle the new logic for storing and retrieving task titles from filenames.
  • \n
  • StatusBarService: A new StatusBarService was implemented to encapsulate the logic for the new status bar component, including its creation, updates, and event handling.
  • \n
  • Issue Templates: The GitHub issue templates for bug reports and questions have been updated to be more structured and improve the quality of submitted reports.
  • \n
  • Documentation: Added a new section to the documentation explaining the storeTitleInFilename feature in detail.
  • \n
\n","text":"This version introduces a new data storage option for tasks, adds a status bar component for time tracking, and includes several bug fixes and internal improvements. New Features# Option to Store Task Title in Filename# A new setting, storeTitleInFilename, is available under \"Task Filenames\" in the settings tab. This feature changes how task titles are stored. Implementation Details: When this setting is enabled, creating a new task will use its title to generate the filename (e.g., My New Task.md). The title field will be omitted from the task's frontmatter. For reading tasks, the application will first look for a title field in the frontmatter. If it is not found, the system will use the filename as the task's title. This ensures backward compatibility with existing tasks. When a task's title is updated, and this setting is active, the file itself is automatically renamed to match the new title. The file's frontmatter is updated before the rename operation occurs to ensure data integrity. Enabling this setting disables and hides the other filename format options (Zettelkasten, timestamp, custom). This setting is disabled by default. Status Bar Component for Tracked Tasks# A new UI component has been added to the app's status bar to display tasks with active time-tracking sessions. Functionality: When a single task is being tracked, its title (truncated if necessary) is displayed in the status bar. The full title is visible in a tooltip. When multiple tasks are being tracked, a count of these tasks is displayed. The tooltip lists the titles of the tracked tasks. The status bar item is hidden when no tasks are being tracked. This feature is controlled by the \"Show tracked tasks in status bar\" setting and is disabled by default. Customizable First Day of Week for Mini Calendar# The mini calendar view now respects the \"First day of the week\" setting in Obsidian's general settings. The calendar grid will adjust to start the week on the day you have configured (e.g., Sunday or Monday). Bug Fixes# Search Functionality: Resolved a type error in the search filter that occurred when a task's title or context field was null. The code now handles null values gracefully during search operations. File Renaming: Corrected the order of operations when storeTitleInFilename is enabled. The previous implementation could rename the file before its frontmatter was updated, which has now been fixed. Internal Improvements & Documentation# Service Refactoring: The TaskService, FieldMapper, and MinimalNativeCache have been updated to handle the new logic for storing and retrieving task titles from filenames. StatusBarService: A new StatusBarService was implemented to encapsulate the logic for the new status bar component, including its creation, updates, and event handling. Issue Templates: The GitHub issue templates for bug reports and questions have been updated to be more structured and improve the quality of submitted reports. Documentation: Added a new section to the documentation explaining the storeTitleInFilename feature in detail."},{"route":"/obsidian/releases/3.11.0/","title":"Release Notes: 3.11.0","description":"This release introduces a new project management system, significant enhancements to the Pomodoro timer and workflows, and a number of quality-of-life improvements and bug fixes.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.11.0.md","namespace":"obsidian","relativePath":"releases/3.11.0.md","raw":"# Release Notes: 3.11.0\r\n\r\nThis release introduces a new project management system, significant enhancements to the Pomodoro timer and workflows, and a number of quality-of-life improvements and bug fixes.\r\n\r\n## New Features\r\n\r\n### Project Management\r\n\r\nA new project management system has been integrated, allowing for better organization and tracking of tasks within projects.\r\n\r\n- **Note-Based Projects**: Projects are now properly integrated into TaskNotes. You can link tasks to any note in your vault, effectively turning that note into a project. This leverages Obsidian's core linking capabilities, allowing you to see all tasks related to a project in the backlinks of the project note.\r\n- **Project Selection UI**: A new project selection modal has been added to the task creation and editing modals. It features fuzzy search to quickly find and assign tasks to project notes.\r\n- **Filtering and Grouping by Project**:\r\n - The Filter Bar in all views now includes a \"Project\" filter, allowing you to see tasks for one or more specific projects.\r\n - The \"Group By\" option now includes \"Project\", which organizes the Task List and Kanban views by project.\r\n- **Clickable Project Links**: In task cards and other views, project names are now clickable links that take you directly to the project note.\r\n\r\n### Workflow and UI Enhancements\r\n\r\n- **Redesigned Pomodoro Timer**: The Pomodoro timer has been completely redesigned for a more modern and user-friendly experience.\r\n - **New Interface**: A more compact and visually appealing interface.\r\n - **Time Adjustment**: You can now add or subtract time from the current session or the prepared timer.\r\n - **Skip Break**: A \"Skip break\" button is now available after a work session.\r\n- **Enhanced Pomodoro Stats**: The Pomodoro statistics view has been improved to provide more insights.\r\n - **Overview Section**: A new overview section shows today's completed Pomodoros, total focus time, and a comparison with yesterday's performance.\r\n- **Instant Task Conversion**: The \"Convert task to TaskNote\" command has been streamlined. It now instantly converts a checkbox task into a TaskNote without opening the creation modal, reducing friction.\r\n- **Quick Actions for Current Task**: A new command, \"Quick actions for current task,\" allows you to open the action palette for the currently active TaskNote, providing quick access to common operations.\r\n- **Improved Sorting Logic**: The task sorting algorithm has been enhanced. When the primary sorting criterion (e.g., due date) is the same for multiple tasks, a fallback sorting order is applied: `scheduled date` -> `due date` -> `priority` -> `title`. This ensures a more predictable and logical ordering of tasks.\r\n- **Archive Button in Edit Modal**: An \"Archive\" button has been added to the task edit modal, allowing for quick archiving and unarchiving of tasks.\r\n- **Week Start Day Setting**: All calendar views now respect the \"Start week on\" setting from Obsidian's calendar preferences.\r\n\r\n## Bug Fixes and Minor Improvements\r\n\r\n- **Recurring Task Date Consistency**: A critical bug has been fixed where recurring task dates could appear on the wrong day in different timezones (especially CST). The handling of dates and timezones for recurring tasks is now more robust, ensuring consistency across all views.\r\n- **Pomodoro Daily Note Integration**: The Pomodoro service now correctly handles adding session history to daily notes, preventing the creation of duplicate entries.\r\n- **Template Processing**:\r\n - The `{{parentNote}}` template variable now correctly resolves to a properly formatted markdown link.\r\n - YAML frontmatter in templates is now processed more safely to avoid parsing errors.\r\n- **Date Validation**: The `complete_instances` field for recurring tasks now has stricter validation to filter out invalid entries, improving data integrity.\r\n- **Natural Language Processing**: The natural language parser now correctly applies scheduled times (e.g., \"do something at 5pm\") to created tasks.\r\n- **Agenda View Quick Select**: A bug that prevented the date quick-select menus in the Agenda View from working after the first use has been fixed.\r\n- **Styling and CSS**: Numerous styling improvements have been made across the plugin for a more polished and consistent look and feel, including to the Pomodoro views, task cards, and modals.\r\n- **Documentation**:\r\n - The documentation has been updated to reflect the new project management features.\r\n - New workflow guides for \"Habit Tracking\" and \"Project Management\" have been added.\r\n\r\n","aliases":["/releases/3.11.0/","/releases/3.11.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"project-management","text":"Project Management"},{"level":3,"id":"workflow-and-ui-enhancements","text":"Workflow and UI Enhancements"},{"level":2,"id":"bug-fixes-and-minor-improvements","text":"Bug Fixes and Minor Improvements"}],"html":"

This release introduces a new project management system, significant enhancements to the Pomodoro timer and workflows, and a number of quality-of-life improvements and bug fixes.

\n

New Features#

\n

Project Management#

\n

A new project management system has been integrated, allowing for better organization and tracking of tasks within projects.

\n
    \n
  • Note-Based Projects: Projects are now properly integrated into TaskNotes. You can link tasks to any note in your vault, effectively turning that note into a project. This leverages Obsidian's core linking capabilities, allowing you to see all tasks related to a project in the backlinks of the project note.
  • \n
  • Project Selection UI: A new project selection modal has been added to the task creation and editing modals. It features fuzzy search to quickly find and assign tasks to project notes.
  • \n
  • Filtering and Grouping by Project:
      \n
    • The Filter Bar in all views now includes a "Project" filter, allowing you to see tasks for one or more specific projects.
    • \n
    • The "Group By" option now includes "Project", which organizes the Task List and Kanban views by project.
    • \n
    \n
  • \n
  • Clickable Project Links: In task cards and other views, project names are now clickable links that take you directly to the project note.
  • \n
\n

Workflow and UI Enhancements#

\n
    \n
  • Redesigned Pomodoro Timer: The Pomodoro timer has been completely redesigned for a more modern and user-friendly experience.
      \n
    • New Interface: A more compact and visually appealing interface.
    • \n
    • Time Adjustment: You can now add or subtract time from the current session or the prepared timer.
    • \n
    • Skip Break: A "Skip break" button is now available after a work session.
    • \n
    \n
  • \n
  • Enhanced Pomodoro Stats: The Pomodoro statistics view has been improved to provide more insights.
      \n
    • Overview Section: A new overview section shows today's completed Pomodoros, total focus time, and a comparison with yesterday's performance.
    • \n
    \n
  • \n
  • Instant Task Conversion: The "Convert task to TaskNote" command has been streamlined. It now instantly converts a checkbox task into a TaskNote without opening the creation modal, reducing friction.
  • \n
  • Quick Actions for Current Task: A new command, "Quick actions for current task," allows you to open the action palette for the currently active TaskNote, providing quick access to common operations.
  • \n
  • Improved Sorting Logic: The task sorting algorithm has been enhanced. When the primary sorting criterion (e.g., due date) is the same for multiple tasks, a fallback sorting order is applied: scheduled date -> due date -> priority -> title. This ensures a more predictable and logical ordering of tasks.
  • \n
  • Archive Button in Edit Modal: An "Archive" button has been added to the task edit modal, allowing for quick archiving and unarchiving of tasks.
  • \n
  • Week Start Day Setting: All calendar views now respect the "Start week on" setting from Obsidian's calendar preferences.
  • \n
\n

Bug Fixes and Minor Improvements#

\n
    \n
  • Recurring Task Date Consistency: A critical bug has been fixed where recurring task dates could appear on the wrong day in different timezones (especially CST). The handling of dates and timezones for recurring tasks is now more robust, ensuring consistency across all views.
  • \n
  • Pomodoro Daily Note Integration: The Pomodoro service now correctly handles adding session history to daily notes, preventing the creation of duplicate entries.
  • \n
  • Template Processing:
      \n
    • The {{parentNote}} template variable now correctly resolves to a properly formatted markdown link.
    • \n
    • YAML frontmatter in templates is now processed more safely to avoid parsing errors.
    • \n
    \n
  • \n
  • Date Validation: The complete_instances field for recurring tasks now has stricter validation to filter out invalid entries, improving data integrity.
  • \n
  • Natural Language Processing: The natural language parser now correctly applies scheduled times (e.g., "do something at 5pm") to created tasks.
  • \n
  • Agenda View Quick Select: A bug that prevented the date quick-select menus in the Agenda View from working after the first use has been fixed.
  • \n
  • Styling and CSS: Numerous styling improvements have been made across the plugin for a more polished and consistent look and feel, including to the Pomodoro views, task cards, and modals.
  • \n
  • Documentation:
      \n
    • The documentation has been updated to reflect the new project management features.
    • \n
    • New workflow guides for "Habit Tracking" and "Project Management" have been added.
    • \n
    \n
  • \n
\n","text":"This release introduces a new project management system, significant enhancements to the Pomodoro timer and workflows, and a number of quality-of-life improvements and bug fixes. New Features# Project Management# A new project management system has been integrated, allowing for better organization and tracking of tasks within projects. Note-Based Projects: Projects are now properly integrated into TaskNotes. You can link tasks to any note in your vault, effectively turning that note into a project. This leverages Obsidian's core linking capabilities, allowing you to see all tasks related to a project in the backlinks of the project note. Project Selection UI: A new project selection modal has been added to the task creation and editing modals. It features fuzzy search to quickly find and assign tasks to project notes. Filtering and Grouping by Project: The Filter Bar in all views now includes a \"Project\" filter, allowing you to see tasks for one or more specific projects. The \"Group By\" option now includes \"Project\", which organizes the Task List and Kanban views by project. Clickable Project Links: In task cards and other views, project names are now clickable links that take you directly to the project note. Workflow and UI Enhancements# Redesigned Pomodoro Timer: The Pomodoro timer has been completely redesigned for a more modern and user-friendly experience. New Interface: A more compact and visually appealing interface. Time Adjustment: You can now add or subtract time from the current session or the prepared timer. Skip Break: A \"Skip break\" button is now available after a work session. Enhanced Pomodoro Stats: The Pomodoro statistics view has been improved to provide more insights. Overview Section: A new overview section shows today's completed Pomodoros, total focus time, and a comparison with yesterday's performance. Instant Task Conversion: The \"Convert task to TaskNote\" command has been streamlined. It now instantly converts a checkbox task into a TaskNote without opening the creation modal, reducing friction. Quick Actions for Current Task: A new command, \"Quick actions for current task,\" allows you to open the action palette for the currently active TaskNote, providing quick access to common operations. Improved Sorting Logic: The task sorting algorithm has been enhanced. When the primary sorting criterion (e.g., due date) is the same for multiple tasks, a fallback sorting order is applied: scheduled date -> due date -> priority -> title. This ensures a more predictable and logical ordering of tasks. Archive Button in Edit Modal: An \"Archive\" button has been added to the task edit modal, allowing for quick archiving and unarchiving of tasks. Week Start Day Setting: All calendar views now respect the \"Start week on\" setting from Obsidian's calendar preferences. Bug Fixes and Minor Improvements# Recurring Task Date Consistency: A critical bug has been fixed where recurring task dates could appear on the wrong day in different timezones (especially CST). The handling of dates and timezones for recurring tasks is now more robust, ensuring consistency across all views. Pomodoro Daily Note Integration: The Pomodoro service now correctly handles adding session history to daily notes, preventing the creation of duplicate entries. Template Processing: The {{parentNote}} template variable now correctly resolves to a properly formatted markdown link. YAML frontmatter in templates is now processed more safely to avoid parsing errors. Date Validation: The complete_instances field for recurring tasks now has stricter validation to filter out invalid entries, improving data integrity. Natural Language Processing: The natural language parser now correctly applies scheduled times (e.g., \"do something at 5pm\") to created tasks. Agenda View Quick Select: A bug that prevented the date quick-select menus in the Agenda View from working after the first use has been fixed. Styling and CSS: Numerous styling improvements have been made across the plugin for a more polished and consistent look and feel, including to the Pomodoro views, task cards, and modals. Documentation: The documentation has been updated to reflect the new project management features. New workflow guides for \"Habit Tracking\" and \"Project Management\" have been added."},{"route":"/obsidian/releases/3.11.1/","title":"Release Notes 3.11.1","description":"This release focuses on adopting Obsidian's official APIs and improving plugin stability through better resource management.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.11.1.md","namespace":"obsidian","relativePath":"releases/3.11.1.md","raw":"# Release Notes 3.11.1\r\n\r\n## API Modernization & Performance Improvements\r\n\r\nThis release focuses on adopting Obsidian's official APIs and improving plugin stability through better resource management.\r\n\r\n### Improved autocomplete\r\n\r\n- Replaced custom autocomplete implementation with Obsidian's native AbstractInputSuggest API\r\n - Better keyboard navigation and visual consistency\r\n - More responsive type-ahead support for contexts and tags in task modals\r\n\r\n### API modernization\r\n\r\n- Atomic Frontmatter Updates: Now uses FileManager.processFrontMatter for safer file modifications\r\n - Eliminates risk of data corruption during migration processes\r\n - More reliable handling of YAML frontmatter updates\r\n- Native Link Parsing: Switched to Obsidian's built-in parseLinktext API\r\n - More robust wikilink parsing with better edge case handling\r\n - Improved consistency with Obsidian's internal link processing\r\n- Vault-Specific Storage: View preferences now use App.loadLocalStorage/saveLocalStorage\r\n - Fixes issue where settings were shared across different vaults\r\n - Each vault now maintains its own view state and preferences\r\n\r\n## Bug fixes & stability\r\n\r\n- Memory Leak Prevention: Properly register and cleanup event listeners\r\n - Event listeners are now tracked with EventRef objects for proper cleanup\r\n - Prevents memory leaks when plugin is disabled or reloaded\r\n- Debounce Optimization: Uses Obsidian's built-in debounce function\r\n - More efficient calendar refresh operations\r\n - Better performance consistency\r\n- UI Polish: Fixed sentence case issues throughout the interface\r\n\r\n## Security & reliability\r\n\r\n- Resource Cleanup: Enhanced plugin lifecycle management\r\n - Better cleanup of event listeners and cached data\r\n - Improved plugin disable/enable reliability\r\n\r\n","aliases":["/releases/3.11.1/","/releases/3.11.1/"],"toc":[{"level":2,"id":"api-modernization-performance-improvements","text":"API Modernization & Performance Improvements"},{"level":3,"id":"improved-autocomplete","text":"Improved autocomplete"},{"level":3,"id":"api-modernization","text":"API modernization"},{"level":2,"id":"bug-fixes-stability","text":"Bug fixes & stability"},{"level":2,"id":"security-reliability","text":"Security & reliability"}],"html":"

API Modernization & Performance Improvements#

\n

This release focuses on adopting Obsidian's official APIs and improving plugin stability through better resource management.

\n

Improved autocomplete#

\n
    \n
  • Replaced custom autocomplete implementation with Obsidian's native AbstractInputSuggest API
      \n
    • Better keyboard navigation and visual consistency
    • \n
    • More responsive type-ahead support for contexts and tags in task modals
    • \n
    \n
  • \n
\n

API modernization#

\n
    \n
  • Atomic Frontmatter Updates: Now uses FileManager.processFrontMatter for safer file modifications
      \n
    • Eliminates risk of data corruption during migration processes
    • \n
    • More reliable handling of YAML frontmatter updates
    • \n
    \n
  • \n
  • Native Link Parsing: Switched to Obsidian's built-in parseLinktext API
      \n
    • More robust wikilink parsing with better edge case handling
    • \n
    • Improved consistency with Obsidian's internal link processing
    • \n
    \n
  • \n
  • Vault-Specific Storage: View preferences now use App.loadLocalStorage/saveLocalStorage
      \n
    • Fixes issue where settings were shared across different vaults
    • \n
    • Each vault now maintains its own view state and preferences
    • \n
    \n
  • \n
\n

Bug fixes & stability#

\n
    \n
  • Memory Leak Prevention: Properly register and cleanup event listeners
      \n
    • Event listeners are now tracked with EventRef objects for proper cleanup
    • \n
    • Prevents memory leaks when plugin is disabled or reloaded
    • \n
    \n
  • \n
  • Debounce Optimization: Uses Obsidian's built-in debounce function
      \n
    • More efficient calendar refresh operations
    • \n
    • Better performance consistency
    • \n
    \n
  • \n
  • UI Polish: Fixed sentence case issues throughout the interface
  • \n
\n

Security & reliability#

\n
    \n
  • Resource Cleanup: Enhanced plugin lifecycle management
      \n
    • Better cleanup of event listeners and cached data
    • \n
    • Improved plugin disable/enable reliability
    • \n
    \n
  • \n
\n","text":"API Modernization & Performance Improvements# This release focuses on adopting Obsidian's official APIs and improving plugin stability through better resource management. Improved autocomplete# Replaced custom autocomplete implementation with Obsidian's native AbstractInputSuggest API Better keyboard navigation and visual consistency More responsive type-ahead support for contexts and tags in task modals API modernization# Atomic Frontmatter Updates: Now uses FileManager.processFrontMatter for safer file modifications Eliminates risk of data corruption during migration processes More reliable handling of YAML frontmatter updates Native Link Parsing: Switched to Obsidian's built-in parseLinktext API More robust wikilink parsing with better edge case handling Improved consistency with Obsidian's internal link processing Vault-Specific Storage: View preferences now use App.loadLocalStorage/saveLocalStorage Fixes issue where settings were shared across different vaults Each vault now maintains its own view state and preferences Bug fixes & stability# Memory Leak Prevention: Properly register and cleanup event listeners Event listeners are now tracked with EventRef objects for proper cleanup Prevents memory leaks when plugin is disabled or reloaded Debounce Optimization: Uses Obsidian's built-in debounce function More efficient calendar refresh operations Better performance consistency UI Polish: Fixed sentence case issues throughout the interface Security & reliability# Resource Cleanup: Enhanced plugin lifecycle management Better cleanup of event listeners and cached data Improved plugin disable/enable reliability"},{"route":"/obsidian/releases/3.11.2/","title":"Release Notes - 3.11.2","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.11.2.md","namespace":"obsidian","relativePath":"releases/3.11.2.md","raw":"# Release Notes - 3.11.2\r\n\r\n## Internal Improvements\r\n\r\n### API Standardization\r\n\r\n- Replaced custom wikilink parsing with Obsidian's native `parseLinktext` API\r\n- Migrated from custom debounce function to Obsidian's built-in debounce utility\r\n\r\n### Files Updated\r\n\r\n- TaskLinkOverlay.ts: Updated wikilink parsing\r\n- FilterService.ts: Improved project link resolution\r\n- TaskLinkDetectionService.ts: Simplified link detection\r\n- MinimalNativeCache.ts: Standardized project link handling\r\n- KanbanView.ts: Replaced custom debounce implementation\r\n- Test files: Updated mocks accordingly\r\n","aliases":["/releases/3.11.2/","/releases/3.11.2/"],"toc":[{"level":2,"id":"internal-improvements","text":"Internal Improvements"},{"level":3,"id":"api-standardization","text":"API Standardization"},{"level":3,"id":"files-updated","text":"Files Updated"}],"html":"

Internal Improvements#

\n

API Standardization#

\n
    \n
  • Replaced custom wikilink parsing with Obsidian's native parseLinktext API
  • \n
  • Migrated from custom debounce function to Obsidian's built-in debounce utility
  • \n
\n

Files Updated#

\n
    \n
  • TaskLinkOverlay.ts: Updated wikilink parsing
  • \n
  • FilterService.ts: Improved project link resolution
  • \n
  • TaskLinkDetectionService.ts: Simplified link detection
  • \n
  • MinimalNativeCache.ts: Standardized project link handling
  • \n
  • KanbanView.ts: Replaced custom debounce implementation
  • \n
  • Test files: Updated mocks accordingly
  • \n
\n","text":"Internal Improvements# API Standardization# Replaced custom wikilink parsing with Obsidian's native parseLinktext API Migrated from custom debounce function to Obsidian's built-in debounce utility Files Updated# TaskLinkOverlay.ts: Updated wikilink parsing FilterService.ts: Improved project link resolution TaskLinkDetectionService.ts: Simplified link detection MinimalNativeCache.ts: Standardized project link handling KanbanView.ts: Replaced custom debounce implementation Test files: Updated mocks accordingly"},{"route":"/obsidian/releases/3.12.0/","title":"Release Notes - 3.12.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.12.0.md","namespace":"obsidian","relativePath":"releases/3.12.0.md","raw":"# Release Notes - 3.12.0\r\n\r\n## New Features\r\n\r\n### Project Subtasks Widget\r\n\r\n- Add a collapsible widget that displays tasks linked to the current project note\r\n- Widget appears automatically in project notes and shows all tasks that reference the rpoject\r\n- Includes collapsible interface with persistent state across sessions\r\n- Updates automatically when tasks are modified or deleted\r\n- Can be enabled or disabled in plugin settings under \"Show project subtasks widget\"\r\n\r\n## Bug Fixes\r\n\r\n### FilterBar Improvements\r\n\r\n- Fixed FilterBar not updating dynamically when tasks get new contexts or projects (#138)\r\n- Fixed archived tasks' contexts and projects still appearing in filter bar (#139)\r\n- Resolved FilterBar showing projects with [[]] brackets\r\n- Fixed empty status list display on initial load\r\n- Improved initialization reliability with better event handling\r\n\r\n### Task Display\r\n\r\n- Fixed wikilink alias handling in TaskCard and inline displays (#145, #147)\r\n- Fixed projects not loading correctly in task edit modal (#141)\r\n- Improved cursor positioning in live preview mode\r\n\r\n## Documentation\r\n\r\n- Added documentation for project subtasks widget feature\r\n- Updated inline task integration documentation\r\n- Added configuration settings documentation\r\n","aliases":["/releases/3.12.0/","/releases/3.12.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"project-subtasks-widget","text":"Project Subtasks Widget"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"filterbar-improvements","text":"FilterBar Improvements"},{"level":3,"id":"task-display","text":"Task Display"},{"level":2,"id":"documentation","text":"Documentation"}],"html":"

New Features#

\n

Project Subtasks Widget#

\n
    \n
  • Add a collapsible widget that displays tasks linked to the current project note
  • \n
  • Widget appears automatically in project notes and shows all tasks that reference the rpoject
  • \n
  • Includes collapsible interface with persistent state across sessions
  • \n
  • Updates automatically when tasks are modified or deleted
  • \n
  • Can be enabled or disabled in plugin settings under "Show project subtasks widget"
  • \n
\n

Bug Fixes#

\n

FilterBar Improvements#

\n
    \n
  • Fixed FilterBar not updating dynamically when tasks get new contexts or projects (#138)
  • \n
  • Fixed archived tasks' contexts and projects still appearing in filter bar (#139)
  • \n
  • Resolved FilterBar showing projects with [[]] brackets
  • \n
  • Fixed empty status list display on initial load
  • \n
  • Improved initialization reliability with better event handling
  • \n
\n

Task Display#

\n
    \n
  • Fixed wikilink alias handling in TaskCard and inline displays (#145, #147)
  • \n
  • Fixed projects not loading correctly in task edit modal (#141)
  • \n
  • Improved cursor positioning in live preview mode
  • \n
\n

Documentation#

\n
    \n
  • Added documentation for project subtasks widget feature
  • \n
  • Updated inline task integration documentation
  • \n
  • Added configuration settings documentation
  • \n
\n","text":"New Features# Project Subtasks Widget# Add a collapsible widget that displays tasks linked to the current project note Widget appears automatically in project notes and shows all tasks that reference the rpoject Includes collapsible interface with persistent state across sessions Updates automatically when tasks are modified or deleted Can be enabled or disabled in plugin settings under \"Show project subtasks widget\" Bug Fixes# FilterBar Improvements# Fixed FilterBar not updating dynamically when tasks get new contexts or projects (#138) Fixed archived tasks' contexts and projects still appearing in filter bar (#139) Resolved FilterBar showing projects with [[]] brackets Fixed empty status list display on initial load Improved initialization reliability with better event handling Task Display# Fixed wikilink alias handling in TaskCard and inline displays (#145, #147) Fixed projects not loading correctly in task edit modal (#141) Improved cursor positioning in live preview mode Documentation# Added documentation for project subtasks widget feature Updated inline task integration documentation Added configuration settings documentation"},{"route":"/obsidian/releases/3.12.1/","title":"Release Notes - 3.12.1","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.12.1.md","namespace":"obsidian","relativePath":"releases/3.12.1.md","raw":"# Release Notes - 3.12.1\r\n\r\n## New Features\r\n\r\n### Project Subtasks Widget Enhancements\r\n\r\n- New button for task creation - Added \"New\" button to widget header for quick task creation\r\n- Auto-populated project field - New tasks automatically reference the current note as their project\r\n- Improved positioning - Widget now appears at the end of documents for better user experience\r\n- Improve visual design - Added dashed border to indicate virtual/generated content and improved styling\r\n\r\n## Bug Fixes\r\n\r\n### Timezone and Date Handling\r\n\r\n- Fixed timezone boundary issues in Agenda view date filtering (#153)\r\n- Resolved missing tasks that were scheduled 7 days ago or yesterday due to timezone drift\r\n- Enhanced date normalization in AgendaView for consistent behavior across timezones\r\n- Improved task filtering with better date handling in getTasksForDate()\r\n\r\n## UI and Display Improvements\r\n\r\n- Fixed cursor positioning to prevent cursor appearing after project subtasks widget\r\n- Resolved pre-populated projects not displaying correctly in task creation modal\r\n- Improved widget rendering with CSS-only styling approach for better performance\r\n\r\n## Settings Reorganization\r\n\r\n### New Misc Tab\r\n\r\n- Renamed \"Performance\" tab to \"Misc\" and moved to end of settings tab list\r\n- Consolidated miscellaneous features into a single organized location\r\n- Improved settings navigation by grouping related toggles together\r\n\r\n### Settings Moved to Misc Tab\r\n\r\n- Status bar toggle - Show tracked tasks in status bar\r\n- Project subtasks widget toggle - Show project subtasks widget in notes\r\n- Notes indexing toggle - Disable note indexing for performance optimization\r\n\r\n## Documentation Updates\r\n\r\n### Settings Documentation\r\n\r\n- Updated all documentation to reflect new settings organization\r\n- Created comprehensive Misc Settings documentation with detailed explanations\r\n- Removed outdated references from Advanced Settings documentation\r\n- Updated troubleshooting guides with correct setting locations\r\n\r\n## Reference Updates\r\n\r\n- Updated inline task feature documentation to reference new Misc tab location\r\n- Fixed all setting location references throughout documentation\r\n- Maintained backward compatibility information for users upgrading\r\n\r\n","aliases":["/releases/3.12.1/","/releases/3.12.1/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"project-subtasks-widget-enhancements","text":"Project Subtasks Widget Enhancements"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"timezone-and-date-handling","text":"Timezone and Date Handling"},{"level":2,"id":"ui-and-display-improvements","text":"UI and Display Improvements"},{"level":2,"id":"settings-reorganization","text":"Settings Reorganization"},{"level":3,"id":"new-misc-tab","text":"New Misc Tab"},{"level":3,"id":"settings-moved-to-misc-tab","text":"Settings Moved to Misc Tab"},{"level":2,"id":"documentation-updates","text":"Documentation Updates"},{"level":3,"id":"settings-documentation","text":"Settings Documentation"},{"level":2,"id":"reference-updates","text":"Reference Updates"}],"html":"

New Features#

\n

Project Subtasks Widget Enhancements#

\n
    \n
  • New button for task creation - Added "New" button to widget header for quick task creation
  • \n
  • Auto-populated project field - New tasks automatically reference the current note as their project
  • \n
  • Improved positioning - Widget now appears at the end of documents for better user experience
  • \n
  • Improve visual design - Added dashed border to indicate virtual/generated content and improved styling
  • \n
\n

Bug Fixes#

\n

Timezone and Date Handling#

\n
    \n
  • Fixed timezone boundary issues in Agenda view date filtering (#153)
  • \n
  • Resolved missing tasks that were scheduled 7 days ago or yesterday due to timezone drift
  • \n
  • Enhanced date normalization in AgendaView for consistent behavior across timezones
  • \n
  • Improved task filtering with better date handling in getTasksForDate()
  • \n
\n

UI and Display Improvements#

\n
    \n
  • Fixed cursor positioning to prevent cursor appearing after project subtasks widget
  • \n
  • Resolved pre-populated projects not displaying correctly in task creation modal
  • \n
  • Improved widget rendering with CSS-only styling approach for better performance
  • \n
\n

Settings Reorganization#

\n

New Misc Tab#

\n
    \n
  • Renamed "Performance" tab to "Misc" and moved to end of settings tab list
  • \n
  • Consolidated miscellaneous features into a single organized location
  • \n
  • Improved settings navigation by grouping related toggles together
  • \n
\n

Settings Moved to Misc Tab#

\n
    \n
  • Status bar toggle - Show tracked tasks in status bar
  • \n
  • Project subtasks widget toggle - Show project subtasks widget in notes
  • \n
  • Notes indexing toggle - Disable note indexing for performance optimization
  • \n
\n

Documentation Updates#

\n

Settings Documentation#

\n
    \n
  • Updated all documentation to reflect new settings organization
  • \n
  • Created comprehensive Misc Settings documentation with detailed explanations
  • \n
  • Removed outdated references from Advanced Settings documentation
  • \n
  • Updated troubleshooting guides with correct setting locations
  • \n
\n

Reference Updates#

\n
    \n
  • Updated inline task feature documentation to reference new Misc tab location
  • \n
  • Fixed all setting location references throughout documentation
  • \n
  • Maintained backward compatibility information for users upgrading
  • \n
\n","text":"New Features# Project Subtasks Widget Enhancements# New button for task creation - Added \"New\" button to widget header for quick task creation Auto-populated project field - New tasks automatically reference the current note as their project Improved positioning - Widget now appears at the end of documents for better user experience Improve visual design - Added dashed border to indicate virtual/generated content and improved styling Bug Fixes# Timezone and Date Handling# Fixed timezone boundary issues in Agenda view date filtering (#153) Resolved missing tasks that were scheduled 7 days ago or yesterday due to timezone drift Enhanced date normalization in AgendaView for consistent behavior across timezones Improved task filtering with better date handling in getTasksForDate() UI and Display Improvements# Fixed cursor positioning to prevent cursor appearing after project subtasks widget Resolved pre-populated projects not displaying correctly in task creation modal Improved widget rendering with CSS-only styling approach for better performance Settings Reorganization# New Misc Tab# Renamed \"Performance\" tab to \"Misc\" and moved to end of settings tab list Consolidated miscellaneous features into a single organized location Improved settings navigation by grouping related toggles together Settings Moved to Misc Tab# Status bar toggle - Show tracked tasks in status bar Project subtasks widget toggle - Show project subtasks widget in notes Notes indexing toggle - Disable note indexing for performance optimization Documentation Updates# Settings Documentation# Updated all documentation to reflect new settings organization Created comprehensive Misc Settings documentation with detailed explanations Removed outdated references from Advanced Settings documentation Updated troubleshooting guides with correct setting locations Reference Updates# Updated inline task feature documentation to reference new Misc tab location Fixed all setting location references throughout documentation Maintained backward compatibility information for users upgrading"},{"route":"/obsidian/releases/3.12.2/","title":"Release Notes - 3.12.2","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.12.2.md","namespace":"obsidian","relativePath":"releases/3.12.2.md","raw":"# Release Notes - 3.12.2\r\n\r\n## Bug Fixes\r\n\r\n### Calendar & Date Handling\r\n- Fixed off-by-one date bugs in completion calendar (#160)\r\n - Resolved timezone inconsistency where calendar showed one date but completion was recorded for another\r\n - Calendar rendering now uses UTC dates consistently across all components\r\n - Fixed \"Friday tasks appearing on Saturday\" issue in completion tracking\r\n\r\n### Task Management\r\n- Fixed project filters not working in agenda view (#161)\r\n - Project filtering now works consistently across all views\r\n- Fixed edit modal crash when tasks have empty project properties\r\n - Added null checks to prevent \"Cannot read properties of null\" errors\r\n - Handles null, undefined, and empty string project values gracefully\r\n- Fixed autofill suggestions not updating internal state (#159)\r\n - Context and tag suggestions now properly sync with modal internal state\r\n - Clicking suggestions now correctly updates the task data\r\n\r\n## UI & Styling\r\n- Fixed consistent styling for priorities and statuses settings tabs (#130)\r\n - Added missing BEM classes for proper grid alignment\r\n - Priority inputs now use same styling as status inputs\r\n - Fixed table column misalignment issues\r\n\r\n## Documentation\r\n\r\n- Improved README and documentation\r\n - Enhanced overview section with better flow and natural language\r\n - Added time-tracking and pomodoro feature descriptions\r\n - Fixed broken documentation links\r\n - Updated Core Features section with more accurate descriptions\r\n\r\n ## Testing\r\n\r\n- Added comprehensive tests for date handling issues\r\n - Increased test coverage for calendar and completion functionality\r\n - Added tests reproducing and verifying fixes for off-by-one date bugs\r\n","aliases":["/releases/3.12.2/","/releases/3.12.2/"],"toc":[{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"calendar-date-handling","text":"Calendar & Date Handling"},{"level":3,"id":"task-management","text":"Task Management"},{"level":2,"id":"ui-styling","text":"UI & Styling"},{"level":2,"id":"documentation","text":"Documentation"},{"level":2,"id":"testing","text":"Testing"}],"html":"

Bug Fixes#

\n

Calendar & Date Handling#

\n
    \n
  • Fixed off-by-one date bugs in completion calendar (#160)
      \n
    • Resolved timezone inconsistency where calendar showed one date but completion was recorded for another
    • \n
    • Calendar rendering now uses UTC dates consistently across all components
    • \n
    • Fixed "Friday tasks appearing on Saturday" issue in completion tracking
    • \n
    \n
  • \n
\n

Task Management#

\n
    \n
  • Fixed project filters not working in agenda view (#161)
      \n
    • Project filtering now works consistently across all views
    • \n
    \n
  • \n
  • Fixed edit modal crash when tasks have empty project properties
      \n
    • Added null checks to prevent "Cannot read properties of null" errors
    • \n
    • Handles null, undefined, and empty string project values gracefully
    • \n
    \n
  • \n
  • Fixed autofill suggestions not updating internal state (#159)
      \n
    • Context and tag suggestions now properly sync with modal internal state
    • \n
    • Clicking suggestions now correctly updates the task data
    • \n
    \n
  • \n
\n

UI & Styling#

\n
    \n
  • Fixed consistent styling for priorities and statuses settings tabs (#130)
      \n
    • Added missing BEM classes for proper grid alignment
    • \n
    • Priority inputs now use same styling as status inputs
    • \n
    • Fixed table column misalignment issues
    • \n
    \n
  • \n
\n

Documentation#

\n
    \n
  • Improved README and documentation
      \n
    • Enhanced overview section with better flow and natural language
    • \n
    • Added time-tracking and pomodoro feature descriptions
    • \n
    • Fixed broken documentation links
    • \n
    • Updated Core Features section with more accurate descriptions
    • \n
    \n
  • \n
\n

Testing#

\n
    \n
  • Added comprehensive tests for date handling issues
      \n
    • Increased test coverage for calendar and completion functionality
    • \n
    • Added tests reproducing and verifying fixes for off-by-one date bugs
    • \n
    \n
  • \n
\n","text":"Bug Fixes# Calendar & Date Handling# Fixed off-by-one date bugs in completion calendar (#160) Resolved timezone inconsistency where calendar showed one date but completion was recorded for another Calendar rendering now uses UTC dates consistently across all components Fixed \"Friday tasks appearing on Saturday\" issue in completion tracking Task Management# Fixed project filters not working in agenda view (#161) Project filtering now works consistently across all views Fixed edit modal crash when tasks have empty project properties Added null checks to prevent \"Cannot read properties of null\" errors Handles null, undefined, and empty string project values gracefully Fixed autofill suggestions not updating internal state (#159) Context and tag suggestions now properly sync with modal internal state Clicking suggestions now correctly updates the task data UI & Styling# Fixed consistent styling for priorities and statuses settings tabs (#130) Added missing BEM classes for proper grid alignment Priority inputs now use same styling as status inputs Fixed table column misalignment issues Documentation# Improved README and documentation Enhanced overview section with better flow and natural language Added time-tracking and pomodoro feature descriptions Fixed broken documentation links Updated Core Features section with more accurate descriptions Testing# Added comprehensive tests for date handling issues Increased test coverage for calendar and completion functionality Added tests reproducing and verifying fixes for off-by-one date bugs"},{"route":"/obsidian/releases/3.13.0/","title":"Release Notes - 3.13.0","description":"##Technical Changes","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.13.0.md","namespace":"obsidian","relativePath":"releases/3.13.0.md","raw":"# Release Notes - 3.13.0 \r\n\r\n## Major Changes\r\n\r\n### Filtering System Overhaul\r\n\r\n- Hierarchical Query Builder: Complete redesign of the filtering system with a query builder interface\r\n- Saved Views: Users can save, manage, and switch between custom filter configurations\r\n- FilterBar Redesign: Updated to use Obsidian components with improved styling\r\n\r\n### UI Updates\r\n\r\n- FilterBar Integration: Added to all task views (Kanban, List, Calendar, Agenda) with state management\r\n- Dropdown Improvements: Status and priority filters now use display labels\r\n- Dropdown Positioning: Fixed positioning and CSS styling issues\r\n\r\n## New Features\r\n\r\n### Natural Language Processing\r\n\r\n- Nested Tag Support: Tags with forward slashes are now supported (e.g., project/subtask)\r\n\r\n### Interface\r\n\r\n- Project Note Decorations: Updated styling and visual elements\r\n- Task Modal Styling: Refined task creation and editing interfaces\r\n\r\n## Bug Fixes\r\n\r\n### Filter System\r\n\r\n- Fixed handling of empty arrays in \"Projects is not empty\" conditions\r\n- Fixed incomplete filter conditions handling\r\n- Fixed saved views dropdown persistence when filters change\r\n- Fixed view options disappearing on refresh\r\n- Fixed view selector dropdown behavior\r\n\r\n### Testing\r\n\r\n- Fixed multiple unit and integration test failures\r\n- Fixed migration workflow test for YAML parsing errors\r\n- Expanded test coverage for task service completion\r\n\r\n### Code Quality\r\n\r\n- Removed debug console.log statements\r\n- Improved async handling and import organization\r\n- Better search functionality implementation\r\n\r\n##Technical Changes\r\n\r\n### Refactoring\r\n\r\n- Refactored FilterBar with Obsidian components\r\n- Updated filter rule definitions and UI components\r\n- Improved state management across views\r\n- Updated ViewStateManager\r\n\r\n## Development\r\n\r\n- Updated Typescript configuration\r\n- Added new Filter Utils.ts utility module\r\n- Improved code organization\r\n\r\n","aliases":["/releases/3.13.0/","/releases/3.13.0/"],"toc":[{"level":2,"id":"major-changes","text":"Major Changes"},{"level":3,"id":"filtering-system-overhaul","text":"Filtering System Overhaul"},{"level":3,"id":"ui-updates","text":"UI Updates"},{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"natural-language-processing","text":"Natural Language Processing"},{"level":3,"id":"interface","text":"Interface"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"filter-system","text":"Filter System"},{"level":3,"id":"testing","text":"Testing"},{"level":3,"id":"code-quality","text":"Code Quality"},{"level":3,"id":"refactoring","text":"Refactoring"},{"level":2,"id":"development","text":"Development"}],"html":"

Major Changes#

\n

Filtering System Overhaul#

\n
    \n
  • Hierarchical Query Builder: Complete redesign of the filtering system with a query builder interface
  • \n
  • Saved Views: Users can save, manage, and switch between custom filter configurations
  • \n
  • FilterBar Redesign: Updated to use Obsidian components with improved styling
  • \n
\n

UI Updates#

\n
    \n
  • FilterBar Integration: Added to all task views (Kanban, List, Calendar, Agenda) with state management
  • \n
  • Dropdown Improvements: Status and priority filters now use display labels
  • \n
  • Dropdown Positioning: Fixed positioning and CSS styling issues
  • \n
\n

New Features#

\n

Natural Language Processing#

\n
    \n
  • Nested Tag Support: Tags with forward slashes are now supported (e.g., project/subtask)
  • \n
\n

Interface#

\n
    \n
  • Project Note Decorations: Updated styling and visual elements
  • \n
  • Task Modal Styling: Refined task creation and editing interfaces
  • \n
\n

Bug Fixes#

\n

Filter System#

\n
    \n
  • Fixed handling of empty arrays in "Projects is not empty" conditions
  • \n
  • Fixed incomplete filter conditions handling
  • \n
  • Fixed saved views dropdown persistence when filters change
  • \n
  • Fixed view options disappearing on refresh
  • \n
  • Fixed view selector dropdown behavior
  • \n
\n

Testing#

\n
    \n
  • Fixed multiple unit and integration test failures
  • \n
  • Fixed migration workflow test for YAML parsing errors
  • \n
  • Expanded test coverage for task service completion
  • \n
\n

Code Quality#

\n
    \n
  • Removed debug console.log statements
  • \n
  • Improved async handling and import organization
  • \n
  • Better search functionality implementation
  • \n
\n

##Technical Changes

\n

Refactoring#

\n
    \n
  • Refactored FilterBar with Obsidian components
  • \n
  • Updated filter rule definitions and UI components
  • \n
  • Improved state management across views
  • \n
  • Updated ViewStateManager
  • \n
\n

Development#

\n
    \n
  • Updated Typescript configuration
  • \n
  • Added new Filter Utils.ts utility module
  • \n
  • Improved code organization
  • \n
\n","text":"Major Changes# Filtering System Overhaul# Hierarchical Query Builder: Complete redesign of the filtering system with a query builder interface Saved Views: Users can save, manage, and switch between custom filter configurations FilterBar Redesign: Updated to use Obsidian components with improved styling UI Updates# FilterBar Integration: Added to all task views (Kanban, List, Calendar, Agenda) with state management Dropdown Improvements: Status and priority filters now use display labels Dropdown Positioning: Fixed positioning and CSS styling issues New Features# Natural Language Processing# Nested Tag Support: Tags with forward slashes are now supported (e.g., project/subtask) Interface# Project Note Decorations: Updated styling and visual elements Task Modal Styling: Refined task creation and editing interfaces Bug Fixes# Filter System# Fixed handling of empty arrays in \"Projects is not empty\" conditions Fixed incomplete filter conditions handling Fixed saved views dropdown persistence when filters change Fixed view options disappearing on refresh Fixed view selector dropdown behavior Testing# Fixed multiple unit and integration test failures Fixed migration workflow test for YAML parsing errors Expanded test coverage for task service completion Code Quality# Removed debug console.log statements Improved async handling and import organization Better search functionality implementation ##Technical Changes Refactoring# Refactored FilterBar with Obsidian components Updated filter rule definitions and UI components Improved state management across views Updated ViewStateManager Development# Updated Typescript configuration Added new Filter Utils.ts utility module Improved code organization"},{"route":"/obsidian/releases/3.13.1/","title":"Release Notes - 3.13.1","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.13.1.md","namespace":"obsidian","relativePath":"releases/3.13.1.md","raw":"# Release Notes - 3.13.1 \r\n\r\n## New Features\r\n\r\n### Saved Filter Views Storage\r\n\r\n- Saved filter views now sync across devices with your vault\r\n- Views are stored in plugin data instead of browser localStorage\r\n- Automatic migration from previous storage system on first load\r\n\r\n### FilterBar Behavior\r\n\r\n- Filter panel now stays open when clicking elsewhere in the interface\r\n- Panel only closes when the filter button is clicked again\r\n- Eliminates accidental filter panel closures during normal use\r\n\r\n## Performance Improvements\r\n\r\n### Filter Operations\r\n\r\n- Adding and removing filters is now significantly faster\r\n- Reduced lag when building complex filter queries\r\n- Search input state preserved during filter modifications\r\n\r\n### Migration System\r\n\r\n- Early migration detection prevents DOM errors on first use\r\n- Better error handling during plugin initialization\r\n- Cleaner migration process for new users\r\n\r\n## Bug Fixes\r\n\r\n### First-Time User Experience\r\n\r\n- Fixed \"removeChild\" DOM errors when using filters for the first time\r\n- Resolved race conditions between migration and UI initialization\r\n- Added fallback UI states for improved reliability\r\n\r\n### FilterBar Stability\r\n\r\n- Added DOM connection checks before manipulation\r\n- Improved error boundaries in filter rendering\r\n- Better cleanup of event listeners on component destruction\r\n\r\n## Technical Changes\r\n\r\n### View State Management\r\n\r\n- Saved views migrate from localStorage to plugin data system\r\n- ViewStateManager now uses plugin settings for persistence\r\n- Enhanced migration detection and completion tracking\r\n\r\n### Error Handling\r\n\r\n- Added safety checks for DOM element manipulation\r\n- Graceful degradation when filter operations fail\r\n- Improved logging for troubleshooting migration issues\r\n\r\n","aliases":["/releases/3.13.1/","/releases/3.13.1/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"saved-filter-views-storage","text":"Saved Filter Views Storage"},{"level":3,"id":"filterbar-behavior","text":"FilterBar Behavior"},{"level":2,"id":"performance-improvements","text":"Performance Improvements"},{"level":3,"id":"filter-operations","text":"Filter Operations"},{"level":3,"id":"migration-system","text":"Migration System"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"first-time-user-experience","text":"First-Time User Experience"},{"level":3,"id":"filterbar-stability","text":"FilterBar Stability"},{"level":2,"id":"technical-changes","text":"Technical Changes"},{"level":3,"id":"view-state-management","text":"View State Management"},{"level":3,"id":"error-handling","text":"Error Handling"}],"html":"

New Features#

\n

Saved Filter Views Storage#

\n
    \n
  • Saved filter views now sync across devices with your vault
  • \n
  • Views are stored in plugin data instead of browser localStorage
  • \n
  • Automatic migration from previous storage system on first load
  • \n
\n

FilterBar Behavior#

\n
    \n
  • Filter panel now stays open when clicking elsewhere in the interface
  • \n
  • Panel only closes when the filter button is clicked again
  • \n
  • Eliminates accidental filter panel closures during normal use
  • \n
\n

Performance Improvements#

\n

Filter Operations#

\n
    \n
  • Adding and removing filters is now significantly faster
  • \n
  • Reduced lag when building complex filter queries
  • \n
  • Search input state preserved during filter modifications
  • \n
\n

Migration System#

\n
    \n
  • Early migration detection prevents DOM errors on first use
  • \n
  • Better error handling during plugin initialization
  • \n
  • Cleaner migration process for new users
  • \n
\n

Bug Fixes#

\n

First-Time User Experience#

\n
    \n
  • Fixed "removeChild" DOM errors when using filters for the first time
  • \n
  • Resolved race conditions between migration and UI initialization
  • \n
  • Added fallback UI states for improved reliability
  • \n
\n

FilterBar Stability#

\n
    \n
  • Added DOM connection checks before manipulation
  • \n
  • Improved error boundaries in filter rendering
  • \n
  • Better cleanup of event listeners on component destruction
  • \n
\n

Technical Changes#

\n

View State Management#

\n
    \n
  • Saved views migrate from localStorage to plugin data system
  • \n
  • ViewStateManager now uses plugin settings for persistence
  • \n
  • Enhanced migration detection and completion tracking
  • \n
\n

Error Handling#

\n
    \n
  • Added safety checks for DOM element manipulation
  • \n
  • Graceful degradation when filter operations fail
  • \n
  • Improved logging for troubleshooting migration issues
  • \n
\n","text":"New Features# Saved Filter Views Storage# Saved filter views now sync across devices with your vault Views are stored in plugin data instead of browser localStorage Automatic migration from previous storage system on first load FilterBar Behavior# Filter panel now stays open when clicking elsewhere in the interface Panel only closes when the filter button is clicked again Eliminates accidental filter panel closures during normal use Performance Improvements# Filter Operations# Adding and removing filters is now significantly faster Reduced lag when building complex filter queries Search input state preserved during filter modifications Migration System# Early migration detection prevents DOM errors on first use Better error handling during plugin initialization Cleaner migration process for new users Bug Fixes# First-Time User Experience# Fixed \"removeChild\" DOM errors when using filters for the first time Resolved race conditions between migration and UI initialization Added fallback UI states for improved reliability FilterBar Stability# Added DOM connection checks before manipulation Improved error boundaries in filter rendering Better cleanup of event listeners on component destruction Technical Changes# View State Management# Saved views migrate from localStorage to plugin data system ViewStateManager now uses plugin settings for persistence Enhanced migration detection and completion tracking Error Handling# Added safety checks for DOM element manipulation Graceful degradation when filter operations fail Improved logging for troubleshooting migration issues"},{"route":"/obsidian/releases/3.13.2/","title":"Release Notes - 3.13.2","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.13.2.md","namespace":"obsidian","relativePath":"releases/3.13.2.md","raw":"# Release Notes - 3.13.2\r\n\r\n## Performance Improvements\r\n\r\n### FilterBar and Saved Views\r\n- Fixed performance issue where adding new filter conditions would unnecessarily re-evaluate all existing filters\r\n- Added \"Select...\" placeholder option for new filter conditions to prevent premature filtering\r\n- Eliminated unnecessary cache re-indexing when saving or deleting saved views\r\n- Made settings system smarter to only trigger cache updates when indexing-related settings actually change\r\n\r\n### Filter Processing\r\n- Implemented index-backed filtering that processes significantly fewer tasks for filtered views\r\n- Added intelligent query result caching with automatic expiration to eliminate redundant operations\r\n- Improved candidate selection using existing status, date, and overdue task indexes\r\n- Enhanced set intersection logic for multiple AND conditions to further reduce processing\r\n\r\n## Bug Fixes\r\n\r\n### Filter Logic\r\n- Fixed critical bug where index optimization incorrectly excluded valid results for OR queries containing indexed conditions\r\n- Added detection logic to prevent unsafe optimizations when indexed conditions are part of OR groups\r\n- Improved query structure analysis to ensure filter correctness\r\n\r\n### Saved Views\r\n- Fixed issue where modifying one saved view could affect others due to shared object references\r\n- Added proper deep cloning of FilterQuery objects throughout the ViewStateManager\r\n- Ensured saved views remain independent when modified\r\n\r\n## Technical Details\r\n\r\n### Index Optimization Safety\r\n- Index optimizations now only apply when provably safe (AND relationships between indexed conditions)\r\n- Added recursive query analysis to detect OR groups containing indexed conditions\r\n- Maintains filter correctness while providing performance benefits where safe\r\n\r\n### Cache Management\r\n- Cache-related settings tracking: taskTag, excludedFolders, disableNoteIndexing, storeTitleInFilename, fieldMapping\r\n- Query result caching with 30-second auto-expiration and immediate invalidation on data changes\r\n- Debug logging available for performance monitoring\r\n\r\n## Performance Impact\r\n\r\n- Filter building is now responsive with no lag when adding conditions\r\n- Saved view operations are instant with no unnecessary re-indexing\r\n- Repeated filter operations are nearly instant due to intelligent caching\r\n- Significant memory usage reduction for large vaults\r\n\r\n","aliases":["/releases/3.13.2/","/releases/3.13.2/"],"toc":[{"level":2,"id":"performance-improvements","text":"Performance Improvements"},{"level":3,"id":"filterbar-and-saved-views","text":"FilterBar and Saved Views"},{"level":3,"id":"filter-processing","text":"Filter Processing"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"filter-logic","text":"Filter Logic"},{"level":3,"id":"saved-views","text":"Saved Views"},{"level":2,"id":"technical-details","text":"Technical Details"},{"level":3,"id":"index-optimization-safety","text":"Index Optimization Safety"},{"level":3,"id":"cache-management","text":"Cache Management"},{"level":2,"id":"performance-impact","text":"Performance Impact"}],"html":"

Performance Improvements#

\n

FilterBar and Saved Views#

\n
    \n
  • Fixed performance issue where adding new filter conditions would unnecessarily re-evaluate all existing filters
  • \n
  • Added "Select..." placeholder option for new filter conditions to prevent premature filtering
  • \n
  • Eliminated unnecessary cache re-indexing when saving or deleting saved views
  • \n
  • Made settings system smarter to only trigger cache updates when indexing-related settings actually change
  • \n
\n

Filter Processing#

\n
    \n
  • Implemented index-backed filtering that processes significantly fewer tasks for filtered views
  • \n
  • Added intelligent query result caching with automatic expiration to eliminate redundant operations
  • \n
  • Improved candidate selection using existing status, date, and overdue task indexes
  • \n
  • Enhanced set intersection logic for multiple AND conditions to further reduce processing
  • \n
\n

Bug Fixes#

\n

Filter Logic#

\n
    \n
  • Fixed critical bug where index optimization incorrectly excluded valid results for OR queries containing indexed conditions
  • \n
  • Added detection logic to prevent unsafe optimizations when indexed conditions are part of OR groups
  • \n
  • Improved query structure analysis to ensure filter correctness
  • \n
\n

Saved Views#

\n
    \n
  • Fixed issue where modifying one saved view could affect others due to shared object references
  • \n
  • Added proper deep cloning of FilterQuery objects throughout the ViewStateManager
  • \n
  • Ensured saved views remain independent when modified
  • \n
\n

Technical Details#

\n

Index Optimization Safety#

\n
    \n
  • Index optimizations now only apply when provably safe (AND relationships between indexed conditions)
  • \n
  • Added recursive query analysis to detect OR groups containing indexed conditions
  • \n
  • Maintains filter correctness while providing performance benefits where safe
  • \n
\n

Cache Management#

\n
    \n
  • Cache-related settings tracking: taskTag, excludedFolders, disableNoteIndexing, storeTitleInFilename, fieldMapping
  • \n
  • Query result caching with 30-second auto-expiration and immediate invalidation on data changes
  • \n
  • Debug logging available for performance monitoring
  • \n
\n

Performance Impact#

\n
    \n
  • Filter building is now responsive with no lag when adding conditions
  • \n
  • Saved view operations are instant with no unnecessary re-indexing
  • \n
  • Repeated filter operations are nearly instant due to intelligent caching
  • \n
  • Significant memory usage reduction for large vaults
  • \n
\n","text":"Performance Improvements# FilterBar and Saved Views# Fixed performance issue where adding new filter conditions would unnecessarily re-evaluate all existing filters Added \"Select...\" placeholder option for new filter conditions to prevent premature filtering Eliminated unnecessary cache re-indexing when saving or deleting saved views Made settings system smarter to only trigger cache updates when indexing-related settings actually change Filter Processing# Implemented index-backed filtering that processes significantly fewer tasks for filtered views Added intelligent query result caching with automatic expiration to eliminate redundant operations Improved candidate selection using existing status, date, and overdue task indexes Enhanced set intersection logic for multiple AND conditions to further reduce processing Bug Fixes# Filter Logic# Fixed critical bug where index optimization incorrectly excluded valid results for OR queries containing indexed conditions Added detection logic to prevent unsafe optimizations when indexed conditions are part of OR groups Improved query structure analysis to ensure filter correctness Saved Views# Fixed issue where modifying one saved view could affect others due to shared object references Added proper deep cloning of FilterQuery objects throughout the ViewStateManager Ensured saved views remain independent when modified Technical Details# Index Optimization Safety# Index optimizations now only apply when provably safe (AND relationships between indexed conditions) Added recursive query analysis to detect OR groups containing indexed conditions Maintains filter correctness while providing performance benefits where safe Cache Management# Cache-related settings tracking: taskTag, excludedFolders, disableNoteIndexing, storeTitleInFilename, fieldMapping Query result caching with 30-second auto-expiration and immediate invalidation on data changes Debug logging available for performance monitoring Performance Impact# Filter building is now responsive with no lag when adding conditions Saved view operations are instant with no unnecessary re-indexing Repeated filter operations are nearly instant due to intelligent caching Significant memory usage reduction for large vaults"},{"route":"/obsidian/releases/3.13.3/","title":"Release Notes - 3.13.3","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.13.3.md","namespace":"obsidian","relativePath":"releases/3.13.3.md","raw":"# Release Notes - 3.13.3\r\n\r\n## Bug Fixes\r\n\r\n### Fixed recurring task completion date recording\r\n- Resolved issue where \"mark completed for this date\" context menu option recorded completion for the wrong date\r\n- Fixed timezone inconsistency between completion date storage and checking logic\r\n- Recurring tasks now properly track completion status per calendar date\r\n\r\n### Improved recurring task filtering\r\n- Fixed \"Is completed\" filter condition to respect per-date completion status for recurring tasks\r\n- Filter results now accurately reflect whether recurring tasks are completed for specific dates\r\n\r\n## Enhancements\r\n\r\n### AgendaView improvements\r\n- Restored Today button with improved header layout\r\n- Reorganized header into three sections: navigation controls, period title, and actions\r\n- Fixed recurring task display to show tasks on their actual recurrence dates rather than just scheduled dates\r\n- Removed keyboard navigation shortcuts (left/right arrows)\r\n\r\n### Interface updates\r\n- Enhanced AgendaView header styling with better spacing and visual hierarchy\r\n- Added responsive design for mobile layouts\r\n- Improved button styling with proper hover and focus states\r\n\r\n## Technical Changes\r\n\r\n- Updated TaskService to use consistent local timezone formatting for completion dates\r\n- Enhanced FilterService to properly evaluate recurring task completion status\r\n- Improved AgendaView task fetching to use FilterService.getTasksForDate() for better recurrence handling\r\n\r\n## Testing\r\n\r\n- Added comprehensive test coverage for timezone handling and date formatting consistency\r\n- Added tests to verify recurring task completion behavior across different scenarios\r\n\r\n\r\n","aliases":["/releases/3.13.3/","/releases/3.13.3/"],"toc":[{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"fixed-recurring-task-completion-date-recording","text":"Fixed recurring task completion date recording"},{"level":3,"id":"improved-recurring-task-filtering","text":"Improved recurring task filtering"},{"level":2,"id":"enhancements","text":"Enhancements"},{"level":3,"id":"agendaview-improvements","text":"AgendaView improvements"},{"level":3,"id":"interface-updates","text":"Interface updates"},{"level":2,"id":"technical-changes","text":"Technical Changes"},{"level":2,"id":"testing","text":"Testing"}],"html":"

Bug Fixes#

\n

Fixed recurring task completion date recording#

\n
    \n
  • Resolved issue where "mark completed for this date" context menu option recorded completion for the wrong date
  • \n
  • Fixed timezone inconsistency between completion date storage and checking logic
  • \n
  • Recurring tasks now properly track completion status per calendar date
  • \n
\n

Improved recurring task filtering#

\n
    \n
  • Fixed "Is completed" filter condition to respect per-date completion status for recurring tasks
  • \n
  • Filter results now accurately reflect whether recurring tasks are completed for specific dates
  • \n
\n

Enhancements#

\n

AgendaView improvements#

\n
    \n
  • Restored Today button with improved header layout
  • \n
  • Reorganized header into three sections: navigation controls, period title, and actions
  • \n
  • Fixed recurring task display to show tasks on their actual recurrence dates rather than just scheduled dates
  • \n
  • Removed keyboard navigation shortcuts (left/right arrows)
  • \n
\n

Interface updates#

\n
    \n
  • Enhanced AgendaView header styling with better spacing and visual hierarchy
  • \n
  • Added responsive design for mobile layouts
  • \n
  • Improved button styling with proper hover and focus states
  • \n
\n

Technical Changes#

\n
    \n
  • Updated TaskService to use consistent local timezone formatting for completion dates
  • \n
  • Enhanced FilterService to properly evaluate recurring task completion status
  • \n
  • Improved AgendaView task fetching to use FilterService.getTasksForDate() for better recurrence handling
  • \n
\n

Testing#

\n
    \n
  • Added comprehensive test coverage for timezone handling and date formatting consistency
  • \n
  • Added tests to verify recurring task completion behavior across different scenarios
  • \n
\n","text":"Bug Fixes# Fixed recurring task completion date recording# Resolved issue where \"mark completed for this date\" context menu option recorded completion for the wrong date Fixed timezone inconsistency between completion date storage and checking logic Recurring tasks now properly track completion status per calendar date Improved recurring task filtering# Fixed \"Is completed\" filter condition to respect per-date completion status for recurring tasks Filter results now accurately reflect whether recurring tasks are completed for specific dates Enhancements# AgendaView improvements# Restored Today button with improved header layout Reorganized header into three sections: navigation controls, period title, and actions Fixed recurring task display to show tasks on their actual recurrence dates rather than just scheduled dates Removed keyboard navigation shortcuts (left/right arrows) Interface updates# Enhanced AgendaView header styling with better spacing and visual hierarchy Added responsive design for mobile layouts Improved button styling with proper hover and focus states Technical Changes# Updated TaskService to use consistent local timezone formatting for completion dates Enhanced FilterService to properly evaluate recurring task completion status Improved AgendaView task fetching to use FilterService.getTasksForDate() for better recurrence handling Testing# Added comprehensive test coverage for timezone handling and date formatting consistency Added tests to verify recurring task completion behavior across different scenarios"},{"route":"/obsidian/releases/3.13.4/","title":"Release Notes - 3.13.4","description":"Thanks to @cathywu, @Crunchnuggetz, @Poly-0000, @jpmoo and finally @bcohen44 for reporting the FilterBar crashes that led to identifying these migration issues.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.13.4.md","namespace":"obsidian","relativePath":"releases/3.13.4.md","raw":"# Release Notes - 3.13.4\r\n\r\n## Bug Fixes\r\n\r\n### FilterBar Migration Issues\r\n- Fixed critical TypeError crashes when upgrading from versions prior to 3.13.0\r\n- Resolved `Cannot read properties of undefined (reading 'forEach')` and `Cannot read properties of undefined (reading 'find')` errors in FilterBar rendering\r\n- Added detection for old FilterQuery format and automatic replacement with fresh defaults\r\n- Users upgrading from older versions now get clean filter states instead of broken data structures\r\n- Preserved valid sort and grouping settings when replacing incompatible filter data\r\n- Added error boundaries with console warnings for better debugging\r\n\r\n*Thanks to @cathywu, @Crunchnuggetz, @Poly-0000, @jpmoo and finally [@bcohen44](https://github.com/callumalpass/tasknotes/issues/170#issuecomment-3066981483) for reporting the FilterBar crashes that led to identifying these migration issues.*\r\n\r\n## Features\r\n\r\n### Calendar View Improvements\r\n- Added ICS refresh button directly in the Advanced Calendar view toolbar\r\n- ICS calendar subscriptions can now be refreshed without opening settings\r\n- Button integrates with existing ICS subscription service and triggers immediate calendar re-render\r\n- Improved ICS settings layout with horizontal button arrangement\r\n- Enhanced calendar styling with proper hover states and removed unnecessary CSS overrides\r\n- Extended today highlight disable to timegrid columns for visual consistency\r\n\r\n## Notes\r\n\r\nThis release focuses on stability improvements for users upgrading from older versions. The FilterBar migration fixes ensure that users moving from pre-3.13.0 versions will have a smooth experience with the new filtering system introduced in 3.13.0.\r\n\r\nThe ICS refresh button provides better user experience by allowing calendar data to be updated directly from the calendar view without navigating to settings.\r\n","aliases":["/releases/3.13.4/","/releases/3.13.4/"],"toc":[{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"filterbar-migration-issues","text":"FilterBar Migration Issues"},{"level":2,"id":"features","text":"Features"},{"level":3,"id":"calendar-view-improvements","text":"Calendar View Improvements"},{"level":2,"id":"notes","text":"Notes"}],"html":"

Bug Fixes#

\n

FilterBar Migration Issues#

\n
    \n
  • Fixed critical TypeError crashes when upgrading from versions prior to 3.13.0
  • \n
  • Resolved Cannot read properties of undefined (reading 'forEach') and Cannot read properties of undefined (reading 'find') errors in FilterBar rendering
  • \n
  • Added detection for old FilterQuery format and automatic replacement with fresh defaults
  • \n
  • Users upgrading from older versions now get clean filter states instead of broken data structures
  • \n
  • Preserved valid sort and grouping settings when replacing incompatible filter data
  • \n
  • Added error boundaries with console warnings for better debugging
  • \n
\n

Thanks to @cathywu, @Crunchnuggetz, @Poly-0000, @jpmoo and finally @bcohen44 for reporting the FilterBar crashes that led to identifying these migration issues.

\n

Features#

\n

Calendar View Improvements#

\n
    \n
  • Added ICS refresh button directly in the Advanced Calendar view toolbar
  • \n
  • ICS calendar subscriptions can now be refreshed without opening settings
  • \n
  • Button integrates with existing ICS subscription service and triggers immediate calendar re-render
  • \n
  • Improved ICS settings layout with horizontal button arrangement
  • \n
  • Enhanced calendar styling with proper hover states and removed unnecessary CSS overrides
  • \n
  • Extended today highlight disable to timegrid columns for visual consistency
  • \n
\n

Notes#

\n

This release focuses on stability improvements for users upgrading from older versions. The FilterBar migration fixes ensure that users moving from pre-3.13.0 versions will have a smooth experience with the new filtering system introduced in 3.13.0.

\n

The ICS refresh button provides better user experience by allowing calendar data to be updated directly from the calendar view without navigating to settings.

\n","text":"Bug Fixes# FilterBar Migration Issues# Fixed critical TypeError crashes when upgrading from versions prior to 3.13.0 Resolved Cannot read properties of undefined (reading 'forEach') and Cannot read properties of undefined (reading 'find') errors in FilterBar rendering Added detection for old FilterQuery format and automatic replacement with fresh defaults Users upgrading from older versions now get clean filter states instead of broken data structures Preserved valid sort and grouping settings when replacing incompatible filter data Added error boundaries with console warnings for better debugging Thanks to @cathywu, @Crunchnuggetz, @Poly-0000, @jpmoo and finally @bcohen44 for reporting the FilterBar crashes that led to identifying these migration issues. Features# Calendar View Improvements# Added ICS refresh button directly in the Advanced Calendar view toolbar ICS calendar subscriptions can now be refreshed without opening settings Button integrates with existing ICS subscription service and triggers immediate calendar re-render Improved ICS settings layout with horizontal button arrangement Enhanced calendar styling with proper hover states and removed unnecessary CSS overrides Extended today highlight disable to timegrid columns for visual consistency Notes# This release focuses on stability improvements for users upgrading from older versions. The FilterBar migration fixes ensure that users moving from pre-3.13.0 versions will have a smooth experience with the new filtering system introduced in 3.13.0. The ICS refresh button provides better user experience by allowing calendar data to be updated directly from the calendar view without navigating to settings."},{"route":"/obsidian/releases/3.14.0/","title":"Release 3.14.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.14.0.md","namespace":"obsidian","relativePath":"releases/3.14.0.md","raw":"# Release 3.14.0\r\n\r\n## New Features\r\n\r\n### Project Management Enhancements\r\n\r\n- Project Indicator Icons: TaskCard now displays visual indicators when tasks are used as projects [#191] - Thanks to @Poly-0000 for the suggestion\r\n- Project Filtering: Added comprehensive project filtering functionality to the main plugin [#191]\r\n- Create Subtask Option: Added \"Create subtask\" option to task card context menu for improved project workflow [#192] - Thanks to @Poly-0000 for the feature request\r\n- Project Detection: Enhanced ProjectSubtasksService with isTaskUsedAsProject method for better project identification [#191]\r\n\r\n### User Interface Improvements\r\n\r\n- Drag-and-Drop Saved Views: Implemented drag-and-drop reordering for saved views to improve workflow customization [#203] - Thanks to @jpmoo for the suggestion\r\n- Project Styling: Added CSS styling for project indicator icons to improve visual hierarchy [#191]\r\n- Created Date Sorting: Added 'Created Date' as a sort key option for better task organization [#188] - Thanks to @bl4z3ng41n for the PR\r\n\r\n## Bug Fixes\r\n\r\n### Calendar and Recurring Tasks\r\n\r\n- Calendar Resize Support: Fixed duration updates for recurring tasks via calendar resize operations\r\n- All-Day Handling: Improved recurring task all-day handling in calendar view [#201] - Thanks to @anomatomato and @bespokecomp for reporting\r\n\r\n### Settings and State Management\r\n\r\n- Pomodoro Session Persistence: Fixed issue where pomodoro sessions were being cleared when changing settings [#196] - Thanks to @anomatomato for the bug report\r\n\r\n### Technical Changes\r\n\r\n### Performance and Stability\r\n\r\n- Enhanced cache management and event handling for project-related functionality\r\n- Improved error handling in project subtask operations\r\n- Optimized project detection algorithms for better performance\r\n\r\n### Code Organization\r\n\r\n- Refactored project-related services for better modularity\r\n- Enhanced TypeScript type definitions for project functionality\r\n- Improved service initialization and cleanup processes\r\n\r\n## Documentation\r\n\r\n- Updated README with new project assets and feature documentation\r\n","aliases":["/releases/3.14.0/","/releases/3.14.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"project-management-enhancements","text":"Project Management Enhancements"},{"level":3,"id":"user-interface-improvements","text":"User Interface Improvements"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"calendar-and-recurring-tasks","text":"Calendar and Recurring Tasks"},{"level":3,"id":"settings-and-state-management","text":"Settings and State Management"},{"level":3,"id":"technical-changes","text":"Technical Changes"},{"level":3,"id":"performance-and-stability","text":"Performance and Stability"},{"level":3,"id":"code-organization","text":"Code Organization"},{"level":2,"id":"documentation","text":"Documentation"}],"html":"

New Features#

\n

Project Management Enhancements#

\n
    \n
  • Project Indicator Icons: TaskCard now displays visual indicators when tasks are used as projects [#191] - Thanks to @Poly-0000 for the suggestion
  • \n
  • Project Filtering: Added comprehensive project filtering functionality to the main plugin [#191]
  • \n
  • Create Subtask Option: Added "Create subtask" option to task card context menu for improved project workflow [#192] - Thanks to @Poly-0000 for the feature request
  • \n
  • Project Detection: Enhanced ProjectSubtasksService with isTaskUsedAsProject method for better project identification [#191]
  • \n
\n

User Interface Improvements#

\n
    \n
  • Drag-and-Drop Saved Views: Implemented drag-and-drop reordering for saved views to improve workflow customization [#203] - Thanks to @jpmoo for the suggestion
  • \n
  • Project Styling: Added CSS styling for project indicator icons to improve visual hierarchy [#191]
  • \n
  • Created Date Sorting: Added 'Created Date' as a sort key option for better task organization [#188] - Thanks to @bl4z3ng41n for the PR
  • \n
\n

Bug Fixes#

\n

Calendar and Recurring Tasks#

\n
    \n
  • Calendar Resize Support: Fixed duration updates for recurring tasks via calendar resize operations
  • \n
  • All-Day Handling: Improved recurring task all-day handling in calendar view [#201] - Thanks to @anomatomato and @bespokecomp for reporting
  • \n
\n

Settings and State Management#

\n
    \n
  • Pomodoro Session Persistence: Fixed issue where pomodoro sessions were being cleared when changing settings [#196] - Thanks to @anomatomato for the bug report
  • \n
\n

Technical Changes#

\n

Performance and Stability#

\n
    \n
  • Enhanced cache management and event handling for project-related functionality
  • \n
  • Improved error handling in project subtask operations
  • \n
  • Optimized project detection algorithms for better performance
  • \n
\n

Code Organization#

\n
    \n
  • Refactored project-related services for better modularity
  • \n
  • Enhanced TypeScript type definitions for project functionality
  • \n
  • Improved service initialization and cleanup processes
  • \n
\n

Documentation#

\n
    \n
  • Updated README with new project assets and feature documentation
  • \n
\n","text":"New Features# Project Management Enhancements# Project Indicator Icons: TaskCard now displays visual indicators when tasks are used as projects [#191] - Thanks to @Poly-0000 for the suggestion Project Filtering: Added comprehensive project filtering functionality to the main plugin [#191] Create Subtask Option: Added \"Create subtask\" option to task card context menu for improved project workflow [#192] - Thanks to @Poly-0000 for the feature request Project Detection: Enhanced ProjectSubtasksService with isTaskUsedAsProject method for better project identification [#191] User Interface Improvements# Drag-and-Drop Saved Views: Implemented drag-and-drop reordering for saved views to improve workflow customization [#203] - Thanks to @jpmoo for the suggestion Project Styling: Added CSS styling for project indicator icons to improve visual hierarchy [#191] Created Date Sorting: Added 'Created Date' as a sort key option for better task organization [#188] - Thanks to @bl4z3ng41n for the PR Bug Fixes# Calendar and Recurring Tasks# Calendar Resize Support: Fixed duration updates for recurring tasks via calendar resize operations All-Day Handling: Improved recurring task all-day handling in calendar view [#201] - Thanks to @anomatomato and @bespokecomp for reporting Settings and State Management# Pomodoro Session Persistence: Fixed issue where pomodoro sessions were being cleared when changing settings [#196] - Thanks to @anomatomato for the bug report Technical Changes# Performance and Stability# Enhanced cache management and event handling for project-related functionality Improved error handling in project subtask operations Optimized project detection algorithms for better performance Code Organization# Refactored project-related services for better modularity Enhanced TypeScript type definitions for project functionality Improved service initialization and cleanup processes Documentation# Updated README with new project assets and feature documentation"},{"route":"/obsidian/releases/3.15.0/","title":"Release 3.15.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.15.0.md","namespace":"obsidian","relativePath":"releases/3.15.0.md","raw":"# Release 3.15.0\n\n## New Features\n\n### NLP Input Enhancements\n\n- Auto-suggestions: Added autocomplete functionality for tags and contexts in NLP input [#131] - Thanks to @Poly-0000 for the suggestion\n- Project Auto-suggestions: Enhanced project auto-suggestions with rich display and field mapper integration\n- Context and Tag Suggestions: Implemented auto-suggestion system to prevent typos and improve consistency [#131]\n\n### Calendar Integration\n\n- ICS Event Integration: Added comprehensive ICS calendar event support with content creation capabilities [#122, #220] - Thanks to @donjjones and @Crunchnuggetz for the feature requests\n- ICS Event Creation: Integrated ICS events into field mapping and type system for note creation [#122, #220]\n- ICS Settings: Added ICS integration settings to calendar tab\n- Calendar Hover Previews: Implemented hover preview functionality for advanced calendar - Thanks @nightroman for noticing this\n- Time Entry Interaction: Added time entry interaction functionality to advanced calendar\n\n### Time Management\n\n- Auto-stop Tracking: Added automatic time tracking termination when tasks are completed - Thanks to @cathywu for the suggestion [#184]\n- Total Tracked Time: Enhanced edit modal to display total tracked time information [#181] - Thanks to @bcohen44 for the feature request\n- Pomodoro View: Added task card display and improved controls to pomodoro view [#184]\n- Timeblock Management: Enhanced TimeblockInfoModal with editing and deletion capabilities [#74] - Thanks to @bepolymathe for the suggestion\n\n### User Interface Improvements\n\n- Fuzzy Note Pickers: Enhanced note pickers with title and alias support [#192] - Thanks to @Poly-0000 for the feedback\n- Persistent Column Ordering: Added persistent column ordering to kanban board [#61] - Thanks to @slepsl for the suggestion\n- Click-outside Support: Added click-outside and keyboard support to filter bar [#227] - Thanks to @cstelmach for the UX improvement request\n- UI Polish: Removed unnecessary borders, shadows and transitions from various UI elements\n\n## Bug Fixes\n\n### Task Management\n\n- Nested Tags: Fixed support for nested tags in FilterBar\n- TypeError Resolution: Resolved TypeError when calling includes on non-array values\n\n### Calendar Integration\n\n- Default Time Estimate: Fixed calendar click-to-add operations to respect default time estimate setting [#233] - Thanks to @nightroman for the bug report\n- Time Slot Duration: Improved click detection in calendar to use time slot duration setting [#233]\n\n## Documentation\n\n- Auto-suggestion Documentation: Added comprehensive documentation for auto-suggestion functionality\n- ICS Integration Guide: Created detailed ICS calendar integration documentation\n- Release Notes: Added comprehensive release notes documentation with links to all versions\n- Inline Task Widget: Added screenshots and documentation for inline task widgets\n\n## Technical Changes\n\n### Code Organization\n\n- Enhanced service architecture for ICS integration\n- Improved field mapping system for calendar events\n- Optimized auto-suggestion algorithms\n- Enhanced type definitions for new functionality\n\n### Performance\n\n- Improved rendering performance for pomodoro view\n- Optimized calendar event handling\n- Enhanced note picker search capabilities\n","aliases":["/releases/3.15.0/","/releases/3.15.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"nlp-input-enhancements","text":"NLP Input Enhancements"},{"level":3,"id":"calendar-integration","text":"Calendar Integration"},{"level":3,"id":"time-management","text":"Time Management"},{"level":3,"id":"user-interface-improvements","text":"User Interface Improvements"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"task-management","text":"Task Management"},{"level":3,"id":"calendar-integration-2","text":"Calendar Integration"},{"level":2,"id":"documentation","text":"Documentation"},{"level":2,"id":"technical-changes","text":"Technical Changes"},{"level":3,"id":"code-organization","text":"Code Organization"},{"level":3,"id":"performance","text":"Performance"}],"html":"

New Features#

\n

NLP Input Enhancements#

\n
    \n
  • Auto-suggestions: Added autocomplete functionality for tags and contexts in NLP input [#131] - Thanks to @Poly-0000 for the suggestion
  • \n
  • Project Auto-suggestions: Enhanced project auto-suggestions with rich display and field mapper integration
  • \n
  • Context and Tag Suggestions: Implemented auto-suggestion system to prevent typos and improve consistency [#131]
  • \n
\n

Calendar Integration#

\n
    \n
  • ICS Event Integration: Added comprehensive ICS calendar event support with content creation capabilities [#122, #220] - Thanks to @donjjones and @Crunchnuggetz for the feature requests
  • \n
  • ICS Event Creation: Integrated ICS events into field mapping and type system for note creation [#122, #220]
  • \n
  • ICS Settings: Added ICS integration settings to calendar tab
  • \n
  • Calendar Hover Previews: Implemented hover preview functionality for advanced calendar - Thanks @nightroman for noticing this
  • \n
  • Time Entry Interaction: Added time entry interaction functionality to advanced calendar
  • \n
\n

Time Management#

\n
    \n
  • Auto-stop Tracking: Added automatic time tracking termination when tasks are completed - Thanks to @cathywu for the suggestion [#184]
  • \n
  • Total Tracked Time: Enhanced edit modal to display total tracked time information [#181] - Thanks to @bcohen44 for the feature request
  • \n
  • Pomodoro View: Added task card display and improved controls to pomodoro view [#184]
  • \n
  • Timeblock Management: Enhanced TimeblockInfoModal with editing and deletion capabilities [#74] - Thanks to @bepolymathe for the suggestion
  • \n
\n

User Interface Improvements#

\n
    \n
  • Fuzzy Note Pickers: Enhanced note pickers with title and alias support [#192] - Thanks to @Poly-0000 for the feedback
  • \n
  • Persistent Column Ordering: Added persistent column ordering to kanban board [#61] - Thanks to @slepsl for the suggestion
  • \n
  • Click-outside Support: Added click-outside and keyboard support to filter bar [#227] - Thanks to @cstelmach for the UX improvement request
  • \n
  • UI Polish: Removed unnecessary borders, shadows and transitions from various UI elements
  • \n
\n

Bug Fixes#

\n

Task Management#

\n
    \n
  • Nested Tags: Fixed support for nested tags in FilterBar
  • \n
  • TypeError Resolution: Resolved TypeError when calling includes on non-array values
  • \n
\n

Calendar Integration#

\n
    \n
  • Default Time Estimate: Fixed calendar click-to-add operations to respect default time estimate setting [#233] - Thanks to @nightroman for the bug report
  • \n
  • Time Slot Duration: Improved click detection in calendar to use time slot duration setting [#233]
  • \n
\n

Documentation#

\n
    \n
  • Auto-suggestion Documentation: Added comprehensive documentation for auto-suggestion functionality
  • \n
  • ICS Integration Guide: Created detailed ICS calendar integration documentation
  • \n
  • Release Notes: Added comprehensive release notes documentation with links to all versions
  • \n
  • Inline Task Widget: Added screenshots and documentation for inline task widgets
  • \n
\n

Technical Changes#

\n

Code Organization#

\n
    \n
  • Enhanced service architecture for ICS integration
  • \n
  • Improved field mapping system for calendar events
  • \n
  • Optimized auto-suggestion algorithms
  • \n
  • Enhanced type definitions for new functionality
  • \n
\n

Performance#

\n
    \n
  • Improved rendering performance for pomodoro view
  • \n
  • Optimized calendar event handling
  • \n
  • Enhanced note picker search capabilities
  • \n
\n","text":"New Features# NLP Input Enhancements# Auto-suggestions: Added autocomplete functionality for tags and contexts in NLP input [#131] - Thanks to @Poly-0000 for the suggestion Project Auto-suggestions: Enhanced project auto-suggestions with rich display and field mapper integration Context and Tag Suggestions: Implemented auto-suggestion system to prevent typos and improve consistency [#131] Calendar Integration# ICS Event Integration: Added comprehensive ICS calendar event support with content creation capabilities [#122, #220] - Thanks to @donjjones and @Crunchnuggetz for the feature requests ICS Event Creation: Integrated ICS events into field mapping and type system for note creation [#122, #220] ICS Settings: Added ICS integration settings to calendar tab Calendar Hover Previews: Implemented hover preview functionality for advanced calendar - Thanks @nightroman for noticing this Time Entry Interaction: Added time entry interaction functionality to advanced calendar Time Management# Auto-stop Tracking: Added automatic time tracking termination when tasks are completed - Thanks to @cathywu for the suggestion [#184] Total Tracked Time: Enhanced edit modal to display total tracked time information [#181] - Thanks to @bcohen44 for the feature request Pomodoro View: Added task card display and improved controls to pomodoro view [#184] Timeblock Management: Enhanced TimeblockInfoModal with editing and deletion capabilities [#74] - Thanks to @bepolymathe for the suggestion User Interface Improvements# Fuzzy Note Pickers: Enhanced note pickers with title and alias support [#192] - Thanks to @Poly-0000 for the feedback Persistent Column Ordering: Added persistent column ordering to kanban board [#61] - Thanks to @slepsl for the suggestion Click-outside Support: Added click-outside and keyboard support to filter bar [#227] - Thanks to @cstelmach for the UX improvement request UI Polish: Removed unnecessary borders, shadows and transitions from various UI elements Bug Fixes# Task Management# Nested Tags: Fixed support for nested tags in FilterBar TypeError Resolution: Resolved TypeError when calling includes on non-array values Calendar Integration# Default Time Estimate: Fixed calendar click-to-add operations to respect default time estimate setting [#233] - Thanks to @nightroman for the bug report Time Slot Duration: Improved click detection in calendar to use time slot duration setting [#233] Documentation# Auto-suggestion Documentation: Added comprehensive documentation for auto-suggestion functionality ICS Integration Guide: Created detailed ICS calendar integration documentation Release Notes: Added comprehensive release notes documentation with links to all versions Inline Task Widget: Added screenshots and documentation for inline task widgets Technical Changes# Code Organization# Enhanced service architecture for ICS integration Improved field mapping system for calendar events Optimized auto-suggestion algorithms Enhanced type definitions for new functionality Performance# Improved rendering performance for pomodoro view Optimized calendar event handling Enhanced note picker search capabilities"},{"route":"/obsidian/releases/3.15.1/","title":"Release 3.15.1","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.15.1.md","namespace":"obsidian","relativePath":"releases/3.15.1.md","raw":"# Release 3.15.1\n\n## New Features\n\n### Kanban Board Enhancements\n\n- Show Empty Status Columns: Kanban board now displays empty columns for all configured statuses, providing better visual structure and workflow clarity\n- Enhanced Task Grouping: Introduced GetGroupedTasksOptions interface for improved task grouping functionality with target date support and group pre-population [#236] - Thanks to @srcnDev for the implementation\n\n### Calendar Improvements\n\n- All-Day Event Styling: Added line-through styling for completed all-day events in the Advanced Calendar view [#252, #254] - Thanks to @anomatomato for reporting the issue and submitting the PR\n- Task Event Customization: Task events in the Advanced Calendar now include CSS classes based on their tags (e.g., `fc-tag-meeting`, `fc-tag-work`), enabling custom styling per tag [#243, #244] - Thanks to @jradam for the feature request and implementation\n\n## Bug Fixes\n\n### Kanban Board\n\n- Duplicate Column Prevention: Fixed issue where renaming existing statuses in Kanban configuration could result in duplicate columns appearing in the board [#258] - Thanks to @mat2022a for the bug report\n\n### Subtask Widget Issues\n\n- Split Pane Display: Resolved issue where subtask widgets would inappropriately appear on notes in split panes when focusing on different notes [#234]\n- Table Cell Interference: Fixed subtask widgets appearing inside table cells when editing tables in project notes [#207]\n\n## Technical Changes\n\n### Documentation\n\n- Fixed line break formatting issues in documentation files\n\n### Code Organization\n\n- Improved task grouping architecture with new options interface\n- Enhanced calendar event rendering system for better tag-based customization\n- Refined subtask widget positioning logic for better editor integration\n","aliases":["/releases/3.15.1/","/releases/3.15.1/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"kanban-board-enhancements","text":"Kanban Board Enhancements"},{"level":3,"id":"calendar-improvements","text":"Calendar Improvements"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"kanban-board","text":"Kanban Board"},{"level":3,"id":"subtask-widget-issues","text":"Subtask Widget Issues"},{"level":2,"id":"technical-changes","text":"Technical Changes"},{"level":3,"id":"documentation","text":"Documentation"},{"level":3,"id":"code-organization","text":"Code Organization"}],"html":"

New Features#

\n

Kanban Board Enhancements#

\n
    \n
  • Show Empty Status Columns: Kanban board now displays empty columns for all configured statuses, providing better visual structure and workflow clarity
  • \n
  • Enhanced Task Grouping: Introduced GetGroupedTasksOptions interface for improved task grouping functionality with target date support and group pre-population [#236] - Thanks to @srcnDev for the implementation
  • \n
\n

Calendar Improvements#

\n
    \n
  • All-Day Event Styling: Added line-through styling for completed all-day events in the Advanced Calendar view [#252, #254] - Thanks to @anomatomato for reporting the issue and submitting the PR
  • \n
  • Task Event Customization: Task events in the Advanced Calendar now include CSS classes based on their tags (e.g., fc-tag-meeting, fc-tag-work), enabling custom styling per tag [#243, #244] - Thanks to @jradam for the feature request and implementation
  • \n
\n

Bug Fixes#

\n

Kanban Board#

\n
    \n
  • Duplicate Column Prevention: Fixed issue where renaming existing statuses in Kanban configuration could result in duplicate columns appearing in the board [#258] - Thanks to @mat2022a for the bug report
  • \n
\n

Subtask Widget Issues#

\n
    \n
  • Split Pane Display: Resolved issue where subtask widgets would inappropriately appear on notes in split panes when focusing on different notes [#234]
  • \n
  • Table Cell Interference: Fixed subtask widgets appearing inside table cells when editing tables in project notes [#207]
  • \n
\n

Technical Changes#

\n

Documentation#

\n
    \n
  • Fixed line break formatting issues in documentation files
  • \n
\n

Code Organization#

\n
    \n
  • Improved task grouping architecture with new options interface
  • \n
  • Enhanced calendar event rendering system for better tag-based customization
  • \n
  • Refined subtask widget positioning logic for better editor integration
  • \n
\n","text":"New Features# Kanban Board Enhancements# Show Empty Status Columns: Kanban board now displays empty columns for all configured statuses, providing better visual structure and workflow clarity Enhanced Task Grouping: Introduced GetGroupedTasksOptions interface for improved task grouping functionality with target date support and group pre-population [#236] - Thanks to @srcnDev for the implementation Calendar Improvements# All-Day Event Styling: Added line-through styling for completed all-day events in the Advanced Calendar view [#252, #254] - Thanks to @anomatomato for reporting the issue and submitting the PR Task Event Customization: Task events in the Advanced Calendar now include CSS classes based on their tags (e.g., fc-tag-meeting, fc-tag-work), enabling custom styling per tag [#243, #244] - Thanks to @jradam for the feature request and implementation Bug Fixes# Kanban Board# Duplicate Column Prevention: Fixed issue where renaming existing statuses in Kanban configuration could result in duplicate columns appearing in the board [#258] - Thanks to @mat2022a for the bug report Subtask Widget Issues# Split Pane Display: Resolved issue where subtask widgets would inappropriately appear on notes in split panes when focusing on different notes [#234] Table Cell Interference: Fixed subtask widgets appearing inside table cells when editing tables in project notes [#207] Technical Changes# Documentation# Fixed line break formatting issues in documentation files Code Organization# Improved task grouping architecture with new options interface Enhanced calendar event rendering system for better tag-based customization Refined subtask widget positioning logic for better editor integration"},{"route":"/obsidian/releases/3.16.0/","title":"TaskNotes 3.16.0","description":"Extra thanks to @Totobal5 for multiple code contributions including (tricky!) Pomodoro timer fixes and advanced calendar resizing fixes","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.16.0.md","namespace":"obsidian","relativePath":"releases/3.16.0.md","raw":"# TaskNotes 3.16.0\n\n## New Features\n\n### Task Management\n\n- **Bulk Task Conversion**: Added command to convert all checkbox tasks in a note to TaskNotes at once (#28) - Thanks to @TheSnakePolyglot for the feature request\n- **Instant Task Conversion Enhancement**: Enable instant task conversion for any line type, not just existing tasks (#259, #262) - Thanks to @ghelton and @cathywu for the suggestions\n- **Default Project Setting**: Added option to set a default project for new tasks in task creation settings (#250) - Thanks to @davidszerman for the request\n- **Advanced Tag and Project Parsing**: Implement intelligent parsing of tags and projects during instant task conversion (#260) - Thanks to @mdbraber for reporting this bug\n- **Enhanced Filter Bar Integration**: Added FilterBar integration to subtask widget for better task organization (#267) - Thanks to @mdbraber for the suggestion\n\n### Calendar and Views\n\n- **Custom Multi-Day Calendar View**: Added configurable custom multi-day calendar view with support for 3-day, work week, and full week layouts (#282) - Thanks to @girisumit for the feature request\n- **Responsive Calendar UI**: Hide calendar title in narrow containers for better responsive design (#285) - Thanks to @girisumit for the improvement suggestion\n- **Locale-Aware Date Formatting**: Added locale-aware date formatting to advanced calendar view (#210) - Thanks to @emes81 for highlighting this usability issue\n- **Saved Views Enhancement**: Added view options support to saved views with active view name display in filter condition builder (#245) - Thanks to @kmaustral and @digitaldoctors for the feedback\n\n### Task Organization\n\n- **Drag and Drop Status Reordering**: Added drag and drop reordering for status configurations with hamburger menu icon (#291) - Thanks to @23426356587 for the suggestion\n- **Overdue Tasks Filter**: Added setting to hide completed tasks from overdue status display (#300) - Thanks to @Lankly and @violetbp for reporting the issue\n- **Project Group Enhancements**: Made project group labels clickable in Task List View with ctrl+hover preview support (#198) - Thanks to @jpmoo for the suggestion\n\n### Pomodoro Timer\n\n- **Background Timer Continuity**: Pomodoro timer now continues running when app is minimized or loses focus (#136) - Thanks to @Poly_0000 for reporting and @Totobal5 for the fix\n- **System Notifications**: Convert Pomodoro notices to system notifications for better visibility (#136)\n- **Manual Duration Adjustment**: Fixed manually adjusted Pomodoro duration being ignored on start (#293) - Thanks to @Totobal5 for identifying and fixing\n- **Task Completion Sorting**: Sort completed tasks to end of Pomodoro task selector for better organization\n\n## Bug Fixes\n\n### UI and Interaction\n\n- **Tooltip Standardization**: Standardized tooltips to use Obsidian's native setTooltip function to eliminate duplicate tooltips (#257) - Thanks to @digitaldoctors for the bug report\n- **Open Note Button Stability**: Stabilized Open note button hover behavior and made font size consistent with other modal buttons\n- **Date Context Menu Clarity**: Added titles to date context menus for better user clarity (#253) - Thanks to @digitaldoctors for the suggestion\n- **Project Removal**: Fixed project removal in edit modal not saving changes properly (#213)\n- **Advanced Calendar Resizing**: Fixed Advanced Calendar view not resizing correctly in detached windows (#137) - Thanks to @macbikegeek for reporting and very much to @Totobal5 for the fix\n\n### Calendar and Recurring Tasks\n\n- **Timezone Bug Fixes**: Resolved multiple timezone-related off-by-one bugs in recurring task completion and agenda view display - A big thanks to @jpmoo and @kmaustral for reporting and describing in detail this bug\n- **Custom Calendar Display**: Fixed undefined days display in custom calendar view\n- **Calendar Recurrence**: Resolved timezone-based off-by-one bugs in calendar recurrence calculations - Thanks to @jpmoo and @kmaustral for reporting this bug\n\n### Task Management\n\n- **Pomodoro Task Tracking**: Handle task filename changes in pomodoro view to prevent tracking issues (#289) - Thanks to @cathywu for the report\n- **Plugin Conflict Protection**: Made suggestion objects defensive against potential plugin conflicts (#304) - Thanks to @zeltak for reporting the plugin conflict\n- **Instant Conversion Improvements**: Use cleaned title for NLP parsing in instant task conversion with fallback to default tasks folder (#128) - Thanks to @bepolymathe for reporting the folder issues\n\n## Improvements\n\n### User Interface\n\n- **Minimalist Design System**: Implemented consistent borderless button design system across all components\n- **UI Polish**: Applied minimalist styling with cleaned up borders and shadows throughout the interface\n- **Settings Enhancement**: Enhanced settings explanatory sections with improved minimalist styling\n- **Advanced Calendar Title**: Made advanced calendar title smaller for better proportions\n\n### Search and Filtering\n\n- **Enhanced Search**: Improved search functionality to preserve existing filters when performing new searches\n- **Filter Preservation**: Better handling of filter states across different search operations\n\n### Development and Code Quality\n\n- **Code Documentation**: Improved code comments and documentation throughout the codebase\n- **Linting Cleanup**: Resolved various linting errors and improved code consistency\n- **Test Infrastructure**: Updated timezone-related tests to work reliably in CI environment\n- **GitHub Actions**: Added timeouts and offline preferences to improve CI reliability\n\n## Technical Improvements\n\n- Reduced excessive console logging from filter components\n- Updated Jest coverage thresholds to realistic levels\n- Improved error handling in various components\n- Improved defensive programming practices throughout the codebase\n\n## Contributors\n\nExtra thanks to **@Totobal5** for multiple code contributions including (tricky!) Pomodoro timer fixes and advanced calendar resizing fixes\n\n","aliases":["/releases/3.16.0/","/releases/3.16.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"task-management","text":"Task Management"},{"level":3,"id":"calendar-and-views","text":"Calendar and Views"},{"level":3,"id":"task-organization","text":"Task Organization"},{"level":3,"id":"pomodoro-timer","text":"Pomodoro Timer"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"ui-and-interaction","text":"UI and Interaction"},{"level":3,"id":"calendar-and-recurring-tasks","text":"Calendar and Recurring Tasks"},{"level":3,"id":"task-management-2","text":"Task Management"},{"level":2,"id":"improvements","text":"Improvements"},{"level":3,"id":"user-interface","text":"User Interface"},{"level":3,"id":"search-and-filtering","text":"Search and Filtering"},{"level":3,"id":"development-and-code-quality","text":"Development and Code Quality"},{"level":2,"id":"technical-improvements","text":"Technical Improvements"},{"level":2,"id":"contributors","text":"Contributors"}],"html":"

New Features#

\n

Task Management#

\n
    \n
  • Bulk Task Conversion: Added command to convert all checkbox tasks in a note to TaskNotes at once (#28) - Thanks to @TheSnakePolyglot for the feature request
  • \n
  • Instant Task Conversion Enhancement: Enable instant task conversion for any line type, not just existing tasks (#259, #262) - Thanks to @ghelton and @cathywu for the suggestions
  • \n
  • Default Project Setting: Added option to set a default project for new tasks in task creation settings (#250) - Thanks to @davidszerman for the request
  • \n
  • Advanced Tag and Project Parsing: Implement intelligent parsing of tags and projects during instant task conversion (#260) - Thanks to @mdbraber for reporting this bug
  • \n
  • Enhanced Filter Bar Integration: Added FilterBar integration to subtask widget for better task organization (#267) - Thanks to @mdbraber for the suggestion
  • \n
\n

Calendar and Views#

\n
    \n
  • Custom Multi-Day Calendar View: Added configurable custom multi-day calendar view with support for 3-day, work week, and full week layouts (#282) - Thanks to @girisumit for the feature request
  • \n
  • Responsive Calendar UI: Hide calendar title in narrow containers for better responsive design (#285) - Thanks to @girisumit for the improvement suggestion
  • \n
  • Locale-Aware Date Formatting: Added locale-aware date formatting to advanced calendar view (#210) - Thanks to @emes81 for highlighting this usability issue
  • \n
  • Saved Views Enhancement: Added view options support to saved views with active view name display in filter condition builder (#245) - Thanks to @kmaustral and @digitaldoctors for the feedback
  • \n
\n

Task Organization#

\n
    \n
  • Drag and Drop Status Reordering: Added drag and drop reordering for status configurations with hamburger menu icon (#291) - Thanks to @23426356587 for the suggestion
  • \n
  • Overdue Tasks Filter: Added setting to hide completed tasks from overdue status display (#300) - Thanks to @Lankly and @violetbp for reporting the issue
  • \n
  • Project Group Enhancements: Made project group labels clickable in Task List View with ctrl+hover preview support (#198) - Thanks to @jpmoo for the suggestion
  • \n
\n

Pomodoro Timer#

\n
    \n
  • Background Timer Continuity: Pomodoro timer now continues running when app is minimized or loses focus (#136) - Thanks to @Poly_0000 for reporting and @Totobal5 for the fix
  • \n
  • System Notifications: Convert Pomodoro notices to system notifications for better visibility (#136)
  • \n
  • Manual Duration Adjustment: Fixed manually adjusted Pomodoro duration being ignored on start (#293) - Thanks to @Totobal5 for identifying and fixing
  • \n
  • Task Completion Sorting: Sort completed tasks to end of Pomodoro task selector for better organization
  • \n
\n

Bug Fixes#

\n

UI and Interaction#

\n
    \n
  • Tooltip Standardization: Standardized tooltips to use Obsidian's native setTooltip function to eliminate duplicate tooltips (#257) - Thanks to @digitaldoctors for the bug report
  • \n
  • Open Note Button Stability: Stabilized Open note button hover behavior and made font size consistent with other modal buttons
  • \n
  • Date Context Menu Clarity: Added titles to date context menus for better user clarity (#253) - Thanks to @digitaldoctors for the suggestion
  • \n
  • Project Removal: Fixed project removal in edit modal not saving changes properly (#213)
  • \n
  • Advanced Calendar Resizing: Fixed Advanced Calendar view not resizing correctly in detached windows (#137) - Thanks to @macbikegeek for reporting and very much to @Totobal5 for the fix
  • \n
\n

Calendar and Recurring Tasks#

\n
    \n
  • Timezone Bug Fixes: Resolved multiple timezone-related off-by-one bugs in recurring task completion and agenda view display - A big thanks to @jpmoo and @kmaustral for reporting and describing in detail this bug
  • \n
  • Custom Calendar Display: Fixed undefined days display in custom calendar view
  • \n
  • Calendar Recurrence: Resolved timezone-based off-by-one bugs in calendar recurrence calculations - Thanks to @jpmoo and @kmaustral for reporting this bug
  • \n
\n

Task Management#

\n
    \n
  • Pomodoro Task Tracking: Handle task filename changes in pomodoro view to prevent tracking issues (#289) - Thanks to @cathywu for the report
  • \n
  • Plugin Conflict Protection: Made suggestion objects defensive against potential plugin conflicts (#304) - Thanks to @zeltak for reporting the plugin conflict
  • \n
  • Instant Conversion Improvements: Use cleaned title for NLP parsing in instant task conversion with fallback to default tasks folder (#128) - Thanks to @bepolymathe for reporting the folder issues
  • \n
\n

Improvements#

\n

User Interface#

\n
    \n
  • Minimalist Design System: Implemented consistent borderless button design system across all components
  • \n
  • UI Polish: Applied minimalist styling with cleaned up borders and shadows throughout the interface
  • \n
  • Settings Enhancement: Enhanced settings explanatory sections with improved minimalist styling
  • \n
  • Advanced Calendar Title: Made advanced calendar title smaller for better proportions
  • \n
\n

Search and Filtering#

\n
    \n
  • Enhanced Search: Improved search functionality to preserve existing filters when performing new searches
  • \n
  • Filter Preservation: Better handling of filter states across different search operations
  • \n
\n

Development and Code Quality#

\n
    \n
  • Code Documentation: Improved code comments and documentation throughout the codebase
  • \n
  • Linting Cleanup: Resolved various linting errors and improved code consistency
  • \n
  • Test Infrastructure: Updated timezone-related tests to work reliably in CI environment
  • \n
  • GitHub Actions: Added timeouts and offline preferences to improve CI reliability
  • \n
\n

Technical Improvements#

\n
    \n
  • Reduced excessive console logging from filter components
  • \n
  • Updated Jest coverage thresholds to realistic levels
  • \n
  • Improved error handling in various components
  • \n
  • Improved defensive programming practices throughout the codebase
  • \n
\n

Contributors#

\n

Extra thanks to @Totobal5 for multiple code contributions including (tricky!) Pomodoro timer fixes and advanced calendar resizing fixes

\n","text":"New Features# Task Management# Bulk Task Conversion: Added command to convert all checkbox tasks in a note to TaskNotes at once (#28) - Thanks to @TheSnakePolyglot for the feature request Instant Task Conversion Enhancement: Enable instant task conversion for any line type, not just existing tasks (#259, #262) - Thanks to @ghelton and @cathywu for the suggestions Default Project Setting: Added option to set a default project for new tasks in task creation settings (#250) - Thanks to @davidszerman for the request Advanced Tag and Project Parsing: Implement intelligent parsing of tags and projects during instant task conversion (#260) - Thanks to @mdbraber for reporting this bug Enhanced Filter Bar Integration: Added FilterBar integration to subtask widget for better task organization (#267) - Thanks to @mdbraber for the suggestion Calendar and Views# Custom Multi-Day Calendar View: Added configurable custom multi-day calendar view with support for 3-day, work week, and full week layouts (#282) - Thanks to @girisumit for the feature request Responsive Calendar UI: Hide calendar title in narrow containers for better responsive design (#285) - Thanks to @girisumit for the improvement suggestion Locale-Aware Date Formatting: Added locale-aware date formatting to advanced calendar view (#210) - Thanks to @emes81 for highlighting this usability issue Saved Views Enhancement: Added view options support to saved views with active view name display in filter condition builder (#245) - Thanks to @kmaustral and @digitaldoctors for the feedback Task Organization# Drag and Drop Status Reordering: Added drag and drop reordering for status configurations with hamburger menu icon (#291) - Thanks to @23426356587 for the suggestion Overdue Tasks Filter: Added setting to hide completed tasks from overdue status display (#300) - Thanks to @Lankly and @violetbp for reporting the issue Project Group Enhancements: Made project group labels clickable in Task List View with ctrl+hover preview support (#198) - Thanks to @jpmoo for the suggestion Pomodoro Timer# Background Timer Continuity: Pomodoro timer now continues running when app is minimized or loses focus (#136) - Thanks to @Poly_0000 for reporting and @Totobal5 for the fix System Notifications: Convert Pomodoro notices to system notifications for better visibility (#136) Manual Duration Adjustment: Fixed manually adjusted Pomodoro duration being ignored on start (#293) - Thanks to @Totobal5 for identifying and fixing Task Completion Sorting: Sort completed tasks to end of Pomodoro task selector for better organization Bug Fixes# UI and Interaction# Tooltip Standardization: Standardized tooltips to use Obsidian's native setTooltip function to eliminate duplicate tooltips (#257) - Thanks to @digitaldoctors for the bug report Open Note Button Stability: Stabilized Open note button hover behavior and made font size consistent with other modal buttons Date Context Menu Clarity: Added titles to date context menus for better user clarity (#253) - Thanks to @digitaldoctors for the suggestion Project Removal: Fixed project removal in edit modal not saving changes properly (#213) Advanced Calendar Resizing: Fixed Advanced Calendar view not resizing correctly in detached windows (#137) - Thanks to @macbikegeek for reporting and very much to @Totobal5 for the fix Calendar and Recurring Tasks# Timezone Bug Fixes: Resolved multiple timezone-related off-by-one bugs in recurring task completion and agenda view display - A big thanks to @jpmoo and @kmaustral for reporting and describing in detail this bug Custom Calendar Display: Fixed undefined days display in custom calendar view Calendar Recurrence: Resolved timezone-based off-by-one bugs in calendar recurrence calculations - Thanks to @jpmoo and @kmaustral for reporting this bug Task Management# Pomodoro Task Tracking: Handle task filename changes in pomodoro view to prevent tracking issues (#289) - Thanks to @cathywu for the report Plugin Conflict Protection: Made suggestion objects defensive against potential plugin conflicts (#304) - Thanks to @zeltak for reporting the plugin conflict Instant Conversion Improvements: Use cleaned title for NLP parsing in instant task conversion with fallback to default tasks folder (#128) - Thanks to @bepolymathe for reporting the folder issues Improvements# User Interface# Minimalist Design System: Implemented consistent borderless button design system across all components UI Polish: Applied minimalist styling with cleaned up borders and shadows throughout the interface Settings Enhancement: Enhanced settings explanatory sections with improved minimalist styling Advanced Calendar Title: Made advanced calendar title smaller for better proportions Search and Filtering# Enhanced Search: Improved search functionality to preserve existing filters when performing new searches Filter Preservation: Better handling of filter states across different search operations Development and Code Quality# Code Documentation: Improved code comments and documentation throughout the codebase Linting Cleanup: Resolved various linting errors and improved code consistency Test Infrastructure: Updated timezone-related tests to work reliably in CI environment GitHub Actions: Added timeouts and offline preferences to improve CI reliability Technical Improvements# Reduced excessive console logging from filter components Updated Jest coverage thresholds to realistic levels Improved error handling in various components Improved defensive programming practices throughout the codebase Contributors# Extra thanks to @Totobal5 for multiple code contributions including (tricky!) Pomodoro timer fixes and advanced calendar resizing fixes"},{"route":"/obsidian/releases/3.16.1/","title":"TaskNotes 3.16.1","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.16.1.md","namespace":"obsidian","relativePath":"releases/3.16.1.md","raw":"# TaskNotes 3.16.1\n\n## New Features\n\n### Task Management\n\n- **Visual Filter State Indicators**: Added visual state indicators for active saved views in FilterBar to provide better feedback when a saved view is currently active\n\n## Bug Fixes\n\n### Link Generation and Consistency\n\n- **Obsidian Link Format Compliance**: Fixed \"Insert tasknote link\" and \"Convert task to TaskNote\" commands to use Obsidian's native generateMarkdownLink method, respecting user's link format preferences in Files & Links settings [#312] - Thanks to @nightroman for reporting the inconsistency and requesting proper format support\n- **Consistent Link Formatting**: Both commands now generate links in the same format and are compatible with external tools when markdown links are preferred\n\n### Timezone and Date Handling\n\n- **Recurring Task Completion Fix**: Resolved critical timezone bug where recurring task completion dates were stored incorrectly in non-UTC timezones [#314] - Thanks to @kmaustral for detailed reporting and testing across multiple views\n- **UTC Date Consistency**: Updated all date utilities to use UTC methods consistently across calendar components, fixing off-by-one date issues in task completion tracking\n- **Calendar Date Normalization**: Added createSafeUTCDate utility function and converted MiniCalendarView navigation to UTC methods for reliable date handling\n\n### User Interface\n\n- **Sort Arrow Visibility**: Enhanced sort direction arrow visibility and positioning in filter condition builder with increased font size, bold weight, and accent color [#307] - Thanks to @kmaustral for noting the arrow was difficult to see in dark mode\n- **Duplicate Tooltip Prevention**: Removed duplicate tooltips on recurring task indicators by using Obsidian's native setTooltip function instead of HTML title attributes\n- **Pointer Cursor Consistency**: Added pointer cursor styling to all buttons in Pomodoro view for better usability [#308] - Thanks to @anomatomato for the contribution\n\n### Error Handling and Stability\n\n- **Daily Note Creation Protection**: Added proper error handling for createDailyNote failures across TimeblockCreationModal, PomodoroService, and helper utilities, preventing \"Cannot read properties of undefined\" errors\n- **Security Compliance**: Replaced unsafe innerHTML assignment with textContent in drag handle creation to resolve ESLint security violations\n\n## Improvements\n\n### User Interface\n\n- **Calendar Styling Enhancements**: Improved advanced calendar view with better borders, header text readability, and removed custom scrollbar styling for system consistency\n- **Enhanced Visual Definition**: Added border and border radius to calendar container, plus consistent borders on column headers and toolbar for cleaner appearance\n\n### Development and Code Quality\n\n- **Test Infrastructure**: Added missing setTooltip mock to resolve 39 failing TaskCard tests\n- **Documentation Updates**: Improved documentation formatting and appearance\n\n## Technical Improvements\n\n- Enhanced date handling throughout the codebase with UTC method standardization\n- Improved defensive programming practices for timezone-sensitive operations\n- Better error messaging for daily note creation failures\n- Code security improvements with ESLint compliance\n\n","aliases":["/releases/3.16.1/","/releases/3.16.1/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"task-management","text":"Task Management"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"link-generation-and-consistency","text":"Link Generation and Consistency"},{"level":3,"id":"timezone-and-date-handling","text":"Timezone and Date Handling"},{"level":3,"id":"user-interface","text":"User Interface"},{"level":3,"id":"error-handling-and-stability","text":"Error Handling and Stability"},{"level":2,"id":"improvements","text":"Improvements"},{"level":3,"id":"user-interface-2","text":"User Interface"},{"level":3,"id":"development-and-code-quality","text":"Development and Code Quality"},{"level":2,"id":"technical-improvements","text":"Technical Improvements"}],"html":"

New Features#

\n

Task Management#

\n
    \n
  • Visual Filter State Indicators: Added visual state indicators for active saved views in FilterBar to provide better feedback when a saved view is currently active
  • \n
\n

Bug Fixes#

\n\n
    \n
  • Obsidian Link Format Compliance: Fixed "Insert tasknote link" and "Convert task to TaskNote" commands to use Obsidian's native generateMarkdownLink method, respecting user's link format preferences in Files & Links settings [#312] - Thanks to @nightroman for reporting the inconsistency and requesting proper format support
  • \n
  • Consistent Link Formatting: Both commands now generate links in the same format and are compatible with external tools when markdown links are preferred
  • \n
\n

Timezone and Date Handling#

\n
    \n
  • Recurring Task Completion Fix: Resolved critical timezone bug where recurring task completion dates were stored incorrectly in non-UTC timezones [#314] - Thanks to @kmaustral for detailed reporting and testing across multiple views
  • \n
  • UTC Date Consistency: Updated all date utilities to use UTC methods consistently across calendar components, fixing off-by-one date issues in task completion tracking
  • \n
  • Calendar Date Normalization: Added createSafeUTCDate utility function and converted MiniCalendarView navigation to UTC methods for reliable date handling
  • \n
\n

User Interface#

\n
    \n
  • Sort Arrow Visibility: Enhanced sort direction arrow visibility and positioning in filter condition builder with increased font size, bold weight, and accent color [#307] - Thanks to @kmaustral for noting the arrow was difficult to see in dark mode
  • \n
  • Duplicate Tooltip Prevention: Removed duplicate tooltips on recurring task indicators by using Obsidian's native setTooltip function instead of HTML title attributes
  • \n
  • Pointer Cursor Consistency: Added pointer cursor styling to all buttons in Pomodoro view for better usability [#308] - Thanks to @anomatomato for the contribution
  • \n
\n

Error Handling and Stability#

\n
    \n
  • Daily Note Creation Protection: Added proper error handling for createDailyNote failures across TimeblockCreationModal, PomodoroService, and helper utilities, preventing "Cannot read properties of undefined" errors
  • \n
  • Security Compliance: Replaced unsafe innerHTML assignment with textContent in drag handle creation to resolve ESLint security violations
  • \n
\n

Improvements#

\n

User Interface#

\n
    \n
  • Calendar Styling Enhancements: Improved advanced calendar view with better borders, header text readability, and removed custom scrollbar styling for system consistency
  • \n
  • Enhanced Visual Definition: Added border and border radius to calendar container, plus consistent borders on column headers and toolbar for cleaner appearance
  • \n
\n

Development and Code Quality#

\n
    \n
  • Test Infrastructure: Added missing setTooltip mock to resolve 39 failing TaskCard tests
  • \n
  • Documentation Updates: Improved documentation formatting and appearance
  • \n
\n

Technical Improvements#

\n
    \n
  • Enhanced date handling throughout the codebase with UTC method standardization
  • \n
  • Improved defensive programming practices for timezone-sensitive operations
  • \n
  • Better error messaging for daily note creation failures
  • \n
  • Code security improvements with ESLint compliance
  • \n
\n","text":"New Features# Task Management# Visual Filter State Indicators: Added visual state indicators for active saved views in FilterBar to provide better feedback when a saved view is currently active Bug Fixes# Link Generation and Consistency# Obsidian Link Format Compliance: Fixed \"Insert tasknote link\" and \"Convert task to TaskNote\" commands to use Obsidian's native generateMarkdownLink method, respecting user's link format preferences in Files & Links settings [#312] - Thanks to @nightroman for reporting the inconsistency and requesting proper format support Consistent Link Formatting: Both commands now generate links in the same format and are compatible with external tools when markdown links are preferred Timezone and Date Handling# Recurring Task Completion Fix: Resolved critical timezone bug where recurring task completion dates were stored incorrectly in non-UTC timezones [#314] - Thanks to @kmaustral for detailed reporting and testing across multiple views UTC Date Consistency: Updated all date utilities to use UTC methods consistently across calendar components, fixing off-by-one date issues in task completion tracking Calendar Date Normalization: Added createSafeUTCDate utility function and converted MiniCalendarView navigation to UTC methods for reliable date handling User Interface# Sort Arrow Visibility: Enhanced sort direction arrow visibility and positioning in filter condition builder with increased font size, bold weight, and accent color [#307] - Thanks to @kmaustral for noting the arrow was difficult to see in dark mode Duplicate Tooltip Prevention: Removed duplicate tooltips on recurring task indicators by using Obsidian's native setTooltip function instead of HTML title attributes Pointer Cursor Consistency: Added pointer cursor styling to all buttons in Pomodoro view for better usability [#308] - Thanks to @anomatomato for the contribution Error Handling and Stability# Daily Note Creation Protection: Added proper error handling for createDailyNote failures across TimeblockCreationModal, PomodoroService, and helper utilities, preventing \"Cannot read properties of undefined\" errors Security Compliance: Replaced unsafe innerHTML assignment with textContent in drag handle creation to resolve ESLint security violations Improvements# User Interface# Calendar Styling Enhancements: Improved advanced calendar view with better borders, header text readability, and removed custom scrollbar styling for system consistency Enhanced Visual Definition: Added border and border radius to calendar container, plus consistent borders on column headers and toolbar for cleaner appearance Development and Code Quality# Test Infrastructure: Added missing setTooltip mock to resolve 39 failing TaskCard tests Documentation Updates: Improved documentation formatting and appearance Technical Improvements# Enhanced date handling throughout the codebase with UTC method standardization Improved defensive programming practices for timezone-sensitive operations Better error messaging for daily note creation failures Code security improvements with ESLint compliance"},{"route":"/obsidian/releases/3.16.2/","title":"TaskNotes 3.16.2","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.16.2.md","namespace":"obsidian","relativePath":"releases/3.16.2.md","raw":"# TaskNotes 3.16.2\n\n## New Features\n\n### Task Link Integration\n\n- **Markdown Link Support for Inline Task Widgets**: Extended task link detection and rendering to support both wikilinks and markdown links. The plugin now properly renders `[text](path)` markdown links as interactive inline task widgets in both live preview and reading modes [#312] - Thanks to @nightroman for noting the missing link overlays on markdown links\n\n## Improvements\n\n### Link Processing\n\n- **Link Detection**: Improved TaskLinkDetectionService to detect both `[[wikilinks]]` and `[markdown](links)` with proper URL decoding for paths containing spaces\n- **Link Rendering**: Updated both TaskLinkOverlay (live preview) and ReadingModeTaskLinkProcessor (reading mode) to handle both link types consistently\n- **API Integration**: Uses proper Obsidian API functions (`parseLinktext()` and `getFirstLinkpathDest()`) for reliable link resolution\n","aliases":["/releases/3.16.2/","/releases/3.16.2/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"task-link-integration","text":"Task Link Integration"},{"level":2,"id":"improvements","text":"Improvements"},{"level":3,"id":"link-processing","text":"Link Processing"}],"html":"

New Features#

\n\n
    \n
  • Markdown Link Support for Inline Task Widgets: Extended task link detection and rendering to support both wikilinks and markdown links. The plugin now properly renders [text](path) markdown links as interactive inline task widgets in both live preview and reading modes [#312] - Thanks to @nightroman for noting the missing link overlays on markdown links
  • \n
\n

Improvements#

\n\n
    \n
  • Link Detection: Improved TaskLinkDetectionService to detect both [[wikilinks]] and [markdown](links) with proper URL decoding for paths containing spaces
  • \n
  • Link Rendering: Updated both TaskLinkOverlay (live preview) and ReadingModeTaskLinkProcessor (reading mode) to handle both link types consistently
  • \n
  • API Integration: Uses proper Obsidian API functions (parseLinktext() and getFirstLinkpathDest()) for reliable link resolution
  • \n
\n","text":"New Features# Task Link Integration# Markdown Link Support for Inline Task Widgets: Extended task link detection and rendering to support both wikilinks and markdown links. The plugin now properly renders [text](path) markdown links as interactive inline task widgets in both live preview and reading modes [#312] - Thanks to @nightroman for noting the missing link overlays on markdown links Improvements# Link Processing# Link Detection: Improved TaskLinkDetectionService to detect both [[wikilinks]] and [markdown](links) with proper URL decoding for paths containing spaces Link Rendering: Updated both TaskLinkOverlay (live preview) and ReadingModeTaskLinkProcessor (reading mode) to handle both link types consistently API Integration: Uses proper Obsidian API functions (parseLinktext() and getFirstLinkpathDest()) for reliable link resolution"},{"route":"/obsidian/releases/3.16.3/","title":"TaskNotes 3.16.3","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.16.3.md","namespace":"obsidian","relativePath":"releases/3.16.3.md","raw":"# TaskNotes 3.16.3\n\n## Bug Fixes\n\n### User Interface\n\n- **Create Task Modal Accessibility**: Fixed UI issues when creating tasks with natural language input disabled. The modal now opens in an expanded state with immediate access to all input fields, eliminating the need to click or tab before entering task details [#324] - Thanks to @nightroman for reporting this usability issue\n\n### Timezone Handling\n\n- **Recurring Task Calendar Display**: Fixed timezone-related display bug where recurring tasks appeared on the wrong day for users in negative UTC timezones. Tuesday tasks no longer incorrectly appear on Monday in the calendar view\n- **Task Completion Calendar**: Improved timezone consistency in the TaskEditModal completion calendar to ensure dates display correctly across all timezones\n\n### Task Conversion\n\n- **Context Detection in Instant Tasks**: Fixed instant task conversion to properly detect and preserve contexts specified with \"@context\" syntax when converting inline tasks to TaskNotes [#320] - Thanks to @nslee123 for reporting this issue\n- **Time Preservation**: Fixed instant task conversion to preserve time information when converting tasks with scheduled or due times. Time components are now correctly carried over during the conversion process\n\n## Improvements\n\n### Code Quality\n\n- **Test Coverage**: Added comprehensive unit tests for InstantTaskConvertService context detection to ensure reliable context parsing in future releases","aliases":["/releases/3.16.3/","/releases/3.16.3/"],"toc":[{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"user-interface","text":"User Interface"},{"level":3,"id":"timezone-handling","text":"Timezone Handling"},{"level":3,"id":"task-conversion","text":"Task Conversion"},{"level":2,"id":"improvements","text":"Improvements"},{"level":3,"id":"code-quality","text":"Code Quality"}],"html":"

Bug Fixes#

\n

User Interface#

\n
    \n
  • Create Task Modal Accessibility: Fixed UI issues when creating tasks with natural language input disabled. The modal now opens in an expanded state with immediate access to all input fields, eliminating the need to click or tab before entering task details [#324] - Thanks to @nightroman for reporting this usability issue
  • \n
\n

Timezone Handling#

\n
    \n
  • Recurring Task Calendar Display: Fixed timezone-related display bug where recurring tasks appeared on the wrong day for users in negative UTC timezones. Tuesday tasks no longer incorrectly appear on Monday in the calendar view
  • \n
  • Task Completion Calendar: Improved timezone consistency in the TaskEditModal completion calendar to ensure dates display correctly across all timezones
  • \n
\n

Task Conversion#

\n
    \n
  • Context Detection in Instant Tasks: Fixed instant task conversion to properly detect and preserve contexts specified with "@context" syntax when converting inline tasks to TaskNotes [#320] - Thanks to @nslee123 for reporting this issue
  • \n
  • Time Preservation: Fixed instant task conversion to preserve time information when converting tasks with scheduled or due times. Time components are now correctly carried over during the conversion process
  • \n
\n

Improvements#

\n

Code Quality#

\n
    \n
  • Test Coverage: Added comprehensive unit tests for InstantTaskConvertService context detection to ensure reliable context parsing in future releases
  • \n
\n","text":"Bug Fixes# User Interface# Create Task Modal Accessibility: Fixed UI issues when creating tasks with natural language input disabled. The modal now opens in an expanded state with immediate access to all input fields, eliminating the need to click or tab before entering task details [#324] - Thanks to @nightroman for reporting this usability issue Timezone Handling# Recurring Task Calendar Display: Fixed timezone-related display bug where recurring tasks appeared on the wrong day for users in negative UTC timezones. Tuesday tasks no longer incorrectly appear on Monday in the calendar view Task Completion Calendar: Improved timezone consistency in the TaskEditModal completion calendar to ensure dates display correctly across all timezones Task Conversion# Context Detection in Instant Tasks: Fixed instant task conversion to properly detect and preserve contexts specified with \"@context\" syntax when converting inline tasks to TaskNotes [#320] - Thanks to @nslee123 for reporting this issue Time Preservation: Fixed instant task conversion to preserve time information when converting tasks with scheduled or due times. Time components are now correctly carried over during the conversion process Improvements# Code Quality# Test Coverage: Added comprehensive unit tests for InstantTaskConvertService context detection to ensure reliable context parsing in future releases"},{"route":"/obsidian/releases/3.16.4/","title":"TaskNotes 3.16.4","description":"This ensures users can always edit task titles regardless of the modal type or natural language input settings.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.16.4.md","namespace":"obsidian","relativePath":"releases/3.16.4.md","raw":"# TaskNotes 3.16.4\n\n## Bug Fixes\n\n### User Interface\n\n- **Task Modal Title Field**: Fixed regression from version 3.16.3 where the title field was inadvertently removed from all task modals. The title field is now properly displayed with correct visibility logic:\n - Edit modals: Title field always visible in the details section\n - Create modals with natural language input enabled: Title field visible in details section (as the main input becomes the NLP textarea)\n - Create modals with natural language input disabled: Title field only appears at the top of the modal\n\nThis ensures users can always edit task titles regardless of the modal type or natural language input settings.","aliases":["/releases/3.16.4/","/releases/3.16.4/"],"toc":[{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"user-interface","text":"User Interface"}],"html":"

Bug Fixes#

\n

User Interface#

\n
    \n
  • Task Modal Title Field: Fixed regression from version 3.16.3 where the title field was inadvertently removed from all task modals. The title field is now properly displayed with correct visibility logic:
      \n
    • Edit modals: Title field always visible in the details section
    • \n
    • Create modals with natural language input enabled: Title field visible in details section (as the main input becomes the NLP textarea)
    • \n
    • Create modals with natural language input disabled: Title field only appears at the top of the modal
    • \n
    \n
  • \n
\n

This ensures users can always edit task titles regardless of the modal type or natural language input settings.

\n","text":"Bug Fixes# User Interface# Task Modal Title Field: Fixed regression from version 3.16.3 where the title field was inadvertently removed from all task modals. The title field is now properly displayed with correct visibility logic: Edit modals: Title field always visible in the details section Create modals with natural language input enabled: Title field visible in details section (as the main input becomes the NLP textarea) Create modals with natural language input disabled: Title field only appears at the top of the modal This ensures users can always edit task titles regardless of the modal type or natural language input settings."},{"route":"/obsidian/releases/3.17.0/","title":"TaskNotes 3.17.0","description":"This release introduces improvements to recurring task handling with full DTSTART (start date/time) integration, addressing long-standing challenges in recurring task management...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.17.0.md","namespace":"obsidian","relativePath":"releases/3.17.0.md","raw":"# TaskNotes 3.17.0\n\n## Major Features\n\n### Enhanced Recurring Tasks with DTSTART Support\n\nThis release introduces improvements to recurring task handling with full DTSTART (start date/time) integration, addressing long-standing challenges in recurring task management and filtering.\n\n**Background and Motivation:**\n\nThe previous recurring task system created difficulties for users in filtering and managing task schedules. Users experienced unintuitive behavior where recurring tasks couldn't be treated consistently with regular tasks, making it challenging to see when the next occurrence would appear or to dynamically update task schedules upon completion. This implementation follows RFC 5545 standards to provide a more robust foundation for recurring task behavior.\n\n**Key Improvements:**\n\n- **DTSTART Integration**: All recurring tasks now include proper start dates and times in their recurrence rules, ensuring consistent behavior across timezones and providing a clear anchor point for the recurring pattern\n- **Dynamic Date Updates**: The `task.scheduled` field now always shows the next uncompleted occurrence, automatically updating when tasks are completed rather than showing static pattern dates\n- **Flexible Next Occurrence Scheduling**: The next scheduled occurrence can now be placed anywhere - before the pattern start date, outside the recurring pattern, or at any custom time, giving users complete control over scheduling\n- **Visual Hierarchy**: Pattern instances display with dashed borders while the next scheduled occurrence shows with solid borders, providing clear visual distinction between the recurring pattern and the active next task\n- **Independent Time Control**: Pattern instances and next occurrences can have different times (e.g., daily pattern at 9 AM, next occurrence at 2:30 PM), allowing for exceptions without breaking the recurring pattern\n- **Dual Drag Behavior**: Dragging pattern instances updates the recurring pattern timing globally, while dragging the next occurrence reschedules only that specific instance\n- **Automatic DTSTART Addition**: The system automatically adds DTSTART when completing recurring tasks, editing recurrence rules, or converting tasks to recurring, ensuring backward compatibility while upgrading task definitions\n- **Manual Rescheduling Support**: Clear flags indicate when tasks have been manually rescheduled, maintaining transparency about schedule modifications\n\n### Expandable Project Subtasks\n\nA new feature allows users to expand project task cards to view subtasks inline with proper visual hierarchy.\n\n**Features:**\n\n- **Chevron Controls**: Click chevron icons on project task cards to expand/collapse subtask display\n- **Configurable**: New \"Show expandable subtasks\" setting allows users to enable/disable the feature\n\n### Responsive Pomodoro View\n\nThe Pomodoro view now adapts seamlessly to different container sizes with comprehensive responsive design.\n\nThanks to @oliverlalan for requesting this improvement (#339).\n\n### Enhanced Filename Templates\n\nSignificant expansion of available template variables for task creation, providing much greater flexibility in filename patterns.\n\n**New Template Variables:**\n\n- **Date/Time Variations**: shortDate, monthName, dayName, week, quarter, time12, time24\n- **Unix Timestamps**: unix (seconds), unixMs (milliseconds) \n- **Title Case Variations**: titleLower, titleUpper, titleSnake, titleKebab, titleCamel, titlePascal\n- **Short Forms**: priorityShort, statusShort for single-letter representations\n- **Unique Identifiers**: zettel (Zettelkasten ID), nano (high-precision unique ID)\n\nThe settings UI now documents all 40+ available template variables for easy reference.\n\nThanks to @fastrick for the original unix timestamp request.\n\n## Bug Fixes\n\n### Critical Timezone Handling Fixes\n\nThis release resolves multiple timezone-related bugs that affected users worldwide, particularly those in non-UTC timezones. These fixes implement the \"UTC Anchor\" principle for consistent date handling.\n\n**Major Timezone Bugs Fixed:**\n\n- **Recurring Task Completion**: Fixed critical issue where marking recurring tasks complete would affect the wrong day for users in certain timezones, addressing reports from multiple users including issues #327, #322, and #314\n- **Calendar Date Misalignment**: Resolved off-by-one day errors in calendar rendering and task indicators, addressing inconsistencies across different views (originally reported by @Crunchnuggetz in issue #129, with additional reports from @donjjones and @robmikulec)\n- **Weekly Task Display**: Fixed issue where weekly recurring tasks set for specific days (e.g., Tuesdays) were showing completion dates on the wrong day (Monday) - reported by @jpmoo in issue #322\n- **Task Completion Date Bug**: Resolved bug where `complete_instances` was being set to the previous day, causing tasks to remain visible in Agenda view until manually corrected - reported in issue #314\n- **Date Parsing Inconsistencies**: Eliminated mixing of UTC and local date parsing that caused timezone-dependent behavior across the application\n- **Filter Date Handling**: Fixed date filtering to work consistently across all timezones\n- **Agenda View \"Today\" Detection**: Corrected timezone-sensitive today detection that affected agenda headers\n- **ICS Import Timezone Issues**: Resolved timezone problems with both recurring and single events from ICS imports\n\n**Technical Implementation:**\n\n- Introduced `parseDateToUTC()` function for consistent UTC anchoring of date-only strings\n- Updated date comparison functions to use UTC anchors throughout\n- Replaced timezone-sensitive date operations with consistent UTC-based alternatives\n- Comprehensive audit and fix of all date handling patterns in the codebase\n\n### Project Filtering Improvements\n\nResolved critical bugs in project filtering that prevented proper task display and project selection.\n\n**Fixes:**\n- **Wikilink Resolution**: Fixed handling of relative vs absolute project wikilinks (e.g., `[[../Projects/My Project]]` vs `[[My Project]]`) - thanks to @xorander00 for the detailed bug report\n- **Filter Grouping Logic**: Corrected AND/OR grouping in project filters to prevent showing too many tasks\n- **Missing Projects**: Fixed issue where not all projects appeared in filter dropdown selection\n- **Cache Management**: Improved cache invalidation and project name extraction with better validation\n\n### Subtask Widget Improvements\n\nFixed several issues with the project subtasks widget affecting user experience and reliability.\n\n**Widget Fixes:**\n\n- **View State Persistence**: Fixed issue where subtask widget views would reset when switching between notes or modifying subtasks (reported by @Poly-0000 in issue #329)\n- **Filter State Isolation**: Prevented filter settings from bleeding between different notes' subtask widgets\n- **Configurable Positioning**: Added setting to control widget placement at top or bottom of notes (requested by @michelebugio in issue #164)\n- **Event Listener Management**: Improved cleanup to prevent memory leaks and event accumulation\n- **Event Bubbling**: Fixed issue where clicking subtasks would trigger both subtask and parent task modals\n- **Styling Isolation**: Prevented completion styles from affecting nested subtasks incorrectly\n\n### ICS Calendar Integration\n\n**Timezone Processing**: Fixed timezone handling bug in ICS calendar subscriptions where VTIMEZONE components weren't being registered before parsing events, causing incorrect display times for timezone-specific calendar events.\n\n### Performance and Reliability\n\n**Cache Optimization**: Restored FilterService cache TTL to 30 seconds after temporary reduction, balancing performance with data freshness.\n\n**Type Safety**: Added proper type assertions for ICAL.TimezoneService calls to resolve TypeScript compilation issues.\n\n**Error Handling**: Enhanced error handling and null safety checks throughout project filtering and service initialization.\n\n## Technical Improvements\n\n### UTC Anchor Implementation\n\nComprehensive implementation of the UTC Anchor principle for robust timezone handling:\n\n- All date-only strings now consistently parsed as UTC anchors\n- Date comparison operations standardized using UTC methods\n- Eliminated timezone-dependent date creation patterns\n- Added comprehensive timezone test coverage\n\n### Service Architecture\n\n**Expanded Projects Service**: Enhanced state management and tracking for expandable project subtasks with proper cleanup and memory management.\n\n**View State Manager**: Improved view state persistence across different contexts and note switches.\n\n### Documentation Updates\n\n- Updated recurring tasks documentation to reflect new behavior\n- Added timezone handling guides for developers\n- Enhanced calendar views documentation with drag behavior explanations\n- Comprehensive template variable documentation\n\n## Breaking Changes\n\n**Date Handling**: While maintaining backward compatibility for user data, the internal date handling now consistently uses the UTC Anchor principle.\n\n## Migration Notes\n\nExisting recurring tasks will continue to work without modification. The system automatically adds DTSTART components when users interact with recurring tasks (completing, editing, or rescheduling).\n\n","aliases":["/releases/3.17.0/","/releases/3.17.0/"],"toc":[{"level":2,"id":"major-features","text":"Major Features"},{"level":3,"id":"enhanced-recurring-tasks-with-dtstart-support","text":"Enhanced Recurring Tasks with DTSTART Support"},{"level":3,"id":"expandable-project-subtasks","text":"Expandable Project Subtasks"},{"level":3,"id":"responsive-pomodoro-view","text":"Responsive Pomodoro View"},{"level":3,"id":"enhanced-filename-templates","text":"Enhanced Filename Templates"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"critical-timezone-handling-fixes","text":"Critical Timezone Handling Fixes"},{"level":3,"id":"project-filtering-improvements","text":"Project Filtering Improvements"},{"level":3,"id":"subtask-widget-improvements","text":"Subtask Widget Improvements"},{"level":3,"id":"ics-calendar-integration","text":"ICS Calendar Integration"},{"level":3,"id":"performance-and-reliability","text":"Performance and Reliability"},{"level":2,"id":"technical-improvements","text":"Technical Improvements"},{"level":3,"id":"utc-anchor-implementation","text":"UTC Anchor Implementation"},{"level":3,"id":"service-architecture","text":"Service Architecture"},{"level":3,"id":"documentation-updates","text":"Documentation Updates"},{"level":2,"id":"breaking-changes","text":"Breaking Changes"},{"level":2,"id":"migration-notes","text":"Migration Notes"}],"html":"

Major Features#

\n

Enhanced Recurring Tasks with DTSTART Support#

\n

This release introduces improvements to recurring task handling with full DTSTART (start date/time) integration, addressing long-standing challenges in recurring task management and filtering.

\n

Background and Motivation:

\n

The previous recurring task system created difficulties for users in filtering and managing task schedules. Users experienced unintuitive behavior where recurring tasks couldn't be treated consistently with regular tasks, making it challenging to see when the next occurrence would appear or to dynamically update task schedules upon completion. This implementation follows RFC 5545 standards to provide a more robust foundation for recurring task behavior.

\n

Key Improvements:

\n
    \n
  • DTSTART Integration: All recurring tasks now include proper start dates and times in their recurrence rules, ensuring consistent behavior across timezones and providing a clear anchor point for the recurring pattern
  • \n
  • Dynamic Date Updates: The task.scheduled field now always shows the next uncompleted occurrence, automatically updating when tasks are completed rather than showing static pattern dates
  • \n
  • Flexible Next Occurrence Scheduling: The next scheduled occurrence can now be placed anywhere - before the pattern start date, outside the recurring pattern, or at any custom time, giving users complete control over scheduling
  • \n
  • Visual Hierarchy: Pattern instances display with dashed borders while the next scheduled occurrence shows with solid borders, providing clear visual distinction between the recurring pattern and the active next task
  • \n
  • Independent Time Control: Pattern instances and next occurrences can have different times (e.g., daily pattern at 9 AM, next occurrence at 2:30 PM), allowing for exceptions without breaking the recurring pattern
  • \n
  • Dual Drag Behavior: Dragging pattern instances updates the recurring pattern timing globally, while dragging the next occurrence reschedules only that specific instance
  • \n
  • Automatic DTSTART Addition: The system automatically adds DTSTART when completing recurring tasks, editing recurrence rules, or converting tasks to recurring, ensuring backward compatibility while upgrading task definitions
  • \n
  • Manual Rescheduling Support: Clear flags indicate when tasks have been manually rescheduled, maintaining transparency about schedule modifications
  • \n
\n

Expandable Project Subtasks#

\n

A new feature allows users to expand project task cards to view subtasks inline with proper visual hierarchy.

\n

Features:

\n
    \n
  • Chevron Controls: Click chevron icons on project task cards to expand/collapse subtask display
  • \n
  • Configurable: New "Show expandable subtasks" setting allows users to enable/disable the feature
  • \n
\n

Responsive Pomodoro View#

\n

The Pomodoro view now adapts seamlessly to different container sizes with comprehensive responsive design.

\n

Thanks to @oliverlalan for requesting this improvement (#339).

\n

Enhanced Filename Templates#

\n

Significant expansion of available template variables for task creation, providing much greater flexibility in filename patterns.

\n

New Template Variables:

\n
    \n
  • Date/Time Variations: shortDate, monthName, dayName, week, quarter, time12, time24
  • \n
  • Unix Timestamps: unix (seconds), unixMs (milliseconds)
  • \n
  • Title Case Variations: titleLower, titleUpper, titleSnake, titleKebab, titleCamel, titlePascal
  • \n
  • Short Forms: priorityShort, statusShort for single-letter representations
  • \n
  • Unique Identifiers: zettel (Zettelkasten ID), nano (high-precision unique ID)
  • \n
\n

The settings UI now documents all 40+ available template variables for easy reference.

\n

Thanks to @fastrick for the original unix timestamp request.

\n

Bug Fixes#

\n

Critical Timezone Handling Fixes#

\n

This release resolves multiple timezone-related bugs that affected users worldwide, particularly those in non-UTC timezones. These fixes implement the "UTC Anchor" principle for consistent date handling.

\n

Major Timezone Bugs Fixed:

\n
    \n
  • Recurring Task Completion: Fixed critical issue where marking recurring tasks complete would affect the wrong day for users in certain timezones, addressing reports from multiple users including issues #327, #322, and #314
  • \n
  • Calendar Date Misalignment: Resolved off-by-one day errors in calendar rendering and task indicators, addressing inconsistencies across different views (originally reported by @Crunchnuggetz in issue #129, with additional reports from @donjjones and @robmikulec)
  • \n
  • Weekly Task Display: Fixed issue where weekly recurring tasks set for specific days (e.g., Tuesdays) were showing completion dates on the wrong day (Monday) - reported by @jpmoo in issue #322
  • \n
  • Task Completion Date Bug: Resolved bug where complete_instances was being set to the previous day, causing tasks to remain visible in Agenda view until manually corrected - reported in issue #314
  • \n
  • Date Parsing Inconsistencies: Eliminated mixing of UTC and local date parsing that caused timezone-dependent behavior across the application
  • \n
  • Filter Date Handling: Fixed date filtering to work consistently across all timezones
  • \n
  • Agenda View "Today" Detection: Corrected timezone-sensitive today detection that affected agenda headers
  • \n
  • ICS Import Timezone Issues: Resolved timezone problems with both recurring and single events from ICS imports
  • \n
\n

Technical Implementation:

\n
    \n
  • Introduced parseDateToUTC() function for consistent UTC anchoring of date-only strings
  • \n
  • Updated date comparison functions to use UTC anchors throughout
  • \n
  • Replaced timezone-sensitive date operations with consistent UTC-based alternatives
  • \n
  • Comprehensive audit and fix of all date handling patterns in the codebase
  • \n
\n

Project Filtering Improvements#

\n

Resolved critical bugs in project filtering that prevented proper task display and project selection.

\n

Fixes:

\n
    \n
  • Wikilink Resolution: Fixed handling of relative vs absolute project wikilinks (e.g., [[../Projects/My Project]] vs [[My Project]]) - thanks to @xorander00 for the detailed bug report
  • \n
  • Filter Grouping Logic: Corrected AND/OR grouping in project filters to prevent showing too many tasks
  • \n
  • Missing Projects: Fixed issue where not all projects appeared in filter dropdown selection
  • \n
  • Cache Management: Improved cache invalidation and project name extraction with better validation
  • \n
\n

Subtask Widget Improvements#

\n

Fixed several issues with the project subtasks widget affecting user experience and reliability.

\n

Widget Fixes:

\n
    \n
  • View State Persistence: Fixed issue where subtask widget views would reset when switching between notes or modifying subtasks (reported by @Poly-0000 in issue #329)
  • \n
  • Filter State Isolation: Prevented filter settings from bleeding between different notes' subtask widgets
  • \n
  • Configurable Positioning: Added setting to control widget placement at top or bottom of notes (requested by @michelebugio in issue #164)
  • \n
  • Event Listener Management: Improved cleanup to prevent memory leaks and event accumulation
  • \n
  • Event Bubbling: Fixed issue where clicking subtasks would trigger both subtask and parent task modals
  • \n
  • Styling Isolation: Prevented completion styles from affecting nested subtasks incorrectly
  • \n
\n

ICS Calendar Integration#

\n

Timezone Processing: Fixed timezone handling bug in ICS calendar subscriptions where VTIMEZONE components weren't being registered before parsing events, causing incorrect display times for timezone-specific calendar events.

\n

Performance and Reliability#

\n

Cache Optimization: Restored FilterService cache TTL to 30 seconds after temporary reduction, balancing performance with data freshness.

\n

Type Safety: Added proper type assertions for ICAL.TimezoneService calls to resolve TypeScript compilation issues.

\n

Error Handling: Enhanced error handling and null safety checks throughout project filtering and service initialization.

\n

Technical Improvements#

\n

UTC Anchor Implementation#

\n

Comprehensive implementation of the UTC Anchor principle for robust timezone handling:

\n
    \n
  • All date-only strings now consistently parsed as UTC anchors
  • \n
  • Date comparison operations standardized using UTC methods
  • \n
  • Eliminated timezone-dependent date creation patterns
  • \n
  • Added comprehensive timezone test coverage
  • \n
\n

Service Architecture#

\n

Expanded Projects Service: Enhanced state management and tracking for expandable project subtasks with proper cleanup and memory management.

\n

View State Manager: Improved view state persistence across different contexts and note switches.

\n

Documentation Updates#

\n
    \n
  • Updated recurring tasks documentation to reflect new behavior
  • \n
  • Added timezone handling guides for developers
  • \n
  • Enhanced calendar views documentation with drag behavior explanations
  • \n
  • Comprehensive template variable documentation
  • \n
\n

Breaking Changes#

\n

Date Handling: While maintaining backward compatibility for user data, the internal date handling now consistently uses the UTC Anchor principle.

\n

Migration Notes#

\n

Existing recurring tasks will continue to work without modification. The system automatically adds DTSTART components when users interact with recurring tasks (completing, editing, or rescheduling).

\n","text":"Major Features# Enhanced Recurring Tasks with DTSTART Support# This release introduces improvements to recurring task handling with full DTSTART (start date/time) integration, addressing long-standing challenges in recurring task management and filtering. Background and Motivation: The previous recurring task system created difficulties for users in filtering and managing task schedules. Users experienced unintuitive behavior where recurring tasks couldn't be treated consistently with regular tasks, making it challenging to see when the next occurrence would appear or to dynamically update task schedules upon completion. This implementation follows RFC 5545 standards to provide a more robust foundation for recurring task behavior. Key Improvements: DTSTART Integration: All recurring tasks now include proper start dates and times in their recurrence rules, ensuring consistent behavior across timezones and providing a clear anchor point for the recurring pattern Dynamic Date Updates: The task.scheduled field now always shows the next uncompleted occurrence, automatically updating when tasks are completed rather than showing static pattern dates Flexible Next Occurrence Scheduling: The next scheduled occurrence can now be placed anywhere - before the pattern start date, outside the recurring pattern, or at any custom time, giving users complete control over scheduling Visual Hierarchy: Pattern instances display with dashed borders while the next scheduled occurrence shows with solid borders, providing clear visual distinction between the recurring pattern and the active next task Independent Time Control: Pattern instances and next occurrences can have different times (e.g., daily pattern at 9 AM, next occurrence at 2:30 PM), allowing for exceptions without breaking the recurring pattern Dual Drag Behavior: Dragging pattern instances updates the recurring pattern timing globally, while dragging the next occurrence reschedules only that specific instance Automatic DTSTART Addition: The system automatically adds DTSTART when completing recurring tasks, editing recurrence rules, or converting tasks to recurring, ensuring backward compatibility while upgrading task definitions Manual Rescheduling Support: Clear flags indicate when tasks have been manually rescheduled, maintaining transparency about schedule modifications Expandable Project Subtasks# A new feature allows users to expand project task cards to view subtasks inline with proper visual hierarchy. Features: Chevron Controls: Click chevron icons on project task cards to expand/collapse subtask display Configurable: New \"Show expandable subtasks\" setting allows users to enable/disable the feature Responsive Pomodoro View# The Pomodoro view now adapts seamlessly to different container sizes with comprehensive responsive design. Thanks to @oliverlalan for requesting this improvement (#339). Enhanced Filename Templates# Significant expansion of available template variables for task creation, providing much greater flexibility in filename patterns. New Template Variables: Date/Time Variations: shortDate, monthName, dayName, week, quarter, time12, time24 Unix Timestamps: unix (seconds), unixMs (milliseconds) Title Case Variations: titleLower, titleUpper, titleSnake, titleKebab, titleCamel, titlePascal Short Forms: priorityShort, statusShort for single-letter representations Unique Identifiers: zettel (Zettelkasten ID), nano (high-precision unique ID) The settings UI now documents all 40+ available template variables for easy reference. Thanks to @fastrick for the original unix timestamp request. Bug Fixes# Critical Timezone Handling Fixes# This release resolves multiple timezone-related bugs that affected users worldwide, particularly those in non-UTC timezones. These fixes implement the \"UTC Anchor\" principle for consistent date handling. Major Timezone Bugs Fixed: Recurring Task Completion: Fixed critical issue where marking recurring tasks complete would affect the wrong day for users in certain timezones, addressing reports from multiple users including issues #327, #322, and #314 Calendar Date Misalignment: Resolved off-by-one day errors in calendar rendering and task indicators, addressing inconsistencies across different views (originally reported by @Crunchnuggetz in issue #129, with additional reports from @donjjones and @robmikulec) Weekly Task Display: Fixed issue where weekly recurring tasks set for specific days (e.g., Tuesdays) were showing completion dates on the wrong day (Monday) - reported by @jpmoo in issue #322 Task Completion Date Bug: Resolved bug where complete_instances was being set to the previous day, causing tasks to remain visible in Agenda view until manually corrected - reported in issue #314 Date Parsing Inconsistencies: Eliminated mixing of UTC and local date parsing that caused timezone-dependent behavior across the application Filter Date Handling: Fixed date filtering to work consistently across all timezones Agenda View \"Today\" Detection: Corrected timezone-sensitive today detection that affected agenda headers ICS Import Timezone Issues: Resolved timezone problems with both recurring and single events from ICS imports Technical Implementation: Introduced parseDateToUTC() function for consistent UTC anchoring of date-only strings Updated date comparison functions to use UTC anchors throughout Replaced timezone-sensitive date operations with consistent UTC-based alternatives Comprehensive audit and fix of all date handling patterns in the codebase Project Filtering Improvements# Resolved critical bugs in project filtering that prevented proper task display and project selection. Fixes: Wikilink Resolution: Fixed handling of relative vs absolute project wikilinks (e.g., [[../Projects/My Project]] vs [[My Project]]) - thanks to @xorander00 for the detailed bug report Filter Grouping Logic: Corrected AND/OR grouping in project filters to prevent showing too many tasks Missing Projects: Fixed issue where not all projects appeared in filter dropdown selection Cache Management: Improved cache invalidation and project name extraction with better validation Subtask Widget Improvements# Fixed several issues with the project subtasks widget affecting user experience and reliability. Widget Fixes: View State Persistence: Fixed issue where subtask widget views would reset when switching between notes or modifying subtasks (reported by @Poly-0000 in issue #329) Filter State Isolation: Prevented filter settings from bleeding between different notes' subtask widgets Configurable Positioning: Added setting to control widget placement at top or bottom of notes (requested by @michelebugio in issue #164) Event Listener Management: Improved cleanup to prevent memory leaks and event accumulation Event Bubbling: Fixed issue where clicking subtasks would trigger both subtask and parent task modals Styling Isolation: Prevented completion styles from affecting nested subtasks incorrectly ICS Calendar Integration# Timezone Processing: Fixed timezone handling bug in ICS calendar subscriptions where VTIMEZONE components weren't being registered before parsing events, causing incorrect display times for timezone-specific calendar events. Performance and Reliability# Cache Optimization: Restored FilterService cache TTL to 30 seconds after temporary reduction, balancing performance with data freshness. Type Safety: Added proper type assertions for ICAL.TimezoneService calls to resolve TypeScript compilation issues. Error Handling: Enhanced error handling and null safety checks throughout project filtering and service initialization. Technical Improvements# UTC Anchor Implementation# Comprehensive implementation of the UTC Anchor principle for robust timezone handling: All date-only strings now consistently parsed as UTC anchors Date comparison operations standardized using UTC methods Eliminated timezone-dependent date creation patterns Added comprehensive timezone test coverage Service Architecture# Expanded Projects Service: Enhanced state management and tracking for expandable project subtasks with proper cleanup and memory management. View State Manager: Improved view state persistence across different contexts and note switches. Documentation Updates# Updated recurring tasks documentation to reflect new behavior Added timezone handling guides for developers Enhanced calendar views documentation with drag behavior explanations Comprehensive template variable documentation Breaking Changes# Date Handling: While maintaining backward compatibility for user data, the internal date handling now consistently uses the UTC Anchor principle. Migration Notes# Existing recurring tasks will continue to work without modification. The system automatically adds DTSTART components when users interact with recurring tasks (completing, editing, or rescheduling)."},{"route":"/obsidian/releases/3.17.1/","title":"TaskNotes 3.17.1","description":"This patch release resolves three critical timezone-related bugs that affected users in specific timezones, particularly those west of UTC (such as users in the Americas). These...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.17.1.md","namespace":"obsidian","relativePath":"releases/3.17.1.md","raw":"# TaskNotes 3.17.1\n\n## Bug Fixes\n\n### Critical Timezone Handling Fixes\n\nThis patch release resolves three critical timezone-related bugs that affected users in specific timezones, particularly those west of UTC (such as users in the Americas). These fixes ensure consistent calendar rendering and task interaction behavior across all timezones.\n\n#### Completions Calendar Rendering (#322)\n\nFixed three critical timezone bugs in the completions calendar that caused visual misalignment for users in timezones west of UTC:\n\n- **Day Number Display**: Corrected day numbers in the calendar grid to display accurately regardless of user timezone by replacing timezone-sensitive formatting with UTC-anchored date extraction\n- **Month Comparison Logic**: Fixed current month highlighting logic that was mixing local and UTC date values, causing incorrect month boundary detection\n- **Calendar Navigation**: Updated previous/next month navigation to use consistent UTC methods, preventing timezone drift when navigating between months\n\nThese fixes ensure the completions calendar visual representation aligns with the underlying UTC-anchored recurrence data for all users.\n\n#### Advanced Calendar Drag-and-Drop Operations (#344)\n\nResolved a critical bug where all-day tasks would shift back by one day after dragging and dropping them in the Advanced Calendar view. This issue particularly affected users in timezones ahead of UTC.\n\nThanks to @trang-ngn for reporting this issue with clear reproduction steps.\n\n**Root Cause**: The drag-and-drop system was using `formatDateForStorage()` which applies UTC methods to Date objects provided by FullCalendar. For users in positive UTC offset timezones, this would cause the stored date to be one day earlier than the date shown in the UI.\n\n**Fixed Operations**:\n\n- All-day and timed event drag-and-drop (`handleEventDrop`)\n- External task drag-and-drop from outside the calendar (`handleExternalDrop`)\n- Modal-based task scheduling (`scheduleTask`)\n- Date selection task creation (`handleDateSelect`)\n- Timeblock creation and event resizing operations\n- Event context menu date handling\n\nThe fix ensures that the date displayed in the calendar UI exactly matches the date that gets stored in the task data.\n\n#### Task Completion Status Checks (#322)\n\nFixed incorrect completion status checks in recurring tasks caused by timezone-sensitive date formatting in `getEffectiveTaskStatus()`. \n\n**Root Cause**: The function was using timezone-sensitive `date-fns format()` for completion date comparisons, causing completion status to be checked against the wrong date for users west of UTC (e.g., checking October 26 instead of October 27 for EDT users).\n\n**Solution**: Replaced timezone-sensitive formatting with `formatDateForStorage()` to ensure consistent UTC-anchored date strings that match the format used in `complete_instances`.\n\nThis fix ensures recurring task completions are correctly identified regardless of user timezone, preventing tasks from incorrectly appearing as incomplete.\n\n## Technical Implementation\n\nAll fixes implement the established \"UTC Anchor\" principle for consistent timezone handling:\n\n- Consistent use of UTC-anchored date operations for date-only comparisons\n- Replacement of timezone-sensitive date formatting with UTC-based alternatives \n- Proper separation of display dates (which can be timezone-sensitive) from storage dates (which must be timezone-neutral)\n\n","aliases":["/releases/3.17.1/","/releases/3.17.1/"],"toc":[{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"critical-timezone-handling-fixes","text":"Critical Timezone Handling Fixes"},{"level":2,"id":"technical-implementation","text":"Technical Implementation"}],"html":"

Bug Fixes#

\n

Critical Timezone Handling Fixes#

\n

This patch release resolves three critical timezone-related bugs that affected users in specific timezones, particularly those west of UTC (such as users in the Americas). These fixes ensure consistent calendar rendering and task interaction behavior across all timezones.

\n

Completions Calendar Rendering (#322)#

\n

Fixed three critical timezone bugs in the completions calendar that caused visual misalignment for users in timezones west of UTC:

\n
    \n
  • Day Number Display: Corrected day numbers in the calendar grid to display accurately regardless of user timezone by replacing timezone-sensitive formatting with UTC-anchored date extraction
  • \n
  • Month Comparison Logic: Fixed current month highlighting logic that was mixing local and UTC date values, causing incorrect month boundary detection
  • \n
  • Calendar Navigation: Updated previous/next month navigation to use consistent UTC methods, preventing timezone drift when navigating between months
  • \n
\n

These fixes ensure the completions calendar visual representation aligns with the underlying UTC-anchored recurrence data for all users.

\n

Advanced Calendar Drag-and-Drop Operations (#344)#

\n

Resolved a critical bug where all-day tasks would shift back by one day after dragging and dropping them in the Advanced Calendar view. This issue particularly affected users in timezones ahead of UTC.

\n

Thanks to @trang-ngn for reporting this issue with clear reproduction steps.

\n

Root Cause: The drag-and-drop system was using formatDateForStorage() which applies UTC methods to Date objects provided by FullCalendar. For users in positive UTC offset timezones, this would cause the stored date to be one day earlier than the date shown in the UI.

\n

Fixed Operations:

\n
    \n
  • All-day and timed event drag-and-drop (handleEventDrop)
  • \n
  • External task drag-and-drop from outside the calendar (handleExternalDrop)
  • \n
  • Modal-based task scheduling (scheduleTask)
  • \n
  • Date selection task creation (handleDateSelect)
  • \n
  • Timeblock creation and event resizing operations
  • \n
  • Event context menu date handling
  • \n
\n

The fix ensures that the date displayed in the calendar UI exactly matches the date that gets stored in the task data.

\n

Task Completion Status Checks (#322)#

\n

Fixed incorrect completion status checks in recurring tasks caused by timezone-sensitive date formatting in getEffectiveTaskStatus().

\n

Root Cause: The function was using timezone-sensitive date-fns format() for completion date comparisons, causing completion status to be checked against the wrong date for users west of UTC (e.g., checking October 26 instead of October 27 for EDT users).

\n

Solution: Replaced timezone-sensitive formatting with formatDateForStorage() to ensure consistent UTC-anchored date strings that match the format used in complete_instances.

\n

This fix ensures recurring task completions are correctly identified regardless of user timezone, preventing tasks from incorrectly appearing as incomplete.

\n

Technical Implementation#

\n

All fixes implement the established "UTC Anchor" principle for consistent timezone handling:

\n
    \n
  • Consistent use of UTC-anchored date operations for date-only comparisons
  • \n
  • Replacement of timezone-sensitive date formatting with UTC-based alternatives
  • \n
  • Proper separation of display dates (which can be timezone-sensitive) from storage dates (which must be timezone-neutral)
  • \n
\n","text":"Bug Fixes# Critical Timezone Handling Fixes# This patch release resolves three critical timezone-related bugs that affected users in specific timezones, particularly those west of UTC (such as users in the Americas). These fixes ensure consistent calendar rendering and task interaction behavior across all timezones. Completions Calendar Rendering (#322)# Fixed three critical timezone bugs in the completions calendar that caused visual misalignment for users in timezones west of UTC: Day Number Display: Corrected day numbers in the calendar grid to display accurately regardless of user timezone by replacing timezone-sensitive formatting with UTC-anchored date extraction Month Comparison Logic: Fixed current month highlighting logic that was mixing local and UTC date values, causing incorrect month boundary detection Calendar Navigation: Updated previous/next month navigation to use consistent UTC methods, preventing timezone drift when navigating between months These fixes ensure the completions calendar visual representation aligns with the underlying UTC-anchored recurrence data for all users. Advanced Calendar Drag-and-Drop Operations (#344)# Resolved a critical bug where all-day tasks would shift back by one day after dragging and dropping them in the Advanced Calendar view. This issue particularly affected users in timezones ahead of UTC. Thanks to @trang-ngn for reporting this issue with clear reproduction steps. Root Cause: The drag-and-drop system was using formatDateForStorage() which applies UTC methods to Date objects provided by FullCalendar. For users in positive UTC offset timezones, this would cause the stored date to be one day earlier than the date shown in the UI. Fixed Operations: All-day and timed event drag-and-drop (handleEventDrop) External task drag-and-drop from outside the calendar (handleExternalDrop) Modal-based task scheduling (scheduleTask) Date selection task creation (handleDateSelect) Timeblock creation and event resizing operations Event context menu date handling The fix ensures that the date displayed in the calendar UI exactly matches the date that gets stored in the task data. Task Completion Status Checks (#322)# Fixed incorrect completion status checks in recurring tasks caused by timezone-sensitive date formatting in getEffectiveTaskStatus(). Root Cause: The function was using timezone-sensitive date-fns format() for completion date comparisons, causing completion status to be checked against the wrong date for users west of UTC (e.g., checking October 26 instead of October 27 for EDT users). Solution: Replaced timezone-sensitive formatting with formatDateForStorage() to ensure consistent UTC-anchored date strings that match the format used in complete_instances. This fix ensures recurring task completions are correctly identified regardless of user timezone, preventing tasks from incorrectly appearing as incomplete. Technical Implementation# All fixes implement the established \"UTC Anchor\" principle for consistent timezone handling: Consistent use of UTC-anchored date operations for date-only comparisons Replacement of timezone-sensitive date formatting with UTC-based alternatives Proper separation of display dates (which can be timezone-sensitive) from storage dates (which must be timezone-neutral)"},{"route":"/obsidian/releases/3.18.0/","title":"TaskNotes 3.18.0","description":"A complete reminder system has been added to TaskNotes, providing iCalendar VALARM-compliant reminder functionality.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.18.0.md","namespace":"obsidian","relativePath":"releases/3.18.0.md","raw":"# TaskNotes 3.18.0\n\n## New Features\n\n### Task Reminders System\n\nA complete reminder system has been added to TaskNotes, providing iCalendar VALARM-compliant reminder functionality.\n\n**Core Features:**\n\n- Support for both relative reminders (e.g., \"15 minutes before due date\") and absolute reminders (specific date/time)\n- Visual reminder indicators on task cards with clickable bell icons\n- Integration with task creation and editing workflows\n\n**User Interface:**\n\n- **Reminder Modal**: Modal for managing task reminders with form validation and real-time preview\n- **Reminder Context Menu**: Quick access to common reminder options (5min, 15min, 1hr, 1day before due/scheduled dates)\n- Reminder management accessible from task creation modal, edit modal, and task cards\n\n**Default Reminders:**\n\n- Configure default reminders that automatically apply to new tasks\n- Support for multiple default reminders per task type\n- Applies to both manual task creation and instant conversion workflows\n\n### Property-Based Task Identification\n\nTasks can now be identified using frontmatter properties instead of requiring tags.\n\n- Configure property name and value for task identification (e.g., `categories: [[Tasks]]`)\n- Full backward compatibility with existing tag-based workflows\n- Addresses modern Obsidian property-based vault organization patterns\n\n*Thanks to @mdbraber for the feature request (#340)*\n\n### Enhanced Saved Views\n- Clicking an active saved view now clears all filters, providing quick access to unfiltered task list\n- Preserves sort and group settings while resetting filters\n\n*Thanks to @oldjove for the suggestion (#351)*\n\n### Parent Note as Project Option\n- New setting to automatically use parent note as project during instant task conversion\n- Useful for users who organize tasks within project-specific notes\n- Merges with existing default projects to avoid duplicates\n\n*Thanks to @FindingJohnny for the feature request (#348)*\n\n## Bug Fixes\n\n### ICS Calendar Integration\n\n- **Fixed recurring event exceptions**: Properly handle EXDATE properties and RECURRENCE-ID for modified instances\n- **Eliminated duplicate events**: Resolved issue where deleted or rescheduled recurring events from external calendars still appeared\n\n*Thanks to @robmikulec for reporting the recurring events issue (#342)*\n\n### Settings Persistence\n\n- **Fixed settings reset during updates**: Prevent user configuration loss when plugin updates introduce new default settings\n- Apply deep merge strategy to preserve customizations in nested configuration objects\n\n## Improvements\n\n### User Interface\n\n- Reminder modal uses consistent design patterns with task creation/edit modals\n- Fixed task card icon overlap issues with proper spacing for multiple indicators\n\n### Code Quality\n\n- Added unit test coverage for new reminder functionality\n- Improved type safety with proper TypeScript interfaces for reminder data structures\n- Improved error handling and user feedback across reminder operations\n\n## Technical Details\n\n### Data Model Changes\n\n- Added optional `reminders` array field to TaskInfo interface\n- Extended field mapping support for custom reminder property names\n- Enhanced cache system to include reminder data in task extraction\n\n","aliases":["/releases/3.18.0/","/releases/3.18.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"task-reminders-system","text":"Task Reminders System"},{"level":3,"id":"property-based-task-identification","text":"Property-Based Task Identification"},{"level":3,"id":"enhanced-saved-views","text":"Enhanced Saved Views"},{"level":3,"id":"parent-note-as-project-option","text":"Parent Note as Project Option"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"ics-calendar-integration","text":"ICS Calendar Integration"},{"level":3,"id":"settings-persistence","text":"Settings Persistence"},{"level":2,"id":"improvements","text":"Improvements"},{"level":3,"id":"user-interface","text":"User Interface"},{"level":3,"id":"code-quality","text":"Code Quality"},{"level":2,"id":"technical-details","text":"Technical Details"},{"level":3,"id":"data-model-changes","text":"Data Model Changes"}],"html":"

New Features#

\n

Task Reminders System#

\n

A complete reminder system has been added to TaskNotes, providing iCalendar VALARM-compliant reminder functionality.

\n

Core Features:

\n
    \n
  • Support for both relative reminders (e.g., "15 minutes before due date") and absolute reminders (specific date/time)
  • \n
  • Visual reminder indicators on task cards with clickable bell icons
  • \n
  • Integration with task creation and editing workflows
  • \n
\n

User Interface:

\n
    \n
  • Reminder Modal: Modal for managing task reminders with form validation and real-time preview
  • \n
  • Reminder Context Menu: Quick access to common reminder options (5min, 15min, 1hr, 1day before due/scheduled dates)
  • \n
  • Reminder management accessible from task creation modal, edit modal, and task cards
  • \n
\n

Default Reminders:

\n
    \n
  • Configure default reminders that automatically apply to new tasks
  • \n
  • Support for multiple default reminders per task type
  • \n
  • Applies to both manual task creation and instant conversion workflows
  • \n
\n

Property-Based Task Identification#

\n

Tasks can now be identified using frontmatter properties instead of requiring tags.

\n
    \n
  • Configure property name and value for task identification (e.g., categories: [[Tasks]])
  • \n
  • Full backward compatibility with existing tag-based workflows
  • \n
  • Addresses modern Obsidian property-based vault organization patterns
  • \n
\n

Thanks to @mdbraber for the feature request (#340)

\n

Enhanced Saved Views#

\n
    \n
  • Clicking an active saved view now clears all filters, providing quick access to unfiltered task list
  • \n
  • Preserves sort and group settings while resetting filters
  • \n
\n

Thanks to @oldjove for the suggestion (#351)

\n

Parent Note as Project Option#

\n
    \n
  • New setting to automatically use parent note as project during instant task conversion
  • \n
  • Useful for users who organize tasks within project-specific notes
  • \n
  • Merges with existing default projects to avoid duplicates
  • \n
\n

Thanks to @FindingJohnny for the feature request (#348)

\n

Bug Fixes#

\n

ICS Calendar Integration#

\n
    \n
  • Fixed recurring event exceptions: Properly handle EXDATE properties and RECURRENCE-ID for modified instances
  • \n
  • Eliminated duplicate events: Resolved issue where deleted or rescheduled recurring events from external calendars still appeared
  • \n
\n

Thanks to @robmikulec for reporting the recurring events issue (#342)

\n

Settings Persistence#

\n
    \n
  • Fixed settings reset during updates: Prevent user configuration loss when plugin updates introduce new default settings
  • \n
  • Apply deep merge strategy to preserve customizations in nested configuration objects
  • \n
\n

Improvements#

\n

User Interface#

\n
    \n
  • Reminder modal uses consistent design patterns with task creation/edit modals
  • \n
  • Fixed task card icon overlap issues with proper spacing for multiple indicators
  • \n
\n

Code Quality#

\n
    \n
  • Added unit test coverage for new reminder functionality
  • \n
  • Improved type safety with proper TypeScript interfaces for reminder data structures
  • \n
  • Improved error handling and user feedback across reminder operations
  • \n
\n

Technical Details#

\n

Data Model Changes#

\n
    \n
  • Added optional reminders array field to TaskInfo interface
  • \n
  • Extended field mapping support for custom reminder property names
  • \n
  • Enhanced cache system to include reminder data in task extraction
  • \n
\n","text":"New Features# Task Reminders System# A complete reminder system has been added to TaskNotes, providing iCalendar VALARM-compliant reminder functionality. Core Features: Support for both relative reminders (e.g., \"15 minutes before due date\") and absolute reminders (specific date/time) Visual reminder indicators on task cards with clickable bell icons Integration with task creation and editing workflows User Interface: Reminder Modal: Modal for managing task reminders with form validation and real-time preview Reminder Context Menu: Quick access to common reminder options (5min, 15min, 1hr, 1day before due/scheduled dates) Reminder management accessible from task creation modal, edit modal, and task cards Default Reminders: Configure default reminders that automatically apply to new tasks Support for multiple default reminders per task type Applies to both manual task creation and instant conversion workflows Property-Based Task Identification# Tasks can now be identified using frontmatter properties instead of requiring tags. Configure property name and value for task identification (e.g., categories: [[Tasks]]) Full backward compatibility with existing tag-based workflows Addresses modern Obsidian property-based vault organization patterns Thanks to @mdbraber for the feature request (#340) Enhanced Saved Views# Clicking an active saved view now clears all filters, providing quick access to unfiltered task list Preserves sort and group settings while resetting filters Thanks to @oldjove for the suggestion (#351) Parent Note as Project Option# New setting to automatically use parent note as project during instant task conversion Useful for users who organize tasks within project-specific notes Merges with existing default projects to avoid duplicates Thanks to @FindingJohnny for the feature request (#348) Bug Fixes# ICS Calendar Integration# Fixed recurring event exceptions: Properly handle EXDATE properties and RECURRENCE-ID for modified instances Eliminated duplicate events: Resolved issue where deleted or rescheduled recurring events from external calendars still appeared Thanks to @robmikulec for reporting the recurring events issue (#342) Settings Persistence# Fixed settings reset during updates: Prevent user configuration loss when plugin updates introduce new default settings Apply deep merge strategy to preserve customizations in nested configuration objects Improvements# User Interface# Reminder modal uses consistent design patterns with task creation/edit modals Fixed task card icon overlap issues with proper spacing for multiple indicators Code Quality# Added unit test coverage for new reminder functionality Improved type safety with proper TypeScript interfaces for reminder data structures Improved error handling and user feedback across reminder operations Technical Details# Data Model Changes# Added optional reminders array field to TaskInfo interface Extended field mapping support for custom reminder property names Enhanced cache system to include reminder data in task extraction"},{"route":"/obsidian/releases/3.18.1/","title":"TaskNotes 3.18.1","description":"Fixed critical race conditions in cache synchronization that occurred when task operations completed before Obsidian's metadata cache had fully processed file changes. This...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.18.1.md","namespace":"obsidian","relativePath":"releases/3.18.1.md","raw":"# TaskNotes 3.18.1\n\n## Bug Fixes\n\n### Cache Synchronization Race Conditions (#358)\n\nFixed critical race conditions in cache synchronization that occurred when task operations completed before Obsidian's metadata cache had fully processed file changes. This resulted in stale or missing task data across all calendar views and task operations.\n\n*Thanks to @willgraham345 for reporting the calendar auto-refresh issue*\n\n## Code Quality Improvements\n\n### Event Listener Management\n\nSimplified event listener cleanup in AdvancedCalendarView by removing manual listener tracking array.\n\n## Technical Details\n\n**Cache Synchronization Strategy**: The implementation follows a \"wait-then-update\" pattern where all cache modifications are preceded by verification that Obsidian's metadata cache contains the expected changes. This prevents race conditions while maintaining performance through minimal wait times.\n\n","aliases":["/releases/3.18.1/","/releases/3.18.1/"],"toc":[{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"cache-synchronization-race-conditions-358","text":"Cache Synchronization Race Conditions (#358)"},{"level":2,"id":"code-quality-improvements","text":"Code Quality Improvements"},{"level":3,"id":"event-listener-management","text":"Event Listener Management"},{"level":2,"id":"technical-details","text":"Technical Details"}],"html":"

Bug Fixes#

\n

Cache Synchronization Race Conditions (#358)#

\n

Fixed critical race conditions in cache synchronization that occurred when task operations completed before Obsidian's metadata cache had fully processed file changes. This resulted in stale or missing task data across all calendar views and task operations.

\n

Thanks to @willgraham345 for reporting the calendar auto-refresh issue

\n

Code Quality Improvements#

\n

Event Listener Management#

\n

Simplified event listener cleanup in AdvancedCalendarView by removing manual listener tracking array.

\n

Technical Details#

\n

Cache Synchronization Strategy: The implementation follows a "wait-then-update" pattern where all cache modifications are preceded by verification that Obsidian's metadata cache contains the expected changes. This prevents race conditions while maintaining performance through minimal wait times.

\n","text":"Bug Fixes# Cache Synchronization Race Conditions (#358)# Fixed critical race conditions in cache synchronization that occurred when task operations completed before Obsidian's metadata cache had fully processed file changes. This resulted in stale or missing task data across all calendar views and task operations. Thanks to @willgraham345 for reporting the calendar auto-refresh issue Code Quality Improvements# Event Listener Management# Simplified event listener cleanup in AdvancedCalendarView by removing manual listener tracking array. Technical Details# Cache Synchronization Strategy: The implementation follows a \"wait-then-update\" pattern where all cache modifications are preceded by verification that Obsidian's metadata cache contains the expected changes. This prevents race conditions while maintaining performance through minimal wait times."},{"route":"/obsidian/releases/3.18.2/","title":"TaskNotes 3.18.2","description":"Fixed timeblocks appearing one day earlier than expected by implementing the UTC Anchor pattern throughout the timeblocking feature. The previous implementation used problematic...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.18.2.md","namespace":"obsidian","relativePath":"releases/3.18.2.md","raw":"# TaskNotes 3.18.2\n\n## Bug Fixes\n\n### Timeblock Date Shift Issue (#368)\n\nFixed timeblocks appearing one day earlier than expected by implementing the UTC Anchor pattern throughout the timeblocking feature. The previous implementation used problematic millisecond-based date iteration that caused timezone-dependent date shift bugs.\n\nTimeblocks now appear on the correct calendar day regardless of user timezone or DST transitions.\n\n*Thanks to @zolotyh-dk for reporting this issue with detailed screenshots and system information.*\n\n### Performance Issues with Task Views\n\nEliminated typing lag that occurred when Task, Agenda, and Kanban views were open in large vaults. The plugin was triggering unnecessary view updates during text editing.\n\n## New Features\n\n### Enhanced Filename Template Variables (#370)\n\nAdded new timestamp variables for filename templates to support ISO 8601 formats and Google Keep compatibility:\n\n- `{milliseconds}`, `{ms}` - 3-digit milliseconds (000-999)\n- `{timezone}`, `{utcOffset}` - UTC offset in ±HH:MM format \n- `{timezoneShort}`, `{utcOffsetShort}` - UTC offset in ±HHMM format\n\n*Thanks to @mnipritom for requesting these variables*. \n\n### Boolean Property Identification\n\nEnhanced property-based task identification to handle boolean values correctly. Tasks can now be identified using boolean properties in frontmatter.\n\n*A big thanks to @renatomen for contributing the boolean property identification implementation, documentation, and test coverage*\n\n### Boolean Status Field Support (#108)\n\nAdded automatic boolean conversion for status values to support Obsidian's checkbox property format. The status field now handles boolean true/false values:\n\n- String \"true\" → boolean true (in frontmatter)\n- String \"false\" → boolean false (in frontmatter) \n- Boolean true → string \"true\" (when read back)\n- Boolean false → string \"false\" (when read back)\n- Other status values remain unchanged as strings\n\n*Thanks to @arminta7 for reporting the checkbox property compatibility issue and @imed-ghomari for contributing to the discussion on status field handling.*\n*And thanks again to @renatomen--the boolean property identification fix inspired this change!*","aliases":["/releases/3.18.2/","/releases/3.18.2/"],"toc":[{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"timeblock-date-shift-issue-368","text":"Timeblock Date Shift Issue (#368)"},{"level":3,"id":"performance-issues-with-task-views","text":"Performance Issues with Task Views"},{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"enhanced-filename-template-variables-370","text":"Enhanced Filename Template Variables (#370)"},{"level":3,"id":"boolean-property-identification","text":"Boolean Property Identification"},{"level":3,"id":"boolean-status-field-support-108","text":"Boolean Status Field Support (#108)"}],"html":"

Bug Fixes#

\n

Timeblock Date Shift Issue (#368)#

\n

Fixed timeblocks appearing one day earlier than expected by implementing the UTC Anchor pattern throughout the timeblocking feature. The previous implementation used problematic millisecond-based date iteration that caused timezone-dependent date shift bugs.

\n

Timeblocks now appear on the correct calendar day regardless of user timezone or DST transitions.

\n

Thanks to @zolotyh-dk for reporting this issue with detailed screenshots and system information.

\n

Performance Issues with Task Views#

\n

Eliminated typing lag that occurred when Task, Agenda, and Kanban views were open in large vaults. The plugin was triggering unnecessary view updates during text editing.

\n

New Features#

\n

Enhanced Filename Template Variables (#370)#

\n

Added new timestamp variables for filename templates to support ISO 8601 formats and Google Keep compatibility:

\n
    \n
  • {milliseconds}, {ms} - 3-digit milliseconds (000-999)
  • \n
  • {timezone}, {utcOffset} - UTC offset in ±HH:MM format
  • \n
  • {timezoneShort}, {utcOffsetShort} - UTC offset in ±HHMM format
  • \n
\n

Thanks to @mnipritom for requesting these variables.

\n

Boolean Property Identification#

\n

Enhanced property-based task identification to handle boolean values correctly. Tasks can now be identified using boolean properties in frontmatter.

\n

A big thanks to @renatomen for contributing the boolean property identification implementation, documentation, and test coverage

\n

Boolean Status Field Support (#108)#

\n

Added automatic boolean conversion for status values to support Obsidian's checkbox property format. The status field now handles boolean true/false values:

\n
    \n
  • String "true" → boolean true (in frontmatter)
  • \n
  • String "false" → boolean false (in frontmatter)
  • \n
  • Boolean true → string "true" (when read back)
  • \n
  • Boolean false → string "false" (when read back)
  • \n
  • Other status values remain unchanged as strings
  • \n
\n

Thanks to @arminta7 for reporting the checkbox property compatibility issue and @imed-ghomari for contributing to the discussion on status field handling.\nAnd thanks again to @renatomen--the boolean property identification fix inspired this change!

\n","text":"Bug Fixes# Timeblock Date Shift Issue (#368)# Fixed timeblocks appearing one day earlier than expected by implementing the UTC Anchor pattern throughout the timeblocking feature. The previous implementation used problematic millisecond-based date iteration that caused timezone-dependent date shift bugs. Timeblocks now appear on the correct calendar day regardless of user timezone or DST transitions. Thanks to @zolotyh-dk for reporting this issue with detailed screenshots and system information. Performance Issues with Task Views# Eliminated typing lag that occurred when Task, Agenda, and Kanban views were open in large vaults. The plugin was triggering unnecessary view updates during text editing. New Features# Enhanced Filename Template Variables (#370)# Added new timestamp variables for filename templates to support ISO 8601 formats and Google Keep compatibility: {milliseconds}, {ms} - 3-digit milliseconds (000-999) {timezone}, {utcOffset} - UTC offset in ±HH:MM format {timezoneShort}, {utcOffsetShort} - UTC offset in ±HHMM format Thanks to @mnipritom for requesting these variables. Boolean Property Identification# Enhanced property-based task identification to handle boolean values correctly. Tasks can now be identified using boolean properties in frontmatter. A big thanks to @renatomen for contributing the boolean property identification implementation, documentation, and test coverage Boolean Status Field Support (#108)# Added automatic boolean conversion for status values to support Obsidian's checkbox property format. The status field now handles boolean true/false values: String \"true\" → boolean true (in frontmatter) String \"false\" → boolean false (in frontmatter) Boolean true → string \"true\" (when read back) Boolean false → string \"false\" (when read back) Other status values remain unchanged as strings Thanks to @arminta7 for reporting the checkbox property compatibility issue and @imed-ghomari for contributing to the discussion on status field handling. And thanks again to @renatomen--the boolean property identification fix inspired this change!"},{"route":"/obsidian/releases/3.19.0/","title":"TaskNotes 3.19.0","description":"TaskNotes now includes a HTTP REST API that enables external integrations and powers companion projects. The API provides full task management capabilities with intelligent natu...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.19.0.md","namespace":"obsidian","relativePath":"releases/3.19.0.md","raw":"# TaskNotes 3.19.0\n\n## New Features\n\n### HTTP REST API with Natural Language Processing\n\nTaskNotes now includes a HTTP REST API that enables external integrations and powers companion projects. The API provides full task management capabilities with intelligent natural language processing.\n\n**Key API Features:**\n\n- Complete CRUD operations for tasks\n- Time tracking endpoints\n- Task statistics and filtering\n- Bearer token authentication\n- CORS support for browser extensions\n- Desktop-only implementation with mobile-safe architecture\n\n**Natural Language Processing Endpoints:**\n\n- `/api/nlp/parse` - Parse natural language into structured task data\n- `/api/nlp/create` - Create tasks directly from natural language input\n- Supports extraction of dates, times, priorities, tags, contexts, projects, and recurrence\n- Intelligent parsing of expressions like \"Review PR #123 tomorrow high priority @work\"\n\n**Companion Project Integration:**\n\nThe HTTP API enables two new companion projects:\n- [tasknotes-cli](https://github.com/callumalpass/tasknotes-cli) - Command-line interface for TaskNotes task management\n- [tasknotes-browser-extension](https://github.com/callumalpass/tasknotes-browser-extension) - Browser extension for quick task creation\n\n**Configuration:**\n\n- Enable via Settings → HTTP API tab (desktop only)\n- Configurable port (default 8080) and optional authentication token\n- Documentation at `/docs/HTTP_API.md` and `/docs/nlp-api.md`\n\n### Enhanced Calendar Integration\n\n#### Calendar Export and Context Menu System\n\n**Task Calendar Export:**\n\n- Add tasks to external calendars (Google, Outlook, Yahoo)\n- Download ICS files\n- Right-click context menu support for quick calendar actions\n\n#### Agenda View Calendar Improvements\n\n**ICS Integration in Agenda:**\n\n- Calendar event cards now display in Agenda view\n- Toggle calendar subscriptions visibility via FilterBar\n- Always-available \"Refresh calendars\" button\n- Normalized scheduled date handling for all-day and timed events\n\n*Thanks @scottaltham-payroc for the feature request!*\n\n## Bug Fixes\n\n### Task Styling Enhancement (#355)\n\nAdded CSS class `task-card--has-projects` to task cards that contain projects.\n\n*Thanks @mdbraber for the suggestion*\n\n### Calendar Event Scheduling\n\nFixed scheduled date normalization when creating tasks from ICS events:\n\n- All-day events: Use YYYY-MM-DD format\n- Timed events: Use YYYY-MM-DDTHH:mm format\n- Consistent behavior across all calendar interfaces\n\n### File Copy Script Improvements\n\nEnhanced copy-files script with better error handling:\n\n- Improved default path handling\n- Destination directory creation\n- Better ENOENT error handling\n\n## API Documentation\n\n### New Documentation Files\n\n- **HTTP_API.md** - Complete API reference with examples\n- **nlp-api.md** - Natural language processing capabilities and usage\n\n## Technical Enhancements\n\n### Core Infrastructure\n\n**API Service Architecture:**\n\n- Mobile-compatible implementation using Node.js http module\n- Platform detection prevents mobile loading\n- Express.js alternative for lightweight operation\n- Full error handling and validation\n\n**Calendar Service Integration:**\n- Extracted reusable CalendarExportService\n- Unified TaskContextMenu component\n- Enhanced event listener management\n\n### Development Improvements\n\n**Code Organization:**\n\n- Modular component extraction for better reusability\n- Consistent API response formats\n- Comprehensive test coverage for new features\n- TypeScript improvements for icon handling\n\n## Migration Notes\n\n### HTTP API Setup\n\nFor users wanting to enable the new HTTP API:\n\n1. Navigate to Settings → HTTP API tab (desktop only)\n2. Configure desired port (default 8080)\n3. Optionally set authentication token for security\n4. Restart Obsidian to start the API server\n5. Test with: `curl http://localhost:8080/api/health`\n\n","aliases":["/releases/3.19.0/","/releases/3.19.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"http-rest-api-with-natural-language-processing","text":"HTTP REST API with Natural Language Processing"},{"level":3,"id":"enhanced-calendar-integration","text":"Enhanced Calendar Integration"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"task-styling-enhancement-355","text":"Task Styling Enhancement (#355)"},{"level":3,"id":"calendar-event-scheduling","text":"Calendar Event Scheduling"},{"level":3,"id":"file-copy-script-improvements","text":"File Copy Script Improvements"},{"level":2,"id":"api-documentation","text":"API Documentation"},{"level":3,"id":"new-documentation-files","text":"New Documentation Files"},{"level":2,"id":"technical-enhancements","text":"Technical Enhancements"},{"level":3,"id":"core-infrastructure","text":"Core Infrastructure"},{"level":3,"id":"development-improvements","text":"Development Improvements"},{"level":2,"id":"migration-notes","text":"Migration Notes"},{"level":3,"id":"http-api-setup","text":"HTTP API Setup"}],"html":"

New Features#

\n

HTTP REST API with Natural Language Processing#

\n

TaskNotes now includes a HTTP REST API that enables external integrations and powers companion projects. The API provides full task management capabilities with intelligent natural language processing.

\n

Key API Features:

\n
    \n
  • Complete CRUD operations for tasks
  • \n
  • Time tracking endpoints
  • \n
  • Task statistics and filtering
  • \n
  • Bearer token authentication
  • \n
  • CORS support for browser extensions
  • \n
  • Desktop-only implementation with mobile-safe architecture
  • \n
\n

Natural Language Processing Endpoints:

\n
    \n
  • /api/nlp/parse - Parse natural language into structured task data
  • \n
  • /api/nlp/create - Create tasks directly from natural language input
  • \n
  • Supports extraction of dates, times, priorities, tags, contexts, projects, and recurrence
  • \n
  • Intelligent parsing of expressions like "Review PR #123 tomorrow high priority @work"
  • \n
\n

Companion Project Integration:

\n

The HTTP API enables two new companion projects:

\n\n

Configuration:

\n
    \n
  • Enable via Settings → HTTP API tab (desktop only)
  • \n
  • Configurable port (default 8080) and optional authentication token
  • \n
  • Documentation at /docs/HTTP_API.md and /docs/nlp-api.md
  • \n
\n

Enhanced Calendar Integration#

\n

Calendar Export and Context Menu System#

\n

Task Calendar Export:

\n
    \n
  • Add tasks to external calendars (Google, Outlook, Yahoo)
  • \n
  • Download ICS files
  • \n
  • Right-click context menu support for quick calendar actions
  • \n
\n

Agenda View Calendar Improvements#

\n

ICS Integration in Agenda:

\n
    \n
  • Calendar event cards now display in Agenda view
  • \n
  • Toggle calendar subscriptions visibility via FilterBar
  • \n
  • Always-available "Refresh calendars" button
  • \n
  • Normalized scheduled date handling for all-day and timed events
  • \n
\n

Thanks @scottaltham-payroc for the feature request!

\n

Bug Fixes#

\n

Task Styling Enhancement (#355)#

\n

Added CSS class task-card--has-projects to task cards that contain projects.

\n

Thanks @mdbraber for the suggestion

\n

Calendar Event Scheduling#

\n

Fixed scheduled date normalization when creating tasks from ICS events:

\n
    \n
  • All-day events: Use YYYY-MM-DD format
  • \n
  • Timed events: Use YYYY-MM-DDTHH:mm format
  • \n
  • Consistent behavior across all calendar interfaces
  • \n
\n

File Copy Script Improvements#

\n

Enhanced copy-files script with better error handling:

\n
    \n
  • Improved default path handling
  • \n
  • Destination directory creation
  • \n
  • Better ENOENT error handling
  • \n
\n

API Documentation#

\n

New Documentation Files#

\n
    \n
  • HTTP_API.md - Complete API reference with examples
  • \n
  • nlp-api.md - Natural language processing capabilities and usage
  • \n
\n

Technical Enhancements#

\n

Core Infrastructure#

\n

API Service Architecture:

\n
    \n
  • Mobile-compatible implementation using Node.js http module
  • \n
  • Platform detection prevents mobile loading
  • \n
  • Express.js alternative for lightweight operation
  • \n
  • Full error handling and validation
  • \n
\n

Calendar Service Integration:

\n
    \n
  • Extracted reusable CalendarExportService
  • \n
  • Unified TaskContextMenu component
  • \n
  • Enhanced event listener management
  • \n
\n

Development Improvements#

\n

Code Organization:

\n
    \n
  • Modular component extraction for better reusability
  • \n
  • Consistent API response formats
  • \n
  • Comprehensive test coverage for new features
  • \n
  • TypeScript improvements for icon handling
  • \n
\n

Migration Notes#

\n

HTTP API Setup#

\n

For users wanting to enable the new HTTP API:

\n
    \n
  1. Navigate to Settings → HTTP API tab (desktop only)
  2. \n
  3. Configure desired port (default 8080)
  4. \n
  5. Optionally set authentication token for security
  6. \n
  7. Restart Obsidian to start the API server
  8. \n
  9. Test with: curl http://localhost:8080/api/health
  10. \n
\n","text":"New Features# HTTP REST API with Natural Language Processing# TaskNotes now includes a HTTP REST API that enables external integrations and powers companion projects. The API provides full task management capabilities with intelligent natural language processing. Key API Features: Complete CRUD operations for tasks Time tracking endpoints Task statistics and filtering Bearer token authentication CORS support for browser extensions Desktop-only implementation with mobile-safe architecture Natural Language Processing Endpoints: /api/nlp/parse - Parse natural language into structured task data /api/nlp/create - Create tasks directly from natural language input Supports extraction of dates, times, priorities, tags, contexts, projects, and recurrence Intelligent parsing of expressions like \"Review PR #123 tomorrow high priority @work\" Companion Project Integration: The HTTP API enables two new companion projects: tasknotes-cli - Command-line interface for TaskNotes task management tasknotes-browser-extension - Browser extension for quick task creation Configuration: Enable via Settings → HTTP API tab (desktop only) Configurable port (default 8080) and optional authentication token Documentation at /docs/HTTP_API.md and /docs/nlp-api.md Enhanced Calendar Integration# Calendar Export and Context Menu System# Task Calendar Export: Add tasks to external calendars (Google, Outlook, Yahoo) Download ICS files Right-click context menu support for quick calendar actions Agenda View Calendar Improvements# ICS Integration in Agenda: Calendar event cards now display in Agenda view Toggle calendar subscriptions visibility via FilterBar Always-available \"Refresh calendars\" button Normalized scheduled date handling for all-day and timed events Thanks @scottaltham-payroc for the feature request! Bug Fixes# Task Styling Enhancement (#355)# Added CSS class task-card--has-projects to task cards that contain projects. Thanks @mdbraber for the suggestion Calendar Event Scheduling# Fixed scheduled date normalization when creating tasks from ICS events: All-day events: Use YYYY-MM-DD format Timed events: Use YYYY-MM-DDTHH:mm format Consistent behavior across all calendar interfaces File Copy Script Improvements# Enhanced copy-files script with better error handling: Improved default path handling Destination directory creation Better ENOENT error handling API Documentation# New Documentation Files# HTTP_API.md - Complete API reference with examples nlp-api.md - Natural language processing capabilities and usage Technical Enhancements# Core Infrastructure# API Service Architecture: Mobile-compatible implementation using Node.js http module Platform detection prevents mobile loading Express.js alternative for lightweight operation Full error handling and validation Calendar Service Integration: Extracted reusable CalendarExportService Unified TaskContextMenu component Enhanced event listener management Development Improvements# Code Organization: Modular component extraction for better reusability Consistent API response formats Comprehensive test coverage for new features TypeScript improvements for icon handling Migration Notes# HTTP API Setup# For users wanting to enable the new HTTP API: Navigate to Settings → HTTP API tab (desktop only) Configure desired port (default 8080) Optionally set authentication token for security Restart Obsidian to start the API server Test with: curl http://localhost:8080/api/health"},{"route":"/obsidian/releases/3.19.1/","title":"TaskNotes 3.19.1","description":"Added webhook system enabling integrations with external services and automation workflows.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.19.1.md","namespace":"obsidian","relativePath":"releases/3.19.1.md","raw":"# TaskNotes 3.19.1\n\n## New Features\n\n### Webhook Support\n\nAdded webhook system enabling integrations with external services and automation workflows.\n\n**Webhook Management:**\n\n- CRUD operations for webhook configuration\n- HTTP API endpoints for webhook management (`POST /api/webhooks`, `GET /api/webhooks`, `DELETE /api/webhooks/{id}`)\n- Delivery history tracking (`GET /api/webhooks/deliveries`)\n- Settings UI integration with event subscription controls\n\n**Event Types:**\n\n- **Task events:** created, updated, deleted, completed, archived, unarchived\n- **Time tracking:** started, stopped\n- **Pomodoro:** started, completed, interrupted \n- **Recurring tasks:** instance completed\n- **Reminders:** triggered\n\n**Security and Reliability:**\n\n- HMAC-SHA256 signature verification for payload authentication\n- Automatic retries with exponential backoff (3 attempts)\n- 10-second delivery timeout with failure monitoring\n- Auto-disable webhooks after repeated failures\n- Non-blocking async delivery maintains TaskNotes responsiveness\n\nDocumentation and testing utilities included in `docs/webhooks.md` and `test-webhook.js`.\n\n## Bug Fixes\n\n### Boolean Property Identification Regression (#367)\n\nFixed regression from version 3.18.2 where boolean checkbox properties stopped working for property-based task identification.\n\nDuring code refactoring, the `comparePropertyValues` function was accidentally removed, breaking boolean-to-string coercion needed for Obsidian checkbox properties. The fix restores this function with proper type-aware comparison logic, allowing boolean `true`/`false` frontmatter values to correctly match `\"true\"`/`\"false\"` setting values.\n\n*Thanks to @renatomen for reporting this regression*\n","aliases":["/releases/3.19.1/","/releases/3.19.1/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"webhook-support","text":"Webhook Support"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"boolean-property-identification-regression-367","text":"Boolean Property Identification Regression (#367)"}],"html":"

New Features#

\n

Webhook Support#

\n

Added webhook system enabling integrations with external services and automation workflows.

\n

Webhook Management:

\n
    \n
  • CRUD operations for webhook configuration
  • \n
  • HTTP API endpoints for webhook management (POST /api/webhooks, GET /api/webhooks, DELETE /api/webhooks/{id})
  • \n
  • Delivery history tracking (GET /api/webhooks/deliveries)
  • \n
  • Settings UI integration with event subscription controls
  • \n
\n

Event Types:

\n
    \n
  • Task events: created, updated, deleted, completed, archived, unarchived
  • \n
  • Time tracking: started, stopped
  • \n
  • Pomodoro: started, completed, interrupted
  • \n
  • Recurring tasks: instance completed
  • \n
  • Reminders: triggered
  • \n
\n

Security and Reliability:

\n
    \n
  • HMAC-SHA256 signature verification for payload authentication
  • \n
  • Automatic retries with exponential backoff (3 attempts)
  • \n
  • 10-second delivery timeout with failure monitoring
  • \n
  • Auto-disable webhooks after repeated failures
  • \n
  • Non-blocking async delivery maintains TaskNotes responsiveness
  • \n
\n

Documentation and testing utilities included in docs/webhooks.md and test-webhook.js.

\n

Bug Fixes#

\n

Boolean Property Identification Regression (#367)#

\n

Fixed regression from version 3.18.2 where boolean checkbox properties stopped working for property-based task identification.

\n

During code refactoring, the comparePropertyValues function was accidentally removed, breaking boolean-to-string coercion needed for Obsidian checkbox properties. The fix restores this function with proper type-aware comparison logic, allowing boolean true/false frontmatter values to correctly match "true"/"false" setting values.

\n

Thanks to @renatomen for reporting this regression

\n","text":"New Features# Webhook Support# Added webhook system enabling integrations with external services and automation workflows. Webhook Management: CRUD operations for webhook configuration HTTP API endpoints for webhook management (POST /api/webhooks, GET /api/webhooks, DELETE /api/webhooks/{id}) Delivery history tracking (GET /api/webhooks/deliveries) Settings UI integration with event subscription controls Event Types: Task events: created, updated, deleted, completed, archived, unarchived Time tracking: started, stopped Pomodoro: started, completed, interrupted Recurring tasks: instance completed Reminders: triggered Security and Reliability: HMAC-SHA256 signature verification for payload authentication Automatic retries with exponential backoff (3 attempts) 10-second delivery timeout with failure monitoring Auto-disable webhooks after repeated failures Non-blocking async delivery maintains TaskNotes responsiveness Documentation and testing utilities included in docs/webhooks.md and test-webhook.js. Bug Fixes# Boolean Property Identification Regression (#367)# Fixed regression from version 3.18.2 where boolean checkbox properties stopped working for property-based task identification. During code refactoring, the comparePropertyValues function was accidentally removed, breaking boolean-to-string coercion needed for Obsidian checkbox properties. The fix restores this function with proper type-aware comparison logic, allowing boolean true/false frontmatter values to correctly match \"true\"/\"false\" setting values. Thanks to @renatomen for reporting this regression"},{"route":"/obsidian/releases/3.20.0/","title":"TaskNotes 3.20.0","description":"Folder-Based Task Filtering - Added task filtering by folder location with dropdown selection of vault folder paths, special handling for root-level tasks, and support for conta...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.20.0.md","namespace":"obsidian","relativePath":"releases/3.20.0.md","raw":"# TaskNotes 3.20.0\n\n## New Features\n\n### Task Organization and Filtering\n\n**Folder-Based Task Filtering** - Added task filtering by folder location with dropdown selection of vault folder paths, special handling for root-level tasks, and support for contains/empty operators. *Addresses issue #369 reported by kmaustral*\n\n**Dynamic Task Folder Organization** - Added template variable support for default task folder setting with task variables (`{{context}}`, `{{project}}`, `{{priority}}`, `{{status}}`, `{{title}}`) and date variables (`{{year}}`, `{{month}}`, `{{day}}`, `{{date}}`). Supports automatic folder creation and title sanitization. *Addresses feature request #376 by Mara-Li*\n\n**Archive Task Organization** - Added optional bidirectional task movement between archive folder and default tasks folder. Disabled by default with settings in Task defaults → Task organization (`moveArchivedTasks`, `archiveFolder`). *Addresses feature request #402 by anareaty*\n\n### Enhanced UI and Controls\n\n**Enhanced Filter Bar** - Improved filter bar with instant badge updates, right-click clear functionality, \"Clear All Filters\" button, and better UI synchronization across main and subtask views. *Contributed by renatomen*\n\n**Collapsible Groups** - Added collapsible groups with persisted state, chevron indicators, and keyboard navigation. Works with all grouping options while preserving wikilink functionality. Extended to subtask widget with consistent behavior. *Contributed by renatomen*\n\n**Expand/Collapse All Controls** - Added \"Expand All\" and \"Collapse All\" buttons to task list toolbar that appear when grouping is active. *Contributed by renatomen*\n\n**Configurable UI Elements** - Added settings for subtask chevron position (right/left) and saved views button positioning in task view toolbar. *Contributed by renatomen*\n\n### Advanced API Architecture and Webhook System\n\nRefactored HTTP API from monolithic design to controller/service pattern, reducing HTTPAPIService from 1,061 to 231 lines (78% reduction). Added dedicated controllers for tasks, time tracking, Pomodoro, system, and webhooks with 100% backward compatibility.\n\n**Webhook System** - Added complete webhook infrastructure with signature verification, automatic retries with exponential backoff, 10-second delivery timeout, and auto-disable after repeated failures. Supports all task lifecycle events (created, updated, deleted, completed, archived, unarchived), time tracking events, Pomodoro sessions, recurring task instances, and reminders.\n\n**Webhook Testing and Development** - Included standalone webhook testing server (`test-webhook.js`) with real-time payload inspection, signature verification testing, and comprehensive event logging for development and debugging.\n\n## Improvements\n\n### UI and Visual Enhancements\n\n**TaskNotes Icons** - Added TaskNotes icons throughout interface and edit task modal headers with new SVG assets.\n\n**Task Card Polish** - Improved status and priority dot alignment and reordered context menu (\"Copy task title\" moved to top). *Addresses alignment issue #410 reported by kmaustral*\n\n**Button Styling** - Fixed agenda view and filter popup button backgrounds with improved styling consistency.\n\n### Technical Improvements\n\n**Settings Architecture** - Decomposed monolithic settings.ts into focused modules: defaults, settings management, type definitions, and utilities for better maintainability.\n\n**Documentation** - Added extensive webhook documentation in `docs/examples/webhook-transforms/` with ready-to-use transform examples for Discord (rich embeds with colors), Slack (compatible attachments), Microsoft Teams (MessageCard format), and generic JSON templates. Expanded API documentation with complete endpoint reference, examples, error handling, authentication, and OpenAPI specification.\n\n**Webhook Integration Services** - Enhanced core services (TaskService, PomodoroService) with webhook notifications integrated into task lifecycle events, ensuring all user actions trigger appropriate webhook deliveries for external automation and monitoring.\n\n## Bug Fixes\n\n**Mobile Modal Close Button** - Fixed close button (X) touch event handling in task edit modals on mobile devices, particularly Android. *Addresses issue #404 reported by anareaty*\n\n**Test Suite Stabilization** - Resolved test failures and linting errors\n\n**HTTP API Field Consistency** - Updated API examples to use correct 'details' field instead of deprecated 'notes' field. *Addresses issue #393 reported by @nightroman*\n\n**Missing Webhook Trigger** - Added webhook trigger for recurring task completion events.\n\n## Documentation Updates\n\n- Task defaults documentation with template variables\n- Miscellaneous settings documentation \n- Webhook transform documentation and examples\n- Demo GIFs for new features\n\nThanks @renatomen!\n\n## Contributors\n\nSpecial thanks to the following contributors:\n\n- **@Mara-Li** - Feature request for template variables in task folders\n- **@kmaustral** - Feature requests for folder filtering and UI alignment improvements\n- **@anareaty** - Bug report for mobile modal close button issue\n- **@nightroman** - Reported mislead API documentation\n\nA really big thanks to @renatomen whose very polished contributions form the bulk of this update!\n\n\n","aliases":["/releases/3.20.0/","/releases/3.20.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"task-organization-and-filtering","text":"Task Organization and Filtering"},{"level":3,"id":"enhanced-ui-and-controls","text":"Enhanced UI and Controls"},{"level":3,"id":"advanced-api-architecture-and-webhook-system","text":"Advanced API Architecture and Webhook System"},{"level":2,"id":"improvements","text":"Improvements"},{"level":3,"id":"ui-and-visual-enhancements","text":"UI and Visual Enhancements"},{"level":3,"id":"technical-improvements","text":"Technical Improvements"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":2,"id":"documentation-updates","text":"Documentation Updates"},{"level":2,"id":"contributors","text":"Contributors"}],"html":"

New Features#

\n

Task Organization and Filtering#

\n

Folder-Based Task Filtering - Added task filtering by folder location with dropdown selection of vault folder paths, special handling for root-level tasks, and support for contains/empty operators. Addresses issue #369 reported by kmaustral

\n

Dynamic Task Folder Organization - Added template variable support for default task folder setting with task variables ({{context}}, {{project}}, {{priority}}, {{status}}, {{title}}) and date variables ({{year}}, {{month}}, {{day}}, {{date}}). Supports automatic folder creation and title sanitization. Addresses feature request #376 by Mara-Li

\n

Archive Task Organization - Added optional bidirectional task movement between archive folder and default tasks folder. Disabled by default with settings in Task defaults → Task organization (moveArchivedTasks, archiveFolder). Addresses feature request #402 by anareaty

\n

Enhanced UI and Controls#

\n

Enhanced Filter Bar - Improved filter bar with instant badge updates, right-click clear functionality, "Clear All Filters" button, and better UI synchronization across main and subtask views. Contributed by renatomen

\n

Collapsible Groups - Added collapsible groups with persisted state, chevron indicators, and keyboard navigation. Works with all grouping options while preserving wikilink functionality. Extended to subtask widget with consistent behavior. Contributed by renatomen

\n

Expand/Collapse All Controls - Added "Expand All" and "Collapse All" buttons to task list toolbar that appear when grouping is active. Contributed by renatomen

\n

Configurable UI Elements - Added settings for subtask chevron position (right/left) and saved views button positioning in task view toolbar. Contributed by renatomen

\n

Advanced API Architecture and Webhook System#

\n

Refactored HTTP API from monolithic design to controller/service pattern, reducing HTTPAPIService from 1,061 to 231 lines (78% reduction). Added dedicated controllers for tasks, time tracking, Pomodoro, system, and webhooks with 100% backward compatibility.

\n

Webhook System - Added complete webhook infrastructure with signature verification, automatic retries with exponential backoff, 10-second delivery timeout, and auto-disable after repeated failures. Supports all task lifecycle events (created, updated, deleted, completed, archived, unarchived), time tracking events, Pomodoro sessions, recurring task instances, and reminders.

\n

Webhook Testing and Development - Included standalone webhook testing server (test-webhook.js) with real-time payload inspection, signature verification testing, and comprehensive event logging for development and debugging.

\n

Improvements#

\n

UI and Visual Enhancements#

\n

TaskNotes Icons - Added TaskNotes icons throughout interface and edit task modal headers with new SVG assets.

\n

Task Card Polish - Improved status and priority dot alignment and reordered context menu ("Copy task title" moved to top). Addresses alignment issue #410 reported by kmaustral

\n

Button Styling - Fixed agenda view and filter popup button backgrounds with improved styling consistency.

\n

Technical Improvements#

\n

Settings Architecture - Decomposed monolithic settings.ts into focused modules: defaults, settings management, type definitions, and utilities for better maintainability.

\n

Documentation - Added extensive webhook documentation in docs/examples/webhook-transforms/ with ready-to-use transform examples for Discord (rich embeds with colors), Slack (compatible attachments), Microsoft Teams (MessageCard format), and generic JSON templates. Expanded API documentation with complete endpoint reference, examples, error handling, authentication, and OpenAPI specification.

\n

Webhook Integration Services - Enhanced core services (TaskService, PomodoroService) with webhook notifications integrated into task lifecycle events, ensuring all user actions trigger appropriate webhook deliveries for external automation and monitoring.

\n

Bug Fixes#

\n

Mobile Modal Close Button - Fixed close button (X) touch event handling in task edit modals on mobile devices, particularly Android. Addresses issue #404 reported by anareaty

\n

Test Suite Stabilization - Resolved test failures and linting errors

\n

HTTP API Field Consistency - Updated API examples to use correct 'details' field instead of deprecated 'notes' field. Addresses issue #393 reported by @nightroman

\n

Missing Webhook Trigger - Added webhook trigger for recurring task completion events.

\n

Documentation Updates#

\n
    \n
  • Task defaults documentation with template variables
  • \n
  • Miscellaneous settings documentation
  • \n
  • Webhook transform documentation and examples
  • \n
  • Demo GIFs for new features
  • \n
\n

Thanks @renatomen!

\n

Contributors#

\n

Special thanks to the following contributors:

\n
    \n
  • @Mara-Li - Feature request for template variables in task folders
  • \n
  • @kmaustral - Feature requests for folder filtering and UI alignment improvements
  • \n
  • @anareaty - Bug report for mobile modal close button issue
  • \n
  • @nightroman - Reported mislead API documentation
  • \n
\n

A really big thanks to @renatomen whose very polished contributions form the bulk of this update!

\n","text":"New Features# Task Organization and Filtering# Folder-Based Task Filtering - Added task filtering by folder location with dropdown selection of vault folder paths, special handling for root-level tasks, and support for contains/empty operators. Addresses issue #369 reported by kmaustral Dynamic Task Folder Organization - Added template variable support for default task folder setting with task variables ({{context}}, {{project}}, {{priority}}, {{status}}, {{title}}) and date variables ({{year}}, {{month}}, {{day}}, {{date}}). Supports automatic folder creation and title sanitization. Addresses feature request #376 by Mara-Li Archive Task Organization - Added optional bidirectional task movement between archive folder and default tasks folder. Disabled by default with settings in Task defaults → Task organization (moveArchivedTasks, archiveFolder). Addresses feature request #402 by anareaty Enhanced UI and Controls# Enhanced Filter Bar - Improved filter bar with instant badge updates, right-click clear functionality, \"Clear All Filters\" button, and better UI synchronization across main and subtask views. Contributed by renatomen Collapsible Groups - Added collapsible groups with persisted state, chevron indicators, and keyboard navigation. Works with all grouping options while preserving wikilink functionality. Extended to subtask widget with consistent behavior. Contributed by renatomen Expand/Collapse All Controls - Added \"Expand All\" and \"Collapse All\" buttons to task list toolbar that appear when grouping is active. Contributed by renatomen Configurable UI Elements - Added settings for subtask chevron position (right/left) and saved views button positioning in task view toolbar. Contributed by renatomen Advanced API Architecture and Webhook System# Refactored HTTP API from monolithic design to controller/service pattern, reducing HTTPAPIService from 1,061 to 231 lines (78% reduction). Added dedicated controllers for tasks, time tracking, Pomodoro, system, and webhooks with 100% backward compatibility. Webhook System - Added complete webhook infrastructure with signature verification, automatic retries with exponential backoff, 10-second delivery timeout, and auto-disable after repeated failures. Supports all task lifecycle events (created, updated, deleted, completed, archived, unarchived), time tracking events, Pomodoro sessions, recurring task instances, and reminders. Webhook Testing and Development - Included standalone webhook testing server (test-webhook.js) with real-time payload inspection, signature verification testing, and comprehensive event logging for development and debugging. Improvements# UI and Visual Enhancements# TaskNotes Icons - Added TaskNotes icons throughout interface and edit task modal headers with new SVG assets. Task Card Polish - Improved status and priority dot alignment and reordered context menu (\"Copy task title\" moved to top). Addresses alignment issue #410 reported by kmaustral Button Styling - Fixed agenda view and filter popup button backgrounds with improved styling consistency. Technical Improvements# Settings Architecture - Decomposed monolithic settings.ts into focused modules: defaults, settings management, type definitions, and utilities for better maintainability. Documentation - Added extensive webhook documentation in docs/examples/webhook-transforms/ with ready-to-use transform examples for Discord (rich embeds with colors), Slack (compatible attachments), Microsoft Teams (MessageCard format), and generic JSON templates. Expanded API documentation with complete endpoint reference, examples, error handling, authentication, and OpenAPI specification. Webhook Integration Services - Enhanced core services (TaskService, PomodoroService) with webhook notifications integrated into task lifecycle events, ensuring all user actions trigger appropriate webhook deliveries for external automation and monitoring. Bug Fixes# Mobile Modal Close Button - Fixed close button (X) touch event handling in task edit modals on mobile devices, particularly Android. Addresses issue #404 reported by anareaty Test Suite Stabilization - Resolved test failures and linting errors HTTP API Field Consistency - Updated API examples to use correct 'details' field instead of deprecated 'notes' field. Addresses issue #393 reported by @nightroman Missing Webhook Trigger - Added webhook trigger for recurring task completion events. Documentation Updates# Task defaults documentation with template variables Miscellaneous settings documentation Webhook transform documentation and examples Demo GIFs for new features Thanks @renatomen! Contributors# Special thanks to the following contributors: @Mara-Li - Feature request for template variables in task folders @kmaustral - Feature requests for folder filtering and UI alignment improvements @anareaty - Bug report for mobile modal close button issue @nightroman - Reported mislead API documentation A really big thanks to @renatomen whose very polished contributions form the bulk of this update!"},{"route":"/obsidian/releases/3.20.1/","title":"TaskNotes 3.20.1","description":"Saved View Headings with Completion Counts - Added visible filter headings across all views (Task List, Subtask Widget, and Agenda) that display the current saved view name and...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.20.1.md","namespace":"obsidian","relativePath":"releases/3.20.1.md","raw":"# TaskNotes 3.20.1\n\n## New Features\n\n### Enhanced View Organization and Visual Feedback\n\n**Saved View Headings with Completion Counts** - Added visible filter headings across all views (Task List, Subtask Widget, and Agenda) that display the current saved view name and completion statistics in \"completed / total\" format. Shows \"All\" when no saved view is active. Headings update immediately on filter changes and persist correctly when switching tabs or reloading. *Contributed by @renatomen*\n\n**Consistent Group Count Badges** - Standardized completion count display across all group headers in Task List, Subtask Widget, and Agenda views using unified \"completed / total\" format. Removed redundant bracketed counts for cleaner presentation. *Contributed by @renatomen*\n\n**Collapsible Agenda Date Groups** - Added collapsible date headers to Agenda view with persistent state management. Date sections can be collapsed individually or controlled via \"Expand All\" / \"Collapse All\" buttons that are always visible in the FilterBar. Collapsed state is preserved between sessions using ViewStateManager. *Contributed by @renatomen*\n\n### Improved User Interface\n\n**Reorganized Task Context Menu** - Enhanced context menu organization by replacing individual buttons with logical submenus for status, priority, dates, recurrence, and reminders. Applied user-configured colors to main menu icons while maintaining all existing functionality. \n\n## Bug Fixes\n\n### Calendar Integration Fixes\n\n**Outlook Calendar 500 Errors** - Fixed Microsoft Outlook ICS endpoint failures by updating User-Agent header from 'TaskNotes-Plugin/1.0' to browser-compatible string and adding Accept-Language header. Improved error handling with specific guidance for Outlook 500 errors. *Fixes issue #458 reported by @girisumit and @heinzochsner*\n\n**Recurring Tasks Date Display** - Fixed timezone-dependent bug where recurring tasks appeared one day ahead or behind their actual due date in Agenda View. Replaced manual UTC date construction with parseDateToUTC() following UTC Anchor principle from development guidelines. Added regression test for consistent date handling. *Fixes issue #439 reported by @brianarn and @jpmoo*\n\n### Task Management Fixes \n\n**Project Suggestions Crash Prevention** - Fixed crash in Task Creation modal when typing \"+\" to add projects inline, caused by non-string title values in frontmatter. Added title normalization (arrays join with \", \", numbers/booleans stringify, objects become empty strings) and defensive guards in suggestion filtering. Particularly important for large vaults with heterogeneous frontmatter. *Contributed by @renatomen*\n\n## Documentation Updates\n\n- Added screenshots demonstrating saved view headings and completion counts for Task List and Subtask Widget\n- Created demo GIF showing Agenda view collapsible groups with Expand/Collapse All functionality \n- Updated view documentation with new visual features\n- Enhanced inline task documentation for Subtask Widget improvements\n\n*Contributed by @renatomen*\n\n## Contributors\n\nSpecial recognition goes to **@renatomen** for the substantial contributions that form the core of this release, including the saved view headings system, consistent count badges, and collapsible Agenda functionality.\n\nThanks to the following community members for their bug reports and feedback:\n\n- **@girisumit and @heinzochsner** - Reported Outlook calendar integration issues\n- **@brianarn and @jpmoo** - Identified recurring tasks date display bug with detailed reproduction steps\n","aliases":["/releases/3.20.1/","/releases/3.20.1/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"enhanced-view-organization-and-visual-feedback","text":"Enhanced View Organization and Visual Feedback"},{"level":3,"id":"improved-user-interface","text":"Improved User Interface"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"calendar-integration-fixes","text":"Calendar Integration Fixes"},{"level":3,"id":"task-management-fixes","text":"Task Management Fixes"},{"level":2,"id":"documentation-updates","text":"Documentation Updates"},{"level":2,"id":"contributors","text":"Contributors"}],"html":"

New Features#

\n

Enhanced View Organization and Visual Feedback#

\n

Saved View Headings with Completion Counts - Added visible filter headings across all views (Task List, Subtask Widget, and Agenda) that display the current saved view name and completion statistics in "completed / total" format. Shows "All" when no saved view is active. Headings update immediately on filter changes and persist correctly when switching tabs or reloading. Contributed by @renatomen

\n

Consistent Group Count Badges - Standardized completion count display across all group headers in Task List, Subtask Widget, and Agenda views using unified "completed / total" format. Removed redundant bracketed counts for cleaner presentation. Contributed by @renatomen

\n

Collapsible Agenda Date Groups - Added collapsible date headers to Agenda view with persistent state management. Date sections can be collapsed individually or controlled via "Expand All" / "Collapse All" buttons that are always visible in the FilterBar. Collapsed state is preserved between sessions using ViewStateManager. Contributed by @renatomen

\n

Improved User Interface#

\n

Reorganized Task Context Menu - Enhanced context menu organization by replacing individual buttons with logical submenus for status, priority, dates, recurrence, and reminders. Applied user-configured colors to main menu icons while maintaining all existing functionality.

\n

Bug Fixes#

\n

Calendar Integration Fixes#

\n

Outlook Calendar 500 Errors - Fixed Microsoft Outlook ICS endpoint failures by updating User-Agent header from 'TaskNotes-Plugin/1.0' to browser-compatible string and adding Accept-Language header. Improved error handling with specific guidance for Outlook 500 errors. Fixes issue #458 reported by @girisumit and @heinzochsner

\n

Recurring Tasks Date Display - Fixed timezone-dependent bug where recurring tasks appeared one day ahead or behind their actual due date in Agenda View. Replaced manual UTC date construction with parseDateToUTC() following UTC Anchor principle from development guidelines. Added regression test for consistent date handling. Fixes issue #439 reported by @brianarn and @jpmoo

\n

Task Management Fixes#

\n

Project Suggestions Crash Prevention - Fixed crash in Task Creation modal when typing "+" to add projects inline, caused by non-string title values in frontmatter. Added title normalization (arrays join with ", ", numbers/booleans stringify, objects become empty strings) and defensive guards in suggestion filtering. Particularly important for large vaults with heterogeneous frontmatter. Contributed by @renatomen

\n

Documentation Updates#

\n
    \n
  • Added screenshots demonstrating saved view headings and completion counts for Task List and Subtask Widget
  • \n
  • Created demo GIF showing Agenda view collapsible groups with Expand/Collapse All functionality
  • \n
  • Updated view documentation with new visual features
  • \n
  • Enhanced inline task documentation for Subtask Widget improvements
  • \n
\n

Contributed by @renatomen

\n

Contributors#

\n

Special recognition goes to @renatomen for the substantial contributions that form the core of this release, including the saved view headings system, consistent count badges, and collapsible Agenda functionality.

\n

Thanks to the following community members for their bug reports and feedback:

\n
    \n
  • @girisumit and @heinzochsner - Reported Outlook calendar integration issues
  • \n
  • @brianarn and @jpmoo - Identified recurring tasks date display bug with detailed reproduction steps
  • \n
\n","text":"New Features# Enhanced View Organization and Visual Feedback# Saved View Headings with Completion Counts - Added visible filter headings across all views (Task List, Subtask Widget, and Agenda) that display the current saved view name and completion statistics in \"completed / total\" format. Shows \"All\" when no saved view is active. Headings update immediately on filter changes and persist correctly when switching tabs or reloading. Contributed by @renatomen Consistent Group Count Badges - Standardized completion count display across all group headers in Task List, Subtask Widget, and Agenda views using unified \"completed / total\" format. Removed redundant bracketed counts for cleaner presentation. Contributed by @renatomen Collapsible Agenda Date Groups - Added collapsible date headers to Agenda view with persistent state management. Date sections can be collapsed individually or controlled via \"Expand All\" / \"Collapse All\" buttons that are always visible in the FilterBar. Collapsed state is preserved between sessions using ViewStateManager. Contributed by @renatomen Improved User Interface# Reorganized Task Context Menu - Enhanced context menu organization by replacing individual buttons with logical submenus for status, priority, dates, recurrence, and reminders. Applied user-configured colors to main menu icons while maintaining all existing functionality. Bug Fixes# Calendar Integration Fixes# Outlook Calendar 500 Errors - Fixed Microsoft Outlook ICS endpoint failures by updating User-Agent header from 'TaskNotes-Plugin/1.0' to browser-compatible string and adding Accept-Language header. Improved error handling with specific guidance for Outlook 500 errors. Fixes issue #458 reported by @girisumit and @heinzochsner Recurring Tasks Date Display - Fixed timezone-dependent bug where recurring tasks appeared one day ahead or behind their actual due date in Agenda View. Replaced manual UTC date construction with parseDateToUTC() following UTC Anchor principle from development guidelines. Added regression test for consistent date handling. Fixes issue #439 reported by @brianarn and @jpmoo Task Management Fixes# Project Suggestions Crash Prevention - Fixed crash in Task Creation modal when typing \"+\" to add projects inline, caused by non-string title values in frontmatter. Added title normalization (arrays join with \", \", numbers/booleans stringify, objects become empty strings) and defensive guards in suggestion filtering. Particularly important for large vaults with heterogeneous frontmatter. Contributed by @renatomen Documentation Updates# Added screenshots demonstrating saved view headings and completion counts for Task List and Subtask Widget Created demo GIF showing Agenda view collapsible groups with Expand/Collapse All functionality Updated view documentation with new visual features Enhanced inline task documentation for Subtask Widget improvements Contributed by @renatomen Contributors# Special recognition goes to @renatomen for the substantial contributions that form the core of this release, including the saved view headings system, consistent count badges, and collapsible Agenda functionality. Thanks to the following community members for their bug reports and feedback: @girisumit and @heinzochsner - Reported Outlook calendar integration issues @brianarn and @jpmoo - Identified recurring tasks date display bug with detailed reproduction steps"},{"route":"/obsidian/releases/3.21.0/","title":"TaskNotes 3.21.0","description":"Custom User Fields Mapping - Added ability to define custom frontmatter properties for task filtering, grouping, and sorting. Users can configure field mappings in Settings → Ad...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.21.0.md","namespace":"obsidian","relativePath":"releases/3.21.0.md","raw":"# TaskNotes 3.21.0\n\n## New Features\n\n### Custom User Fields System\n\n**Custom User Fields Mapping** - Added ability to define custom frontmatter properties for task filtering, grouping, and sorting. Users can configure field mappings in Settings → Advanced → User Fields with support for text, number, date, boolean, and list field types. List fields preserve wikilinks and quoted tokens, while numeric fields intelligently parse mixed text-number values like \"2-Medium\" as numeric 2. *Contributed by @renatomen*\n\n**Group and Sort by Custom User Fields** - Extended grouping and sorting functionality to work with user-defined custom fields. Includes type-aware comparators for each field type and proper group header ordering when grouping and sorting by the same field. *Contributed by @renatomen*\n\n**User Fields in Task Modals** - Added custom user field support to task creation and edit modals with autocomplete suggestions from existing field values. Fields are stored as frontmatter properties and include change detection for edit scenarios. *Contributed by @callumalpass*\n\n### Enhanced Task Interaction\n\n**Configurable Click Behavior** - Added option to configure single-click and double-click behavior for task cards and inline task widgets. Users can choose between opening the edit modal or the source note file for each click type. Includes shared click handler utility with 250ms detection delay. *Contributed by @fastrick*\n\n### Calendar Integration Enhancements\n\n**Calendar Event Filename Templates** - Added separate filename template configuration for notes created from calendar events. Supports ICS-specific template variables including `{icsEventTitle}`, `{icsEventLocation}`, `{icsEventDescription}`, and `{icsEventTitleWithDate}`. The `{title}` variable now uses clean event titles without date suffixes. *Fixes issue #362 reported by @bepolymathe*\n\n**Chronological ICS Event Sorting** - Fixed ICS calendar events to display in chronological order by start time within each day in the agenda view. Applied to both grouped and flat agenda view modes. *Fixes issue #472 reported by @Crunchnuggetz*\n\n## Bug Fixes\n\n### API Endpoint Improvements\n\n**Custom Status Configuration Support** - Fixed API endpoints (`/api/nlp/parse` and `/api/nlp/create`) not respecting custom status configurations. API now uses proper default status logic matching the UI instead of hardcoded 'todo' values, with proper handling of boolean status values. *Fixes issue #487 reported by @23maverick23*\n\n**Task Creation Defaults** - Fixed REST API endpoint (`POST /api/tasks`) missing default properties like scheduled dates, tags, and reminders. API-created tasks now receive the same defaults as UI-created tasks. *Fixes issue reported by @nightroman*\n\n### Project Management Fixes\n\n**Project Consolidation and Display** - Fixed project grouping to consolidate different formats pointing to the same file (e.g., `[[project]]` and `[[project|alias]]` now group together). Improved display formatting with clickable headers showing absolute paths without `.md` extensions and proper wikilink alias parsing. Task cards preserve original formats while grouping logic ignores display aliases. *Fixes issues #448 reported by @minchinweb and #469 reported by @anareaty*\n\n### User Experience Improvements\n\n**Tag Input Sanitization** - Added automatic sanitization to remove `#` prefixes from tag input, preventing duplicate tags like `#tag1` and `##tag1`. Applied to task creation, editing, and real-time input handling. *Fixes issue #331 reported by @AndreMonthy*\n\n## Contributors\n\nSpecial recognition goes to **@renatomen** for the extensive custom user fields system that forms the core of this release, including field mapping, filtering, grouping, and sorting capabilities.\n\nThanks to **@fastrick** for implementing the configurable click behavior feature.\n\nThanks to the following community members for their bug reports and feature requests:\n\n- **@23maverick23** - Reported API custom status configuration issues with detailed technical analysis\n- **@Crunchnuggetz** - Identified ICS calendar event sorting problem in agenda view\n- **@minchinweb** - Reported project consolidation issues with wikilink variations \n- **@anareaty** - Identified project display formatting problems in kanban view\n- **@bepolymathe** - Requested calendar event filename template functionality\n- **@AndreMonthy** - Reported tag input sanitization issues with clear examples\n- **@nightroman** - Reported API issues where defaults were not being applied","aliases":["/releases/3.21.0/","/releases/3.21.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"custom-user-fields-system","text":"Custom User Fields System"},{"level":3,"id":"enhanced-task-interaction","text":"Enhanced Task Interaction"},{"level":3,"id":"calendar-integration-enhancements","text":"Calendar Integration Enhancements"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"api-endpoint-improvements","text":"API Endpoint Improvements"},{"level":3,"id":"project-management-fixes","text":"Project Management Fixes"},{"level":3,"id":"user-experience-improvements","text":"User Experience Improvements"},{"level":2,"id":"contributors","text":"Contributors"}],"html":"

New Features#

\n

Custom User Fields System#

\n

Custom User Fields Mapping - Added ability to define custom frontmatter properties for task filtering, grouping, and sorting. Users can configure field mappings in Settings → Advanced → User Fields with support for text, number, date, boolean, and list field types. List fields preserve wikilinks and quoted tokens, while numeric fields intelligently parse mixed text-number values like "2-Medium" as numeric 2. Contributed by @renatomen

\n

Group and Sort by Custom User Fields - Extended grouping and sorting functionality to work with user-defined custom fields. Includes type-aware comparators for each field type and proper group header ordering when grouping and sorting by the same field. Contributed by @renatomen

\n

User Fields in Task Modals - Added custom user field support to task creation and edit modals with autocomplete suggestions from existing field values. Fields are stored as frontmatter properties and include change detection for edit scenarios. Contributed by @callumalpass

\n

Enhanced Task Interaction#

\n

Configurable Click Behavior - Added option to configure single-click and double-click behavior for task cards and inline task widgets. Users can choose between opening the edit modal or the source note file for each click type. Includes shared click handler utility with 250ms detection delay. Contributed by @fastrick

\n

Calendar Integration Enhancements#

\n

Calendar Event Filename Templates - Added separate filename template configuration for notes created from calendar events. Supports ICS-specific template variables including {icsEventTitle}, {icsEventLocation}, {icsEventDescription}, and {icsEventTitleWithDate}. The {title} variable now uses clean event titles without date suffixes. Fixes issue #362 reported by @bepolymathe

\n

Chronological ICS Event Sorting - Fixed ICS calendar events to display in chronological order by start time within each day in the agenda view. Applied to both grouped and flat agenda view modes. Fixes issue #472 reported by @Crunchnuggetz

\n

Bug Fixes#

\n

API Endpoint Improvements#

\n

Custom Status Configuration Support - Fixed API endpoints (/api/nlp/parse and /api/nlp/create) not respecting custom status configurations. API now uses proper default status logic matching the UI instead of hardcoded 'todo' values, with proper handling of boolean status values. Fixes issue #487 reported by @23maverick23

\n

Task Creation Defaults - Fixed REST API endpoint (POST /api/tasks) missing default properties like scheduled dates, tags, and reminders. API-created tasks now receive the same defaults as UI-created tasks. Fixes issue reported by @nightroman

\n

Project Management Fixes#

\n

Project Consolidation and Display - Fixed project grouping to consolidate different formats pointing to the same file (e.g., [[project]] and [[project|alias]] now group together). Improved display formatting with clickable headers showing absolute paths without .md extensions and proper wikilink alias parsing. Task cards preserve original formats while grouping logic ignores display aliases. Fixes issues #448 reported by @minchinweb and #469 reported by @anareaty

\n

User Experience Improvements#

\n

Tag Input Sanitization - Added automatic sanitization to remove # prefixes from tag input, preventing duplicate tags like #tag1 and ##tag1. Applied to task creation, editing, and real-time input handling. Fixes issue #331 reported by @AndreMonthy

\n

Contributors#

\n

Special recognition goes to @renatomen for the extensive custom user fields system that forms the core of this release, including field mapping, filtering, grouping, and sorting capabilities.

\n

Thanks to @fastrick for implementing the configurable click behavior feature.

\n

Thanks to the following community members for their bug reports and feature requests:

\n
    \n
  • @23maverick23 - Reported API custom status configuration issues with detailed technical analysis
  • \n
  • @Crunchnuggetz - Identified ICS calendar event sorting problem in agenda view
  • \n
  • @minchinweb - Reported project consolidation issues with wikilink variations
  • \n
  • @anareaty - Identified project display formatting problems in kanban view
  • \n
  • @bepolymathe - Requested calendar event filename template functionality
  • \n
  • @AndreMonthy - Reported tag input sanitization issues with clear examples
  • \n
  • @nightroman - Reported API issues where defaults were not being applied
  • \n
\n","text":"New Features# Custom User Fields System# Custom User Fields Mapping - Added ability to define custom frontmatter properties for task filtering, grouping, and sorting. Users can configure field mappings in Settings → Advanced → User Fields with support for text, number, date, boolean, and list field types. List fields preserve wikilinks and quoted tokens, while numeric fields intelligently parse mixed text-number values like \"2-Medium\" as numeric 2. Contributed by @renatomen Group and Sort by Custom User Fields - Extended grouping and sorting functionality to work with user-defined custom fields. Includes type-aware comparators for each field type and proper group header ordering when grouping and sorting by the same field. Contributed by @renatomen User Fields in Task Modals - Added custom user field support to task creation and edit modals with autocomplete suggestions from existing field values. Fields are stored as frontmatter properties and include change detection for edit scenarios. Contributed by @callumalpass Enhanced Task Interaction# Configurable Click Behavior - Added option to configure single-click and double-click behavior for task cards and inline task widgets. Users can choose between opening the edit modal or the source note file for each click type. Includes shared click handler utility with 250ms detection delay. Contributed by @fastrick Calendar Integration Enhancements# Calendar Event Filename Templates - Added separate filename template configuration for notes created from calendar events. Supports ICS-specific template variables including {icsEventTitle}, {icsEventLocation}, {icsEventDescription}, and {icsEventTitleWithDate}. The {title} variable now uses clean event titles without date suffixes. Fixes issue #362 reported by @bepolymathe Chronological ICS Event Sorting - Fixed ICS calendar events to display in chronological order by start time within each day in the agenda view. Applied to both grouped and flat agenda view modes. Fixes issue #472 reported by @Crunchnuggetz Bug Fixes# API Endpoint Improvements# Custom Status Configuration Support - Fixed API endpoints (/api/nlp/parse and /api/nlp/create) not respecting custom status configurations. API now uses proper default status logic matching the UI instead of hardcoded 'todo' values, with proper handling of boolean status values. Fixes issue #487 reported by @23maverick23 Task Creation Defaults - Fixed REST API endpoint (POST /api/tasks) missing default properties like scheduled dates, tags, and reminders. API-created tasks now receive the same defaults as UI-created tasks. Fixes issue reported by @nightroman Project Management Fixes# Project Consolidation and Display - Fixed project grouping to consolidate different formats pointing to the same file (e.g., [[project]] and [[project|alias]] now group together). Improved display formatting with clickable headers showing absolute paths without .md extensions and proper wikilink alias parsing. Task cards preserve original formats while grouping logic ignores display aliases. Fixes issues #448 reported by @minchinweb and #469 reported by @anareaty User Experience Improvements# Tag Input Sanitization - Added automatic sanitization to remove # prefixes from tag input, preventing duplicate tags like #tag1 and ##tag1. Applied to task creation, editing, and real-time input handling. Fixes issue #331 reported by @AndreMonthy Contributors# Special recognition goes to @renatomen for the extensive custom user fields system that forms the core of this release, including field mapping, filtering, grouping, and sorting capabilities. Thanks to @fastrick for implementing the configurable click behavior feature. Thanks to the following community members for their bug reports and feature requests: @23maverick23 - Reported API custom status configuration issues with detailed technical analysis @Crunchnuggetz - Identified ICS calendar event sorting problem in agenda view @minchinweb - Reported project consolidation issues with wikilink variations @anareaty - Identified project display formatting problems in kanban view @bepolymathe - Requested calendar event filename template functionality @AndreMonthy - Reported tag input sanitization issues with clear examples @nightroman - Reported API issues where defaults were not being applied"},{"route":"/obsidian/releases/3.22.0/","title":"TaskNotes 3.22.0","description":"Added modular properties system allowing users to control visibility of task properties (due date, scheduled date, priority, projects, contexts, tags, custom fields, and total t...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.22.0.md","namespace":"obsidian","relativePath":"releases/3.22.0.md","raw":"# TaskNotes 3.22.0\n\n## Major Features\n\n### Modular Properties System\n\n- Added modular properties system allowing users to control visibility of task properties (due date, scheduled date, priority, projects, contexts, tags, custom fields, and total tracked time) both globally and per saved view. Properties can be configured through a new Properties dropdown in the filter bar, with settings automatically saved per view. Includes performance optimizations to render properties only when visible. *Thanks to @renatomen for the initial implementation of this feature*\n\n- Task cards now dynamically render properties based on visibility settings with improved error handling and type safety. System supports both core properties and user-defined custom fields with proper fallback to default configurations for new users.\n\n- Added total tracked time as a configurable property in the modular system, calculated from time entries and displayed consistently across all views when enabled.\n\n### Bases-style Filter Bar Redesign\n\n- Complete filter bar redesign matching Obsidian's bases plugin styling with improved layout, spacing, and button appearance. Added text labels and chevron icons to all filter buttons (Sort, Filters, Properties, New) for better discoverability.\n- Replaced dropdown menus with native Obsidian context menus featuring section headers and improved reliability. Sort/Group functionality now uses unified context menu system with better organization.\n- Implemented intelligent filter popup positioning using boundary detection to prevent popups from hiding under adjacent panes. Increased default popup width from 300px to 500px for better usability.\n- Moved expand/collapse controls from separate containers directly into filter headings across all views (TaskListView, AgendaView, subtask widget) for cleaner interface and consistent user experience.\n- Added dedicated \"+ New\" task creation button to filter bar with neutral styling and proper view context awareness.\n\n### Statistics view\n\n- Implement a new view to track statistics about projects and time tracking. \n\n## UX\n\n### Task Interaction Improvements\n\n- Changed \"This Week\" grouping label to \"Next seven days\" for clearer, more specific language about the 7-day time period while maintaining identical underlying functionality. *Fixes issue #516 reported by @anareaty*\n\n### External Contributions\n\n- Type-aware input fields in task modals now provide appropriate UI components based on field type (text/list with autosuggest, date with picker icon, boolean with toggle). Project autosuggest during task creation now supports multi-word project names without interrupting suggestions on spaces. *Contributed by @renatomen*\n- Fixed subtask right-click context menus that were incorrectly showing parent task options instead of subtask-specific options. Enhanced inline task overlay cursor behavior with configurable timing settings (0-500ms) for predictable overlay hiding when cursor approaches link boundaries. *Contributed by @renatomen* \n- Fixed project names containing commas (e.g., `[[Money, Org & Adm]]`) being incorrectly split, breaking selection and display across task modals, settings, and instant conversion. Now uses proper wikilink parsing to preserve comma-containing project names as single entities. *Contributed by @renatomen*\n- Fixed date parsing errors caused by hardcoded field mapping not respecting user's custom field configurations. Plugin now properly uses field mapper for note date extraction with fallback to hardcoded fields for backward compatibility. *Contributed by @renatomen*\n- Fixed User Fields column order in settings to match Field mapping configuration for consistency. *Contributed by @renatomen*\n\n## Bug Fixes\n\n### Timezone and Date Handling\n\n- Fixed timezone-dependent \"Today\" identification issues across multiple views including MiniCalendarView tooltips, PomodoroService session categorization, PomodoroStatsView statistics, and StatsView date calculations. All date-sensitive components now use UTC-anchored dates for timezone-independent behavior. *Fixes issue #452 reported by @MinchinWeb*\n\n\n### User Interface Fixes\n\n- Redesigned group counters with clean appearance (removed background, border, padding), positioned to far right of headers using muted text color for subtle display while maintaining left-aligned headings.\n- Improved contrast for INTERRUPTED status badge in pomodoro statistics for better readability. *Fixes issue #529 reported by @motusira*\n- Removed title length limits that were causing text truncation, allowing full title display. *Fixes issue #378 reported by @nsstrickland*\n- Added all-day slot toggle to calendar view for better event organization. *Fixes issue #242 requested by @Crunchnuggetz*\n- Added calendar locale configuration for international calendar support with proper localization. *Contributed by @pixeler*\n- Fixed task states not refreshing when date changes at midnight, ensuring accurate daily task status updates. *Fixes issue #527 reported by @jordandrako*\n- Fixed inline task overlay title wrapping using `white-space: break-spaces` for proper text display. *Fixes issue #517 reported by @cathywu*\n\n### New Capabilities\n\n- Added weekday display and increment options to date picker with integration into task context menus for improved date selection experience. *Fixes issue #238 requested by @girisumit*\n- Added tags to available sorting and grouping options for more flexible task organization. *Fixes issue #169 requested by @bce283c*\n- Added create inline task command for quick task creation within notes with NLP project support for automatic project assignment based on context. *Fixes issue #299 requested by @0dfa1bc*\n- Added filename template variables to folder templates including support for additional customization options. *Fixes issue #473 requested by @oliverlalan*\n- Implemented status auto-suggestion with NLP integration for intelligent status recommendations during task creation and editing.\n\n## Infrastructure Improvements\n\n### Development and Testing\n\n- Updated multiple npm dependencies including ical.js (1.5.0 → 2.2.1) and Jest (29.7.0 → 30.1.1) with compatibility fixes. Resolved all npm security vulnerabilities and updated ICS subscription service for ical.js v2.x compatibility.\n- Fixed all test suite failures and infrastructure issues including Jest 30 compatibility, RRule mocking, TypeScript configuration, and CI environment setup. Removed coverage thresholds that were causing CI failures while maintaining test quality.\n- Improved code quality throughout modular properties system with proper TypeScript compliance, error handling, performance optimizations, and memory cleanup functions. Replaced 'any' types with proper type guards and added comprehensive interface definitions.\n\n## Contributors\n\nSpecial recognition goes to **@renatomen** for multiple substantial contributions including type-aware custom field inputs, enhanced task interaction fixes, project name handling improvements, date parsing fixes, and settings alignment.\n\nThanks to the following community members for their bug reports and feature requests:\n\n- **@anareaty** - Reported grouping label confusion with clear examples\n- **@MinchinWeb** - Identified timezone handling inconsistencies across multiple views\n- **@motusira** - Reported contrast issues with INTERRUPTED status badge\n- **@nsstrickland** - Identified title truncation problems\n- **@Crunchnuggetz** - Requested all-day slot toggle for calendar views\n- **@jordandrako** - Reported task state refresh issues at midnight\n- **@cathywu** - Identified text wrapping problems in overlays \n- **@girisumit** - Requested enhanced date picker functionality\n- **@oliverlalan** - Requested template variable enhancements","aliases":["/releases/3.22.0/","/releases/3.22.0/"],"toc":[{"level":2,"id":"major-features","text":"Major Features"},{"level":3,"id":"modular-properties-system","text":"Modular Properties System"},{"level":3,"id":"bases-style-filter-bar-redesign","text":"Bases-style Filter Bar Redesign"},{"level":3,"id":"statistics-view","text":"Statistics view"},{"level":2,"id":"ux","text":"UX"},{"level":3,"id":"task-interaction-improvements","text":"Task Interaction Improvements"},{"level":3,"id":"external-contributions","text":"External Contributions"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"timezone-and-date-handling","text":"Timezone and Date Handling"},{"level":3,"id":"user-interface-fixes","text":"User Interface Fixes"},{"level":3,"id":"new-capabilities","text":"New Capabilities"},{"level":2,"id":"infrastructure-improvements","text":"Infrastructure Improvements"},{"level":3,"id":"development-and-testing","text":"Development and Testing"},{"level":2,"id":"contributors","text":"Contributors"}],"html":"

Major Features#

\n

Modular Properties System#

\n
    \n
  • Added modular properties system allowing users to control visibility of task properties (due date, scheduled date, priority, projects, contexts, tags, custom fields, and total tracked time) both globally and per saved view. Properties can be configured through a new Properties dropdown in the filter bar, with settings automatically saved per view. Includes performance optimizations to render properties only when visible. Thanks to @renatomen for the initial implementation of this feature

    \n
  • \n
  • Task cards now dynamically render properties based on visibility settings with improved error handling and type safety. System supports both core properties and user-defined custom fields with proper fallback to default configurations for new users.

    \n
  • \n
  • Added total tracked time as a configurable property in the modular system, calculated from time entries and displayed consistently across all views when enabled.

    \n
  • \n
\n

Bases-style Filter Bar Redesign#

\n
    \n
  • Complete filter bar redesign matching Obsidian's bases plugin styling with improved layout, spacing, and button appearance. Added text labels and chevron icons to all filter buttons (Sort, Filters, Properties, New) for better discoverability.
  • \n
  • Replaced dropdown menus with native Obsidian context menus featuring section headers and improved reliability. Sort/Group functionality now uses unified context menu system with better organization.
  • \n
  • Implemented intelligent filter popup positioning using boundary detection to prevent popups from hiding under adjacent panes. Increased default popup width from 300px to 500px for better usability.
  • \n
  • Moved expand/collapse controls from separate containers directly into filter headings across all views (TaskListView, AgendaView, subtask widget) for cleaner interface and consistent user experience.
  • \n
  • Added dedicated "+ New" task creation button to filter bar with neutral styling and proper view context awareness.
  • \n
\n

Statistics view#

\n
    \n
  • Implement a new view to track statistics about projects and time tracking.
  • \n
\n

UX#

\n

Task Interaction Improvements#

\n
    \n
  • Changed "This Week" grouping label to "Next seven days" for clearer, more specific language about the 7-day time period while maintaining identical underlying functionality. Fixes issue #516 reported by @anareaty
  • \n
\n

External Contributions#

\n
    \n
  • Type-aware input fields in task modals now provide appropriate UI components based on field type (text/list with autosuggest, date with picker icon, boolean with toggle). Project autosuggest during task creation now supports multi-word project names without interrupting suggestions on spaces. Contributed by @renatomen
  • \n
  • Fixed subtask right-click context menus that were incorrectly showing parent task options instead of subtask-specific options. Enhanced inline task overlay cursor behavior with configurable timing settings (0-500ms) for predictable overlay hiding when cursor approaches link boundaries. Contributed by @renatomen
  • \n
  • Fixed project names containing commas (e.g., [[Money, Org & Adm]]) being incorrectly split, breaking selection and display across task modals, settings, and instant conversion. Now uses proper wikilink parsing to preserve comma-containing project names as single entities. Contributed by @renatomen
  • \n
  • Fixed date parsing errors caused by hardcoded field mapping not respecting user's custom field configurations. Plugin now properly uses field mapper for note date extraction with fallback to hardcoded fields for backward compatibility. Contributed by @renatomen
  • \n
  • Fixed User Fields column order in settings to match Field mapping configuration for consistency. Contributed by @renatomen
  • \n
\n

Bug Fixes#

\n

Timezone and Date Handling#

\n
    \n
  • Fixed timezone-dependent "Today" identification issues across multiple views including MiniCalendarView tooltips, PomodoroService session categorization, PomodoroStatsView statistics, and StatsView date calculations. All date-sensitive components now use UTC-anchored dates for timezone-independent behavior. Fixes issue #452 reported by @MinchinWeb
  • \n
\n

User Interface Fixes#

\n
    \n
  • Redesigned group counters with clean appearance (removed background, border, padding), positioned to far right of headers using muted text color for subtle display while maintaining left-aligned headings.
  • \n
  • Improved contrast for INTERRUPTED status badge in pomodoro statistics for better readability. Fixes issue #529 reported by @motusira
  • \n
  • Removed title length limits that were causing text truncation, allowing full title display. Fixes issue #378 reported by @nsstrickland
  • \n
  • Added all-day slot toggle to calendar view for better event organization. Fixes issue #242 requested by @Crunchnuggetz
  • \n
  • Added calendar locale configuration for international calendar support with proper localization. Contributed by @pixeler
  • \n
  • Fixed task states not refreshing when date changes at midnight, ensuring accurate daily task status updates. Fixes issue #527 reported by @jordandrako
  • \n
  • Fixed inline task overlay title wrapping using white-space: break-spaces for proper text display. Fixes issue #517 reported by @cathywu
  • \n
\n

New Capabilities#

\n
    \n
  • Added weekday display and increment options to date picker with integration into task context menus for improved date selection experience. Fixes issue #238 requested by @girisumit
  • \n
  • Added tags to available sorting and grouping options for more flexible task organization. Fixes issue #169 requested by @bce283c
  • \n
  • Added create inline task command for quick task creation within notes with NLP project support for automatic project assignment based on context. Fixes issue #299 requested by @0dfa1bc
  • \n
  • Added filename template variables to folder templates including support for additional customization options. Fixes issue #473 requested by @oliverlalan
  • \n
  • Implemented status auto-suggestion with NLP integration for intelligent status recommendations during task creation and editing.
  • \n
\n

Infrastructure Improvements#

\n

Development and Testing#

\n
    \n
  • Updated multiple npm dependencies including ical.js (1.5.0 → 2.2.1) and Jest (29.7.0 → 30.1.1) with compatibility fixes. Resolved all npm security vulnerabilities and updated ICS subscription service for ical.js v2.x compatibility.
  • \n
  • Fixed all test suite failures and infrastructure issues including Jest 30 compatibility, RRule mocking, TypeScript configuration, and CI environment setup. Removed coverage thresholds that were causing CI failures while maintaining test quality.
  • \n
  • Improved code quality throughout modular properties system with proper TypeScript compliance, error handling, performance optimizations, and memory cleanup functions. Replaced 'any' types with proper type guards and added comprehensive interface definitions.
  • \n
\n

Contributors#

\n

Special recognition goes to @renatomen for multiple substantial contributions including type-aware custom field inputs, enhanced task interaction fixes, project name handling improvements, date parsing fixes, and settings alignment.

\n

Thanks to the following community members for their bug reports and feature requests:

\n
    \n
  • @anareaty - Reported grouping label confusion with clear examples
  • \n
  • @MinchinWeb - Identified timezone handling inconsistencies across multiple views
  • \n
  • @motusira - Reported contrast issues with INTERRUPTED status badge
  • \n
  • @nsstrickland - Identified title truncation problems
  • \n
  • @Crunchnuggetz - Requested all-day slot toggle for calendar views
  • \n
  • @jordandrako - Reported task state refresh issues at midnight
  • \n
  • @cathywu - Identified text wrapping problems in overlays
  • \n
  • @girisumit - Requested enhanced date picker functionality
  • \n
  • @oliverlalan - Requested template variable enhancements
  • \n
\n","text":"Major Features# Modular Properties System# Added modular properties system allowing users to control visibility of task properties (due date, scheduled date, priority, projects, contexts, tags, custom fields, and total tracked time) both globally and per saved view. Properties can be configured through a new Properties dropdown in the filter bar, with settings automatically saved per view. Includes performance optimizations to render properties only when visible. Thanks to @renatomen for the initial implementation of this feature Task cards now dynamically render properties based on visibility settings with improved error handling and type safety. System supports both core properties and user-defined custom fields with proper fallback to default configurations for new users. Added total tracked time as a configurable property in the modular system, calculated from time entries and displayed consistently across all views when enabled. Bases-style Filter Bar Redesign# Complete filter bar redesign matching Obsidian's bases plugin styling with improved layout, spacing, and button appearance. Added text labels and chevron icons to all filter buttons (Sort, Filters, Properties, New) for better discoverability. Replaced dropdown menus with native Obsidian context menus featuring section headers and improved reliability. Sort/Group functionality now uses unified context menu system with better organization. Implemented intelligent filter popup positioning using boundary detection to prevent popups from hiding under adjacent panes. Increased default popup width from 300px to 500px for better usability. Moved expand/collapse controls from separate containers directly into filter headings across all views (TaskListView, AgendaView, subtask widget) for cleaner interface and consistent user experience. Added dedicated \"+ New\" task creation button to filter bar with neutral styling and proper view context awareness. Statistics view# Implement a new view to track statistics about projects and time tracking. UX# Task Interaction Improvements# Changed \"This Week\" grouping label to \"Next seven days\" for clearer, more specific language about the 7-day time period while maintaining identical underlying functionality. Fixes issue #516 reported by @anareaty External Contributions# Type-aware input fields in task modals now provide appropriate UI components based on field type (text/list with autosuggest, date with picker icon, boolean with toggle). Project autosuggest during task creation now supports multi-word project names without interrupting suggestions on spaces. Contributed by @renatomen Fixed subtask right-click context menus that were incorrectly showing parent task options instead of subtask-specific options. Enhanced inline task overlay cursor behavior with configurable timing settings (0-500ms) for predictable overlay hiding when cursor approaches link boundaries. Contributed by @renatomen Fixed project names containing commas (e.g., [[Money, Org & Adm]]) being incorrectly split, breaking selection and display across task modals, settings, and instant conversion. Now uses proper wikilink parsing to preserve comma-containing project names as single entities. Contributed by @renatomen Fixed date parsing errors caused by hardcoded field mapping not respecting user's custom field configurations. Plugin now properly uses field mapper for note date extraction with fallback to hardcoded fields for backward compatibility. Contributed by @renatomen Fixed User Fields column order in settings to match Field mapping configuration for consistency. Contributed by @renatomen Bug Fixes# Timezone and Date Handling# Fixed timezone-dependent \"Today\" identification issues across multiple views including MiniCalendarView tooltips, PomodoroService session categorization, PomodoroStatsView statistics, and StatsView date calculations. All date-sensitive components now use UTC-anchored dates for timezone-independent behavior. Fixes issue #452 reported by @MinchinWeb User Interface Fixes# Redesigned group counters with clean appearance (removed background, border, padding), positioned to far right of headers using muted text color for subtle display while maintaining left-aligned headings. Improved contrast for INTERRUPTED status badge in pomodoro statistics for better readability. Fixes issue #529 reported by @motusira Removed title length limits that were causing text truncation, allowing full title display. Fixes issue #378 reported by @nsstrickland Added all-day slot toggle to calendar view for better event organization. Fixes issue #242 requested by @Crunchnuggetz Added calendar locale configuration for international calendar support with proper localization. Contributed by @pixeler Fixed task states not refreshing when date changes at midnight, ensuring accurate daily task status updates. Fixes issue #527 reported by @jordandrako Fixed inline task overlay title wrapping using white-space: break-spaces for proper text display. Fixes issue #517 reported by @cathywu New Capabilities# Added weekday display and increment options to date picker with integration into task context menus for improved date selection experience. Fixes issue #238 requested by @girisumit Added tags to available sorting and grouping options for more flexible task organization. Fixes issue #169 requested by @bce283c Added create inline task command for quick task creation within notes with NLP project support for automatic project assignment based on context. Fixes issue #299 requested by @0dfa1bc Added filename template variables to folder templates including support for additional customization options. Fixes issue #473 requested by @oliverlalan Implemented status auto-suggestion with NLP integration for intelligent status recommendations during task creation and editing. Infrastructure Improvements# Development and Testing# Updated multiple npm dependencies including ical.js (1.5.0 → 2.2.1) and Jest (29.7.0 → 30.1.1) with compatibility fixes. Resolved all npm security vulnerabilities and updated ICS subscription service for ical.js v2.x compatibility. Fixed all test suite failures and infrastructure issues including Jest 30 compatibility, RRule mocking, TypeScript configuration, and CI environment setup. Removed coverage thresholds that were causing CI failures while maintaining test quality. Improved code quality throughout modular properties system with proper TypeScript compliance, error handling, performance optimizations, and memory cleanup functions. Replaced 'any' types with proper type guards and added comprehensive interface definitions. Contributors# Special recognition goes to @renatomen for multiple substantial contributions including type-aware custom field inputs, enhanced task interaction fixes, project name handling improvements, date parsing fixes, and settings alignment. Thanks to the following community members for their bug reports and feature requests: @anareaty - Reported grouping label confusion with clear examples @MinchinWeb - Identified timezone handling inconsistencies across multiple views @motusira - Reported contrast issues with INTERRUPTED status badge @nsstrickland - Identified title truncation problems @Crunchnuggetz - Requested all-day slot toggle for calendar views @jordandrako - Reported task state refresh issues at midnight @cathywu - Identified text wrapping problems in overlays @girisumit - Requested enhanced date picker functionality @oliverlalan - Requested template variable enhancements"},{"route":"/obsidian/releases/3.22.1/","title":"TaskNotes 3.22.1","description":"Thanks to @jhedlund for implementing the configurable recurring task due date feature.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.22.1.md","namespace":"obsidian","relativePath":"releases/3.22.1.md","raw":"# TaskNotes 3.22.1\n\n## New Features\n\n### Configurable Recurring Task Due Date Behavior\n\n- Added optional due date advancement for recurring tasks. When enabled, maintains the time separation between scheduled and due dates when tasks are completed. The new \"Maintain due date offset in recurring tasks\" setting in Misc preferences controls this behavior and defaults to disabled to preserve existing behavior. *Contributed by @jhedlund, fixes issue #470*\n\n## Bug Fixes\n\n### Calendar and Task Display\n\n- Fixed calendar view issues where tasks were not displaying correctly due to empty status values causing infinite loops and TypeErrors. Resolved `timeEntries.filter is not a function` errors when loading calendar events and prevented Obsidian freezing during task creation with empty status text. *Fixes issue #520 reported by @cathywu*\n\n### Saved Views and Property Management\n\n- Fixed property visibility settings not being preserved when saving filter views. View configurations now properly store and restore property display preferences. *Fixes issue #545 reported by @anareaty*\n- Fixed saved view selection to prefer newly created views over older matching views, ensuring the correct view is activated after saving.\n- Added proper null safety checks for FilterBar interactions to prevent errors during view save operations.\n\n### User Interface Improvements\n\n- Added responsive behavior to filter bar buttons that automatically hide button text when pane width falls below 500px to prevent overflow in narrow sidebars. Uses container queries with media query fallback for broader browser support. *Fixes issue #549 reported by @TonyAtlas*\n\n## Development Improvements\n\n- Reduced excessive console logging in TaskListView by removing 37+ debug statements while preserving essential error logging for troubleshooting.\n\n## Contributors\n\nThanks to **@jhedlund** for implementing the configurable recurring task due date feature.\n\nThanks to the following community members for their bug reports:\n\n- **@cathywu** - Reported calendar view task display issues with detailed technical information\n- **@anareaty** - Identified property visibility persistence problems in saved views \n- **@TonyAtlas** - Reported filter bar overflow issues in narrow sidebars with helpful screenshots","aliases":["/releases/3.22.1/","/releases/3.22.1/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"configurable-recurring-task-due-date-behavior","text":"Configurable Recurring Task Due Date Behavior"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"calendar-and-task-display","text":"Calendar and Task Display"},{"level":3,"id":"saved-views-and-property-management","text":"Saved Views and Property Management"},{"level":3,"id":"user-interface-improvements","text":"User Interface Improvements"},{"level":2,"id":"development-improvements","text":"Development Improvements"},{"level":2,"id":"contributors","text":"Contributors"}],"html":"

New Features#

\n

Configurable Recurring Task Due Date Behavior#

\n
    \n
  • Added optional due date advancement for recurring tasks. When enabled, maintains the time separation between scheduled and due dates when tasks are completed. The new "Maintain due date offset in recurring tasks" setting in Misc preferences controls this behavior and defaults to disabled to preserve existing behavior. Contributed by @jhedlund, fixes issue #470
  • \n
\n

Bug Fixes#

\n

Calendar and Task Display#

\n
    \n
  • Fixed calendar view issues where tasks were not displaying correctly due to empty status values causing infinite loops and TypeErrors. Resolved timeEntries.filter is not a function errors when loading calendar events and prevented Obsidian freezing during task creation with empty status text. Fixes issue #520 reported by @cathywu
  • \n
\n

Saved Views and Property Management#

\n
    \n
  • Fixed property visibility settings not being preserved when saving filter views. View configurations now properly store and restore property display preferences. Fixes issue #545 reported by @anareaty
  • \n
  • Fixed saved view selection to prefer newly created views over older matching views, ensuring the correct view is activated after saving.
  • \n
  • Added proper null safety checks for FilterBar interactions to prevent errors during view save operations.
  • \n
\n

User Interface Improvements#

\n
    \n
  • Added responsive behavior to filter bar buttons that automatically hide button text when pane width falls below 500px to prevent overflow in narrow sidebars. Uses container queries with media query fallback for broader browser support. Fixes issue #549 reported by @TonyAtlas
  • \n
\n

Development Improvements#

\n
    \n
  • Reduced excessive console logging in TaskListView by removing 37+ debug statements while preserving essential error logging for troubleshooting.
  • \n
\n

Contributors#

\n

Thanks to @jhedlund for implementing the configurable recurring task due date feature.

\n

Thanks to the following community members for their bug reports:

\n
    \n
  • @cathywu - Reported calendar view task display issues with detailed technical information
  • \n
  • @anareaty - Identified property visibility persistence problems in saved views
  • \n
  • @TonyAtlas - Reported filter bar overflow issues in narrow sidebars with helpful screenshots
  • \n
\n","text":"New Features# Configurable Recurring Task Due Date Behavior# Added optional due date advancement for recurring tasks. When enabled, maintains the time separation between scheduled and due dates when tasks are completed. The new \"Maintain due date offset in recurring tasks\" setting in Misc preferences controls this behavior and defaults to disabled to preserve existing behavior. Contributed by @jhedlund, fixes issue #470 Bug Fixes# Calendar and Task Display# Fixed calendar view issues where tasks were not displaying correctly due to empty status values causing infinite loops and TypeErrors. Resolved timeEntries.filter is not a function errors when loading calendar events and prevented Obsidian freezing during task creation with empty status text. Fixes issue #520 reported by @cathywu Saved Views and Property Management# Fixed property visibility settings not being preserved when saving filter views. View configurations now properly store and restore property display preferences. Fixes issue #545 reported by @anareaty Fixed saved view selection to prefer newly created views over older matching views, ensuring the correct view is activated after saving. Added proper null safety checks for FilterBar interactions to prevent errors during view save operations. User Interface Improvements# Added responsive behavior to filter bar buttons that automatically hide button text when pane width falls below 500px to prevent overflow in narrow sidebars. Uses container queries with media query fallback for broader browser support. Fixes issue #549 reported by @TonyAtlas Development Improvements# Reduced excessive console logging in TaskListView by removing 37+ debug statements while preserving essential error logging for troubleshooting. Contributors# Thanks to @jhedlund for implementing the configurable recurring task due date feature. Thanks to the following community members for their bug reports: @cathywu - Reported calendar view task display issues with detailed technical information @anareaty - Identified property visibility persistence problems in saved views @TonyAtlas - Reported filter bar overflow issues in narrow sidebars with helpful screenshots"},{"route":"/obsidian/releases/3.23.0/","title":"TaskNotes 3.23.0","description":"We extend special thanks to @renatomen for his exceptional contributions to this release:","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.23.0.md","namespace":"obsidian","relativePath":"releases/3.23.0.md","raw":"# TaskNotes 3.23.0\n\n## New Features\n\n### ICS Export and Calendar Integration\n\n- Added full ICS export functionality with proper RFC 5545 compliance for improved calendar application compatibility\n- Implemented automatic ICS export with configurable interval updates (5-1440 minutes) for calendar subscription workflows\n- Added manual \"Export all tasks as ICS file\" command for bulk export operations\n- *Thanks to @mdbraber for requesting this feature (#422)*\n\n### Status-Based Auto-Archive\n\n- Introduced configurable auto-archive system with per-status timeout settings (1-1440 minutes)\n- Added persistent queue that survives plugin restarts for reliable task archiving\n- Implemented settings UI for fine-grained control over auto-archive behavior\n- *Thanks to @TonyAtlas for requesting this feature (#547) and to @renatomen for design suggestions*\n\n### Multi-Language Natural Language Processing\n\n- Added NLP support for 12 languages: English, Spanish, French, German, Russian, Chinese, Japanese, Italian, Dutch, Portuguese, Swedish, Ukrainian\n- Implemented locale-specific date parsing using chrono-node language support\n- Enhanced pattern matching with proper handling for Latin, Cyrillic, Chinese, and Japanese scripts\n- *Thanks to @pschoenbach for requesting German language support (#563)*\n\n### Enhanced Project Autosuggest\n\n- Implemented configurable multi-row project cards with customizable display fields\n- Added selective search functionality across chosen fields with simple flag system\n- Introduced fuzzy search option for broader, multi-word matching capabilities\n- Enhanced project selection with clear metadata display (title, aliases, path)\n- *Thanks to @renatomen for implementing this feature (#555)*\n\n### Bases Plugin Integration\n\n- Added experimental integration with the Bases plugin for enhanced task management workflows\n- Implemented direct formula computation and custom property support\n- Added clickable tags and contexts with accessibility support\n- Created simplified kanban view integration with proper lifecycle management\n- *Thanks to @renatomen for his incredible work developing the proof-of-concept for this feature*\n\n### Settings UI Modernization\n\n- Complete redesign of settings interface with card-based design system\n- Added collapsible functionality and live API documentation\n- Enhanced calendar subscription interface with local file support\n\n## Bug Fixes\n\n### Task Creation and File Handling\n\n- Fixed startup crash when templates contain empty reminders property (*reported by @glpayson, #583*)\n- Implemented automatic sanitization of forbidden characters in task titles instead of blocking creation (*reported by @glpayson, #590*)\n- Added support for platform-specific filename characters (hash, square brackets)\n- Resolved inconsistent behavior between instant convert and manual task creation\n\n### Project and Link Functionality \n\n- Added clickable project links in task edit modal for better navigation (*requested by @anareaty, #432*)\n- Fixed completion date timezone handling to ensure consistent local time recording\n- Corrected frontmatter property naming in Bases kanban drag-and-drop operations\n\n### Property Display and Performance\n\n- Fixed custom property duplication when configured in both settings and filter bar\n- Resolved unwanted total tracked time display showing zero values\n- Standardized custom property identifiers with consistent prefix format\n\n### Plugin Integration and Stability\n\n- Resolved Bases plugin integration issues and view switching problems\n- Fixed kanban view loading with proper static imports and interface consistency\n- Improved error handling and cleanup patterns for better stability\n- Fixed API endpoints to respect custom status configurations (*reported by @23maverick23, #487*)\n\n## Acknowledgments\n\n### Special Recognition\n\nWe extend special thanks to **@renatomen** for his exceptional contributions to this release:\n\n- Created the enhanced project autosuggest system with configurable cards and selective search functionality (PR #555)\n- Developed a proof-of-concept integration with the Bases plugin that demonstrated full compatibility and provided the technical foundation for our experimental Bases integration\n- His innovative work on the Bases POC revealed that everything that I was hoping might be possible in a future integration with Bases was actually possible!\n\n### Community Contributors\n\nWe're grateful to the community members whose issues were resolved in this release:\n\n- **@glpayson** for providing detailed bug reports with reproduction steps that led to fixes for the startup crash with empty reminders (#583) and character handling improvements (#590)\n- **@mdbraber** for requesting ICS export functionality that became a major feature in this release (#422)\n- **@TonyAtlas** for the auto-archive feature request that resulted in the new status-based auto-archive system (#547)\n- **@anareaty** for requesting clickable project links (#432) and reporting the \"This Week\" grouping label issue (#516)\n- **@pschoenbach** for requesting multi-language NLP support, specifically German language support (#563)\n- **@23maverick23** for reporting API status configuration issues that improved custom status handling (#487)\n- **@Burrish** for the documentation correction (#597)\n\n---\n\n**Full Changelog**: [3.22.1...3.23.0](https://github.com/callumalpass/tasknotes/compare/3.22.1...3.23.0)\n\n","aliases":["/releases/3.23.0/","/releases/3.23.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"ics-export-and-calendar-integration","text":"ICS Export and Calendar Integration"},{"level":3,"id":"status-based-auto-archive","text":"Status-Based Auto-Archive"},{"level":3,"id":"multi-language-natural-language-processing","text":"Multi-Language Natural Language Processing"},{"level":3,"id":"enhanced-project-autosuggest","text":"Enhanced Project Autosuggest"},{"level":3,"id":"bases-plugin-integration","text":"Bases Plugin Integration"},{"level":3,"id":"settings-ui-modernization","text":"Settings UI Modernization"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"task-creation-and-file-handling","text":"Task Creation and File Handling"},{"level":3,"id":"project-and-link-functionality","text":"Project and Link Functionality"},{"level":3,"id":"property-display-and-performance","text":"Property Display and Performance"},{"level":3,"id":"plugin-integration-and-stability","text":"Plugin Integration and Stability"},{"level":2,"id":"acknowledgments","text":"Acknowledgments"},{"level":3,"id":"special-recognition","text":"Special Recognition"},{"level":3,"id":"community-contributors","text":"Community Contributors"}],"html":"

New Features#

\n

ICS Export and Calendar Integration#

\n
    \n
  • Added full ICS export functionality with proper RFC 5545 compliance for improved calendar application compatibility
  • \n
  • Implemented automatic ICS export with configurable interval updates (5-1440 minutes) for calendar subscription workflows
  • \n
  • Added manual "Export all tasks as ICS file" command for bulk export operations
  • \n
  • Thanks to @mdbraber for requesting this feature (#422)
  • \n
\n

Status-Based Auto-Archive#

\n
    \n
  • Introduced configurable auto-archive system with per-status timeout settings (1-1440 minutes)
  • \n
  • Added persistent queue that survives plugin restarts for reliable task archiving
  • \n
  • Implemented settings UI for fine-grained control over auto-archive behavior
  • \n
  • Thanks to @TonyAtlas for requesting this feature (#547) and to @renatomen for design suggestions
  • \n
\n

Multi-Language Natural Language Processing#

\n
    \n
  • Added NLP support for 12 languages: English, Spanish, French, German, Russian, Chinese, Japanese, Italian, Dutch, Portuguese, Swedish, Ukrainian
  • \n
  • Implemented locale-specific date parsing using chrono-node language support
  • \n
  • Enhanced pattern matching with proper handling for Latin, Cyrillic, Chinese, and Japanese scripts
  • \n
  • Thanks to @pschoenbach for requesting German language support (#563)
  • \n
\n

Enhanced Project Autosuggest#

\n
    \n
  • Implemented configurable multi-row project cards with customizable display fields
  • \n
  • Added selective search functionality across chosen fields with simple flag system
  • \n
  • Introduced fuzzy search option for broader, multi-word matching capabilities
  • \n
  • Enhanced project selection with clear metadata display (title, aliases, path)
  • \n
  • Thanks to @renatomen for implementing this feature (#555)
  • \n
\n

Bases Plugin Integration#

\n
    \n
  • Added experimental integration with the Bases plugin for enhanced task management workflows
  • \n
  • Implemented direct formula computation and custom property support
  • \n
  • Added clickable tags and contexts with accessibility support
  • \n
  • Created simplified kanban view integration with proper lifecycle management
  • \n
  • Thanks to @renatomen for his incredible work developing the proof-of-concept for this feature
  • \n
\n

Settings UI Modernization#

\n
    \n
  • Complete redesign of settings interface with card-based design system
  • \n
  • Added collapsible functionality and live API documentation
  • \n
  • Enhanced calendar subscription interface with local file support
  • \n
\n

Bug Fixes#

\n

Task Creation and File Handling#

\n
    \n
  • Fixed startup crash when templates contain empty reminders property (reported by @glpayson, #583)
  • \n
  • Implemented automatic sanitization of forbidden characters in task titles instead of blocking creation (reported by @glpayson, #590)
  • \n
  • Added support for platform-specific filename characters (hash, square brackets)
  • \n
  • Resolved inconsistent behavior between instant convert and manual task creation
  • \n
\n\n
    \n
  • Added clickable project links in task edit modal for better navigation (requested by @anareaty, #432)
  • \n
  • Fixed completion date timezone handling to ensure consistent local time recording
  • \n
  • Corrected frontmatter property naming in Bases kanban drag-and-drop operations
  • \n
\n

Property Display and Performance#

\n
    \n
  • Fixed custom property duplication when configured in both settings and filter bar
  • \n
  • Resolved unwanted total tracked time display showing zero values
  • \n
  • Standardized custom property identifiers with consistent prefix format
  • \n
\n

Plugin Integration and Stability#

\n
    \n
  • Resolved Bases plugin integration issues and view switching problems
  • \n
  • Fixed kanban view loading with proper static imports and interface consistency
  • \n
  • Improved error handling and cleanup patterns for better stability
  • \n
  • Fixed API endpoints to respect custom status configurations (reported by @23maverick23, #487)
  • \n
\n

Acknowledgments#

\n

Special Recognition#

\n

We extend special thanks to @renatomen for his exceptional contributions to this release:

\n
    \n
  • Created the enhanced project autosuggest system with configurable cards and selective search functionality (PR #555)
  • \n
  • Developed a proof-of-concept integration with the Bases plugin that demonstrated full compatibility and provided the technical foundation for our experimental Bases integration
  • \n
  • His innovative work on the Bases POC revealed that everything that I was hoping might be possible in a future integration with Bases was actually possible!
  • \n
\n

Community Contributors#

\n

We're grateful to the community members whose issues were resolved in this release:

\n
    \n
  • @glpayson for providing detailed bug reports with reproduction steps that led to fixes for the startup crash with empty reminders (#583) and character handling improvements (#590)
  • \n
  • @mdbraber for requesting ICS export functionality that became a major feature in this release (#422)
  • \n
  • @TonyAtlas for the auto-archive feature request that resulted in the new status-based auto-archive system (#547)
  • \n
  • @anareaty for requesting clickable project links (#432) and reporting the "This Week" grouping label issue (#516)
  • \n
  • @pschoenbach for requesting multi-language NLP support, specifically German language support (#563)
  • \n
  • @23maverick23 for reporting API status configuration issues that improved custom status handling (#487)
  • \n
  • @Burrish for the documentation correction (#597)
  • \n
\n
\n

Full Changelog: 3.22.1...3.23.0

\n","text":"New Features# ICS Export and Calendar Integration# Added full ICS export functionality with proper RFC 5545 compliance for improved calendar application compatibility Implemented automatic ICS export with configurable interval updates (5-1440 minutes) for calendar subscription workflows Added manual \"Export all tasks as ICS file\" command for bulk export operations Thanks to @mdbraber for requesting this feature (#422) Status-Based Auto-Archive# Introduced configurable auto-archive system with per-status timeout settings (1-1440 minutes) Added persistent queue that survives plugin restarts for reliable task archiving Implemented settings UI for fine-grained control over auto-archive behavior Thanks to @TonyAtlas for requesting this feature (#547) and to @renatomen for design suggestions Multi-Language Natural Language Processing# Added NLP support for 12 languages: English, Spanish, French, German, Russian, Chinese, Japanese, Italian, Dutch, Portuguese, Swedish, Ukrainian Implemented locale-specific date parsing using chrono-node language support Enhanced pattern matching with proper handling for Latin, Cyrillic, Chinese, and Japanese scripts Thanks to @pschoenbach for requesting German language support (#563) Enhanced Project Autosuggest# Implemented configurable multi-row project cards with customizable display fields Added selective search functionality across chosen fields with simple flag system Introduced fuzzy search option for broader, multi-word matching capabilities Enhanced project selection with clear metadata display (title, aliases, path) Thanks to @renatomen for implementing this feature (#555) Bases Plugin Integration# Added experimental integration with the Bases plugin for enhanced task management workflows Implemented direct formula computation and custom property support Added clickable tags and contexts with accessibility support Created simplified kanban view integration with proper lifecycle management Thanks to @renatomen for his incredible work developing the proof-of-concept for this feature Settings UI Modernization# Complete redesign of settings interface with card-based design system Added collapsible functionality and live API documentation Enhanced calendar subscription interface with local file support Bug Fixes# Task Creation and File Handling# Fixed startup crash when templates contain empty reminders property (reported by @glpayson, #583) Implemented automatic sanitization of forbidden characters in task titles instead of blocking creation (reported by @glpayson, #590) Added support for platform-specific filename characters (hash, square brackets) Resolved inconsistent behavior between instant convert and manual task creation Project and Link Functionality# Added clickable project links in task edit modal for better navigation (requested by @anareaty, #432) Fixed completion date timezone handling to ensure consistent local time recording Corrected frontmatter property naming in Bases kanban drag-and-drop operations Property Display and Performance# Fixed custom property duplication when configured in both settings and filter bar Resolved unwanted total tracked time display showing zero values Standardized custom property identifiers with consistent prefix format Plugin Integration and Stability# Resolved Bases plugin integration issues and view switching problems Fixed kanban view loading with proper static imports and interface consistency Improved error handling and cleanup patterns for better stability Fixed API endpoints to respect custom status configurations (reported by @23maverick23, #487) Acknowledgments# Special Recognition# We extend special thanks to @renatomen for his exceptional contributions to this release: Created the enhanced project autosuggest system with configurable cards and selective search functionality (PR #555) Developed a proof-of-concept integration with the Bases plugin that demonstrated full compatibility and provided the technical foundation for our experimental Bases integration His innovative work on the Bases POC revealed that everything that I was hoping might be possible in a future integration with Bases was actually possible! Community Contributors# We're grateful to the community members whose issues were resolved in this release: @glpayson for providing detailed bug reports with reproduction steps that led to fixes for the startup crash with empty reminders (#583) and character handling improvements (#590) @mdbraber for requesting ICS export functionality that became a major feature in this release (#422) @TonyAtlas for the auto-archive feature request that resulted in the new status-based auto-archive system (#547) @anareaty for requesting clickable project links (#432) and reporting the \"This Week\" grouping label issue (#516) @pschoenbach for requesting multi-language NLP support, specifically German language support (#563) @23maverick23 for reporting API status configuration issues that improved custom status handling (#487) @Burrish for the documentation correction (#597) Full Changelog: 3.22.1...3.23.0"},{"route":"/obsidian/releases/3.23.1/","title":"TaskNotes 3.23.1","description":"Full Changelog: 3.23.0...3.23.1","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.23.1.md","namespace":"obsidian","relativePath":"releases/3.23.1.md","raw":"# TaskNotes 3.23.1\n\n## Bug Fixes\n\n### Bases Plugin Integration\n\n- Fixed Bases views not recognizing custom field mappings when using non-default property names. Status dots, priority colors, and dates now display correctly in Bases views when using custom field names, including Cyrillic and other localized property names. *Thanks to @anareaty for reporting this issue (#607)*\n\n---\n\n**Full Changelog**: [3.23.0...3.23.1](https://github.com/callumalpass/tasknotes/compare/3.23.0...3.23.1)","aliases":["/releases/3.23.1/","/releases/3.23.1/"],"toc":[{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"bases-plugin-integration","text":"Bases Plugin Integration"}],"html":"

Bug Fixes#

\n

Bases Plugin Integration#

\n
    \n
  • Fixed Bases views not recognizing custom field mappings when using non-default property names. Status dots, priority colors, and dates now display correctly in Bases views when using custom field names, including Cyrillic and other localized property names. Thanks to @anareaty for reporting this issue (#607)
  • \n
\n
\n

Full Changelog: 3.23.0...3.23.1

\n","text":"Bug Fixes# Bases Plugin Integration# Fixed Bases views not recognizing custom field mappings when using non-default property names. Status dots, priority colors, and dates now display correctly in Bases views when using custom field names, including Cyrillic and other localized property names. Thanks to @anareaty for reporting this issue (#607) Full Changelog: 3.23.0...3.23.1"},{"route":"/obsidian/releases/3.23.2/","title":"TaskNotes v3.23.2 Release Notes","description":"This release focusses on performance improvements. These improvements should be especially noticeable in vaults with a large number of tasks.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.23.2.md","namespace":"obsidian","relativePath":"releases/3.23.2.md","raw":"# TaskNotes v3.23.2 Release Notes\n\nThis release focusses on performance improvements. These improvements should be especially noticeable in vaults with a large number of tasks. \n\n## New Features\n\n- Added agenda/list view to Advanced Calendar \n- New `{{contexts}}` template variable for joining multiple context values\n- New `{{projects}}` template variable for joining multiple project values *Thanks to @Mara-Li for these additions*\n\n### Time Format Consistency\n\n- Plugin-wide 12hr/24hr time format preference support\n- Consistent time display across all calendar views and components\n- *Thanks to @anareaty and @Astrusia for this suggestion #431*\n\n### Performance Architecture\n\n- Centralized ViewPerformanceService for all TaskNotes views\n- Global task version cache with change detection\n- Debounced updates with configurable batching\n- View-specific update handlers with selective refresh logic\n- Memory management and automatic cache cleanup\n\n## Bug Fixes\n\n- Fixed cursor positioning issues when creating subtask widgets *Thanks to @jhedlund for this fix!*\n\n## Contributors\n\nSpecial thanks to contributors:\n- @jhedlund for fixing cursor positioning with subtasks\n- @Mara-Li for implementing context/project template variables and bracket fixes\n- @anareaty for reporting time format inconsistencies\n","aliases":["/releases/3.23.2/","/releases/3.23.2/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"time-format-consistency","text":"Time Format Consistency"},{"level":3,"id":"performance-architecture","text":"Performance Architecture"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":2,"id":"contributors","text":"Contributors"}],"html":"

This release focusses on performance improvements. These improvements should be especially noticeable in vaults with a large number of tasks.

\n

New Features#

\n
    \n
  • Added agenda/list view to Advanced Calendar
  • \n
  • New {{contexts}} template variable for joining multiple context values
  • \n
  • New {{projects}} template variable for joining multiple project values Thanks to @Mara-Li for these additions
  • \n
\n

Time Format Consistency#

\n
    \n
  • Plugin-wide 12hr/24hr time format preference support
  • \n
  • Consistent time display across all calendar views and components
  • \n
  • Thanks to @anareaty and @Astrusia for this suggestion #431
  • \n
\n

Performance Architecture#

\n
    \n
  • Centralized ViewPerformanceService for all TaskNotes views
  • \n
  • Global task version cache with change detection
  • \n
  • Debounced updates with configurable batching
  • \n
  • View-specific update handlers with selective refresh logic
  • \n
  • Memory management and automatic cache cleanup
  • \n
\n

Bug Fixes#

\n
    \n
  • Fixed cursor positioning issues when creating subtask widgets Thanks to @jhedlund for this fix!
  • \n
\n

Contributors#

\n

Special thanks to contributors:

\n
    \n
  • @jhedlund for fixing cursor positioning with subtasks
  • \n
  • @Mara-Li for implementing context/project template variables and bracket fixes
  • \n
  • @anareaty for reporting time format inconsistencies
  • \n
\n","text":"This release focusses on performance improvements. These improvements should be especially noticeable in vaults with a large number of tasks. New Features# Added agenda/list view to Advanced Calendar New {{contexts}} template variable for joining multiple context values New {{projects}} template variable for joining multiple project values Thanks to @Mara-Li for these additions Time Format Consistency# Plugin-wide 12hr/24hr time format preference support Consistent time display across all calendar views and components Thanks to @anareaty and @Astrusia for this suggestion #431 Performance Architecture# Centralized ViewPerformanceService for all TaskNotes views Global task version cache with change detection Debounced updates with configurable batching View-specific update handlers with selective refresh logic Memory management and automatic cache cleanup Bug Fixes# Fixed cursor positioning issues when creating subtask widgets Thanks to @jhedlund for this fix! Contributors# Special thanks to contributors: @jhedlund for fixing cursor positioning with subtasks @Mara-Li for implementing context/project template variables and bracket fixes @anareaty for reporting time format inconsistencies"},{"route":"/obsidian/releases/3.23.3/","title":"TaskNotes v3.23.3 Release Notes","description":"This release addresses critical bugs with project and subtask functionality, ensuring proper field mapping support and expanding project filtering capabilities.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.23.3.md","namespace":"obsidian","relativePath":"releases/3.23.3.md","raw":"# TaskNotes v3.23.3 Release Notes\n\nThis release addresses critical bugs with project and subtask functionality, ensuring proper field mapping support and expanding project filtering capabilities.\n\n## New Features\n\n### Project Property Filter Support\n\n- Added property-based filtering for project picker dropdown\n- Configure projects to appear in picker based on frontmatter properties (e.g., `type: project`)\n- Complements existing folder and tag filtering options\n- *Thanks to @aubreyz for requesting this feature enhancement (#660)*\n\n## Bug Fixes\n\n### Project/Subtask Field Mapping\n\n- Fixed project and subtask functionality not working when users customize project field names\n- ProjectSubtasksService and MinimalNativeCache now properly respect user field mapping configuration\n- Resolves issue where hardcoded 'projects' field lookup ignored custom field mappings\n- *Thanks to @JD2026 (#674), @anareaty, (#674) and @Volker-brdb (#672) and for reporting these subtask display issues*\n\n### Test Infrastructure\n\n- Added missing test mocks for `isTaskUsedAsProjectSync` and `formatDateForStorage` functions\n- Ensures test suite stability for project-related functionality\n","aliases":["/releases/3.23.3/","/releases/3.23.3/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"project-property-filter-support","text":"Project Property Filter Support"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"projectsubtask-field-mapping","text":"Project/Subtask Field Mapping"},{"level":3,"id":"test-infrastructure","text":"Test Infrastructure"}],"html":"

This release addresses critical bugs with project and subtask functionality, ensuring proper field mapping support and expanding project filtering capabilities.

\n

New Features#

\n

Project Property Filter Support#

\n
    \n
  • Added property-based filtering for project picker dropdown
  • \n
  • Configure projects to appear in picker based on frontmatter properties (e.g., type: project)
  • \n
  • Complements existing folder and tag filtering options
  • \n
  • Thanks to @aubreyz for requesting this feature enhancement (#660)
  • \n
\n

Bug Fixes#

\n

Project/Subtask Field Mapping#

\n
    \n
  • Fixed project and subtask functionality not working when users customize project field names
  • \n
  • ProjectSubtasksService and MinimalNativeCache now properly respect user field mapping configuration
  • \n
  • Resolves issue where hardcoded 'projects' field lookup ignored custom field mappings
  • \n
  • Thanks to @JD2026 (#674), @anareaty, (#674) and @Volker-brdb (#672) and for reporting these subtask display issues
  • \n
\n

Test Infrastructure#

\n
    \n
  • Added missing test mocks for isTaskUsedAsProjectSync and formatDateForStorage functions
  • \n
  • Ensures test suite stability for project-related functionality
  • \n
\n","text":"This release addresses critical bugs with project and subtask functionality, ensuring proper field mapping support and expanding project filtering capabilities. New Features# Project Property Filter Support# Added property-based filtering for project picker dropdown Configure projects to appear in picker based on frontmatter properties (e.g., type: project) Complements existing folder and tag filtering options Thanks to @aubreyz for requesting this feature enhancement (#660) Bug Fixes# Project/Subtask Field Mapping# Fixed project and subtask functionality not working when users customize project field names ProjectSubtasksService and MinimalNativeCache now properly respect user field mapping configuration Resolves issue where hardcoded 'projects' field lookup ignored custom field mappings Thanks to @JD2026 (#674), @anareaty, (#674) and @Volker-brdb (#672) and for reporting these subtask display issues Test Infrastructure# Added missing test mocks for isTaskUsedAsProjectSync and formatDateForStorage functions Ensures test suite stability for project-related functionality"},{"route":"/obsidian/releases/3.23.4/","title":"TaskNotes 3.23.4","description":"Special thanks to contributors:","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.23.4.md","namespace":"obsidian","relativePath":"releases/3.23.4.md","raw":"# TaskNotes 3.23.4\n\n## Bug Fixes\n\n### Task Scheduling & Natural Language Processing\n\n- Fixed Russian weekday scheduling conflict where single weekdays (e.g., \"воскресенье\") were incorrectly interpreted as recurring tasks instead of single-day scheduling ([#665](https://github.com/callumalpass/tasknotes/issues/665), thanks to @anareaty for the report)\n- Fixed issue where natural language processing failed to save parsed time estimates in task creation modal ([#682](https://github.com/callumalpass/tasknotes/issues/682), thanks to @RumiaKitinari for the detailed report)\n- Fixed scheduled task grouping UTC anchor regression that caused today's tasks to appear under \"Past Scheduled\" instead of \"Today\" ([#384](https://github.com/callumalpass/tasknotes/issues/384), thanks to @jcromwell for the report)\n\n### Settings & Configuration\n\n- Fixed plugin failure when excluded folders setting contains trailing commas - the parsing logic now properly filters empty strings ([#664](https://github.com/callumalpass/tasknotes/issues/664), thanks to @Yoav6 for identifying this issue)\n\n### Calendar & Time Management\n\n- Fixed calendar not refreshing when task duration or time tracking changes ([#382](https://github.com/callumalpass/tasknotes/issues/382), thanks to @mdbraber)\n- Fixed calendar not refreshing after task archive or move operations\n- Fixed timeblock editing using stored date instead of current date for past day modifications ([#647](https://github.com/callumalpass/tasknotes/issues/647), thanks to @RumiaKitinari)\n- Fixed Pomodoro timer not preserving task context when auto-starting sessions ([#641](https://github.com/callumalpass/tasknotes/issues/641), thanks to @RumiaKitinari)\n- Fixed all-day tasks not rendering properly across multiple days in calendar view (thanks to [Danny Talks Tech](https://www.youtube.com/watch?v=SRavkMUYWzo) for reporting this in his video review)\n\n### User Interface\n\n- Fixed mini calendar header overflow issue in sidebar view ([#459](https://github.com/callumalpass/tasknotes/issues/459), with CSS improvements suggested by @jsonshanks, thanks to @girisumit for the report)\n\n## New Features & Enhancements\n\n### Visual Improvements\n\n- Added file-text icon to note cards in agenda view for better visual distinction from headers and consistency with task and calendar event icons ([#662](https://github.com/callumalpass/tasknotes/issues/662), thanks to @ras0q for the suggestion)\n- Improved mini calendar styling, interactions, and legend display\n- Enhanced task dot visualization to reflect accurate matching dates\n\n### Settings Organization\n\n- Moved timeblocking settings to Features tab with improved usage instructions for better discoverability\n\n## Documentation\n\n- Updated documentation to fix auto-archiving settings reference ([#673](https://github.com/callumalpass/tasknotes/issues/673), thanks to @antonio for pointing out the inconsistency)\n\n## Contributors\n\nSpecial thanks to contributors:\n\n- @anareaty for reporting the Russian weekday scheduling conflict\n- @RumiaKitinari for detailed reports on natural language processing, timeblock editing, and Pomodoro timer issues\n- @jcromwell for reporting the scheduled task grouping UTC regression\n- @Yoav6 for identifying the excluded folders trailing comma issue\n- @mdbraber for reporting calendar refresh issues with time tracking changes\n- @girisumit for reporting the mini calendar header overflow issue\n- @jsonshanks for providing CSS improvement suggestions for the mini calendar\n- @ras0q for suggesting the file-text icon addition to agenda view\n- @antonio for pointing out the auto-archiving documentation inconsistency\n- [Danny Talks Tech](https://www.youtube.com/watch?v=SRavkMUYWzo) for reporting the all-day task rendering issue in his video review\n\n---\n\nThis release focuses primarily on bug fixes and stability improvements, particularly around calendar functionality, natural language processing, and user interface polish.","aliases":["/releases/3.23.4/","/releases/3.23.4/"],"toc":[{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"task-scheduling-natural-language-processing","text":"Task Scheduling & Natural Language Processing"},{"level":3,"id":"settings-configuration","text":"Settings & Configuration"},{"level":3,"id":"calendar-time-management","text":"Calendar & Time Management"},{"level":3,"id":"user-interface","text":"User Interface"},{"level":2,"id":"new-features-enhancements","text":"New Features & Enhancements"},{"level":3,"id":"visual-improvements","text":"Visual Improvements"},{"level":3,"id":"settings-organization","text":"Settings Organization"},{"level":2,"id":"documentation","text":"Documentation"},{"level":2,"id":"contributors","text":"Contributors"}],"html":"

Bug Fixes#

\n

Task Scheduling & Natural Language Processing#

\n
    \n
  • Fixed Russian weekday scheduling conflict where single weekdays (e.g., "воскресенье") were incorrectly interpreted as recurring tasks instead of single-day scheduling (#665, thanks to @anareaty for the report)
  • \n
  • Fixed issue where natural language processing failed to save parsed time estimates in task creation modal (#682, thanks to @RumiaKitinari for the detailed report)
  • \n
  • Fixed scheduled task grouping UTC anchor regression that caused today's tasks to appear under "Past Scheduled" instead of "Today" (#384, thanks to @jcromwell for the report)
  • \n
\n

Settings & Configuration#

\n
    \n
  • Fixed plugin failure when excluded folders setting contains trailing commas - the parsing logic now properly filters empty strings (#664, thanks to @Yoav6 for identifying this issue)
  • \n
\n

Calendar & Time Management#

\n
    \n
  • Fixed calendar not refreshing when task duration or time tracking changes (#382, thanks to @mdbraber)
  • \n
  • Fixed calendar not refreshing after task archive or move operations
  • \n
  • Fixed timeblock editing using stored date instead of current date for past day modifications (#647, thanks to @RumiaKitinari)
  • \n
  • Fixed Pomodoro timer not preserving task context when auto-starting sessions (#641, thanks to @RumiaKitinari)
  • \n
  • Fixed all-day tasks not rendering properly across multiple days in calendar view (thanks to Danny Talks Tech for reporting this in his video review)
  • \n
\n

User Interface#

\n
    \n
  • Fixed mini calendar header overflow issue in sidebar view (#459, with CSS improvements suggested by @jsonshanks, thanks to @girisumit for the report)
  • \n
\n

New Features & Enhancements#

\n

Visual Improvements#

\n
    \n
  • Added file-text icon to note cards in agenda view for better visual distinction from headers and consistency with task and calendar event icons (#662, thanks to @ras0q for the suggestion)
  • \n
  • Improved mini calendar styling, interactions, and legend display
  • \n
  • Enhanced task dot visualization to reflect accurate matching dates
  • \n
\n

Settings Organization#

\n
    \n
  • Moved timeblocking settings to Features tab with improved usage instructions for better discoverability
  • \n
\n

Documentation#

\n
    \n
  • Updated documentation to fix auto-archiving settings reference (#673, thanks to @antonio for pointing out the inconsistency)
  • \n
\n

Contributors#

\n

Special thanks to contributors:

\n
    \n
  • @anareaty for reporting the Russian weekday scheduling conflict
  • \n
  • @RumiaKitinari for detailed reports on natural language processing, timeblock editing, and Pomodoro timer issues
  • \n
  • @jcromwell for reporting the scheduled task grouping UTC regression
  • \n
  • @Yoav6 for identifying the excluded folders trailing comma issue
  • \n
  • @mdbraber for reporting calendar refresh issues with time tracking changes
  • \n
  • @girisumit for reporting the mini calendar header overflow issue
  • \n
  • @jsonshanks for providing CSS improvement suggestions for the mini calendar
  • \n
  • @ras0q for suggesting the file-text icon addition to agenda view
  • \n
  • @antonio for pointing out the auto-archiving documentation inconsistency
  • \n
  • Danny Talks Tech for reporting the all-day task rendering issue in his video review
  • \n
\n
\n

This release focuses primarily on bug fixes and stability improvements, particularly around calendar functionality, natural language processing, and user interface polish.

\n","text":"Bug Fixes# Task Scheduling & Natural Language Processing# Fixed Russian weekday scheduling conflict where single weekdays (e.g., \"воскресенье\") were incorrectly interpreted as recurring tasks instead of single-day scheduling (#665, thanks to @anareaty for the report) Fixed issue where natural language processing failed to save parsed time estimates in task creation modal (#682, thanks to @RumiaKitinari for the detailed report) Fixed scheduled task grouping UTC anchor regression that caused today's tasks to appear under \"Past Scheduled\" instead of \"Today\" (#384, thanks to @jcromwell for the report) Settings & Configuration# Fixed plugin failure when excluded folders setting contains trailing commas - the parsing logic now properly filters empty strings (#664, thanks to @Yoav6 for identifying this issue) Calendar & Time Management# Fixed calendar not refreshing when task duration or time tracking changes (#382, thanks to @mdbraber) Fixed calendar not refreshing after task archive or move operations Fixed timeblock editing using stored date instead of current date for past day modifications (#647, thanks to @RumiaKitinari) Fixed Pomodoro timer not preserving task context when auto-starting sessions (#641, thanks to @RumiaKitinari) Fixed all-day tasks not rendering properly across multiple days in calendar view (thanks to Danny Talks Tech for reporting this in his video review) User Interface# Fixed mini calendar header overflow issue in sidebar view (#459, with CSS improvements suggested by @jsonshanks, thanks to @girisumit for the report) New Features & Enhancements# Visual Improvements# Added file-text icon to note cards in agenda view for better visual distinction from headers and consistency with task and calendar event icons (#662, thanks to @ras0q for the suggestion) Improved mini calendar styling, interactions, and legend display Enhanced task dot visualization to reflect accurate matching dates Settings Organization# Moved timeblocking settings to Features tab with improved usage instructions for better discoverability Documentation# Updated documentation to fix auto-archiving settings reference (#673, thanks to @antonio for pointing out the inconsistency) Contributors# Special thanks to contributors: @anareaty for reporting the Russian weekday scheduling conflict @RumiaKitinari for detailed reports on natural language processing, timeblock editing, and Pomodoro timer issues @jcromwell for reporting the scheduled task grouping UTC regression @Yoav6 for identifying the excluded folders trailing comma issue @mdbraber for reporting calendar refresh issues with time tracking changes @girisumit for reporting the mini calendar header overflow issue @jsonshanks for providing CSS improvement suggestions for the mini calendar @ras0q for suggesting the file-text icon addition to agenda view @antonio for pointing out the auto-archiving documentation inconsistency Danny Talks Tech for reporting the all-day task rendering issue in his video review This release focuses primarily on bug fixes and stability improvements, particularly around calendar functionality, natural language processing, and user interface polish."},{"route":"/obsidian/releases/3.24.0/","title":"TaskNotes 3.24.0","description":"Special thanks to all this release's contributors:","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.24.0.md","namespace":"obsidian","relativePath":"releases/3.24.0.md","raw":"# TaskNotes 3.24.0\n\n## New Features\n\n### Agenda View Overdue Section\n\n- Added separate \"Overdue\" section in Agenda view instead of mixing overdue tasks with today's tasks ([#557](https://github.com/callumalpass/tasknotes/issues/557), thanks to @backyardbiomech for the detailed report)\n- Collapsible section with task completion statistics and proper internationalization support\n- Includes overdue recurring tasks based on their scheduled dates\n\n### Task Dependencies and Blocking Relationships\n\n- Implemented blocking/blocked task dependencies with persistent relationships ([#701](https://github.com/callumalpass/tasknotes/issues/701), thanks to @prayidae for the detailed feature request)\n- Tasks can be marked as blocking other tasks or blocked by other tasks\n- Dependency relationships persist in frontmatter as structural links\n- Dynamic blocked state computed based on blocking task completion status\n\n### Task Card Widget in Notes\n\n- Added configurable task card widget displaying at the top of task notes ([#576](https://github.com/callumalpass/tasknotes/issues/576), thanks to @jhedlund for the request)\n- Provides immediate access to task actions and context menus without requiring command palette\n- Uses CodeMirror widget system for integration\n- Appears above project subtasks widget when both enabled\n- Can be disabled via settings\n\n### Hierarchical Subgrouping\n\n- Implemented hierarchical subgrouping functionality for TaskListView and AgendaView (thanks to @renatomen for this major feature contribution)\n- Allows two-level task organization (e.g., Group by Status, Subgroup by Priority)\n- Cross-view support with consistent behavior\n- State persistence for expand/collapse preferences\n- Custom user fields supported as subgroup options\n\n### Internationalization Support\n\n- Added i18n framework with multi-language support\n- Support for German, Spanish, French, Russian, Chinese, and Japanese\n- Translation coverage for command palette entries and UI strings\n- Localized agenda and filter interface elements\n\n### Template Variables\n\n- Added `{{hashtags}}` template variable for space-separated hashtag rendering ([#612](https://github.com/callumalpass/tasknotes/issues/612), thanks to @strazto for the suggestion)\n- Added `{{currentNoteTitle}}` template variable for note-specific folder organization ([#637](https://github.com/callumalpass/tasknotes/issues/637), thanks to @Mara-Li for the request)\n- Added template variable support for archive folder paths ([#677](https://github.com/callumalpass/tasknotes/issues/677), thanks to @dsebastien for the request)\n- Fixed `{{project}}` variables to properly extract basenames from wikilinks ([#490](https://github.com/callumalpass/tasknotes/issues/490), thanks to @nsstrickland for the detailed bug report)\n\n### Project and Subtask Management\n\n- Enhanced task modals with project and subtask management capabilities\n- Added \"Add to project\" and \"Add subtasks\" sections in task creation/edit modals\n- Context menu options for assigning tasks to projects and adding subtasks\n- Collapsible lists with visual separators between form sections\n\n### View and Grouping Enhancements\n\n- Added \"Completed Date\" as grouping option for analyzing productivity ([#430](https://github.com/callumalpass/tasknotes/issues/430), thanks to @anareaty for the suggestion)\n- Added \"Status\" as sorting option in Kanban and Task List views ([#633](https://github.com/callumalpass/tasknotes/issues/633), thanks to @mdbraber for the report)\n- Implemented per-grouping column persistence for Kanban views\n- Smart default ordering respecting StatusManager and PriorityManager configurations\n\n## Bug Fixes\n\n### Calendar and Advanced Calendar\n\n- Fixed calendar not refreshing when task duration or time tracking changes\n- Fixed calendar not refreshing after task archive or move operations\n- Fixed agenda duplication for all-day ICS events ([#695](https://github.com/callumalpass/tasknotes/issues/695), thanks to @realJohnDoe for the report)\n- Added configurable `eventMinHeight` for Advanced Calendar to make short duration tasks readable ([#718](https://github.com/callumalpass/tasknotes/issues/718), thanks to @Ruboks-Cube for the detailed report)\n- Fixed multi-day task creation in month/year view to properly calculate time estimates ([#564](https://github.com/callumalpass/tasknotes/issues/564), thanks to @same774 for the report)\n\n### Kanban View\n\n- Fixed kanban view losing columns after upgrades ([#689](https://github.com/callumalpass/tasknotes/issues/689), thanks to @mikesale for the report)\n- Fixed clearing filters defaulting to \"none\" instead of \"status\" grouping ([#679](https://github.com/callumalpass/tasknotes/issues/679), thanks to @camara-tech-pro for the question)\n- Fixed column order changes when switching between views ([#710](https://github.com/callumalpass/tasknotes/issues/710), thanks to @phortx for the report)\n- Fixed kanban drag-and-drop for custom field grouping ([#494](https://github.com/callumalpass/tasknotes/issues/494), thanks to @anareaty for the report)\n- Enhanced save view modal functionality with improved styling and accessibility\n\n### Task Management\n\n- Fixed HTTP API task creation to return sanitized title matching stored content ([#635](https://github.com/callumalpass/tasknotes/issues/635), thanks to @nightroman for the detailed report)\n- Fixed `#task` tag being incorrectly added when using property-based task identification ([#570](https://github.com/callumalpass/tasknotes/issues/570), thanks to @RobbK17 for the report)\n- Fixed recurring task completion styling in Bases views ([#669](https://github.com/callumalpass/tasknotes/issues/669), thanks to @jordandrako for the report)\n\n### Hierarchical Tag Support\n\n- Added hierarchical tag support with exclusion patterns for Obsidian nested tags ([#584](https://github.com/callumalpass/tasknotes/issues/584), thanks to @renatomen for the detailed feature request)\n- Hierarchical matching allows searching for parent tags to match child tags (e.g., `t/ef` matches `t/ef/project`, `t/ef/task`)\n- Exclusion patterns support using `-` prefix to exclude specific tags and their children\n- Maintains backward compatibility with existing substring matching\n\n### Natural Language Processing and Tags\n\n- Fixed nested tags losing slashes in agenda view rendering ([#712](https://github.com/callumalpass/tasknotes/issues/712), thanks to @antonio for the report and fix)\n- Added support for hyphens in NLP tag parsing ([#568](https://github.com/callumalpass/tasknotes/issues/568), thanks to @jordandrako for the report)\n\n### Settings and Configuration\n\n- Fixed property value truncation in project autosuggest settings by adding input debouncing ([#705](https://github.com/callumalpass/tasknotes/issues/705), thanks to @aubreyz for the report)\n- Improved webhook transform error handling with detailed logging ([#719](https://github.com/callumalpass/tasknotes/issues/719), thanks to @stephen-netu for the detailed report)\n- Added save button disable logic to prevent duplicate task creation (thanks to @hamlim for the report and implementation)\n\n### Code Quality and Development\n\n- Configured Prettier formatter for consistent code formatting ([#717](https://github.com/callumalpass/tasknotes/issues/717), thanks to @ras0q for the request)\n- Applied ESLint fixes reducing problems from 209 to 97\n- Added format and format:check scripts for development workflow\n- Fixed browser extension repository URL in README (thanks to @elijahmanor for the correction)\n\n## Enhancements\n\n### Performance and Reliability\n\n- Added debouncing to project autosuggest property inputs\n- Improved error handling for webhook transform failures\n\n### User Interface\n\n- Added time display based on `timeEstimate` property in task statistics (thanks to Sergen Aras for the implementation)\n- Enhanced language selection display with native scripts\n\n### Settings Organization\n\n- Reorganized settings with improved categorization\n- Added collapsible functionality to various UI sections\n- Enhanced accessibility with proper button labeling\n\n## Documentation\n\n- Added documentation for task dependencies feature\n- Updated comprehensive subgrouping feature documentation\n- Enhanced template variable documentation\n- Updated various view documentation for new features\n\n## Contributors\n\nSpecial thanks to all this release's contributors:\n\n### Feature Contributors\n\n- **@renatomen** for implementing the major hierarchical subgrouping feature and hierarchical tag support feature request (#584)\n- **@antonio** for implementing nested tag slash preservation and providing the fix\n- **@elijahmanor** for fixing the browser extension repository URL\n- **@sergenaras** for implementing time display based on timeEstimate property in task statistics\n- **@hamlim** for implementing save button disable logic to prevent duplicate task creation\n\n### Issue Reporters and Feature Requesters\n\n- **@backyardbiomech** for the detailed overdue recurring tasks report (#557)\n- **@prayidae** for the detailed task dependencies feature request (#701)\n- **@jhedlund** for requesting task context menu in notes (#576)\n- **@anareaty** for requesting completed date grouping (#430) and reporting kanban custom field drag issues (#494)\n- **@mdbraber** for reporting missing status sorting option (#633)\n- **@strazto** for requesting hashtags template variable (#612)\n- **@Mara-Li** for requesting currentNoteTitle template variable (#637)\n- **@dsebastien** for requesting archive folder template support (#677)\n- **@nsstrickland** for the detailed project variable bug report (#490)\n- **@realJohnDoe** for reporting ICS all-day event duplication (#695)\n- **@Ruboks-Cube** for reporting short duration task rendering issues (#718)\n- **@same774** for reporting multi-day task creation issues (#564)\n- **@mikesale** for reporting kanban column loss (#689)\n- **@camara-tech-pro** for the kanban grouping question (#679)\n- **@phortx** for reporting column order changes (#710)\n- **@nightroman** for the detailed HTTP API title sanitization report (#635)\n- **@RobbK17** for reporting property identification tag issue (#570)\n- **@jordandrako** for reporting recurring task styling in Bases (#669) and NLP tag parsing with hyphens (#568)\n- **@aubreyz** for reporting project autosuggest truncation issue (#705)\n- **@ras0q** for requesting code formatting improvements (#717)\n- **@stephen-netu** for the detailed webhook transform script loading report (#719)\n","aliases":["/releases/3.24.0/","/releases/3.24.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":3,"id":"agenda-view-overdue-section","text":"Agenda View Overdue Section"},{"level":3,"id":"task-dependencies-and-blocking-relationships","text":"Task Dependencies and Blocking Relationships"},{"level":3,"id":"task-card-widget-in-notes","text":"Task Card Widget in Notes"},{"level":3,"id":"hierarchical-subgrouping","text":"Hierarchical Subgrouping"},{"level":3,"id":"internationalization-support","text":"Internationalization Support"},{"level":3,"id":"template-variables","text":"Template Variables"},{"level":3,"id":"project-and-subtask-management","text":"Project and Subtask Management"},{"level":3,"id":"view-and-grouping-enhancements","text":"View and Grouping Enhancements"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"calendar-and-advanced-calendar","text":"Calendar and Advanced Calendar"},{"level":3,"id":"kanban-view","text":"Kanban View"},{"level":3,"id":"task-management","text":"Task Management"},{"level":3,"id":"hierarchical-tag-support","text":"Hierarchical Tag Support"},{"level":3,"id":"natural-language-processing-and-tags","text":"Natural Language Processing and Tags"},{"level":3,"id":"settings-and-configuration","text":"Settings and Configuration"},{"level":3,"id":"code-quality-and-development","text":"Code Quality and Development"},{"level":2,"id":"enhancements","text":"Enhancements"},{"level":3,"id":"performance-and-reliability","text":"Performance and Reliability"},{"level":3,"id":"user-interface","text":"User Interface"},{"level":3,"id":"settings-organization","text":"Settings Organization"},{"level":2,"id":"documentation","text":"Documentation"},{"level":2,"id":"contributors","text":"Contributors"},{"level":3,"id":"feature-contributors","text":"Feature Contributors"},{"level":3,"id":"issue-reporters-and-feature-requesters","text":"Issue Reporters and Feature Requesters"}],"html":"

New Features#

\n

Agenda View Overdue Section#

\n
    \n
  • Added separate "Overdue" section in Agenda view instead of mixing overdue tasks with today's tasks (#557, thanks to @backyardbiomech for the detailed report)
  • \n
  • Collapsible section with task completion statistics and proper internationalization support
  • \n
  • Includes overdue recurring tasks based on their scheduled dates
  • \n
\n

Task Dependencies and Blocking Relationships#

\n
    \n
  • Implemented blocking/blocked task dependencies with persistent relationships (#701, thanks to @prayidae for the detailed feature request)
  • \n
  • Tasks can be marked as blocking other tasks or blocked by other tasks
  • \n
  • Dependency relationships persist in frontmatter as structural links
  • \n
  • Dynamic blocked state computed based on blocking task completion status
  • \n
\n

Task Card Widget in Notes#

\n
    \n
  • Added configurable task card widget displaying at the top of task notes (#576, thanks to @jhedlund for the request)
  • \n
  • Provides immediate access to task actions and context menus without requiring command palette
  • \n
  • Uses CodeMirror widget system for integration
  • \n
  • Appears above project subtasks widget when both enabled
  • \n
  • Can be disabled via settings
  • \n
\n

Hierarchical Subgrouping#

\n
    \n
  • Implemented hierarchical subgrouping functionality for TaskListView and AgendaView (thanks to @renatomen for this major feature contribution)
  • \n
  • Allows two-level task organization (e.g., Group by Status, Subgroup by Priority)
  • \n
  • Cross-view support with consistent behavior
  • \n
  • State persistence for expand/collapse preferences
  • \n
  • Custom user fields supported as subgroup options
  • \n
\n

Internationalization Support#

\n
    \n
  • Added i18n framework with multi-language support
  • \n
  • Support for German, Spanish, French, Russian, Chinese, and Japanese
  • \n
  • Translation coverage for command palette entries and UI strings
  • \n
  • Localized agenda and filter interface elements
  • \n
\n

Template Variables#

\n
    \n
  • Added {{hashtags}} template variable for space-separated hashtag rendering (#612, thanks to @strazto for the suggestion)
  • \n
  • Added {{currentNoteTitle}} template variable for note-specific folder organization (#637, thanks to @Mara-Li for the request)
  • \n
  • Added template variable support for archive folder paths (#677, thanks to @dsebastien for the request)
  • \n
  • Fixed {{project}} variables to properly extract basenames from wikilinks (#490, thanks to @nsstrickland for the detailed bug report)
  • \n
\n

Project and Subtask Management#

\n
    \n
  • Enhanced task modals with project and subtask management capabilities
  • \n
  • Added "Add to project" and "Add subtasks" sections in task creation/edit modals
  • \n
  • Context menu options for assigning tasks to projects and adding subtasks
  • \n
  • Collapsible lists with visual separators between form sections
  • \n
\n

View and Grouping Enhancements#

\n
    \n
  • Added "Completed Date" as grouping option for analyzing productivity (#430, thanks to @anareaty for the suggestion)
  • \n
  • Added "Status" as sorting option in Kanban and Task List views (#633, thanks to @mdbraber for the report)
  • \n
  • Implemented per-grouping column persistence for Kanban views
  • \n
  • Smart default ordering respecting StatusManager and PriorityManager configurations
  • \n
\n

Bug Fixes#

\n

Calendar and Advanced Calendar#

\n
    \n
  • Fixed calendar not refreshing when task duration or time tracking changes
  • \n
  • Fixed calendar not refreshing after task archive or move operations
  • \n
  • Fixed agenda duplication for all-day ICS events (#695, thanks to @realJohnDoe for the report)
  • \n
  • Added configurable eventMinHeight for Advanced Calendar to make short duration tasks readable (#718, thanks to @Ruboks-Cube for the detailed report)
  • \n
  • Fixed multi-day task creation in month/year view to properly calculate time estimates (#564, thanks to @same774 for the report)
  • \n
\n

Kanban View#

\n
    \n
  • Fixed kanban view losing columns after upgrades (#689, thanks to @mikesale for the report)
  • \n
  • Fixed clearing filters defaulting to "none" instead of "status" grouping (#679, thanks to @camara-tech-pro for the question)
  • \n
  • Fixed column order changes when switching between views (#710, thanks to @phortx for the report)
  • \n
  • Fixed kanban drag-and-drop for custom field grouping (#494, thanks to @anareaty for the report)
  • \n
  • Enhanced save view modal functionality with improved styling and accessibility
  • \n
\n

Task Management#

\n
    \n
  • Fixed HTTP API task creation to return sanitized title matching stored content (#635, thanks to @nightroman for the detailed report)
  • \n
  • Fixed #task tag being incorrectly added when using property-based task identification (#570, thanks to @RobbK17 for the report)
  • \n
  • Fixed recurring task completion styling in Bases views (#669, thanks to @jordandrako for the report)
  • \n
\n

Hierarchical Tag Support#

\n
    \n
  • Added hierarchical tag support with exclusion patterns for Obsidian nested tags (#584, thanks to @renatomen for the detailed feature request)
  • \n
  • Hierarchical matching allows searching for parent tags to match child tags (e.g., t/ef matches t/ef/project, t/ef/task)
  • \n
  • Exclusion patterns support using - prefix to exclude specific tags and their children
  • \n
  • Maintains backward compatibility with existing substring matching
  • \n
\n

Natural Language Processing and Tags#

\n
    \n
  • Fixed nested tags losing slashes in agenda view rendering (#712, thanks to @antonio for the report and fix)
  • \n
  • Added support for hyphens in NLP tag parsing (#568, thanks to @jordandrako for the report)
  • \n
\n

Settings and Configuration#

\n
    \n
  • Fixed property value truncation in project autosuggest settings by adding input debouncing (#705, thanks to @aubreyz for the report)
  • \n
  • Improved webhook transform error handling with detailed logging (#719, thanks to @stephen-netu for the detailed report)
  • \n
  • Added save button disable logic to prevent duplicate task creation (thanks to @hamlim for the report and implementation)
  • \n
\n

Code Quality and Development#

\n
    \n
  • Configured Prettier formatter for consistent code formatting (#717, thanks to @ras0q for the request)
  • \n
  • Applied ESLint fixes reducing problems from 209 to 97
  • \n
  • Added format and format:check scripts for development workflow
  • \n
  • Fixed browser extension repository URL in README (thanks to @elijahmanor for the correction)
  • \n
\n

Enhancements#

\n

Performance and Reliability#

\n
    \n
  • Added debouncing to project autosuggest property inputs
  • \n
  • Improved error handling for webhook transform failures
  • \n
\n

User Interface#

\n
    \n
  • Added time display based on timeEstimate property in task statistics (thanks to Sergen Aras for the implementation)
  • \n
  • Enhanced language selection display with native scripts
  • \n
\n

Settings Organization#

\n
    \n
  • Reorganized settings with improved categorization
  • \n
  • Added collapsible functionality to various UI sections
  • \n
  • Enhanced accessibility with proper button labeling
  • \n
\n

Documentation#

\n
    \n
  • Added documentation for task dependencies feature
  • \n
  • Updated comprehensive subgrouping feature documentation
  • \n
  • Enhanced template variable documentation
  • \n
  • Updated various view documentation for new features
  • \n
\n

Contributors#

\n

Special thanks to all this release's contributors:

\n

Feature Contributors#

\n
    \n
  • @renatomen for implementing the major hierarchical subgrouping feature and hierarchical tag support feature request (#584)
  • \n
  • @antonio for implementing nested tag slash preservation and providing the fix
  • \n
  • @elijahmanor for fixing the browser extension repository URL
  • \n
  • @sergenaras for implementing time display based on timeEstimate property in task statistics
  • \n
  • @hamlim for implementing save button disable logic to prevent duplicate task creation
  • \n
\n

Issue Reporters and Feature Requesters#

\n
    \n
  • @backyardbiomech for the detailed overdue recurring tasks report (#557)
  • \n
  • @prayidae for the detailed task dependencies feature request (#701)
  • \n
  • @jhedlund for requesting task context menu in notes (#576)
  • \n
  • @anareaty for requesting completed date grouping (#430) and reporting kanban custom field drag issues (#494)
  • \n
  • @mdbraber for reporting missing status sorting option (#633)
  • \n
  • @strazto for requesting hashtags template variable (#612)
  • \n
  • @Mara-Li for requesting currentNoteTitle template variable (#637)
  • \n
  • @dsebastien for requesting archive folder template support (#677)
  • \n
  • @nsstrickland for the detailed project variable bug report (#490)
  • \n
  • @realJohnDoe for reporting ICS all-day event duplication (#695)
  • \n
  • @Ruboks-Cube for reporting short duration task rendering issues (#718)
  • \n
  • @same774 for reporting multi-day task creation issues (#564)
  • \n
  • @mikesale for reporting kanban column loss (#689)
  • \n
  • @camara-tech-pro for the kanban grouping question (#679)
  • \n
  • @phortx for reporting column order changes (#710)
  • \n
  • @nightroman for the detailed HTTP API title sanitization report (#635)
  • \n
  • @RobbK17 for reporting property identification tag issue (#570)
  • \n
  • @jordandrako for reporting recurring task styling in Bases (#669) and NLP tag parsing with hyphens (#568)
  • \n
  • @aubreyz for reporting project autosuggest truncation issue (#705)
  • \n
  • @ras0q for requesting code formatting improvements (#717)
  • \n
  • @stephen-netu for the detailed webhook transform script loading report (#719)
  • \n
\n","text":"New Features# Agenda View Overdue Section# Added separate \"Overdue\" section in Agenda view instead of mixing overdue tasks with today's tasks (#557, thanks to @backyardbiomech for the detailed report) Collapsible section with task completion statistics and proper internationalization support Includes overdue recurring tasks based on their scheduled dates Task Dependencies and Blocking Relationships# Implemented blocking/blocked task dependencies with persistent relationships (#701, thanks to @prayidae for the detailed feature request) Tasks can be marked as blocking other tasks or blocked by other tasks Dependency relationships persist in frontmatter as structural links Dynamic blocked state computed based on blocking task completion status Task Card Widget in Notes# Added configurable task card widget displaying at the top of task notes (#576, thanks to @jhedlund for the request) Provides immediate access to task actions and context menus without requiring command palette Uses CodeMirror widget system for integration Appears above project subtasks widget when both enabled Can be disabled via settings Hierarchical Subgrouping# Implemented hierarchical subgrouping functionality for TaskListView and AgendaView (thanks to @renatomen for this major feature contribution) Allows two-level task organization (e.g., Group by Status, Subgroup by Priority) Cross-view support with consistent behavior State persistence for expand/collapse preferences Custom user fields supported as subgroup options Internationalization Support# Added i18n framework with multi-language support Support for German, Spanish, French, Russian, Chinese, and Japanese Translation coverage for command palette entries and UI strings Localized agenda and filter interface elements Template Variables# Added {{hashtags}} template variable for space-separated hashtag rendering (#612, thanks to @strazto for the suggestion) Added {{currentNoteTitle}} template variable for note-specific folder organization (#637, thanks to @Mara-Li for the request) Added template variable support for archive folder paths (#677, thanks to @dsebastien for the request) Fixed {{project}} variables to properly extract basenames from wikilinks (#490, thanks to @nsstrickland for the detailed bug report) Project and Subtask Management# Enhanced task modals with project and subtask management capabilities Added \"Add to project\" and \"Add subtasks\" sections in task creation/edit modals Context menu options for assigning tasks to projects and adding subtasks Collapsible lists with visual separators between form sections View and Grouping Enhancements# Added \"Completed Date\" as grouping option for analyzing productivity (#430, thanks to @anareaty for the suggestion) Added \"Status\" as sorting option in Kanban and Task List views (#633, thanks to @mdbraber for the report) Implemented per-grouping column persistence for Kanban views Smart default ordering respecting StatusManager and PriorityManager configurations Bug Fixes# Calendar and Advanced Calendar# Fixed calendar not refreshing when task duration or time tracking changes Fixed calendar not refreshing after task archive or move operations Fixed agenda duplication for all-day ICS events (#695, thanks to @realJohnDoe for the report) Added configurable eventMinHeight for Advanced Calendar to make short duration tasks readable (#718, thanks to @Ruboks-Cube for the detailed report) Fixed multi-day task creation in month/year view to properly calculate time estimates (#564, thanks to @same774 for the report) Kanban View# Fixed kanban view losing columns after upgrades (#689, thanks to @mikesale for the report) Fixed clearing filters defaulting to \"none\" instead of \"status\" grouping (#679, thanks to @camara-tech-pro for the question) Fixed column order changes when switching between views (#710, thanks to @phortx for the report) Fixed kanban drag-and-drop for custom field grouping (#494, thanks to @anareaty for the report) Enhanced save view modal functionality with improved styling and accessibility Task Management# Fixed HTTP API task creation to return sanitized title matching stored content (#635, thanks to @nightroman for the detailed report) Fixed #task tag being incorrectly added when using property-based task identification (#570, thanks to @RobbK17 for the report) Fixed recurring task completion styling in Bases views (#669, thanks to @jordandrako for the report) Hierarchical Tag Support# Added hierarchical tag support with exclusion patterns for Obsidian nested tags (#584, thanks to @renatomen for the detailed feature request) Hierarchical matching allows searching for parent tags to match child tags (e.g., t/ef matches t/ef/project, t/ef/task) Exclusion patterns support using - prefix to exclude specific tags and their children Maintains backward compatibility with existing substring matching Natural Language Processing and Tags# Fixed nested tags losing slashes in agenda view rendering (#712, thanks to @antonio for the report and fix) Added support for hyphens in NLP tag parsing (#568, thanks to @jordandrako for the report) Settings and Configuration# Fixed property value truncation in project autosuggest settings by adding input debouncing (#705, thanks to @aubreyz for the report) Improved webhook transform error handling with detailed logging (#719, thanks to @stephen-netu for the detailed report) Added save button disable logic to prevent duplicate task creation (thanks to @hamlim for the report and implementation) Code Quality and Development# Configured Prettier formatter for consistent code formatting (#717, thanks to @ras0q for the request) Applied ESLint fixes reducing problems from 209 to 97 Added format and format:check scripts for development workflow Fixed browser extension repository URL in README (thanks to @elijahmanor for the correction) Enhancements# Performance and Reliability# Added debouncing to project autosuggest property inputs Improved error handling for webhook transform failures User Interface# Added time display based on timeEstimate property in task statistics (thanks to Sergen Aras for the implementation) Enhanced language selection display with native scripts Settings Organization# Reorganized settings with improved categorization Added collapsible functionality to various UI sections Enhanced accessibility with proper button labeling Documentation# Added documentation for task dependencies feature Updated comprehensive subgrouping feature documentation Enhanced template variable documentation Updated various view documentation for new features Contributors# Special thanks to all this release's contributors: Feature Contributors# @renatomen for implementing the major hierarchical subgrouping feature and hierarchical tag support feature request (#584) @antonio for implementing nested tag slash preservation and providing the fix @elijahmanor for fixing the browser extension repository URL @sergenaras for implementing time display based on timeEstimate property in task statistics @hamlim for implementing save button disable logic to prevent duplicate task creation Issue Reporters and Feature Requesters# @backyardbiomech for the detailed overdue recurring tasks report (#557) @prayidae for the detailed task dependencies feature request (#701) @jhedlund for requesting task context menu in notes (#576) @anareaty for requesting completed date grouping (#430) and reporting kanban custom field drag issues (#494) @mdbraber for reporting missing status sorting option (#633) @strazto for requesting hashtags template variable (#612) @Mara-Li for requesting currentNoteTitle template variable (#637) @dsebastien for requesting archive folder template support (#677) @nsstrickland for the detailed project variable bug report (#490) @realJohnDoe for reporting ICS all-day event duplication (#695) @Ruboks-Cube for reporting short duration task rendering issues (#718) @same774 for reporting multi-day task creation issues (#564) @mikesale for reporting kanban column loss (#689) @camara-tech-pro for the kanban grouping question (#679) @phortx for reporting column order changes (#710) @nightroman for the detailed HTTP API title sanitization report (#635) @RobbK17 for reporting property identification tag issue (#570) @jordandrako for reporting recurring task styling in Bases (#669) and NLP tag parsing with hyphens (#568) @aubreyz for reporting project autosuggest truncation issue (#705) @ras0q for requesting code formatting improvements (#717) @stephen-netu for the detailed webhook transform script loading report (#719)"},{"route":"/obsidian/releases/3.24.1/","title":"TaskNotes 3.24.1","description":"This patch release fixes the task card widget introduced in 3.24.0 to only display on actual task notes.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.24.1.md","namespace":"obsidian","relativePath":"releases/3.24.1.md","raw":"# TaskNotes 3.24.1\n\n## Bug Fixes\n\n### Task Card Widget\n\n- Fixed task card widget appearing on all notes instead of only task notes\n- Widget now properly respects task identification settings (tag or property-based)\n\nThis patch release fixes the task card widget introduced in 3.24.0 to only display on actual task notes.","aliases":["/releases/3.24.1/","/releases/3.24.1/"],"toc":[{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"task-card-widget","text":"Task Card Widget"}],"html":"

Bug Fixes#

\n

Task Card Widget#

\n
    \n
  • Fixed task card widget appearing on all notes instead of only task notes
  • \n
  • Widget now properly respects task identification settings (tag or property-based)
  • \n
\n

This patch release fixes the task card widget introduced in 3.24.0 to only display on actual task notes.

\n","text":"Bug Fixes# Task Card Widget# Fixed task card widget appearing on all notes instead of only task notes Widget now properly respects task identification settings (tag or property-based) This patch release fixes the task card widget introduced in 3.24.0 to only display on actual task notes."},{"route":"/obsidian/releases/3.24.2/","title":"TaskNotes 3.24.2","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.24.2.md","namespace":"obsidian","relativePath":"releases/3.24.2.md","raw":"# TaskNotes 3.24.2 \n\n## Fixed\n\n- (#766) Fixed tag parsing incorrectly identifying notes with tags containing \"task\" (like \"pkm-task\") as task notes\n - Added exact hierarchical tag matching for task identification to prevent false positives\n - Preserved substring matching behavior for filter bar searches where it's desired\n - Only exact matches or hierarchical children (like \"task/work\") now identify notes as tasks\n - Thanks to @anareaty and @fastrick for reporting this issue\n- (#767) Fixed subgroups not rendering under the \"Overdue\" agenda group\n - Thanks to @renatomen for reporting this issue\n- (#768) Fixed calendar view appearing empty in week and day views due to invalid time configuration values\n - Added time validation in settings UI with proper error messages and debouncing\n - Added runtime sanitization in calendar with safe defaults (00:00:00, 24:00:00, 08:00:00)\n - Prevents \"Cannot read properties of null (reading 'years')\" error from FullCalendar\n - Thanks to @kmaustral for reporting\n- (#769) Fixed NLP processor incorrectly assigning hardcoded \"waiting\" status when \"blocked\" appears in task titles\n - NLP now only uses user-defined status configurations when available, ignoring hardcoded fallback patterns\n - Prevents unexpected status assignments for users with custom status workflows\n - Fallback patterns still work when no custom status configurations are defined\n - Thanks to @renatomen for reporting this issue\n","aliases":["/releases/3.24.2/","/releases/3.24.2/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Fixed#

\n
    \n
  • (#766) Fixed tag parsing incorrectly identifying notes with tags containing "task" (like "pkm-task") as task notes
      \n
    • Added exact hierarchical tag matching for task identification to prevent false positives
    • \n
    • Preserved substring matching behavior for filter bar searches where it's desired
    • \n
    • Only exact matches or hierarchical children (like "task/work") now identify notes as tasks
    • \n
    • Thanks to @anareaty and @fastrick for reporting this issue
    • \n
    \n
  • \n
  • (#767) Fixed subgroups not rendering under the "Overdue" agenda group
      \n
    • Thanks to @renatomen for reporting this issue
    • \n
    \n
  • \n
  • (#768) Fixed calendar view appearing empty in week and day views due to invalid time configuration values
      \n
    • Added time validation in settings UI with proper error messages and debouncing
    • \n
    • Added runtime sanitization in calendar with safe defaults (00:00:00, 24:00:00, 08:00:00)
    • \n
    • Prevents "Cannot read properties of null (reading 'years')" error from FullCalendar
    • \n
    • Thanks to @kmaustral for reporting
    • \n
    \n
  • \n
  • (#769) Fixed NLP processor incorrectly assigning hardcoded "waiting" status when "blocked" appears in task titles
      \n
    • NLP now only uses user-defined status configurations when available, ignoring hardcoded fallback patterns
    • \n
    • Prevents unexpected status assignments for users with custom status workflows
    • \n
    • Fallback patterns still work when no custom status configurations are defined
    • \n
    • Thanks to @renatomen for reporting this issue
    • \n
    \n
  • \n
\n","text":"Fixed# (#766) Fixed tag parsing incorrectly identifying notes with tags containing \"task\" (like \"pkm-task\") as task notes Added exact hierarchical tag matching for task identification to prevent false positives Preserved substring matching behavior for filter bar searches where it's desired Only exact matches or hierarchical children (like \"task/work\") now identify notes as tasks Thanks to @anareaty and @fastrick for reporting this issue (#767) Fixed subgroups not rendering under the \"Overdue\" agenda group Thanks to @renatomen for reporting this issue (#768) Fixed calendar view appearing empty in week and day views due to invalid time configuration values Added time validation in settings UI with proper error messages and debouncing Added runtime sanitization in calendar with safe defaults (00:00:00, 24:00:00, 08:00:00) Prevents \"Cannot read properties of null (reading 'years')\" error from FullCalendar Thanks to @kmaustral for reporting (#769) Fixed NLP processor incorrectly assigning hardcoded \"waiting\" status when \"blocked\" appears in task titles NLP now only uses user-defined status configurations when available, ignoring hardcoded fallback patterns Prevents unexpected status assignments for users with custom status workflows Fallback patterns still work when no custom status configurations are defined Thanks to @renatomen for reporting this issue"},{"route":"/obsidian/releases/3.24.3/","title":"TaskNotes 3.24.3","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.24.3.md","namespace":"obsidian","relativePath":"releases/3.24.3.md","raw":"# TaskNotes 3.24.3\n\n- (#776) Fixed screens failing to load with \"toLowerCase is not a function\" error\n - Issue occurred when frontmatter tags array contained non-string values (numbers, booleans, etc.)\n - Added type validation to filter out non-string values before processing tags\n - Valid string tags continue to work normally while invalid types are safely skipped\n - Thanks to @kmf and @Andre-Ioda for help debugging this issue\n","aliases":["/releases/3.24.3/","/releases/3.24.3/"],"toc":[],"html":"
    \n
  • (#776) Fixed screens failing to load with "toLowerCase is not a function" error
      \n
    • Issue occurred when frontmatter tags array contained non-string values (numbers, booleans, etc.)
    • \n
    • Added type validation to filter out non-string values before processing tags
    • \n
    • Valid string tags continue to work normally while invalid types are safely skipped
    • \n
    • Thanks to @kmf and @Andre-Ioda for help debugging this issue
    • \n
    \n
  • \n
\n","text":"(#776) Fixed screens failing to load with \"toLowerCase is not a function\" error Issue occurred when frontmatter tags array contained non-string values (numbers, booleans, etc.) Added type validation to filter out non-string values before processing tags Valid string tags continue to work normally while invalid types are safely skipped Thanks to @kmf and @Andre-Ioda for help debugging this issue"},{"route":"/obsidian/releases/3.24.4/","title":"TaskNotes 3.24.4","description":"(#768) Fixed calendar view crashes when tasks contain null values in grouping fields","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.24.4.md","namespace":"obsidian","relativePath":"releases/3.24.4.md","raw":"# TaskNotes 3.24.4\n\n## Fixed\n\n- (#768) Fixed calendar view crashes when tasks contain null values in grouping fields\n - Added null/undefined checks in sort comparisons to prevent localeCompare errors\n - Calendar now handles null values in tags, contexts, and custom fields gracefully\n - Thanks to @kmaustral for reporting\n\n- (#601) Fixed Unicode characters not displaying in tags and contexts\n - Unicode characters (Š, Ė, Ž, Ą, etc.) are now properly preserved in tags and contexts\n - Affects Agenda View, Task List View, and all other views displaying tags\n - Thanks to @Kapinekas for reporting\n\n- (#778) Fixed cursor artifacts in CodeMirror widgets\n - Thanks to @jhedlund for the fix\n\n- Fixed task card widgets in note editor not updating for archive and time tracking changes\n - Task card widgets now properly detect when tasks are archived/unarchived\n - Task card widgets now properly detect when time tracking starts/stops\n - Blue \"tracking\" border now appears/disappears correctly in live preview\n - Archive styling now updates correctly in live preview\n\n## Changed\n\n- (#751) Status bar tracked task click behavior now opens task notes directly\n - Single tracked task: opens the task note immediately\n - Multiple tracked tasks: shows selector modal to choose which task note to open\n - Provides faster access to tracked tasks compared to previous task list view\n\n- (#727) \"Create New Inline Task\" command now respects the \"Include Current Note in Project\" setting\n - When enabled, the current note is automatically added as a project to inline tasks\n - Provides consistency with instant convert functionality\n - Thanks to @chrisfeagles for the suggestion\n\n- Improved link handling throughout the plugin using Obsidian's native APIs\n - Replaced manual wikilink generation with `FileManager.generateMarkdownLink()`\n - Now respects user's link format settings (wikilink vs markdown, relative paths)\n - Replaced manual link parsing with `parseLinktext()` for proper alias handling\n - Better compatibility with future Obsidian updates\n - Added centralized link utilities in `linkUtils.ts`\n\n- Refactored widget cursor styles into reusable utility class\n - Consolidated shared CSS into .cm-widget-cursor-fix utility\n - Improved maintainability across widget components\n\n","aliases":["/releases/3.24.4/","/releases/3.24.4/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"changed","text":"Changed"}],"html":"

Fixed#

\n
    \n
  • (#768) Fixed calendar view crashes when tasks contain null values in grouping fields

    \n
      \n
    • Added null/undefined checks in sort comparisons to prevent localeCompare errors
    • \n
    • Calendar now handles null values in tags, contexts, and custom fields gracefully
    • \n
    • Thanks to @kmaustral for reporting
    • \n
    \n
  • \n
  • (#601) Fixed Unicode characters not displaying in tags and contexts

    \n
      \n
    • Unicode characters (Š, Ė, Ž, Ą, etc.) are now properly preserved in tags and contexts
    • \n
    • Affects Agenda View, Task List View, and all other views displaying tags
    • \n
    • Thanks to @Kapinekas for reporting
    • \n
    \n
  • \n
  • (#778) Fixed cursor artifacts in CodeMirror widgets

    \n
      \n
    • Thanks to @jhedlund for the fix
    • \n
    \n
  • \n
  • Fixed task card widgets in note editor not updating for archive and time tracking changes

    \n
      \n
    • Task card widgets now properly detect when tasks are archived/unarchived
    • \n
    • Task card widgets now properly detect when time tracking starts/stops
    • \n
    • Blue "tracking" border now appears/disappears correctly in live preview
    • \n
    • Archive styling now updates correctly in live preview
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • (#751) Status bar tracked task click behavior now opens task notes directly

    \n
      \n
    • Single tracked task: opens the task note immediately
    • \n
    • Multiple tracked tasks: shows selector modal to choose which task note to open
    • \n
    • Provides faster access to tracked tasks compared to previous task list view
    • \n
    \n
  • \n
  • (#727) "Create New Inline Task" command now respects the "Include Current Note in Project" setting

    \n
      \n
    • When enabled, the current note is automatically added as a project to inline tasks
    • \n
    • Provides consistency with instant convert functionality
    • \n
    • Thanks to @chrisfeagles for the suggestion
    • \n
    \n
  • \n
  • Improved link handling throughout the plugin using Obsidian's native APIs

    \n
      \n
    • Replaced manual wikilink generation with FileManager.generateMarkdownLink()
    • \n
    • Now respects user's link format settings (wikilink vs markdown, relative paths)
    • \n
    • Replaced manual link parsing with parseLinktext() for proper alias handling
    • \n
    • Better compatibility with future Obsidian updates
    • \n
    • Added centralized link utilities in linkUtils.ts
    • \n
    \n
  • \n
  • Refactored widget cursor styles into reusable utility class

    \n
      \n
    • Consolidated shared CSS into .cm-widget-cursor-fix utility
    • \n
    • Improved maintainability across widget components
    • \n
    \n
  • \n
\n","text":"Fixed# (#768) Fixed calendar view crashes when tasks contain null values in grouping fields Added null/undefined checks in sort comparisons to prevent localeCompare errors Calendar now handles null values in tags, contexts, and custom fields gracefully Thanks to @kmaustral for reporting (#601) Fixed Unicode characters not displaying in tags and contexts Unicode characters (Š, Ė, Ž, Ą, etc.) are now properly preserved in tags and contexts Affects Agenda View, Task List View, and all other views displaying tags Thanks to @Kapinekas for reporting (#778) Fixed cursor artifacts in CodeMirror widgets Thanks to @jhedlund for the fix Fixed task card widgets in note editor not updating for archive and time tracking changes Task card widgets now properly detect when tasks are archived/unarchived Task card widgets now properly detect when time tracking starts/stops Blue \"tracking\" border now appears/disappears correctly in live preview Archive styling now updates correctly in live preview Changed# (#751) Status bar tracked task click behavior now opens task notes directly Single tracked task: opens the task note immediately Multiple tracked tasks: shows selector modal to choose which task note to open Provides faster access to tracked tasks compared to previous task list view (#727) \"Create New Inline Task\" command now respects the \"Include Current Note in Project\" setting When enabled, the current note is automatically added as a project to inline tasks Provides consistency with instant convert functionality Thanks to @chrisfeagles for the suggestion Improved link handling throughout the plugin using Obsidian's native APIs Replaced manual wikilink generation with FileManager.generateMarkdownLink() Now respects user's link format settings (wikilink vs markdown, relative paths) Replaced manual link parsing with parseLinktext() for proper alias handling Better compatibility with future Obsidian updates Added centralized link utilities in linkUtils.ts Refactored widget cursor styles into reusable utility class Consolidated shared CSS into .cm-widget-cursor-fix utility Improved maintainability across widget components"},{"route":"/obsidian/releases/3.24.5/","title":"TaskNotes 3.24.5","description":"(#806) Fixed Bases views crashing on Obsidian 1.10.0 startup","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.24.5.md","namespace":"obsidian","relativePath":"releases/3.24.5.md","raw":"# TaskNotes 3.24.5\n\n## Fixed\n\n- (#806) Fixed Bases views crashing on Obsidian 1.10.0 startup\n - TaskNotes Bases views (Task List and Kanban) now restore correctly when already open at startup\n - Added defensive checks in `setEphemeralState` to handle early lifecycle calls\n - Added `focus()` method to view objects for proper restoration\n - Made root elements focusable to support Obsidian 1.10.0 view lifecycle\n\n- (#792, #800) Fixed markdown-style project and dependency links not being recognized in frontmatter\n - Added support for markdown link format `[text](path)` in projects and blockedBy fields\n - Handles URL-encoded paths like `[Car Maintenance](../../projects/Car%20Maintenance.md)`\n - Markdown links now render as clickable links showing display text instead of raw `[text](path)` format\n - Links are properly resolved for grouping, filtering, and project-task associations\n - Previously only wikilink format `[[path]]` was supported\n - Prevents automatic removal of project assignments when editing tasks\n - Thanks to @minchinweb for reporting\n\n- (#780) Fixed \"Cannot Create Timeblocks\" error when daily notes folder doesn't exist\n - Added proper error handling when `createDailyNote` fails due to missing folder\n - Improved error messages to guide users to check Daily Notes plugin configuration\n - Prevents uncaught errors from `obsidian-daily-notes-interface` package\n - Thanks to @uberunix for reporting\n\n","aliases":["/releases/3.24.5/","/releases/3.24.5/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Fixed#

\n
    \n
  • (#806) Fixed Bases views crashing on Obsidian 1.10.0 startup

    \n
      \n
    • TaskNotes Bases views (Task List and Kanban) now restore correctly when already open at startup
    • \n
    • Added defensive checks in setEphemeralState to handle early lifecycle calls
    • \n
    • Added focus() method to view objects for proper restoration
    • \n
    • Made root elements focusable to support Obsidian 1.10.0 view lifecycle
    • \n
    \n
  • \n
  • (#792, #800) Fixed markdown-style project and dependency links not being recognized in frontmatter

    \n
      \n
    • Added support for markdown link format [text](path) in projects and blockedBy fields
    • \n
    • Handles URL-encoded paths like [Car Maintenance](../../projects/Car%20Maintenance.md)
    • \n
    • Markdown links now render as clickable links showing display text instead of raw [text](path) format
    • \n
    • Links are properly resolved for grouping, filtering, and project-task associations
    • \n
    • Previously only wikilink format [[path]] was supported
    • \n
    • Prevents automatic removal of project assignments when editing tasks
    • \n
    • Thanks to @minchinweb for reporting
    • \n
    \n
  • \n
  • (#780) Fixed "Cannot Create Timeblocks" error when daily notes folder doesn't exist

    \n
      \n
    • Added proper error handling when createDailyNote fails due to missing folder
    • \n
    • Improved error messages to guide users to check Daily Notes plugin configuration
    • \n
    • Prevents uncaught errors from obsidian-daily-notes-interface package
    • \n
    • Thanks to @uberunix for reporting
    • \n
    \n
  • \n
\n","text":"Fixed# (#806) Fixed Bases views crashing on Obsidian 1.10.0 startup TaskNotes Bases views (Task List and Kanban) now restore correctly when already open at startup Added defensive checks in setEphemeralState to handle early lifecycle calls Added focus() method to view objects for proper restoration Made root elements focusable to support Obsidian 1.10.0 view lifecycle (#792, #800) Fixed markdown-style project and dependency links not being recognized in frontmatter Added support for markdown link format [text](path) in projects and blockedBy fields Handles URL-encoded paths like [Car Maintenance](../../projects/Car%20Maintenance.md) Markdown links now render as clickable links showing display text instead of raw [text](path) format Links are properly resolved for grouping, filtering, and project-task associations Previously only wikilink format [[path]] was supported Prevents automatic removal of project assignments when editing tasks Thanks to @minchinweb for reporting (#780) Fixed \"Cannot Create Timeblocks\" error when daily notes folder doesn't exist Added proper error handling when createDailyNote fails due to missing folder Improved error messages to guide users to check Daily Notes plugin configuration Prevents uncaught errors from obsidian-daily-notes-interface package Thanks to @uberunix for reporting"},{"route":"/obsidian/releases/3.24.6/","title":"TaskNotes 3.24.6","description":"(#440) Fixed inline task replacement not working for links with relative paths","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.24.6.md","namespace":"obsidian","relativePath":"releases/3.24.6.md","raw":"# TaskNotes 3.24.6\n\n## Added\n\n- Added release notes viewer\n - New view displays release notes in a dedicated tab when plugin updates\n - Automatically opens after updating to a new version\n - Access anytime via command palette \"TaskNotes: View release notes\" or Settings > General\n - Release notes are rendered using native Obsidian markdown rendering\n - Includes link to view all releases on GitHub\n - Fully internationalized with i18n support\n - Auto-generation system ensures correct version is loaded without manual updates\n\n## Fixed\n\n- (#440) Fixed inline task replacement not working for links with relative paths\n - Markdown links with relative paths like `[task](../../../GTD/tasks/task.md)` now display inline previews\n - Wikilinks with relative paths now work correctly\n - Removed overly aggressive path sanitization that was stripping `..` from all link paths\n - Works in both Live Preview and Reading Mode\n - Thanks to @minchinweb for reporting\n\n- (#814) Fixed markdown links in projects field not being recognized on Project notes\n - Tasks with markdown-style project links `[text](path)` now appear in project's Subtasks section\n - Updated project link detection to use `parseLinkToPath` utility which handles both wikilinks and markdown links\n - Handles URL-encoded paths like `[z Test Project](z%20Test%20Project.md)`\n - Thanks to @minchinweb for reporting\n\n- (#827) Fixed project links being generated as markdown links for users with markdown links enabled in Obsidian settings\n - Project links in frontmatter are now always generated as wikilinks `[[link]]` by default for Obsidian compatibility\n - Obsidian does not support markdown links in frontmatter properties without third-party plugins\n - Added optional setting to enable markdown links in frontmatter for users with `obsidian-frontmatter-markdown-links` plugin\n - Setting only appears when user has markdown links enabled globally in Obsidian\n - Thanks to @nightroman for reporting\n","aliases":["/releases/3.24.6/","/releases/3.24.6/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • Added release notes viewer
      \n
    • New view displays release notes in a dedicated tab when plugin updates
    • \n
    • Automatically opens after updating to a new version
    • \n
    • Access anytime via command palette "TaskNotes: View release notes" or Settings > General
    • \n
    • Release notes are rendered using native Obsidian markdown rendering
    • \n
    • Includes link to view all releases on GitHub
    • \n
    • Fully internationalized with i18n support
    • \n
    • Auto-generation system ensures correct version is loaded without manual updates
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#440) Fixed inline task replacement not working for links with relative paths

    \n
      \n
    • Markdown links with relative paths like [task](../../../GTD/tasks/task.md) now display inline previews
    • \n
    • Wikilinks with relative paths now work correctly
    • \n
    • Removed overly aggressive path sanitization that was stripping .. from all link paths
    • \n
    • Works in both Live Preview and Reading Mode
    • \n
    • Thanks to @minchinweb for reporting
    • \n
    \n
  • \n
  • (#814) Fixed markdown links in projects field not being recognized on Project notes

    \n
      \n
    • Tasks with markdown-style project links [text](path) now appear in project's Subtasks section
    • \n
    • Updated project link detection to use parseLinkToPath utility which handles both wikilinks and markdown links
    • \n
    • Handles URL-encoded paths like [z Test Project](z%20Test%20Project.md)
    • \n
    • Thanks to @minchinweb for reporting
    • \n
    \n
  • \n
  • (#827) Fixed project links being generated as markdown links for users with markdown links enabled in Obsidian settings

    \n
      \n
    • Project links in frontmatter are now always generated as wikilinks [[link]] by default for Obsidian compatibility
    • \n
    • Obsidian does not support markdown links in frontmatter properties without third-party plugins
    • \n
    • Added optional setting to enable markdown links in frontmatter for users with obsidian-frontmatter-markdown-links plugin
    • \n
    • Setting only appears when user has markdown links enabled globally in Obsidian
    • \n
    • Thanks to @nightroman for reporting
    • \n
    \n
  • \n
\n","text":"Added# Added release notes viewer New view displays release notes in a dedicated tab when plugin updates Automatically opens after updating to a new version Access anytime via command palette \"TaskNotes: View release notes\" or Settings > General Release notes are rendered using native Obsidian markdown rendering Includes link to view all releases on GitHub Fully internationalized with i18n support Auto-generation system ensures correct version is loaded without manual updates Fixed# (#440) Fixed inline task replacement not working for links with relative paths Markdown links with relative paths like [task](../../../GTD/tasks/task.md) now display inline previews Wikilinks with relative paths now work correctly Removed overly aggressive path sanitization that was stripping .. from all link paths Works in both Live Preview and Reading Mode Thanks to @minchinweb for reporting (#814) Fixed markdown links in projects field not being recognized on Project notes Tasks with markdown-style project links [text](path) now appear in project's Subtasks section Updated project link detection to use parseLinkToPath utility which handles both wikilinks and markdown links Handles URL-encoded paths like [z Test Project](z%20Test%20Project.md) Thanks to @minchinweb for reporting (#827) Fixed project links being generated as markdown links for users with markdown links enabled in Obsidian settings Project links in frontmatter are now always generated as wikilinks [[link]] by default for Obsidian compatibility Obsidian does not support markdown links in frontmatter properties without third-party plugins Added optional setting to enable markdown links in frontmatter for users with obsidian-frontmatter-markdown-links plugin Setting only appears when user has markdown links enabled globally in Obsidian Thanks to @nightroman for reporting"},{"route":"/obsidian/releases/3.25.0/","title":"TaskNotes 3.25.0","description":"Added Calendar view for Bases plugin integration (requires Bases 1.10.0+)","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.25.0.md","namespace":"obsidian","relativePath":"releases/3.25.0.md","raw":"# TaskNotes 3.25.0\n\n## Added\n\n- Added Calendar view for Bases plugin integration (requires Bases 1.10.0+)\n - Supports month, week, day, year, and list views\n - Property-based events from note date properties (configurable start date, end date, and title properties)\n - Custom card rendering in list view for tasks, timeblocks, ICS events, and property-based events\n - Layout options: time format, weekend visibility, all-day slot, today highlight, scroll time, event height\n - Visibility toggles for event types (scheduled, due, recurring, time entries, timeblocks, property-based)\n - Date validation to handle invalid property values\n - Drag-and-drop to update property-based event dates in frontmatter\n - Full internationalization support for calendar features in 7 languages (English, French, Spanish, German, Japanese, Russian, Chinese)\n\n- Added grouped rendering support for Bases integration list and kanban views\n - List view displays collapsible groups with toggle controls\n - Kanban view renders grouped columns with drag-drop support\n - Automatically detects ungrouped views and renders as flat list\n\n- (#842) Added keyboard navigation support for task forms\n - Action bar icons now focusable with proper tab order and ARIA attributes\n - Enter and Space keys trigger actions on focused elements\n - Added submenu support for reminders button for better keyboard accessibility\n - Improved focus indicators for better visual feedback\n - Thanks to @maybetm for this excellent contribution!\n\n## Changed\n\n- Migrated Bases integration to use public API (Bases 1.10.0+) with graceful fallback to internal API for older versions\n\n## Fixed\n\n- (#789) Fixed folder path truncation in settings causing tasks to be created in wrong paths\n - Changed debounce to trailing mode to ensure final value is saved instead of partial input\n - Fixes issue where rapid typing, paste, or autocomplete would save incomplete folder paths\n - Thanks to @sascha224 for reporting\n\n- (#806) Fixed Bases views crashing on Obsidian 1.10.0 startup\n - TaskNotes Bases views (Task List and Kanban) now restore correctly when already open at startup\n - Added defensive checks in `setEphemeralState` to handle early lifecycle calls\n - Added `focus()` method to view objects for proper restoration\n - Made root elements focusable to support Obsidian 1.10.0 view lifecycle\n\n- (#825) Fixed single/double click settings not applying to calendar views\n - Shared click handling now works consistently across Advanced Calendar and Bases Calendar\n - Ctrl/Cmd+click opens tasks in new tab as expected\n - Single and double-click actions respect user settings\n\n- (#699) Fixed Obsidian freezing when moving calendar tab to new window\n - Skip calendar resize during window transfer to prevent freeze\n - Calendar may display incorrectly after move but can be fixed by switching views\n - Prevents complete UI lockup during tab transfer\n\n- (#816) Fixed template variables not processing in ICS subscription note folder paths\n - Template variables like `{{year}}`, `{{month}}`, `{{date}}` now work in ICS note folder settings\n - Extracted folder template processing into shared utility for consistency\n - Added support for ICS-specific variables: `{{icsEventTitle}}`, `{{icsEventLocation}}`, `{{icsEventDescription}}`\n - Users can now organize ICS notes in date-based hierarchies (e.g., `Daily/{{year}}/{{month}}/`)\n - Thanks to @j-peeters for reporting\n\n- (#813) Fixed subscribed ICS calendars irregularly disappearing from calendar views\n - Added 5-minute grace period after cache expiration to keep events visible during refresh\n - Trigger automatic background refresh when cache is stale or missing\n - Initialize ICS service instances early so views can register event listeners before data loads\n - Prevents disappearance during network errors or when calendar opens at Obsidian startup\n - Thanks to @j-peeters for reporting\n\n- (#829) Fixed time estimates and recurrence patterns being lost during instant task conversion\n - Added `timeEstimate` field to `ParsedTaskData` interface\n - Time estimates from natural language parsing now properly transferred to task frontmatter\n - Parsed values now take priority over default settings\n - RRule strings passed directly without conversion (preferred format)\n - Thanks to @Justin-Burg for reporting\n\n- (#826) Fixed task card widget not appearing when Obsidian starts with task note open\n - Deferred dispatch calls to avoid \"EditorView.update not allowed during update\" error\n - Widget now renders correctly on startup without requiring workarounds\n - Thanks to @nightroman for reporting\n\n- (#781), (#841) Fixed ICS calendar events displaying incorrect times due to timezone conversion issues\n - Events with non-IANA timezone identifiers (e.g., `TZID=Zurich` without VTIMEZONE) now display at correct local times\n - Fixed Outlook/Exchange calendar events showing original timezone instead of user's local timezone\n - Replaced unreliable `toJSDate()` conversion with `toUnixTime()` for accurate UTC timestamp handling\n - Affects all ICS subscriptions including Infomaniak, Outlook, and other providers with non-standard timezone formats\n - Thanks to @chrlaney for reporting and @wilf80 for detailed analysis\n\n- (#810) Fixed recurring tasks with overdue due dates disappearing from agenda view\n - Recurring tasks now check both `due` and `scheduled` dates for overdue status\n - Previously only `scheduled` was checked for recurring tasks, causing tasks with overdue `due` dates to be hidden\n - Ensures consistent overdue detection logic between recurring and non-recurring tasks\n - Thanks to @skyrunner15 for reporting\n\n- (#822) Fixed mini calendar showing incorrect dates in negative UTC offset timezones\n - Calendar tooltips and month displays now show correct dates for users in Americas/Pacific timezones\n - UTC-anchored dates are now converted to local calendar dates before formatting\n - Fixes off-by-one day error that affected date selection and display\n - Thanks to @kenhsmith for reporting\n\n","aliases":["/releases/3.25.0/","/releases/3.25.0/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • Added Calendar view for Bases plugin integration (requires Bases 1.10.0+)

    \n
      \n
    • Supports month, week, day, year, and list views
    • \n
    • Property-based events from note date properties (configurable start date, end date, and title properties)
    • \n
    • Custom card rendering in list view for tasks, timeblocks, ICS events, and property-based events
    • \n
    • Layout options: time format, weekend visibility, all-day slot, today highlight, scroll time, event height
    • \n
    • Visibility toggles for event types (scheduled, due, recurring, time entries, timeblocks, property-based)
    • \n
    • Date validation to handle invalid property values
    • \n
    • Drag-and-drop to update property-based event dates in frontmatter
    • \n
    • Full internationalization support for calendar features in 7 languages (English, French, Spanish, German, Japanese, Russian, Chinese)
    • \n
    \n
  • \n
  • Added grouped rendering support for Bases integration list and kanban views

    \n
      \n
    • List view displays collapsible groups with toggle controls
    • \n
    • Kanban view renders grouped columns with drag-drop support
    • \n
    • Automatically detects ungrouped views and renders as flat list
    • \n
    \n
  • \n
  • (#842) Added keyboard navigation support for task forms

    \n
      \n
    • Action bar icons now focusable with proper tab order and ARIA attributes
    • \n
    • Enter and Space keys trigger actions on focused elements
    • \n
    • Added submenu support for reminders button for better keyboard accessibility
    • \n
    • Improved focus indicators for better visual feedback
    • \n
    • Thanks to @maybetm for this excellent contribution!
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Migrated Bases integration to use public API (Bases 1.10.0+) with graceful fallback to internal API for older versions
  • \n
\n

Fixed#

\n
    \n
  • (#789) Fixed folder path truncation in settings causing tasks to be created in wrong paths

    \n
      \n
    • Changed debounce to trailing mode to ensure final value is saved instead of partial input
    • \n
    • Fixes issue where rapid typing, paste, or autocomplete would save incomplete folder paths
    • \n
    • Thanks to @sascha224 for reporting
    • \n
    \n
  • \n
  • (#806) Fixed Bases views crashing on Obsidian 1.10.0 startup

    \n
      \n
    • TaskNotes Bases views (Task List and Kanban) now restore correctly when already open at startup
    • \n
    • Added defensive checks in setEphemeralState to handle early lifecycle calls
    • \n
    • Added focus() method to view objects for proper restoration
    • \n
    • Made root elements focusable to support Obsidian 1.10.0 view lifecycle
    • \n
    \n
  • \n
  • (#825) Fixed single/double click settings not applying to calendar views

    \n
      \n
    • Shared click handling now works consistently across Advanced Calendar and Bases Calendar
    • \n
    • Ctrl/Cmd+click opens tasks in new tab as expected
    • \n
    • Single and double-click actions respect user settings
    • \n
    \n
  • \n
  • (#699) Fixed Obsidian freezing when moving calendar tab to new window

    \n
      \n
    • Skip calendar resize during window transfer to prevent freeze
    • \n
    • Calendar may display incorrectly after move but can be fixed by switching views
    • \n
    • Prevents complete UI lockup during tab transfer
    • \n
    \n
  • \n
  • (#816) Fixed template variables not processing in ICS subscription note folder paths

    \n
      \n
    • Template variables like {{year}}, {{month}}, {{date}} now work in ICS note folder settings
    • \n
    • Extracted folder template processing into shared utility for consistency
    • \n
    • Added support for ICS-specific variables: {{icsEventTitle}}, {{icsEventLocation}}, {{icsEventDescription}}
    • \n
    • Users can now organize ICS notes in date-based hierarchies (e.g., Daily/{{year}}/{{month}}/)
    • \n
    • Thanks to @j-peeters for reporting
    • \n
    \n
  • \n
  • (#813) Fixed subscribed ICS calendars irregularly disappearing from calendar views

    \n
      \n
    • Added 5-minute grace period after cache expiration to keep events visible during refresh
    • \n
    • Trigger automatic background refresh when cache is stale or missing
    • \n
    • Initialize ICS service instances early so views can register event listeners before data loads
    • \n
    • Prevents disappearance during network errors or when calendar opens at Obsidian startup
    • \n
    • Thanks to @j-peeters for reporting
    • \n
    \n
  • \n
  • (#829) Fixed time estimates and recurrence patterns being lost during instant task conversion

    \n
      \n
    • Added timeEstimate field to ParsedTaskData interface
    • \n
    • Time estimates from natural language parsing now properly transferred to task frontmatter
    • \n
    • Parsed values now take priority over default settings
    • \n
    • RRule strings passed directly without conversion (preferred format)
    • \n
    • Thanks to @Justin-Burg for reporting
    • \n
    \n
  • \n
  • (#826) Fixed task card widget not appearing when Obsidian starts with task note open

    \n
      \n
    • Deferred dispatch calls to avoid "EditorView.update not allowed during update" error
    • \n
    • Widget now renders correctly on startup without requiring workarounds
    • \n
    • Thanks to @nightroman for reporting
    • \n
    \n
  • \n
  • (#781), (#841) Fixed ICS calendar events displaying incorrect times due to timezone conversion issues

    \n
      \n
    • Events with non-IANA timezone identifiers (e.g., TZID=Zurich without VTIMEZONE) now display at correct local times
    • \n
    • Fixed Outlook/Exchange calendar events showing original timezone instead of user's local timezone
    • \n
    • Replaced unreliable toJSDate() conversion with toUnixTime() for accurate UTC timestamp handling
    • \n
    • Affects all ICS subscriptions including Infomaniak, Outlook, and other providers with non-standard timezone formats
    • \n
    • Thanks to @chrlaney for reporting and @wilf80 for detailed analysis
    • \n
    \n
  • \n
  • (#810) Fixed recurring tasks with overdue due dates disappearing from agenda view

    \n
      \n
    • Recurring tasks now check both due and scheduled dates for overdue status
    • \n
    • Previously only scheduled was checked for recurring tasks, causing tasks with overdue due dates to be hidden
    • \n
    • Ensures consistent overdue detection logic between recurring and non-recurring tasks
    • \n
    • Thanks to @skyrunner15 for reporting
    • \n
    \n
  • \n
  • (#822) Fixed mini calendar showing incorrect dates in negative UTC offset timezones

    \n
      \n
    • Calendar tooltips and month displays now show correct dates for users in Americas/Pacific timezones
    • \n
    • UTC-anchored dates are now converted to local calendar dates before formatting
    • \n
    • Fixes off-by-one day error that affected date selection and display
    • \n
    • Thanks to @kenhsmith for reporting
    • \n
    \n
  • \n
\n","text":"Added# Added Calendar view for Bases plugin integration (requires Bases 1.10.0+) Supports month, week, day, year, and list views Property-based events from note date properties (configurable start date, end date, and title properties) Custom card rendering in list view for tasks, timeblocks, ICS events, and property-based events Layout options: time format, weekend visibility, all-day slot, today highlight, scroll time, event height Visibility toggles for event types (scheduled, due, recurring, time entries, timeblocks, property-based) Date validation to handle invalid property values Drag-and-drop to update property-based event dates in frontmatter Full internationalization support for calendar features in 7 languages (English, French, Spanish, German, Japanese, Russian, Chinese) Added grouped rendering support for Bases integration list and kanban views List view displays collapsible groups with toggle controls Kanban view renders grouped columns with drag-drop support Automatically detects ungrouped views and renders as flat list (#842) Added keyboard navigation support for task forms Action bar icons now focusable with proper tab order and ARIA attributes Enter and Space keys trigger actions on focused elements Added submenu support for reminders button for better keyboard accessibility Improved focus indicators for better visual feedback Thanks to @maybetm for this excellent contribution! Changed# Migrated Bases integration to use public API (Bases 1.10.0+) with graceful fallback to internal API for older versions Fixed# (#789) Fixed folder path truncation in settings causing tasks to be created in wrong paths Changed debounce to trailing mode to ensure final value is saved instead of partial input Fixes issue where rapid typing, paste, or autocomplete would save incomplete folder paths Thanks to @sascha224 for reporting (#806) Fixed Bases views crashing on Obsidian 1.10.0 startup TaskNotes Bases views (Task List and Kanban) now restore correctly when already open at startup Added defensive checks in setEphemeralState to handle early lifecycle calls Added focus() method to view objects for proper restoration Made root elements focusable to support Obsidian 1.10.0 view lifecycle (#825) Fixed single/double click settings not applying to calendar views Shared click handling now works consistently across Advanced Calendar and Bases Calendar Ctrl/Cmd+click opens tasks in new tab as expected Single and double-click actions respect user settings (#699) Fixed Obsidian freezing when moving calendar tab to new window Skip calendar resize during window transfer to prevent freeze Calendar may display incorrectly after move but can be fixed by switching views Prevents complete UI lockup during tab transfer (#816) Fixed template variables not processing in ICS subscription note folder paths Template variables like {{year}}, {{month}}, {{date}} now work in ICS note folder settings Extracted folder template processing into shared utility for consistency Added support for ICS-specific variables: {{icsEventTitle}}, {{icsEventLocation}}, {{icsEventDescription}} Users can now organize ICS notes in date-based hierarchies (e.g., Daily/{{year}}/{{month}}/) Thanks to @j-peeters for reporting (#813) Fixed subscribed ICS calendars irregularly disappearing from calendar views Added 5-minute grace period after cache expiration to keep events visible during refresh Trigger automatic background refresh when cache is stale or missing Initialize ICS service instances early so views can register event listeners before data loads Prevents disappearance during network errors or when calendar opens at Obsidian startup Thanks to @j-peeters for reporting (#829) Fixed time estimates and recurrence patterns being lost during instant task conversion Added timeEstimate field to ParsedTaskData interface Time estimates from natural language parsing now properly transferred to task frontmatter Parsed values now take priority over default settings RRule strings passed directly without conversion (preferred format) Thanks to @Justin-Burg for reporting (#826) Fixed task card widget not appearing when Obsidian starts with task note open Deferred dispatch calls to avoid \"EditorView.update not allowed during update\" error Widget now renders correctly on startup without requiring workarounds Thanks to @nightroman for reporting (#781), (#841) Fixed ICS calendar events displaying incorrect times due to timezone conversion issues Events with non-IANA timezone identifiers (e.g., TZID=Zurich without VTIMEZONE) now display at correct local times Fixed Outlook/Exchange calendar events showing original timezone instead of user's local timezone Replaced unreliable toJSDate() conversion with toUnixTime() for accurate UTC timestamp handling Affects all ICS subscriptions including Infomaniak, Outlook, and other providers with non-standard timezone formats Thanks to @chrlaney for reporting and @wilf80 for detailed analysis (#810) Fixed recurring tasks with overdue due dates disappearing from agenda view Recurring tasks now check both due and scheduled dates for overdue status Previously only scheduled was checked for recurring tasks, causing tasks with overdue due dates to be hidden Ensures consistent overdue detection logic between recurring and non-recurring tasks Thanks to @skyrunner15 for reporting (#822) Fixed mini calendar showing incorrect dates in negative UTC offset timezones Calendar tooltips and month displays now show correct dates for users in Americas/Pacific timezones UTC-anchored dates are now converted to local calendar dates before formatting Fixes off-by-one day error that affected date selection and display Thanks to @kenhsmith for reporting"},{"route":"/obsidian/releases/3.25.1/","title":"TaskNotes 3.25.1","description":"(#854) (#695) Fixed all-day ICS calendar events displaying on wrong day and appearing twice","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.25.1.md","namespace":"obsidian","relativePath":"releases/3.25.1.md","raw":"# TaskNotes 3.25.1\n\n## Fixed\n\n- (#854) (#695) Fixed all-day ICS calendar events displaying on wrong day and appearing twice\n - All-day events now stored as date-only strings (YYYY-MM-DD) instead of UTC timestamps\n - Events display on correct calendar date regardless of user timezone (fixes issue in PST, EST, and other negative UTC offset timezones)\n - All-day events no longer appear twice in Agenda view\n - Updated all date parsing throughout the codebase to handle date-only format correctly\n - Maintains compatibility with FullCalendar and preserves iCalendar RFC 5545 semantics for VALUE=DATE events\n - Thanks to @needo37 for reporting #854 and @realJohnDoe for reporting #695\n\n- (#859) Fixed multi-day task creation in Bases calendar view\n - Extracted shared task creation logic to `calendar-core.ts` for consistency between calendar views\n - Multi-day all-day selections now correctly set time estimate based on number of days dragged\n - Timed task selections (week view) now correctly calculate duration in minutes\n - Single-day clicks no longer override default time estimate settings\n - Both Bases calendar and AdvancedCalendarView now use same logic for consistent behavior\n - Fixed all-day task rendering to use 24-hour days (1440 minutes = 1 day on calendar)\n - Follows UTC Anchor principle for date-only strings\n - Thanks to @anareaty for reporting\n","aliases":["/releases/3.25.1/","/releases/3.25.1/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Fixed#

\n
    \n
  • (#854) (#695) Fixed all-day ICS calendar events displaying on wrong day and appearing twice

    \n
      \n
    • All-day events now stored as date-only strings (YYYY-MM-DD) instead of UTC timestamps
    • \n
    • Events display on correct calendar date regardless of user timezone (fixes issue in PST, EST, and other negative UTC offset timezones)
    • \n
    • All-day events no longer appear twice in Agenda view
    • \n
    • Updated all date parsing throughout the codebase to handle date-only format correctly
    • \n
    • Maintains compatibility with FullCalendar and preserves iCalendar RFC 5545 semantics for VALUE=DATE events
    • \n
    • Thanks to @needo37 for reporting #854 and @realJohnDoe for reporting #695
    • \n
    \n
  • \n
  • (#859) Fixed multi-day task creation in Bases calendar view

    \n
      \n
    • Extracted shared task creation logic to calendar-core.ts for consistency between calendar views
    • \n
    • Multi-day all-day selections now correctly set time estimate based on number of days dragged
    • \n
    • Timed task selections (week view) now correctly calculate duration in minutes
    • \n
    • Single-day clicks no longer override default time estimate settings
    • \n
    • Both Bases calendar and AdvancedCalendarView now use same logic for consistent behavior
    • \n
    • Fixed all-day task rendering to use 24-hour days (1440 minutes = 1 day on calendar)
    • \n
    • Follows UTC Anchor principle for date-only strings
    • \n
    • Thanks to @anareaty for reporting
    • \n
    \n
  • \n
\n","text":"Fixed# (#854) (#695) Fixed all-day ICS calendar events displaying on wrong day and appearing twice All-day events now stored as date-only strings (YYYY-MM-DD) instead of UTC timestamps Events display on correct calendar date regardless of user timezone (fixes issue in PST, EST, and other negative UTC offset timezones) All-day events no longer appear twice in Agenda view Updated all date parsing throughout the codebase to handle date-only format correctly Maintains compatibility with FullCalendar and preserves iCalendar RFC 5545 semantics for VALUE=DATE events Thanks to @needo37 for reporting #854 and @realJohnDoe for reporting #695 (#859) Fixed multi-day task creation in Bases calendar view Extracted shared task creation logic to calendar-core.ts for consistency between calendar views Multi-day all-day selections now correctly set time estimate based on number of days dragged Timed task selections (week view) now correctly calculate duration in minutes Single-day clicks no longer override default time estimate settings Both Bases calendar and AdvancedCalendarView now use same logic for consistent behavior Fixed all-day task rendering to use 24-hour days (1440 minutes = 1 day on calendar) Follows UTC Anchor principle for date-only strings Thanks to @anareaty for reporting"},{"route":"/obsidian/releases/3.25.2/","title":"TaskNotes 3.25.2","description":"(#857) Fixed Mini Calendar opening previous day's daily note when clicked","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.25.2.md","namespace":"obsidian","relativePath":"releases/3.25.2.md","raw":"# TaskNotes 3.25.2\n\n## Fixed\n\n- (#857) Fixed Mini Calendar opening previous day's daily note when clicked\n - Affects users in negative UTC offset timezones (Americas, Pacific)\n - Thanks to @tsweezy for reporting\n\n- (#871) Fixed Bases Kanban drag-and-drop updating wrong property when grouped by custom fields\n - Added support for both Bases 1.10.0+ format (`{property: string, direction: string}`) and legacy string format\n - Note: GroupBy is not exposed in the Bases public API (`config.get('groupBy')` returns undefined)\n - Known limitation: When grouping by projects, Bases groups by literal wikilink strings, not resolved file paths\n - Tasks with different wikilink formats pointing to the same project file will appear in separate columns\n - Example: `[[Project]]`, `[[path/to/Project]]`, and `[[Project|Alias]]` create separate columns\n - This differs from native TaskNotes Kanban which resolves all wikilinks to absolute paths\n - Thanks to @kmaustral for reporting\n\n## Added\n\n- Added date navigation configuration for Bases calendar views\n - Hardcoded date option: Set a specific date (YYYY-MM-DD format) for the calendar to display on load\n - Property-based navigation: Automatically navigate to dates from filtered note properties\n - Three navigation strategies: First result, Earliest date, or Latest date\n\n## Changed\n\n- Release notes now bundle all versions from current and previous minor series with collapsible sections\n - Added setting to disable automatic release notes display after updates\n","aliases":["/releases/3.25.2/","/releases/3.25.2/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"}],"html":"

Fixed#

\n
    \n
  • (#857) Fixed Mini Calendar opening previous day's daily note when clicked

    \n
      \n
    • Affects users in negative UTC offset timezones (Americas, Pacific)
    • \n
    • Thanks to @tsweezy for reporting
    • \n
    \n
  • \n
  • (#871) Fixed Bases Kanban drag-and-drop updating wrong property when grouped by custom fields

    \n
      \n
    • Added support for both Bases 1.10.0+ format ({property: string, direction: string}) and legacy string format
    • \n
    • Note: GroupBy is not exposed in the Bases public API (config.get('groupBy') returns undefined)
    • \n
    • Known limitation: When grouping by projects, Bases groups by literal wikilink strings, not resolved file paths
        \n
      • Tasks with different wikilink formats pointing to the same project file will appear in separate columns
      • \n
      • Example: [[Project]], [[path/to/Project]], and [[Project|Alias]] create separate columns
      • \n
      • This differs from native TaskNotes Kanban which resolves all wikilinks to absolute paths
      • \n
      \n
    • \n
    • Thanks to @kmaustral for reporting
    • \n
    \n
  • \n
\n

Added#

\n
    \n
  • Added date navigation configuration for Bases calendar views
      \n
    • Hardcoded date option: Set a specific date (YYYY-MM-DD format) for the calendar to display on load
    • \n
    • Property-based navigation: Automatically navigate to dates from filtered note properties
    • \n
    • Three navigation strategies: First result, Earliest date, or Latest date
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Release notes now bundle all versions from current and previous minor series with collapsible sections
      \n
    • Added setting to disable automatic release notes display after updates
    • \n
    \n
  • \n
\n","text":"Fixed# (#857) Fixed Mini Calendar opening previous day's daily note when clicked Affects users in negative UTC offset timezones (Americas, Pacific) Thanks to @tsweezy for reporting (#871) Fixed Bases Kanban drag-and-drop updating wrong property when grouped by custom fields Added support for both Bases 1.10.0+ format ({property: string, direction: string}) and legacy string format Note: GroupBy is not exposed in the Bases public API (config.get('groupBy') returns undefined) Known limitation: When grouping by projects, Bases groups by literal wikilink strings, not resolved file paths Tasks with different wikilink formats pointing to the same project file will appear in separate columns Example: [[Project]], [[path/to/Project]], and [[Project|Alias]] create separate columns This differs from native TaskNotes Kanban which resolves all wikilinks to absolute paths Thanks to @kmaustral for reporting Added# Added date navigation configuration for Bases calendar views Hardcoded date option: Set a specific date (YYYY-MM-DD format) for the calendar to display on load Property-based navigation: Automatically navigate to dates from filtered note properties Three navigation strategies: First result, Earliest date, or Latest date Changed# Release notes now bundle all versions from current and previous minor series with collapsible sections Added setting to disable automatic release notes display after updates"},{"route":"/obsidian/releases/3.25.3/","title":"TaskNotes 3.25.3","description":"(#899) Fixed \"Folder for converted tasks\" setting being hidden when convert button is disabled","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.25.3.md","namespace":"obsidian","relativePath":"releases/3.25.3.md","raw":"# TaskNotes 3.25.3\n\n## Added\n\n- (#877) Added standard Obsidian CSS classes to settings tab buttons for improved theme compatibility\n - Fixes issue where themes like Retroma couldn't distinguish active tabs\n - Thanks to @Bregor for the contribution\n\n## Fixed\n\n- (#899) Fixed \"Folder for converted tasks\" setting being hidden when convert button is disabled\n - Setting now always visible since it affects command palette task conversion\n - Resolves confusion for users who convert tasks via command palette\n - Thanks to @nnnell for the fix\n\n- (#905), (#907) Fixed project filter incorrectly affecting custom field suggestions\n - Custom field wikilink suggestions (`[[`) now show all vault files instead of only filtered projects\n - Task Edit modal now uses consistent hierarchical tag matching with Task Creation modal\n - Thanks to @renatomen for the thorough fix and tests\n","aliases":["/releases/3.25.3/","/releases/3.25.3/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • (#877) Added standard Obsidian CSS classes to settings tab buttons for improved theme compatibility
      \n
    • Fixes issue where themes like Retroma couldn't distinguish active tabs
    • \n
    • Thanks to @Bregor for the contribution
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#899) Fixed "Folder for converted tasks" setting being hidden when convert button is disabled

    \n
      \n
    • Setting now always visible since it affects command palette task conversion
    • \n
    • Resolves confusion for users who convert tasks via command palette
    • \n
    • Thanks to @nnnell for the fix
    • \n
    \n
  • \n
  • (#905), (#907) Fixed project filter incorrectly affecting custom field suggestions

    \n
      \n
    • Custom field wikilink suggestions ([[) now show all vault files instead of only filtered projects
    • \n
    • Task Edit modal now uses consistent hierarchical tag matching with Task Creation modal
    • \n
    • Thanks to @renatomen for the thorough fix and tests
    • \n
    \n
  • \n
\n","text":"Added# (#877) Added standard Obsidian CSS classes to settings tab buttons for improved theme compatibility Fixes issue where themes like Retroma couldn't distinguish active tabs Thanks to @Bregor for the contribution Fixed# (#899) Fixed \"Folder for converted tasks\" setting being hidden when convert button is disabled Setting now always visible since it affects command palette task conversion Resolves confusion for users who convert tasks via command palette Thanks to @nnnell for the fix (#905), (#907) Fixed project filter incorrectly affecting custom field suggestions Custom field wikilink suggestions ([[) now show all vault files instead of only filtered projects Task Edit modal now uses consistent hierarchical tag matching with Task Creation modal Thanks to @renatomen for the thorough fix and tests"},{"route":"/obsidian/releases/3.25.4/","title":"TaskNotes 3.25.4","description":"(#937), (#956) Added optional setting to hide identification tags in task cards","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.25.4.md","namespace":"obsidian","relativePath":"releases/3.25.4.md","raw":"# TaskNotes 3.25.4\n\n## Added\n\n- (#937), (#956) Added optional setting to hide identification tags in task cards\n - New \"Hide identification tags in task cards\" setting (only visible when using tag-based identification)\n - Hides exact matches (e.g., `#task`) and hierarchical children (e.g., `#task/project`, `#task/work/urgent`)\n - Reduces visual clutter while keeping tags in frontmatter for organizational purposes\n - Backward compatible - disabled by default\n - Thanks to @renatomen for implementing this feature and @edakimling for reporting\n\n- (#911) Added custom field suggestion filtering\n - New `autosuggestFilter` field to `UserMappedField` interface allows filtering suggestions by current filter context\n - Added collapsible filter section in settings with visual indicator\n - Comprehensive test coverage for custom field filtering feature\n - Thanks to @renatomen for this enhancement\n\n## Fixed\n\n- (#903) Fixed Edit Task modal not adding completedDate when marking tasks as done\n - Edit Task modal now correctly adds completedDate when changing status to completed\n - Fixed Edit Task modal adding empty contexts and projects arrays to frontmatter\n - Behavior now consistent with other completion methods (Agenda view, widget context menu, quick actions)\n - Thanks to @nightroman for reporting\n\n- (#969), (#967) Fixed Bases Kanban layout not displaying correctly when no groupBy is configured\n - All tasks were appearing in a single \"None\" column\n - Columns now appear in the order defined in TaskNotes settings (not alphabetical)\n - Detects invalid Bases grouping and falls back to status-based grouping\n - Tasks are properly distributed across status columns\n - Thanks to @mweichert for the fix and @PacoTaco2, @abuhammer for reporting\n\n","aliases":["/releases/3.25.4/","/releases/3.25.4/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • (#937), (#956) Added optional setting to hide identification tags in task cards

    \n
      \n
    • New "Hide identification tags in task cards" setting (only visible when using tag-based identification)
    • \n
    • Hides exact matches (e.g., #task) and hierarchical children (e.g., #task/project, #task/work/urgent)
    • \n
    • Reduces visual clutter while keeping tags in frontmatter for organizational purposes
    • \n
    • Backward compatible - disabled by default
    • \n
    • Thanks to @renatomen for implementing this feature and @edakimling for reporting
    • \n
    \n
  • \n
  • (#911) Added custom field suggestion filtering

    \n
      \n
    • New autosuggestFilter field to UserMappedField interface allows filtering suggestions by current filter context
    • \n
    • Added collapsible filter section in settings with visual indicator
    • \n
    • Comprehensive test coverage for custom field filtering feature
    • \n
    • Thanks to @renatomen for this enhancement
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#903) Fixed Edit Task modal not adding completedDate when marking tasks as done

    \n
      \n
    • Edit Task modal now correctly adds completedDate when changing status to completed
    • \n
    • Fixed Edit Task modal adding empty contexts and projects arrays to frontmatter
    • \n
    • Behavior now consistent with other completion methods (Agenda view, widget context menu, quick actions)
    • \n
    • Thanks to @nightroman for reporting
    • \n
    \n
  • \n
  • (#969), (#967) Fixed Bases Kanban layout not displaying correctly when no groupBy is configured

    \n
      \n
    • All tasks were appearing in a single "None" column
    • \n
    • Columns now appear in the order defined in TaskNotes settings (not alphabetical)
    • \n
    • Detects invalid Bases grouping and falls back to status-based grouping
    • \n
    • Tasks are properly distributed across status columns
    • \n
    • Thanks to @mweichert for the fix and @PacoTaco2, @abuhammer for reporting
    • \n
    \n
  • \n
\n","text":"Added# (#937), (#956) Added optional setting to hide identification tags in task cards New \"Hide identification tags in task cards\" setting (only visible when using tag-based identification) Hides exact matches (e.g., #task) and hierarchical children (e.g., #task/project, #task/work/urgent) Reduces visual clutter while keeping tags in frontmatter for organizational purposes Backward compatible - disabled by default Thanks to @renatomen for implementing this feature and @edakimling for reporting (#911) Added custom field suggestion filtering New autosuggestFilter field to UserMappedField interface allows filtering suggestions by current filter context Added collapsible filter section in settings with visual indicator Comprehensive test coverage for custom field filtering feature Thanks to @renatomen for this enhancement Fixed# (#903) Fixed Edit Task modal not adding completedDate when marking tasks as done Edit Task modal now correctly adds completedDate when changing status to completed Fixed Edit Task modal adding empty contexts and projects arrays to frontmatter Behavior now consistent with other completion methods (Agenda view, widget context menu, quick actions) Thanks to @nightroman for reporting (#969), (#967) Fixed Bases Kanban layout not displaying correctly when no groupBy is configured All tasks were appearing in a single \"None\" column Columns now appear in the order defined in TaskNotes settings (not alphabetical) Detects invalid Bases grouping and falls back to status-based grouping Tasks are properly distributed across status columns Thanks to @mweichert for the fix and @PacoTaco2, @abuhammer for reporting"},{"route":"/obsidian/releases/3.25.6/","title":"Tasknotes 3.25.6","description":"(#1013) Fixed inability to subscribe to Apple iCloud calendars","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.25.6.md","namespace":"obsidian","relativePath":"releases/3.25.6.md","raw":"# Tasknotes 3.25.6\n\n## Fixed\n\n- (#1013) Fixed inability to subscribe to Apple iCloud calendars\n - Calendar URLs copied from Apple Calendar (starting with webcal://) can now be pasted directly\n - Previously required manually changing the URL format before it would be accepted\n - Works with both standard and secure calendar URLs (webcal:// and webcals://)\n - Thanks to @nickbirch51 for reporting\n\n- (#1022) Fixed tasks randomly disappearing from views and not being recognized\n - Tasks would appear initially but disappear after a few seconds, especially during long sessions\n - Restarting Obsidian or using \"Refresh Cache\" would only temporarily fix the issue\n - Thanks to @seepage87 for reporting and @alejandrospoz for help debugging\n\n- (#968) Fixed timeEntries being duplicated when mapped to custom property name\n - When timeEntries was configured to use a custom property name in Metadata settings (e.g., time_entries), saving tasks would create duplicate entries in both the custom property and the default timeEntries property\n - FieldMapper now correctly uses only the configured property name for time tracking data\n - Thanks to @minchinweb for reporting this issue \n\n- (#953) Fixed non-task notes incorrectly appearing as subtasks in views\n - Notes with Parent or project properties but no task tag/property no longer show up as tasks\n - Views now update correctly when task tags are removed from files\n - Improved performance for large vaults by optimizing cache invalidation\n - Thanks to @renatomen for reporting and submitting PR #955\n","aliases":["/releases/3.25.6/","/releases/3.25.6/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Fixed#

\n
    \n
  • (#1013) Fixed inability to subscribe to Apple iCloud calendars

    \n
      \n
    • Calendar URLs copied from Apple Calendar (starting with webcal://) can now be pasted directly
    • \n
    • Previously required manually changing the URL format before it would be accepted
    • \n
    • Works with both standard and secure calendar URLs (webcal:// and webcals://)
    • \n
    • Thanks to @nickbirch51 for reporting
    • \n
    \n
  • \n
  • (#1022) Fixed tasks randomly disappearing from views and not being recognized

    \n
      \n
    • Tasks would appear initially but disappear after a few seconds, especially during long sessions
    • \n
    • Restarting Obsidian or using "Refresh Cache" would only temporarily fix the issue
    • \n
    • Thanks to @seepage87 for reporting and @alejandrospoz for help debugging
    • \n
    \n
  • \n
  • (#968) Fixed timeEntries being duplicated when mapped to custom property name

    \n
      \n
    • When timeEntries was configured to use a custom property name in Metadata settings (e.g., time_entries), saving tasks would create duplicate entries in both the custom property and the default timeEntries property
    • \n
    • FieldMapper now correctly uses only the configured property name for time tracking data
    • \n
    • Thanks to @minchinweb for reporting this issue
    • \n
    \n
  • \n
  • (#953) Fixed non-task notes incorrectly appearing as subtasks in views

    \n
      \n
    • Notes with Parent or project properties but no task tag/property no longer show up as tasks
    • \n
    • Views now update correctly when task tags are removed from files
    • \n
    • Improved performance for large vaults by optimizing cache invalidation
    • \n
    • Thanks to @renatomen for reporting and submitting PR #955
    • \n
    \n
  • \n
\n","text":"Fixed# (#1013) Fixed inability to subscribe to Apple iCloud calendars Calendar URLs copied from Apple Calendar (starting with webcal://) can now be pasted directly Previously required manually changing the URL format before it would be accepted Works with both standard and secure calendar URLs (webcal:// and webcals://) Thanks to @nickbirch51 for reporting (#1022) Fixed tasks randomly disappearing from views and not being recognized Tasks would appear initially but disappear after a few seconds, especially during long sessions Restarting Obsidian or using \"Refresh Cache\" would only temporarily fix the issue Thanks to @seepage87 for reporting and @alejandrospoz for help debugging (#968) Fixed timeEntries being duplicated when mapped to custom property name When timeEntries was configured to use a custom property name in Metadata settings (e.g., time_entries), saving tasks would create duplicate entries in both the custom property and the default timeEntries property FieldMapper now correctly uses only the configured property name for time tracking data Thanks to @minchinweb for reporting this issue (#953) Fixed non-task notes incorrectly appearing as subtasks in views Notes with Parent or project properties but no task tag/property no longer show up as tasks Views now update correctly when task tags are removed from files Improved performance for large vaults by optimizing cache invalidation Thanks to @renatomen for reporting and submitting PR #955"},{"route":"/obsidian/releases/3.3.0/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.1.1...3.3.0","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.3.0.md","namespace":"obsidian","relativePath":"releases/3.3.0.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.1.1...3.3.0\n","aliases":["/releases/3.3.0/","/releases/3.3.0/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.1.1...3.3.0

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.1.1...3.3.0"},{"route":"/obsidian/releases/3.4.0/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.3.0...3.4.0","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.4.0.md","namespace":"obsidian","relativePath":"releases/3.4.0.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.3.0...3.4.0\n","aliases":["/releases/3.4.0/","/releases/3.4.0/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.3.0...3.4.0

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.3.0...3.4.0"},{"route":"/obsidian/releases/3.4.1/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.0...3.4.1","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.4.1.md","namespace":"obsidian","relativePath":"releases/3.4.1.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.4.0...3.4.1\n","aliases":["/releases/3.4.1/","/releases/3.4.1/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.0...3.4.1

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.0...3.4.1"},{"route":"/obsidian/releases/3.4.2/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.1...3.4.2","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.4.2.md","namespace":"obsidian","relativePath":"releases/3.4.2.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.4.1...3.4.2\n","aliases":["/releases/3.4.2/","/releases/3.4.2/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.1...3.4.2

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.1...3.4.2"},{"route":"/obsidian/releases/3.5.1/","title":"Untitled","description":"This release focusses on significant performance improvements by migrating away from the baroque plugin caching system to Obsidian's native cache.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.5.1.md","namespace":"obsidian","relativePath":"releases/3.5.1.md","raw":"This release focusses on significant performance improvements by migrating away from the baroque plugin caching system to Obsidian's native cache.\r\n\r\n**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.4.0...3.5.1\n","aliases":["/releases/3.5.1/","/releases/3.5.1/"],"toc":[],"html":"

This release focusses on significant performance improvements by migrating away from the baroque plugin caching system to Obsidian's native cache.

\n

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.0...3.5.1

\n","text":"This release focusses on significant performance improvements by migrating away from the baroque plugin caching system to Obsidian's native cache. Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.0...3.5.1"},{"route":"/obsidian/releases/3.6.0/","title":"Untitled","description":"Fix task tag check. Add optional timeblocking.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.6.0.md","namespace":"obsidian","relativePath":"releases/3.6.0.md","raw":"Fix task tag check. \r\nAdd optional timeblocking. \n","aliases":["/releases/3.6.0/","/releases/3.6.0/"],"toc":[],"html":"

Fix task tag check. \nAdd optional timeblocking.

\n","text":"Fix task tag check. Add optional timeblocking."},{"route":"/obsidian/releases/3.7.0/","title":"TaskNotes v3.7.0 Release Notes","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.6.0...3.7.0","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.7.0.md","namespace":"obsidian","relativePath":"releases/3.7.0.md","raw":"# TaskNotes v3.7.0 Release Notes\r\n\r\n### Reading Mode Task Previews (thank you @amithkk)\r\n\r\n- Task link previews now work in Reading Mode in addition to Live Preview \r\n- Consistent interactive experience across all Obsidian view modes\r\n- Same functionality: click to edit, right-click for context menu, hover for file preview\r\n- New ReadingModeTaskLinkProcessor.ts with dedicated CSS styling\r\n\r\n### Task Action Palette\r\n\r\n- New quick-action command palette for rapid task management\r\n- Access via command palette: \"TaskNotes: Open Task Action Palette\"\r\n- Change status/priority with fuzzy search, set dates, start/stop timers, archive/delete tasks\r\n- Handles recurring task instances vs. series intelligently\r\n- Fully keyboard navigable with categorized actions\r\n\r\n### Natural Language Task Input\r\n\r\n- Parse natural language when creating tasks: \"Buy groceries tomorrow 3pm high priority @home #errands\"\r\n- Powered by chrono-node for robust date/time parsing\r\n- Extracts dates, priorities, status, contexts (@), tags (#), recurrence, and time estimates\r\n- Multi-line support: first line parsed, additional lines become task details\r\n- Toggle in Settings → Basic Defaults\r\n\r\n## UI/UX Improvements\r\n\r\n### Enhanced Task Creation Modal\r\n\r\n- Smart input mode with simplified interface when natural language is enabled\r\n- Progressive disclosure to detailed form when needed\r\n- Better conversion flow with pre-populated forms\r\n- Live filename preview as you type\r\n\r\n### Settings & Modal Improvements\r\n\r\n- Moved Natural Language Input to Basic Defaults section\r\n- Updated task link overlay description to mention both view modes\r\n- Reusable confirmation modal for consistent dialogs\r\n- Better error handling and accessibility improvements\r\n\r\n## Bug Fixes\r\n\r\n### Fixed: Inline Tasks Not Respecting Default Status & Priority (Issue #58)\r\n\r\n- Problem: Inline task conversion applied \"none\" instead of configured defaults\r\n- Solution: Changed useDefaultsOnInstantConvert default from false to true\r\n\r\n### Timer Function Standardization\r\n\r\n- Fixed browser compatibility by replacing Node.js timer types with browser-native timers\r\n- Resolved timing issues across different environments\r\n\r\n### Enhanced Task Link Overlays\r\n\r\n- Better path resolution with security enhancements\r\n- Graceful fallbacks for invalid or missing task files\r\n- Improved handling of rapid view changes\r\n\r\n## Technical Improvements\r\n\r\n### Enhanced Date Support\r\n\r\n- Full due date and scheduled date support in task creation and filename generation\r\n- New filename template variables: {dueDate} and {scheduledDate} (YYYY-MM-DD format)\r\n- Support for ISO dates, relative dates, named dates, and natural language\r\n\r\n### Performance & Code Quality\r\n\r\n- Improved event handling with better refresh logic\r\n- Layout change listeners for immediate overlay updates\r\n- Enhanced error handling with user-friendly messages\r\n- Better TypeScript types and modular design\r\n\r\n## New Files & Dependencies\r\n\r\n### New Files\r\n\r\n- src/editor/ReadingModeTaskLinkProcessor.ts\r\n- src/modals/TaskActionPaletteModal.ts\r\n- src/services/NaturalLanguageParser.ts\r\n- src/modals/ConfirmationModal.ts\r\n- styles/task-action-palette-modal.css\r\n\r\n### New Dependency\r\n\r\n- chrono-node: Natural language date parsing library\r\n\r\n## What's Changed\r\n* Feat/task previews in reading mode by @amithkk in https://github.com/callumalpass/tasknotes/pull/57\r\n\r\n## New Contributors\r\n* @amithkk made their first contribution in https://github.com/callumalpass/tasknotes/pull/57\r\n\r\n**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.6.0...3.7.0\n","aliases":["/releases/3.7.0/","/releases/3.7.0/"],"toc":[{"level":3,"id":"reading-mode-task-previews-thank-you-amithkk","text":"Reading Mode Task Previews (thank you @amithkk)"},{"level":3,"id":"task-action-palette","text":"Task Action Palette"},{"level":3,"id":"natural-language-task-input","text":"Natural Language Task Input"},{"level":2,"id":"uiux-improvements","text":"UI/UX Improvements"},{"level":3,"id":"enhanced-task-creation-modal","text":"Enhanced Task Creation Modal"},{"level":3,"id":"settings-modal-improvements","text":"Settings & Modal Improvements"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"},{"level":3,"id":"fixed-inline-tasks-not-respecting-default-status-priority-issue-58","text":"Fixed: Inline Tasks Not Respecting Default Status & Priority (Issue #58)"},{"level":3,"id":"timer-function-standardization","text":"Timer Function Standardization"},{"level":3,"id":"enhanced-task-link-overlays","text":"Enhanced Task Link Overlays"},{"level":2,"id":"technical-improvements","text":"Technical Improvements"},{"level":3,"id":"enhanced-date-support","text":"Enhanced Date Support"},{"level":3,"id":"performance-code-quality","text":"Performance & Code Quality"},{"level":2,"id":"new-files-dependencies","text":"New Files & Dependencies"},{"level":3,"id":"new-files","text":"New Files"},{"level":3,"id":"new-dependency","text":"New Dependency"},{"level":2,"id":"what39s-changed","text":"What's Changed"},{"level":2,"id":"new-contributors","text":"New Contributors"}],"html":"

Reading Mode Task Previews (thank you @amithkk)#

\n
    \n
  • Task link previews now work in Reading Mode in addition to Live Preview
  • \n
  • Consistent interactive experience across all Obsidian view modes
  • \n
  • Same functionality: click to edit, right-click for context menu, hover for file preview
  • \n
  • New ReadingModeTaskLinkProcessor.ts with dedicated CSS styling
  • \n
\n

Task Action Palette#

\n
    \n
  • New quick-action command palette for rapid task management
  • \n
  • Access via command palette: "TaskNotes: Open Task Action Palette"
  • \n
  • Change status/priority with fuzzy search, set dates, start/stop timers, archive/delete tasks
  • \n
  • Handles recurring task instances vs. series intelligently
  • \n
  • Fully keyboard navigable with categorized actions
  • \n
\n

Natural Language Task Input#

\n
    \n
  • Parse natural language when creating tasks: "Buy groceries tomorrow 3pm high priority @home #errands"
  • \n
  • Powered by chrono-node for robust date/time parsing
  • \n
  • Extracts dates, priorities, status, contexts (@), tags (#), recurrence, and time estimates
  • \n
  • Multi-line support: first line parsed, additional lines become task details
  • \n
  • Toggle in Settings → Basic Defaults
  • \n
\n

UI/UX Improvements#

\n

Enhanced Task Creation Modal#

\n
    \n
  • Smart input mode with simplified interface when natural language is enabled
  • \n
  • Progressive disclosure to detailed form when needed
  • \n
  • Better conversion flow with pre-populated forms
  • \n
  • Live filename preview as you type
  • \n
\n

Settings & Modal Improvements#

\n
    \n
  • Moved Natural Language Input to Basic Defaults section
  • \n
  • Updated task link overlay description to mention both view modes
  • \n
  • Reusable confirmation modal for consistent dialogs
  • \n
  • Better error handling and accessibility improvements
  • \n
\n

Bug Fixes#

\n

Fixed: Inline Tasks Not Respecting Default Status & Priority (Issue #58)#

\n
    \n
  • Problem: Inline task conversion applied "none" instead of configured defaults
  • \n
  • Solution: Changed useDefaultsOnInstantConvert default from false to true
  • \n
\n

Timer Function Standardization#

\n
    \n
  • Fixed browser compatibility by replacing Node.js timer types with browser-native timers
  • \n
  • Resolved timing issues across different environments
  • \n
\n\n
    \n
  • Better path resolution with security enhancements
  • \n
  • Graceful fallbacks for invalid or missing task files
  • \n
  • Improved handling of rapid view changes
  • \n
\n

Technical Improvements#

\n

Enhanced Date Support#

\n
    \n
  • Full due date and scheduled date support in task creation and filename generation
  • \n
  • New filename template variables: {dueDate} and {scheduledDate} (YYYY-MM-DD format)
  • \n
  • Support for ISO dates, relative dates, named dates, and natural language
  • \n
\n

Performance & Code Quality#

\n
    \n
  • Improved event handling with better refresh logic
  • \n
  • Layout change listeners for immediate overlay updates
  • \n
  • Enhanced error handling with user-friendly messages
  • \n
  • Better TypeScript types and modular design
  • \n
\n

New Files & Dependencies#

\n

New Files#

\n
    \n
  • src/editor/ReadingModeTaskLinkProcessor.ts
  • \n
  • src/modals/TaskActionPaletteModal.ts
  • \n
  • src/services/NaturalLanguageParser.ts
  • \n
  • src/modals/ConfirmationModal.ts
  • \n
  • styles/task-action-palette-modal.css
  • \n
\n

New Dependency#

\n
    \n
  • chrono-node: Natural language date parsing library
  • \n
\n

What's Changed#

\n\n

New Contributors#

\n\n

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.6.0...3.7.0

\n","text":"Reading Mode Task Previews (thank you @amithkk)# Task link previews now work in Reading Mode in addition to Live Preview Consistent interactive experience across all Obsidian view modes Same functionality: click to edit, right-click for context menu, hover for file preview New ReadingModeTaskLinkProcessor.ts with dedicated CSS styling Task Action Palette# New quick-action command palette for rapid task management Access via command palette: \"TaskNotes: Open Task Action Palette\" Change status/priority with fuzzy search, set dates, start/stop timers, archive/delete tasks Handles recurring task instances vs. series intelligently Fully keyboard navigable with categorized actions Natural Language Task Input# Parse natural language when creating tasks: \"Buy groceries tomorrow 3pm high priority @home #errands\" Powered by chrono-node for robust date/time parsing Extracts dates, priorities, status, contexts (@), tags (#), recurrence, and time estimates Multi-line support: first line parsed, additional lines become task details Toggle in Settings → Basic Defaults UI/UX Improvements# Enhanced Task Creation Modal# Smart input mode with simplified interface when natural language is enabled Progressive disclosure to detailed form when needed Better conversion flow with pre-populated forms Live filename preview as you type Settings & Modal Improvements# Moved Natural Language Input to Basic Defaults section Updated task link overlay description to mention both view modes Reusable confirmation modal for consistent dialogs Better error handling and accessibility improvements Bug Fixes# Fixed: Inline Tasks Not Respecting Default Status & Priority (Issue #58)# Problem: Inline task conversion applied \"none\" instead of configured defaults Solution: Changed useDefaultsOnInstantConvert default from false to true Timer Function Standardization# Fixed browser compatibility by replacing Node.js timer types with browser-native timers Resolved timing issues across different environments Enhanced Task Link Overlays# Better path resolution with security enhancements Graceful fallbacks for invalid or missing task files Improved handling of rapid view changes Technical Improvements# Enhanced Date Support# Full due date and scheduled date support in task creation and filename generation New filename template variables: {dueDate} and {scheduledDate} (YYYY-MM-DD format) Support for ISO dates, relative dates, named dates, and natural language Performance & Code Quality# Improved event handling with better refresh logic Layout change listeners for immediate overlay updates Enhanced error handling with user-friendly messages Better TypeScript types and modular design New Files & Dependencies# New Files# src/editor/ReadingModeTaskLinkProcessor.ts src/modals/TaskActionPaletteModal.ts src/services/NaturalLanguageParser.ts src/modals/ConfirmationModal.ts styles/task-action-palette-modal.css New Dependency# chrono-node: Natural language date parsing library What's Changed# Feat/task previews in reading mode by @amithkk in https://github.com/callumalpass/tasknotes/pull/57 New Contributors# @amithkk made their first contribution in https://github.com/callumalpass/tasknotes/pull/57 Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.6.0...3.7.0"},{"route":"/obsidian/releases/3.7.1/","title":"Version 3.7.1","description":"Files with Major Changes:","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.7.1.md","namespace":"obsidian","relativePath":"releases/3.7.1.md","raw":"# Version 3.7.1\r\n\r\n## Major UI/UX Enhancements\r\n\r\n### Interactive Inline Task Previews\r\n\r\n- Clickable Status Dots: Status indicators in inline task previews are now interactive - click to cycle through task statuses directly from the preview\r\n- Clickable Date Fields: Due and scheduled dates are now clickable and open dedicated modals for quick editing\r\n- Enhanced Visual Design:\r\n - Redesigned with minimal styling\r\n - Improved spacing and vertical alignment between status dots, priority indicators, and task titles\r\n - Better hover effects with brightness and subtle animations\r\n - Status dots now use bordered design for better visibility\r\n\r\n### Modernized Task Card Design\r\n\r\n- Interactive Status Cycling: Click status dots on task cards to quickly change task status\r\n- Improved Mobile Support: Better touch targets and responsive behavior\r\n- Enhanced Animations: Smooth hover effects, scaling, and transition animations\r\n- Cleaner Layout: Streamlined design with better visual hierarchy\r\n\r\n### Enhanced Natural Language Processing\r\n\r\n#### Advanced Date Parsing\r\n\r\n- Explicit Trigger Recognition: Now recognizes specific phrases:\r\n - Due dates: \"due on\", \"deadline\", \"must be done by\", \"needs to be completed\"\r\n - Scheduled dates: \"scheduled for\", \"start on\", \"work on\", \"planned for\"\r\n- Configurable Defaults: New setting to choose whether ambiguous dates default to \"due\" or \"scheduled\"\r\n- Enhanced Recurrence Patterns:\r\n - \"every [weekday]\" patterns (every monday, every friday)\r\n - Plural day patterns (mondays, tuesdays, etc.)\r\n - \"Every other\" interval patterns (every other week, every 2 days)\r\n - Multiple days (\"every tuesday and thursday\")\r\n\r\n#### Improved Date/Time Handling\r\n\r\n- Better Time Component Support: Enhanced parsing of specific times with dates\r\n- Robust Validation: Improved handling of edge cases and malformed input\r\n- Smart Cleanup: Automatic removal of duplicate tags and contexts\r\n\r\n## Performance & Developer Experience\r\n\r\n### Instant Task Conversion Improvements\r\n\r\n- Real-time Updates: Task link overlays refresh immediately after task conversion\r\n- Smart Caching: Improved metadata cache management for newly created tasks\r\n- Better Error Handling: Enhanced validation with user-friendly error messages\r\n- Multi-line Support: Enhanced conversion of tasks with details from multiple selected lines\r\n\r\n### Technical Improvements\r\n\r\n- Improved Event Handling: Fixed n.dispatch is not a function error with proper validation\r\n- BEM CSS Methodology: Migrated to Block Element Modifier naming for better CSS organization\r\n- Performance Optimizations: Reduced unnecessary re-renders and improved widget caching\r\n- Enhanced State Management: Better synchronization between UI updates and task data\r\n\r\n## Modal & Interface Enhancements\r\n\r\n### Enhanced Date/Time Modals\r\n\r\n- Better Keyboard Navigation: Enter to save, Escape to cancel\r\n- Separate Time Inputs: Dedicated date and time fields for precision\r\n- Quick Date Buttons: Common date selections for faster input\r\n- Improved Accessibility: Proper ARIA labels and screen reader support\r\n\r\n### Better User Experience\r\n\r\n- One-Click Status Changes: Direct status cycling from any task preview\r\n- Direct Date Editing: Click any date to immediately edit it\r\n- Enhanced Visual Feedback: Better hover states, transitions, and loading animations\r\n- Accessibility Improvements: Enhanced keyboard navigation and screen reader support\r\n\r\n### Bug Fixes & Stability\r\n\r\n- Fixed: Inline task widget dispatch errors that caused console warnings\r\n- Fixed: Vertical alignment issues with different-sized status and priority indicators\r\n- Fixed: Layout conflicts between flexbox and inline display properties\r\n- Fixed: Spacing issues in inline task previews causing cramped appearance\r\n- Fixed: Missing task link overlay refreshes after instant task conversion\r\n\r\n## Configuration & Settings\r\n\r\n### New User Settings\r\n\r\n- Natural Language Default: Configure whether ambiguous dates default to \"due\" or \"scheduled\"\r\n- Enhanced Task Creation: Improved default value application for instant task conversion\r\n\r\n## Technical Details\r\n\r\nFiles with Major Changes:\r\n- Enhanced inline task previews (TaskLinkWidget.ts, TaskLinkOverlay.ts)\r\n- Modernized task card design (TaskCard.ts)\r\n- Advanced natural language processing (NaturalLanguageParser.ts)\r\n- Improved modal interfaces (DueDateModal.ts, ScheduledDateModal.ts)\r\n- Comprehensive CSS overhaul with BEM methodology\r\n","aliases":["/releases/3.7.1/","/releases/3.7.1/"],"toc":[{"level":2,"id":"major-uiux-enhancements","text":"Major UI/UX Enhancements"},{"level":3,"id":"interactive-inline-task-previews","text":"Interactive Inline Task Previews"},{"level":3,"id":"modernized-task-card-design","text":"Modernized Task Card Design"},{"level":3,"id":"enhanced-natural-language-processing","text":"Enhanced Natural Language Processing"},{"level":2,"id":"performance-developer-experience","text":"Performance & Developer Experience"},{"level":3,"id":"instant-task-conversion-improvements","text":"Instant Task Conversion Improvements"},{"level":3,"id":"technical-improvements","text":"Technical Improvements"},{"level":2,"id":"modal-interface-enhancements","text":"Modal & Interface Enhancements"},{"level":3,"id":"enhanced-datetime-modals","text":"Enhanced Date/Time Modals"},{"level":3,"id":"better-user-experience","text":"Better User Experience"},{"level":3,"id":"bug-fixes-stability","text":"Bug Fixes & Stability"},{"level":2,"id":"configuration-settings","text":"Configuration & Settings"},{"level":3,"id":"new-user-settings","text":"New User Settings"},{"level":2,"id":"technical-details","text":"Technical Details"}],"html":"

Major UI/UX Enhancements#

\n

Interactive Inline Task Previews#

\n
    \n
  • Clickable Status Dots: Status indicators in inline task previews are now interactive - click to cycle through task statuses directly from the preview
  • \n
  • Clickable Date Fields: Due and scheduled dates are now clickable and open dedicated modals for quick editing
  • \n
  • Enhanced Visual Design:
      \n
    • Redesigned with minimal styling
    • \n
    • Improved spacing and vertical alignment between status dots, priority indicators, and task titles
    • \n
    • Better hover effects with brightness and subtle animations
    • \n
    • Status dots now use bordered design for better visibility
    • \n
    \n
  • \n
\n

Modernized Task Card Design#

\n
    \n
  • Interactive Status Cycling: Click status dots on task cards to quickly change task status
  • \n
  • Improved Mobile Support: Better touch targets and responsive behavior
  • \n
  • Enhanced Animations: Smooth hover effects, scaling, and transition animations
  • \n
  • Cleaner Layout: Streamlined design with better visual hierarchy
  • \n
\n

Enhanced Natural Language Processing#

\n

Advanced Date Parsing#

\n
    \n
  • Explicit Trigger Recognition: Now recognizes specific phrases:
      \n
    • Due dates: "due on", "deadline", "must be done by", "needs to be completed"
    • \n
    • Scheduled dates: "scheduled for", "start on", "work on", "planned for"
    • \n
    \n
  • \n
  • Configurable Defaults: New setting to choose whether ambiguous dates default to "due" or "scheduled"
  • \n
  • Enhanced Recurrence Patterns:
      \n
    • "every [weekday]" patterns (every monday, every friday)
    • \n
    • Plural day patterns (mondays, tuesdays, etc.)
    • \n
    • "Every other" interval patterns (every other week, every 2 days)
    • \n
    • Multiple days ("every tuesday and thursday")
    • \n
    \n
  • \n
\n

Improved Date/Time Handling#

\n
    \n
  • Better Time Component Support: Enhanced parsing of specific times with dates
  • \n
  • Robust Validation: Improved handling of edge cases and malformed input
  • \n
  • Smart Cleanup: Automatic removal of duplicate tags and contexts
  • \n
\n

Performance & Developer Experience#

\n

Instant Task Conversion Improvements#

\n
    \n
  • Real-time Updates: Task link overlays refresh immediately after task conversion
  • \n
  • Smart Caching: Improved metadata cache management for newly created tasks
  • \n
  • Better Error Handling: Enhanced validation with user-friendly error messages
  • \n
  • Multi-line Support: Enhanced conversion of tasks with details from multiple selected lines
  • \n
\n

Technical Improvements#

\n
    \n
  • Improved Event Handling: Fixed n.dispatch is not a function error with proper validation
  • \n
  • BEM CSS Methodology: Migrated to Block Element Modifier naming for better CSS organization
  • \n
  • Performance Optimizations: Reduced unnecessary re-renders and improved widget caching
  • \n
  • Enhanced State Management: Better synchronization between UI updates and task data
  • \n
\n

Modal & Interface Enhancements#

\n

Enhanced Date/Time Modals#

\n
    \n
  • Better Keyboard Navigation: Enter to save, Escape to cancel
  • \n
  • Separate Time Inputs: Dedicated date and time fields for precision
  • \n
  • Quick Date Buttons: Common date selections for faster input
  • \n
  • Improved Accessibility: Proper ARIA labels and screen reader support
  • \n
\n

Better User Experience#

\n
    \n
  • One-Click Status Changes: Direct status cycling from any task preview
  • \n
  • Direct Date Editing: Click any date to immediately edit it
  • \n
  • Enhanced Visual Feedback: Better hover states, transitions, and loading animations
  • \n
  • Accessibility Improvements: Enhanced keyboard navigation and screen reader support
  • \n
\n

Bug Fixes & Stability#

\n
    \n
  • Fixed: Inline task widget dispatch errors that caused console warnings
  • \n
  • Fixed: Vertical alignment issues with different-sized status and priority indicators
  • \n
  • Fixed: Layout conflicts between flexbox and inline display properties
  • \n
  • Fixed: Spacing issues in inline task previews causing cramped appearance
  • \n
  • Fixed: Missing task link overlay refreshes after instant task conversion
  • \n
\n

Configuration & Settings#

\n

New User Settings#

\n
    \n
  • Natural Language Default: Configure whether ambiguous dates default to "due" or "scheduled"
  • \n
  • Enhanced Task Creation: Improved default value application for instant task conversion
  • \n
\n

Technical Details#

\n

Files with Major Changes:

\n
    \n
  • Enhanced inline task previews (TaskLinkWidget.ts, TaskLinkOverlay.ts)
  • \n
  • Modernized task card design (TaskCard.ts)
  • \n
  • Advanced natural language processing (NaturalLanguageParser.ts)
  • \n
  • Improved modal interfaces (DueDateModal.ts, ScheduledDateModal.ts)
  • \n
  • Comprehensive CSS overhaul with BEM methodology
  • \n
\n","text":"Major UI/UX Enhancements# Interactive Inline Task Previews# Clickable Status Dots: Status indicators in inline task previews are now interactive - click to cycle through task statuses directly from the preview Clickable Date Fields: Due and scheduled dates are now clickable and open dedicated modals for quick editing Enhanced Visual Design: Redesigned with minimal styling Improved spacing and vertical alignment between status dots, priority indicators, and task titles Better hover effects with brightness and subtle animations Status dots now use bordered design for better visibility Modernized Task Card Design# Interactive Status Cycling: Click status dots on task cards to quickly change task status Improved Mobile Support: Better touch targets and responsive behavior Enhanced Animations: Smooth hover effects, scaling, and transition animations Cleaner Layout: Streamlined design with better visual hierarchy Enhanced Natural Language Processing# Advanced Date Parsing# Explicit Trigger Recognition: Now recognizes specific phrases: Due dates: \"due on\", \"deadline\", \"must be done by\", \"needs to be completed\" Scheduled dates: \"scheduled for\", \"start on\", \"work on\", \"planned for\" Configurable Defaults: New setting to choose whether ambiguous dates default to \"due\" or \"scheduled\" Enhanced Recurrence Patterns: \"every [weekday]\" patterns (every monday, every friday) Plural day patterns (mondays, tuesdays, etc.) \"Every other\" interval patterns (every other week, every 2 days) Multiple days (\"every tuesday and thursday\") Improved Date/Time Handling# Better Time Component Support: Enhanced parsing of specific times with dates Robust Validation: Improved handling of edge cases and malformed input Smart Cleanup: Automatic removal of duplicate tags and contexts Performance & Developer Experience# Instant Task Conversion Improvements# Real-time Updates: Task link overlays refresh immediately after task conversion Smart Caching: Improved metadata cache management for newly created tasks Better Error Handling: Enhanced validation with user-friendly error messages Multi-line Support: Enhanced conversion of tasks with details from multiple selected lines Technical Improvements# Improved Event Handling: Fixed n.dispatch is not a function error with proper validation BEM CSS Methodology: Migrated to Block Element Modifier naming for better CSS organization Performance Optimizations: Reduced unnecessary re-renders and improved widget caching Enhanced State Management: Better synchronization between UI updates and task data Modal & Interface Enhancements# Enhanced Date/Time Modals# Better Keyboard Navigation: Enter to save, Escape to cancel Separate Time Inputs: Dedicated date and time fields for precision Quick Date Buttons: Common date selections for faster input Improved Accessibility: Proper ARIA labels and screen reader support Better User Experience# One-Click Status Changes: Direct status cycling from any task preview Direct Date Editing: Click any date to immediately edit it Enhanced Visual Feedback: Better hover states, transitions, and loading animations Accessibility Improvements: Enhanced keyboard navigation and screen reader support Bug Fixes & Stability# Fixed: Inline task widget dispatch errors that caused console warnings Fixed: Vertical alignment issues with different-sized status and priority indicators Fixed: Layout conflicts between flexbox and inline display properties Fixed: Spacing issues in inline task previews causing cramped appearance Fixed: Missing task link overlay refreshes after instant task conversion Configuration & Settings# New User Settings# Natural Language Default: Configure whether ambiguous dates default to \"due\" or \"scheduled\" Enhanced Task Creation: Improved default value application for instant task conversion Technical Details# Files with Major Changes: Enhanced inline task previews (TaskLinkWidget.ts, TaskLinkOverlay.ts) Modernized task card design (TaskCard.ts) Advanced natural language processing (NaturalLanguageParser.ts) Improved modal interfaces (DueDateModal.ts, ScheduledDateModal.ts) Comprehensive CSS overhaul with BEM methodology"},{"route":"/obsidian/releases/3.8.1/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.7.1...3.8.1","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.8.1.md","namespace":"obsidian","relativePath":"releases/3.8.1.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.7.1...3.8.1\n","aliases":["/releases/3.8.1/","/releases/3.8.1/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.7.1...3.8.1

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.7.1...3.8.1"},{"route":"/obsidian/releases/3.8.5/","title":"TaskNotes 3.8.5 Release Notes","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.1...3.8.5","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.8.5.md","namespace":"obsidian","relativePath":"releases/3.8.5.md","raw":"# TaskNotes 3.8.5 Release Notes\r\n\r\n## UI/UX Improvements\r\n\r\n### Compact Filter Bar (Special thanks to @amithkk :tada: )\r\n\r\n- Complete redesign of FilterBar component with compact, modern interface\r\n- Native Obsidian dropdowns replace basic HTML select elements for better consistency\r\n- Collapsible controls - settings are hidden by default with expandable controls via settings button\r\n- Visual indicators showing active filter count on settings button\r\n- Integrated search bar with search icon and improved visual hierarchy\r\n- Right-aligned control buttons for better layout organization\r\n\r\n### Advanced Calendar View Integration\r\n\r\n- Unified view options - calendar view toggles now integrated into FilterBar dropdown\r\n- Streamlined interface - removed separate toggle controls in favor of FilterBar integration\r\n- Consistent UX across different view types with shared filter/view controls\r\n- Dynamic option management with real-time updates and state synchronization\r\n\r\n## Enhanced Natural Language Processing\r\n\r\n### Improved Text Processing\r\n\r\n- Better whitespace handling with new cleanupWhitespace() function for consistent text normalization\r\n- Enhanced priority detection with improved pattern matching and conflict resolution\r\n- Completion status support - added isCompleted field to parsed task data\r\n- More robust text extraction across tags, contexts, priorities, and dates\r\n\r\n### Date and Time Handling Improvements\r\n\r\n- Enhanced date parsing with better timezone handling for date-only strings\r\n- Improved date normalization with direct Date constructor to avoid timezone issues\r\n- Better error handling for invalid date strings and edge cases\r\n- More robust timestamp formatting with validation checks\r\n\r\n## Testing Infrastructure\r\n\r\n### Comprehensive Test Suite\r\n\r\n- Complete testing infrastructure with Jest configuration for both unit and integration tests\r\n- Enhanced mocking system with improved Obsidian API mocks and better type safety\r\n- Integration test helpers with utilities for end-to-end workflow testing\r\n- Improved test coverage across core components and services\r\n\r\n### Mock Improvements\r\n\r\n- Updated mock factories with better type consistency and realistic data generation\r\n- Enhanced DOM simulation for better UI component testing\r\n- Improved date-fns mocking with support for \"MMM d, yyyy h:mm a\" format\r\n- Better Obsidian API compatibility in test mocks\r\n\r\n## Developer Experience\r\n\r\n### Type Safety Enhancements\r\n\r\n- Refactored type definitions for improved consistency across the codebase\r\n- Better TypeScript integration with enhanced type checking and inference\r\n- Improved callback types for better development experience\r\n\r\n## Build and Deployment\r\n\r\n- Updated GitHub Actions with artifact uploader v4 for improved CI/CD\r\n- Enhanced development workflow with better testing and build processes\r\n\r\n## User Interface Polish\r\n\r\n### Task Creation Modal\r\n\r\n- Improved placeholder text with more natural language examples\r\n- Better user guidance for natural language task input format\r\n- Clearer instruction formatting for enhanced user experience\r\n\r\n### Visual Consistency\r\n\r\n- Native Obsidian styling throughout filter and control components\r\n- Consistent iconography using Obsidian's icon system\r\n- Improved responsive design with better mobile and small screen support\r\n\r\n## Bug Fixes and Stability\r\n\r\n#### Error Handling\r\n\r\n- Improved error handling in date parsing and normalization functions\r\n- Better validation for user input and edge cases\r\n- Enhanced robustness in text processing and natural language parsing\r\n\r\n### Code Quality\r\n\r\n- Refactored components for better maintainability and performance\r\n- Simplified scheduled date logic with cleaner default handling\r\n- Enhanced code organization with better separation of concerns\r\n\r\n\r\n## What's Changed\r\n\r\n* Add compact filter bar by @amithkk in https://github.com/callumalpass/tasknotes/pull/73\r\n\r\n\r\n**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.8.1...3.8.5\n","aliases":["/releases/3.8.5/","/releases/3.8.5/"],"toc":[{"level":2,"id":"uiux-improvements","text":"UI/UX Improvements"},{"level":3,"id":"compact-filter-bar-special-thanks-to-amithkk-tada","text":"Compact Filter Bar (Special thanks to @amithkk :tada: )"},{"level":3,"id":"advanced-calendar-view-integration","text":"Advanced Calendar View Integration"},{"level":2,"id":"enhanced-natural-language-processing","text":"Enhanced Natural Language Processing"},{"level":3,"id":"improved-text-processing","text":"Improved Text Processing"},{"level":3,"id":"date-and-time-handling-improvements","text":"Date and Time Handling Improvements"},{"level":2,"id":"testing-infrastructure","text":"Testing Infrastructure"},{"level":3,"id":"comprehensive-test-suite","text":"Comprehensive Test Suite"},{"level":3,"id":"mock-improvements","text":"Mock Improvements"},{"level":2,"id":"developer-experience","text":"Developer Experience"},{"level":3,"id":"type-safety-enhancements","text":"Type Safety Enhancements"},{"level":2,"id":"build-and-deployment","text":"Build and Deployment"},{"level":2,"id":"user-interface-polish","text":"User Interface Polish"},{"level":3,"id":"task-creation-modal","text":"Task Creation Modal"},{"level":3,"id":"visual-consistency","text":"Visual Consistency"},{"level":2,"id":"bug-fixes-and-stability","text":"Bug Fixes and Stability"},{"level":3,"id":"code-quality","text":"Code Quality"},{"level":2,"id":"what39s-changed","text":"What's Changed"}],"html":"

UI/UX Improvements#

\n

Compact Filter Bar (Special thanks to @amithkk :tada: )#

\n
    \n
  • Complete redesign of FilterBar component with compact, modern interface
  • \n
  • Native Obsidian dropdowns replace basic HTML select elements for better consistency
  • \n
  • Collapsible controls - settings are hidden by default with expandable controls via settings button
  • \n
  • Visual indicators showing active filter count on settings button
  • \n
  • Integrated search bar with search icon and improved visual hierarchy
  • \n
  • Right-aligned control buttons for better layout organization
  • \n
\n

Advanced Calendar View Integration#

\n
    \n
  • Unified view options - calendar view toggles now integrated into FilterBar dropdown
  • \n
  • Streamlined interface - removed separate toggle controls in favor of FilterBar integration
  • \n
  • Consistent UX across different view types with shared filter/view controls
  • \n
  • Dynamic option management with real-time updates and state synchronization
  • \n
\n

Enhanced Natural Language Processing#

\n

Improved Text Processing#

\n
    \n
  • Better whitespace handling with new cleanupWhitespace() function for consistent text normalization
  • \n
  • Enhanced priority detection with improved pattern matching and conflict resolution
  • \n
  • Completion status support - added isCompleted field to parsed task data
  • \n
  • More robust text extraction across tags, contexts, priorities, and dates
  • \n
\n

Date and Time Handling Improvements#

\n
    \n
  • Enhanced date parsing with better timezone handling for date-only strings
  • \n
  • Improved date normalization with direct Date constructor to avoid timezone issues
  • \n
  • Better error handling for invalid date strings and edge cases
  • \n
  • More robust timestamp formatting with validation checks
  • \n
\n

Testing Infrastructure#

\n

Comprehensive Test Suite#

\n
    \n
  • Complete testing infrastructure with Jest configuration for both unit and integration tests
  • \n
  • Enhanced mocking system with improved Obsidian API mocks and better type safety
  • \n
  • Integration test helpers with utilities for end-to-end workflow testing
  • \n
  • Improved test coverage across core components and services
  • \n
\n

Mock Improvements#

\n
    \n
  • Updated mock factories with better type consistency and realistic data generation
  • \n
  • Enhanced DOM simulation for better UI component testing
  • \n
  • Improved date-fns mocking with support for "MMM d, yyyy h:mm a" format
  • \n
  • Better Obsidian API compatibility in test mocks
  • \n
\n

Developer Experience#

\n

Type Safety Enhancements#

\n
    \n
  • Refactored type definitions for improved consistency across the codebase
  • \n
  • Better TypeScript integration with enhanced type checking and inference
  • \n
  • Improved callback types for better development experience
  • \n
\n

Build and Deployment#

\n
    \n
  • Updated GitHub Actions with artifact uploader v4 for improved CI/CD
  • \n
  • Enhanced development workflow with better testing and build processes
  • \n
\n

User Interface Polish#

\n

Task Creation Modal#

\n
    \n
  • Improved placeholder text with more natural language examples
  • \n
  • Better user guidance for natural language task input format
  • \n
  • Clearer instruction formatting for enhanced user experience
  • \n
\n

Visual Consistency#

\n
    \n
  • Native Obsidian styling throughout filter and control components
  • \n
  • Consistent iconography using Obsidian's icon system
  • \n
  • Improved responsive design with better mobile and small screen support
  • \n
\n

Bug Fixes and Stability#

\n

Error Handling#

\n
    \n
  • Improved error handling in date parsing and normalization functions
  • \n
  • Better validation for user input and edge cases
  • \n
  • Enhanced robustness in text processing and natural language parsing
  • \n
\n

Code Quality#

\n
    \n
  • Refactored components for better maintainability and performance
  • \n
  • Simplified scheduled date logic with cleaner default handling
  • \n
  • Enhanced code organization with better separation of concerns
  • \n
\n

What's Changed#

\n\n

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.1...3.8.5

\n","text":"UI/UX Improvements# Compact Filter Bar (Special thanks to @amithkk :tada: )# Complete redesign of FilterBar component with compact, modern interface Native Obsidian dropdowns replace basic HTML select elements for better consistency Collapsible controls - settings are hidden by default with expandable controls via settings button Visual indicators showing active filter count on settings button Integrated search bar with search icon and improved visual hierarchy Right-aligned control buttons for better layout organization Advanced Calendar View Integration# Unified view options - calendar view toggles now integrated into FilterBar dropdown Streamlined interface - removed separate toggle controls in favor of FilterBar integration Consistent UX across different view types with shared filter/view controls Dynamic option management with real-time updates and state synchronization Enhanced Natural Language Processing# Improved Text Processing# Better whitespace handling with new cleanupWhitespace() function for consistent text normalization Enhanced priority detection with improved pattern matching and conflict resolution Completion status support - added isCompleted field to parsed task data More robust text extraction across tags, contexts, priorities, and dates Date and Time Handling Improvements# Enhanced date parsing with better timezone handling for date-only strings Improved date normalization with direct Date constructor to avoid timezone issues Better error handling for invalid date strings and edge cases More robust timestamp formatting with validation checks Testing Infrastructure# Comprehensive Test Suite# Complete testing infrastructure with Jest configuration for both unit and integration tests Enhanced mocking system with improved Obsidian API mocks and better type safety Integration test helpers with utilities for end-to-end workflow testing Improved test coverage across core components and services Mock Improvements# Updated mock factories with better type consistency and realistic data generation Enhanced DOM simulation for better UI component testing Improved date-fns mocking with support for \"MMM d, yyyy h:mm a\" format Better Obsidian API compatibility in test mocks Developer Experience# Type Safety Enhancements# Refactored type definitions for improved consistency across the codebase Better TypeScript integration with enhanced type checking and inference Improved callback types for better development experience Build and Deployment# Updated GitHub Actions with artifact uploader v4 for improved CI/CD Enhanced development workflow with better testing and build processes User Interface Polish# Task Creation Modal# Improved placeholder text with more natural language examples Better user guidance for natural language task input format Clearer instruction formatting for enhanced user experience Visual Consistency# Native Obsidian styling throughout filter and control components Consistent iconography using Obsidian's icon system Improved responsive design with better mobile and small screen support Bug Fixes and Stability# Error Handling# Improved error handling in date parsing and normalization functions Better validation for user input and edge cases Enhanced robustness in text processing and natural language parsing Code Quality# Refactored components for better maintainability and performance Simplified scheduled date logic with cleaner default handling Enhanced code organization with better separation of concerns What's Changed# Add compact filter bar by @amithkk in https://github.com/callumalpass/tasknotes/pull/73 Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.1...3.8.5"},{"route":"/obsidian/releases/3.8.6/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.5...3.8.6","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.8.6.md","namespace":"obsidian","relativePath":"releases/3.8.6.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.8.5...3.8.6\n","aliases":["/releases/3.8.6/","/releases/3.8.6/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.5...3.8.6

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.5...3.8.6"},{"route":"/obsidian/releases/3.8.7/","title":"Untitled","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.6...3.8.7","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.8.7.md","namespace":"obsidian","relativePath":"releases/3.8.7.md","raw":"**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.8.6...3.8.7\n","aliases":["/releases/3.8.7/","/releases/3.8.7/"],"toc":[],"html":"

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.6...3.8.7

\n","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.6...3.8.7"},{"route":"/obsidian/releases/3.9.0/","title":"Release Notes v3.9.0","description":"This release introduces a host of new features, bug fixes, and significant enhancements to improve your task and time management experience. Key updates include a more powerful...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.9.0.md","namespace":"obsidian","relativePath":"releases/3.9.0.md","raw":"# Release Notes v3.9.0\r\n\r\nThis release introduces a host of new features, bug fixes, and significant enhancements to improve your task and time management experience.\r\nKey updates include a more powerful and standards-compliant recurrence system, a streamlined user interface, and improved performance.\r\n\r\nA special thank you to amithkk (https://github.com/amithkk) for their contributions to this release!\r\n\r\n## New Features\r\n\r\n * RRule-Based Recurrence: Task recurrence is now powered by the iCalendar standard (RFC 5545), allowing for more complex and flexible\r\n recurring task schedules. A migration assistant will help you update your existing tasks to the new format.\r\n * Interactive Recurring Task Calendar: An interactive calendar has been added to the task edit modal, allowing you to visualize and manage\r\n individual completions of recurring tasks.\r\n * \"Show\" Dropdown in Filter Bar: A unified \"Show\" dropdown has been added to the filter bar, providing enhanced filtering options for your\r\n tasks.\r\n * Insert Tasknote Link Command: A new command has been added to insert a link to a tasknote, streamlining your workflow.\r\n * Dedicated Inline Task Folder Setting: You can now specify a dedicated folder for inline tasks, with support for {{currentNotePath}} to save\r\n tasks in the same folder as the current note.\r\n * \"Show Due Dates When Scheduled\" Setting: A new setting allows you to display due dates for scheduled tasks in the calendar view.\r\n * Compact Filter Bar: A more compact filter bar option is now available for a cleaner interface. (Thanks, amithkk!)\r\n * Multiple New Ribbon Icons: New ribbon icons have been added for extended views and actions, providing quicker access to features.\r\n * \"Highlight Today\" in Calendar View: The calendar view now highlights the current day for better visibility.\r\n * New Documentation Site: A new documentation site, built with MkDocs, is now available with improved structure and searchability.\r\n * CI/CD and Testing:\r\n * A comprehensive testing suite using Jest has been added to improve code quality and prevent regressions.\r\n * GitHub Actions workflows have been implemented for automated testing, documentation deployment, and releases.\r\n\r\n## Enhancements\r\n\r\n * UI/UX Improvements:\r\n * The task edit and creation modals have been redesigned for a more minimalist and intuitive experience.\r\n * Task-related icons have been updated for better clarity.\r\n * Context menus have been added to task cards for quick actions.\r\n * The agenda view sorting options have been fixed.\r\n * The recurring calendar widget is now centered and on a separate line from its label.\r\n * Dropdown menus now handle clicks on text labels more reliably.\r\n * Performance and Reliability:\r\n * The task link overlay has been refactored to use a ViewPlugin for better performance.\r\n * The Advanced Calendar view now handles resizing and being moved to a new window more gracefully.\r\n * The natural language processing for task creation has been improved with a fallback mechanism.\r\n * Date parsing and handling have been made more robust, especially for UTC and different date formats.\r\n * Development Workflow:\r\n * ESLint configuration has been updated with new rules and plugins for better code consistency.\r\n * The build process for CSS has been improved.\r\n * The development guidelines have been updated to reflect the new architecture.\r\n\r\n## Bug Fixes\r\n\r\n\r\n * Fixed an issue where agenda view sorting options were not working correctly.\r\n * Fixed a bug that caused a forced reflow when moving the Advanced Calendar to a new window.\r\n * Resolved a TypeError in the task modal's suggestion filtering.\r\n * Fixed an issue where the Pomodoro task selector did not show all un-archived tasks.\r\n * Corrected the filtering of daily notes in the getNotesForDate function.\r\n * Fixed a bug where the underlying markdown of a task link was not revealed on hover.\r\n * Removed misleading placeholder symbols from the settings.\r\n * Addressed various linting issues and improved code quality.\r\n\r\n**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.7.1...3.9.0\n","aliases":["/releases/3.9.0/","/releases/3.9.0/"],"toc":[{"level":2,"id":"new-features","text":"New Features"},{"level":2,"id":"enhancements","text":"Enhancements"},{"level":2,"id":"bug-fixes","text":"Bug Fixes"}],"html":"

This release introduces a host of new features, bug fixes, and significant enhancements to improve your task and time management experience.\nKey updates include a more powerful and standards-compliant recurrence system, a streamlined user interface, and improved performance.

\n

A special thank you to amithkk (https://github.com/amithkk) for their contributions to this release!

\n

New Features#

\n
    \n
  • RRule-Based Recurrence: Task recurrence is now powered by the iCalendar standard (RFC 5545), allowing for more complex and flexible\nrecurring task schedules. A migration assistant will help you update your existing tasks to the new format.
  • \n
  • Interactive Recurring Task Calendar: An interactive calendar has been added to the task edit modal, allowing you to visualize and manage\nindividual completions of recurring tasks.
  • \n
  • "Show" Dropdown in Filter Bar: A unified "Show" dropdown has been added to the filter bar, providing enhanced filtering options for your\ntasks.
  • \n
  • Insert Tasknote Link Command: A new command has been added to insert a link to a tasknote, streamlining your workflow.
  • \n
  • Dedicated Inline Task Folder Setting: You can now specify a dedicated folder for inline tasks, with support for {{currentNotePath}} to save\ntasks in the same folder as the current note.
  • \n
  • "Show Due Dates When Scheduled" Setting: A new setting allows you to display due dates for scheduled tasks in the calendar view.
  • \n
  • Compact Filter Bar: A more compact filter bar option is now available for a cleaner interface. (Thanks, amithkk!)
  • \n
  • Multiple New Ribbon Icons: New ribbon icons have been added for extended views and actions, providing quicker access to features.
  • \n
  • "Highlight Today" in Calendar View: The calendar view now highlights the current day for better visibility.
  • \n
  • New Documentation Site: A new documentation site, built with MkDocs, is now available with improved structure and searchability.
  • \n
  • CI/CD and Testing:
      \n
    • A comprehensive testing suite using Jest has been added to improve code quality and prevent regressions.
    • \n
    • GitHub Actions workflows have been implemented for automated testing, documentation deployment, and releases.
    • \n
    \n
  • \n
\n

Enhancements#

\n
    \n
  • UI/UX Improvements:
      \n
    • The task edit and creation modals have been redesigned for a more minimalist and intuitive experience.
    • \n
    • Task-related icons have been updated for better clarity.
    • \n
    • Context menus have been added to task cards for quick actions.
    • \n
    • The agenda view sorting options have been fixed.
    • \n
    • The recurring calendar widget is now centered and on a separate line from its label.
    • \n
    • Dropdown menus now handle clicks on text labels more reliably.
    • \n
    \n
  • \n
  • Performance and Reliability:
      \n
    • The task link overlay has been refactored to use a ViewPlugin for better performance.
    • \n
    • The Advanced Calendar view now handles resizing and being moved to a new window more gracefully.
    • \n
    • The natural language processing for task creation has been improved with a fallback mechanism.
    • \n
    • Date parsing and handling have been made more robust, especially for UTC and different date formats.
    • \n
    \n
  • \n
  • Development Workflow:
      \n
    • ESLint configuration has been updated with new rules and plugins for better code consistency.
    • \n
    • The build process for CSS has been improved.
    • \n
    • The development guidelines have been updated to reflect the new architecture.
    • \n
    \n
  • \n
\n

Bug Fixes#

\n
    \n
  • Fixed an issue where agenda view sorting options were not working correctly.
  • \n
  • Fixed a bug that caused a forced reflow when moving the Advanced Calendar to a new window.
  • \n
  • Resolved a TypeError in the task modal's suggestion filtering.
  • \n
  • Fixed an issue where the Pomodoro task selector did not show all un-archived tasks.
  • \n
  • Corrected the filtering of daily notes in the getNotesForDate function.
  • \n
  • Fixed a bug where the underlying markdown of a task link was not revealed on hover.
  • \n
  • Removed misleading placeholder symbols from the settings.
  • \n
  • Addressed various linting issues and improved code quality.
  • \n
\n

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.7.1...3.9.0

\n","text":"This release introduces a host of new features, bug fixes, and significant enhancements to improve your task and time management experience. Key updates include a more powerful and standards-compliant recurrence system, a streamlined user interface, and improved performance. A special thank you to amithkk (https://github.com/amithkk) for their contributions to this release! New Features# RRule-Based Recurrence: Task recurrence is now powered by the iCalendar standard (RFC 5545), allowing for more complex and flexible recurring task schedules. A migration assistant will help you update your existing tasks to the new format. Interactive Recurring Task Calendar: An interactive calendar has been added to the task edit modal, allowing you to visualize and manage individual completions of recurring tasks. \"Show\" Dropdown in Filter Bar: A unified \"Show\" dropdown has been added to the filter bar, providing enhanced filtering options for your tasks. Insert Tasknote Link Command: A new command has been added to insert a link to a tasknote, streamlining your workflow. Dedicated Inline Task Folder Setting: You can now specify a dedicated folder for inline tasks, with support for {{currentNotePath}} to save tasks in the same folder as the current note. \"Show Due Dates When Scheduled\" Setting: A new setting allows you to display due dates for scheduled tasks in the calendar view. Compact Filter Bar: A more compact filter bar option is now available for a cleaner interface. (Thanks, amithkk!) Multiple New Ribbon Icons: New ribbon icons have been added for extended views and actions, providing quicker access to features. \"Highlight Today\" in Calendar View: The calendar view now highlights the current day for better visibility. New Documentation Site: A new documentation site, built with MkDocs, is now available with improved structure and searchability. CI/CD and Testing: A comprehensive testing suite using Jest has been added to improve code quality and prevent regressions. GitHub Actions workflows have been implemented for automated testing, documentation deployment, and releases. Enhancements# UI/UX Improvements: The task edit and creation modals have been redesigned for a more minimalist and intuitive experience. Task-related icons have been updated for better clarity. Context menus have been added to task cards for quick actions. The agenda view sorting options have been fixed. The recurring calendar widget is now centered and on a separate line from its label. Dropdown menus now handle clicks on text labels more reliably. Performance and Reliability: The task link overlay has been refactored to use a ViewPlugin for better performance. The Advanced Calendar view now handles resizing and being moved to a new window more gracefully. The natural language processing for task creation has been improved with a fallback mechanism. Date parsing and handling have been made more robust, especially for UTC and different date formats. Development Workflow: ESLint configuration has been updated with new rules and plugins for better code consistency. The build process for CSS has been improved. The development guidelines have been updated to reflect the new architecture. Bug Fixes# Fixed an issue where agenda view sorting options were not working correctly. Fixed a bug that caused a forced reflow when moving the Advanced Calendar to a new window. Resolved a TypeError in the task modal's suggestion filtering. Fixed an issue where the Pomodoro task selector did not show all un-archived tasks. Corrected the filtering of daily notes in the getNotesForDate function. Fixed a bug where the underlying markdown of a task link was not revealed on hover. Removed misleading placeholder symbols from the settings. Addressed various linting issues and improved code quality. Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.7.1...3.9.0"},{"route":"/obsidian/releases/3.9.1/","title":"Release Notes: 3.9.1","description":"New Features","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/3.9.1.md","namespace":"obsidian","relativePath":"releases/3.9.1.md","raw":"# Release Notes: 3.9.1\r\n\r\nNew Features\r\n\r\n * GitHub Issue Templates: Added templates for bug reports and feature requests to streamline issue submission and ensure all necessary information is provided.\r\n\r\nBug Fixes\r\n\r\n * Pomodoro Timer: Fixed an issue where a long break would incorrectly start after the first work session. The timer now correctly schedules a short break as intended.\r\n * Task Creation: The \"Magic Wand\" (Natural Language Processing) now properly fills the context and tag fields in the task creation modal. Default contexts and tags are preserved if none are found in the natural language input.\r\n\r\n\r\n\r\n## What's Changed\r\n* Add github issue templates by @amithkk in https://github.com/callumalpass/tasknotes/pull/101\r\n\r\n\r\n**Full Changelog**: https://github.com/callumalpass/tasknotes/compare/3.9.0...3.9.1\n","aliases":["/releases/3.9.1/","/releases/3.9.1/"],"toc":[{"level":2,"id":"what39s-changed","text":"What's Changed"}],"html":"

New Features

\n
    \n
  • GitHub Issue Templates: Added templates for bug reports and feature requests to streamline issue submission and ensure all necessary information is provided.
  • \n
\n

Bug Fixes

\n
    \n
  • Pomodoro Timer: Fixed an issue where a long break would incorrectly start after the first work session. The timer now correctly schedules a short break as intended.
  • \n
  • Task Creation: The "Magic Wand" (Natural Language Processing) now properly fills the context and tag fields in the task creation modal. Default contexts and tags are preserved if none are found in the natural language input.
  • \n
\n

What's Changed#

\n\n

Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.9.0...3.9.1

\n","text":"New Features GitHub Issue Templates: Added templates for bug reports and feature requests to streamline issue submission and ensure all necessary information is provided. Bug Fixes Pomodoro Timer: Fixed an issue where a long break would incorrectly start after the first work session. The timer now correctly schedules a short break as intended. Task Creation: The \"Magic Wand\" (Natural Language Processing) now properly fills the context and tag fields in the task creation modal. Default contexts and tags are preserved if none are found in the natural language input. What's Changed# Add github issue templates by @amithkk in https://github.com/callumalpass/tasknotes/pull/101 Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.9.0...3.9.1"},{"route":"/obsidian/releases/4.0.0-beta.0/","title":"TaskNotes 4.0.0-beta.0","description":"Beta Release","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.0.0-beta.0.md","namespace":"obsidian","relativePath":"releases/4.0.0-beta.0.md","raw":"# TaskNotes 4.0.0-beta.0\n\n> **Beta Release**\n>\n> You may encounter issues. Report problems on [GitHub Issues](https://github.com/callumalpass/tasknotes/issues).\n\n## What's New in v4\n\nTaskNotes v4 migrates all views to the Bases system.\n\n### Breaking Changes\n\n- **Minimum Obsidian version: 1.10.1**\n- **View commands now use Bases files** - Ribbon icons and command palette commands (Calendar, Kanban, Tasks, Agenda, Project Subtasks) now open `.base` files created automatically in your vault\n- **Saved filter views** - Custom saved views can be converted to `.base` files using a conversion button in settings\n\n## Added\n\n### OAuth Calendar Integration\n\n- Google Calendar and Microsoft Outlook integration via OAuth 2.0\n - View and sync calendar events in Bases calendar\n - Drag events in the TaskNotes bases calendar to change the event's time online\n - Events sync every 15 minutes or upon local change\n - Requires creating your own OAuth application (approximately 15 minutes)\n - See [Calendar Setup Guide](https://tasknotes.dev/calendar-setup)\n\n### Time Entry Editor Modal\n\n- Dedicated interface for managing time entries\n - Alt-drag on Bases calendar to create time entries\n - View total tracked time per task\n - Edit and delete time entries\n - Access via Task Action Palette (Alt/Opt + Enter)\n\n### Kanban Swimlane Layout\n\n- Horizontal swimlane grouping option for Bases Kanban\n - Group tasks by status, priority, or other fields\n - Hide empty columns\n - Configurable column widths\n - Improved drag-and-drop in swimlane mode\n\n### Saved View Converter\n\n- Conversion button in settings to convert saved filter views to `.base` files\n- Original settings preserved\n- Converted views created in `TaskNotes/Views/`\n\n## Changed\n\n### View System Architecture\n\n- All views now use Bases architecture\n - Calendar, Kanban, Tasks, Agenda, and Project Subtasks are `.base` files\n - Views stored in `TaskNotes/Views/`\n - Keyboard shortcuts and ribbon icons map to `.base` files\n - Configure file paths in Settings → Integrations → Bases Integration\n\n### Calendar\n\n- Control which calendar sources display\n - Toggle Google Calendar, Microsoft Calendar, and ICS events independently\n - Configurable list view with custom day count (2-10 days)\n - Improved timezone handling for recurring events\n\n### Settings\n\n- Reorganized settings tabs\n - OAuth calendar settings in Integrations tab\n - Updated help text\n\n## Fixed\n\n- (#843) Fixed task tag being added when \"Identify tasks by\" is set to \"Property\"\n - TaskCreationModal, TaskEditModal, and InstantTaskConvertService now respect taskIdentificationMethod setting\n - Thanks to @jack2game\n- Fixed dark mode calendar borders\n- Fixed Bases Kanban column ordering - Thanks to @mweichert\n- Fixed state management bug in FilterSettingsComponent\n- Fixed timezone handling for recurring events\n\n## Migration Guide\n\n### First Launch\n\n1. Default view files are created automatically in `TaskNotes/Views/`\n2. Ribbon and command palette commands now open `.base` files\n3. Review Settings → General to customize view file paths\n\n### Converting Saved Filter Views\n\n1. Go to Settings → General\n2. Click the conversion button to convert saved filter views to `.base` files\n3. Converted views appear in a file in `TaskNotes/Views/`\n\n### Calendar Integration (Optional)\n\n1. Go to Settings → Integrations → OAuth Calendar Integration\n2. Follow the [Calendar Setup Guide](https://tasknotes.dev/calendar-setup)\n3. Create OAuth applications with Google and/or Microsoft (approximately 15 minutes)\n4. Enter Client ID and Secret in calendar cards\n5. Click Connect\n\n## Known Limitations\n\n- Quick OAuth setup is disabled - only advanced setup (your own credentials) is available\n- Saved filter views require manual conversion using the button in settings\n- Migration is one-way - downgrading to v3 may require manual reconfiguration\n- OAuth setup requires creating applications with Google/Microsoft\n\n## Feedback\n\nReport issues on [GitHub](https://github.com/callumalpass/tasknotes/issues). Include:\n\n- Obsidian version\n- Steps to reproduce\n- Console errors (Ctrl/Cmd + Shift + I)\n- Whether issue occurs after migration or fresh install\n","aliases":["/releases/4.0.0-beta.0/","/releases/4.0.0-beta.0/"],"toc":[{"level":2,"id":"what39s-new-in-v4","text":"What's New in v4"},{"level":3,"id":"breaking-changes","text":"Breaking Changes"},{"level":2,"id":"added","text":"Added"},{"level":3,"id":"oauth-calendar-integration","text":"OAuth Calendar Integration"},{"level":3,"id":"time-entry-editor-modal","text":"Time Entry Editor Modal"},{"level":3,"id":"kanban-swimlane-layout","text":"Kanban Swimlane Layout"},{"level":3,"id":"saved-view-converter","text":"Saved View Converter"},{"level":2,"id":"changed","text":"Changed"},{"level":3,"id":"view-system-architecture","text":"View System Architecture"},{"level":3,"id":"calendar","text":"Calendar"},{"level":3,"id":"settings","text":"Settings"},{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"migration-guide","text":"Migration Guide"},{"level":3,"id":"first-launch","text":"First Launch"},{"level":3,"id":"converting-saved-filter-views","text":"Converting Saved Filter Views"},{"level":3,"id":"calendar-integration-optional","text":"Calendar Integration (Optional)"},{"level":2,"id":"known-limitations","text":"Known Limitations"},{"level":2,"id":"feedback","text":"Feedback"}],"html":"
\n

Beta Release

\n

You may encounter issues. Report problems on GitHub Issues.

\n
\n

What's New in v4#

\n

TaskNotes v4 migrates all views to the Bases system.

\n

Breaking Changes#

\n
    \n
  • Minimum Obsidian version: 1.10.1
  • \n
  • View commands now use Bases files - Ribbon icons and command palette commands (Calendar, Kanban, Tasks, Agenda, Project Subtasks) now open .base files created automatically in your vault
  • \n
  • Saved filter views - Custom saved views can be converted to .base files using a conversion button in settings
  • \n
\n

Added#

\n

OAuth Calendar Integration#

\n
    \n
  • Google Calendar and Microsoft Outlook integration via OAuth 2.0
      \n
    • View and sync calendar events in Bases calendar
    • \n
    • Drag events in the TaskNotes bases calendar to change the event's time online
    • \n
    • Events sync every 15 minutes or upon local change
    • \n
    • Requires creating your own OAuth application (approximately 15 minutes)
    • \n
    • See Calendar Setup Guide
    • \n
    \n
  • \n
\n

Time Entry Editor Modal#

\n
    \n
  • Dedicated interface for managing time entries
      \n
    • Alt-drag on Bases calendar to create time entries
    • \n
    • View total tracked time per task
    • \n
    • Edit and delete time entries
    • \n
    • Access via Task Action Palette (Alt/Opt + Enter)
    • \n
    \n
  • \n
\n

Kanban Swimlane Layout#

\n
    \n
  • Horizontal swimlane grouping option for Bases Kanban
      \n
    • Group tasks by status, priority, or other fields
    • \n
    • Hide empty columns
    • \n
    • Configurable column widths
    • \n
    • Improved drag-and-drop in swimlane mode
    • \n
    \n
  • \n
\n

Saved View Converter#

\n
    \n
  • Conversion button in settings to convert saved filter views to .base files
  • \n
  • Original settings preserved
  • \n
  • Converted views created in TaskNotes/Views/
  • \n
\n

Changed#

\n

View System Architecture#

\n
    \n
  • All views now use Bases architecture
      \n
    • Calendar, Kanban, Tasks, Agenda, and Project Subtasks are .base files
    • \n
    • Views stored in TaskNotes/Views/
    • \n
    • Keyboard shortcuts and ribbon icons map to .base files
    • \n
    • Configure file paths in Settings → Integrations → Bases Integration
    • \n
    \n
  • \n
\n

Calendar#

\n
    \n
  • Control which calendar sources display
      \n
    • Toggle Google Calendar, Microsoft Calendar, and ICS events independently
    • \n
    • Configurable list view with custom day count (2-10 days)
    • \n
    • Improved timezone handling for recurring events
    • \n
    \n
  • \n
\n

Settings#

\n
    \n
  • Reorganized settings tabs
      \n
    • OAuth calendar settings in Integrations tab
    • \n
    • Updated help text
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#843) Fixed task tag being added when "Identify tasks by" is set to "Property"
      \n
    • TaskCreationModal, TaskEditModal, and InstantTaskConvertService now respect taskIdentificationMethod setting
    • \n
    • Thanks to @jack2game
    • \n
    \n
  • \n
  • Fixed dark mode calendar borders
  • \n
  • Fixed Bases Kanban column ordering - Thanks to @mweichert
  • \n
  • Fixed state management bug in FilterSettingsComponent
  • \n
  • Fixed timezone handling for recurring events
  • \n
\n

Migration Guide#

\n

First Launch#

\n
    \n
  1. Default view files are created automatically in TaskNotes/Views/
  2. \n
  3. Ribbon and command palette commands now open .base files
  4. \n
  5. Review Settings → General to customize view file paths
  6. \n
\n

Converting Saved Filter Views#

\n
    \n
  1. Go to Settings → General
  2. \n
  3. Click the conversion button to convert saved filter views to .base files
  4. \n
  5. Converted views appear in a file in TaskNotes/Views/
  6. \n
\n

Calendar Integration (Optional)#

\n
    \n
  1. Go to Settings → Integrations → OAuth Calendar Integration
  2. \n
  3. Follow the Calendar Setup Guide
  4. \n
  5. Create OAuth applications with Google and/or Microsoft (approximately 15 minutes)
  6. \n
  7. Enter Client ID and Secret in calendar cards
  8. \n
  9. Click Connect
  10. \n
\n

Known Limitations#

\n
    \n
  • Quick OAuth setup is disabled - only advanced setup (your own credentials) is available
  • \n
  • Saved filter views require manual conversion using the button in settings
  • \n
  • Migration is one-way - downgrading to v3 may require manual reconfiguration
  • \n
  • OAuth setup requires creating applications with Google/Microsoft
  • \n
\n

Feedback#

\n

Report issues on GitHub. Include:

\n
    \n
  • Obsidian version
  • \n
  • Steps to reproduce
  • \n
  • Console errors (Ctrl/Cmd + Shift + I)
  • \n
  • Whether issue occurs after migration or fresh install
  • \n
\n","text":"Beta Release You may encounter issues. Report problems on GitHub Issues. What's New in v4# TaskNotes v4 migrates all views to the Bases system. Breaking Changes# Minimum Obsidian version: 1.10.1 View commands now use Bases files - Ribbon icons and command palette commands (Calendar, Kanban, Tasks, Agenda, Project Subtasks) now open .base files created automatically in your vault Saved filter views - Custom saved views can be converted to .base files using a conversion button in settings Added# OAuth Calendar Integration# Google Calendar and Microsoft Outlook integration via OAuth 2.0 View and sync calendar events in Bases calendar Drag events in the TaskNotes bases calendar to change the event's time online Events sync every 15 minutes or upon local change Requires creating your own OAuth application (approximately 15 minutes) See Calendar Setup Guide Time Entry Editor Modal# Dedicated interface for managing time entries Alt-drag on Bases calendar to create time entries View total tracked time per task Edit and delete time entries Access via Task Action Palette (Alt/Opt + Enter) Kanban Swimlane Layout# Horizontal swimlane grouping option for Bases Kanban Group tasks by status, priority, or other fields Hide empty columns Configurable column widths Improved drag-and-drop in swimlane mode Saved View Converter# Conversion button in settings to convert saved filter views to .base files Original settings preserved Converted views created in TaskNotes/Views/ Changed# View System Architecture# All views now use Bases architecture Calendar, Kanban, Tasks, Agenda, and Project Subtasks are .base files Views stored in TaskNotes/Views/ Keyboard shortcuts and ribbon icons map to .base files Configure file paths in Settings → Integrations → Bases Integration Calendar# Control which calendar sources display Toggle Google Calendar, Microsoft Calendar, and ICS events independently Configurable list view with custom day count (2-10 days) Improved timezone handling for recurring events Settings# Reorganized settings tabs OAuth calendar settings in Integrations tab Updated help text Fixed# (#843) Fixed task tag being added when \"Identify tasks by\" is set to \"Property\" TaskCreationModal, TaskEditModal, and InstantTaskConvertService now respect taskIdentificationMethod setting Thanks to @jack2game Fixed dark mode calendar borders Fixed Bases Kanban column ordering - Thanks to @mweichert Fixed state management bug in FilterSettingsComponent Fixed timezone handling for recurring events Migration Guide# First Launch# Default view files are created automatically in TaskNotes/Views/ Ribbon and command palette commands now open .base files Review Settings → General to customize view file paths Converting Saved Filter Views# Go to Settings → General Click the conversion button to convert saved filter views to .base files Converted views appear in a file in TaskNotes/Views/ Calendar Integration (Optional)# Go to Settings → Integrations → OAuth Calendar Integration Follow the Calendar Setup Guide Create OAuth applications with Google and/or Microsoft (approximately 15 minutes) Enter Client ID and Secret in calendar cards Click Connect Known Limitations# Quick OAuth setup is disabled - only advanced setup (your own credentials) is available Saved filter views require manual conversion using the button in settings Migration is one-way - downgrading to v3 may require manual reconfiguration OAuth setup requires creating applications with Google/Microsoft Feedback# Report issues on GitHub. Include: Obsidian version Steps to reproduce Console errors (Ctrl/Cmd + Shift + I) Whether issue occurs after migration or fresh install"},{"route":"/obsidian/releases/4.0.0-beta.1/","title":"TaskNotes 4.0.0-beta.1","description":"Beta Release","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.0.0-beta.1.md","namespace":"obsidian","relativePath":"releases/4.0.0-beta.1.md","raw":"# TaskNotes 4.0.0-beta.1\n\n> **Beta Release**\n>\n> You may encounter issues. Report problems on [GitHub Issues](https://github.com/callumalpass/tasknotes/issues).\n\n## Added\n\n- Added context menus for time entries and ICS events in calendar\n - Time entries: Right-click shows task context menu, left-click opens time entry editor modal\n - ICS/Google/Microsoft Calendar events: Right-click shows ICS event context menu with options to show details, create task/note, link note, and copy info\n- Added calendar icon to ICS event titles for better visual distinction\n- Added hover tooltips for timeblocks in calendar views\n- Added **MiniCalendar view** for Bases integration\n - Monthly calendar grid with dot indicators on days with notes\n - Configurable date property (file.ctime, note.dateCreated, etc.)\n - Fuzzy selector modal for selecting notes on clicked days\n - Ctrl+click (or Cmd+click on Mac) on any day opens/creates daily note\n- Added virtual scrolling and lazy rendering to Bases views for high-performance handling of large datasets\n - TaskListView: Virtual scrolling for 100+ tasks in flat and grouped views with collapsible groups\n - KanbanView: Virtual scrolling for regular columns (30+ tasks) and swimlane cells (30+ tasks per cell)\n - Tested with up to **30,000 notes** with no performance degradation\n - Thanks to @aubreyz and @turingexmachina for their reports of performance issues and diagnosis help\n\n\n## Changed\n\n- Refactored Bases integration to use public API and trust pre-sorted data\n - Migrated all three views (Task List, Kanban, Calendar) to clean class-based architecture\n - Removed legacy view files and ~500 lines of redundant sorting/grouping logic\n - Introduced BasesDataAdapter, PropertyMappingService, and BasesViewBase abstractions\n - Trusts Bases plugin to provide pre-sorted and pre-grouped data via public API\n - Reduced code duplication by 40% while maintaining full feature parity\n- Refactored calendar modules to use ES6 imports instead of lazy require() calls\n - Removed all dynamic require() calls from calendar-core.ts and calendar-view.ts\n - Consolidated all imports at module top level\n - Improves code maintainability, makes dependencies explicit, and follows modern TypeScript best practices\n- Time entry events now show task context menu on right-click (previously had no context menu)\n- Replaced MinimalNativeCache with just-in-time TaskManager for improved reliability\n - Removed complex index synchronization in favor of direct MetadataCache queries\n - Eliminated 7 internal indexes (tasksByDate, tasksByStatus, overdueTasks, etc.)\n - Added minimal DependencyCache for task dependencies and project references only\n - Zero startup time (no index building required)\n - Always provides fresh, accurate task data from Obsidian's MetadataCache\n- Completed internationalization with 100% translation coverage across all supported languages\n - Added 90 missing translation keys to English base\n - Completed 829 translations across 6 languages (German, Spanish, French, Japanese, Russian, Chinese)\n - All locales now have complete coverage (1745/1745 keys)\n - Improved translation quality for migration system, calendar settings, statistics, ICS events, and filter components\n- Migrated to i18n-state-manager CLI tool for translation management\n - Replaced custom scripts with more robust i18n-state-manager package\n - Added i18n-state.config.json for project-specific patterns\n - New features: find-unused, check-duplicates, improved stale detection\n - Hash-based state tracking and ripgrep-based scanning for performance\n- Bases view templates now generate dynamically based on user settings\n - Task filters adapt to user's task identification method (tag or property)\n - Property ordering reflects defaultVisibleProperties setting\n - Uses correct YAML object notation for Bases filters\n - Maintains backward compatibility with legacy static templates\n- Updated Bases CalendarView to show TaskNotes in property-based events\n - Tasks can now be visualized on calendar via any date property (dateCreated, scheduled, due, etc.)\n - Previously all TaskNotes were filtered out from property-based events\n\n## Fixed\n\n- (#1022, #684) Fixed tasks randomly disappearing when Smart Connections plugin is enabled\n - Eliminated race condition caused by index synchronization delays\n - TaskManager now reads directly from Obsidian's MetadataCache instead of maintaining separate indexes\n - No more timing-sensitive code that could conflict with other plugins' metadata processing\n - Tasks will always be visible regardless of other plugins' processing times\n - Thanks to @alejandrospoz, @seepage87, @amarjt, @luckb0x, camara-tech for reporting and help debugging. \n- (#992) Fixed \"Failed to resolve module specifier 'obsidian'\" error when moving recurring task instances in calendar\n - Removed unnecessary dynamic imports that were causing module resolution failures\n - Consolidated imports at top of calendar-core.ts module\n - Thanks to @jalooc for reporting this issue\n- Fixed task dependencies not displaying on task cards\n - TaskManager now properly calculates isBlocked and isBlocking flags from dependency data\n - Added missing property extractors and renderers in TaskCard for all dependency-related fields\n - Dependency information now shows correctly in Bases views, task note widgets, and other views\n - Shows \"Blocked (n)\" and \"Blocking (n)\" pills, plus detailed task links\n- Fixed Bases property mapping for user-configured field names\n - PropertyMappingService now correctly strips prefixes and applies FieldMapper transformations\n - Example: User configures \"state\" → \"status\", Bases provides \"note.state\", now correctly maps to \"status\"\n - Ensures TaskCard properly recognizes and renders user-configured properties\n- Fixed Bases views not respecting user-configured visible properties\n - Now prioritizes Bases 1.10.0+ public API config.getOrder() method\n - Removed reliance on internal API paths that no longer work\n - Filters out blocked/blocking properties when using defaults (only shown when explicitly requested via blockedBy)\n- Fixed MiniCalendar UTC anchoring for consistent timezone-independent date handling\n- Fixed DateValue conversion in BasesDataAdapter\n - DateValue objects have {date: Date, time: boolean} structure\n - Now properly checks for value.date instanceof Date before legacy conversion methods\n - Fixes property-based events in CalendarView\n\n","aliases":["/releases/4.0.0-beta.1/","/releases/4.0.0-beta.1/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"
\n

Beta Release

\n

You may encounter issues. Report problems on GitHub Issues.

\n
\n

Added#

\n
    \n
  • Added context menus for time entries and ICS events in calendar
      \n
    • Time entries: Right-click shows task context menu, left-click opens time entry editor modal
    • \n
    • ICS/Google/Microsoft Calendar events: Right-click shows ICS event context menu with options to show details, create task/note, link note, and copy info
    • \n
    \n
  • \n
  • Added calendar icon to ICS event titles for better visual distinction
  • \n
  • Added hover tooltips for timeblocks in calendar views
  • \n
  • Added MiniCalendar view for Bases integration
      \n
    • Monthly calendar grid with dot indicators on days with notes
    • \n
    • Configurable date property (file.ctime, note.dateCreated, etc.)
    • \n
    • Fuzzy selector modal for selecting notes on clicked days
    • \n
    • Ctrl+click (or Cmd+click on Mac) on any day opens/creates daily note
    • \n
    \n
  • \n
  • Added virtual scrolling and lazy rendering to Bases views for high-performance handling of large datasets
      \n
    • TaskListView: Virtual scrolling for 100+ tasks in flat and grouped views with collapsible groups
    • \n
    • KanbanView: Virtual scrolling for regular columns (30+ tasks) and swimlane cells (30+ tasks per cell)
    • \n
    • Tested with up to 30,000 notes with no performance degradation
    • \n
    • Thanks to @aubreyz and @turingexmachina for their reports of performance issues and diagnosis help
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Refactored Bases integration to use public API and trust pre-sorted data
      \n
    • Migrated all three views (Task List, Kanban, Calendar) to clean class-based architecture
    • \n
    • Removed legacy view files and ~500 lines of redundant sorting/grouping logic
    • \n
    • Introduced BasesDataAdapter, PropertyMappingService, and BasesViewBase abstractions
    • \n
    • Trusts Bases plugin to provide pre-sorted and pre-grouped data via public API
    • \n
    • Reduced code duplication by 40% while maintaining full feature parity
    • \n
    \n
  • \n
  • Refactored calendar modules to use ES6 imports instead of lazy require() calls
      \n
    • Removed all dynamic require() calls from calendar-core.ts and calendar-view.ts
    • \n
    • Consolidated all imports at module top level
    • \n
    • Improves code maintainability, makes dependencies explicit, and follows modern TypeScript best practices
    • \n
    \n
  • \n
  • Time entry events now show task context menu on right-click (previously had no context menu)
  • \n
  • Replaced MinimalNativeCache with just-in-time TaskManager for improved reliability
      \n
    • Removed complex index synchronization in favor of direct MetadataCache queries
    • \n
    • Eliminated 7 internal indexes (tasksByDate, tasksByStatus, overdueTasks, etc.)
    • \n
    • Added minimal DependencyCache for task dependencies and project references only
    • \n
    • Zero startup time (no index building required)
    • \n
    • Always provides fresh, accurate task data from Obsidian's MetadataCache
    • \n
    \n
  • \n
  • Completed internationalization with 100% translation coverage across all supported languages
      \n
    • Added 90 missing translation keys to English base
    • \n
    • Completed 829 translations across 6 languages (German, Spanish, French, Japanese, Russian, Chinese)
    • \n
    • All locales now have complete coverage (1745/1745 keys)
    • \n
    • Improved translation quality for migration system, calendar settings, statistics, ICS events, and filter components
    • \n
    \n
  • \n
  • Migrated to i18n-state-manager CLI tool for translation management
      \n
    • Replaced custom scripts with more robust i18n-state-manager package
    • \n
    • Added i18n-state.config.json for project-specific patterns
    • \n
    • New features: find-unused, check-duplicates, improved stale detection
    • \n
    • Hash-based state tracking and ripgrep-based scanning for performance
    • \n
    \n
  • \n
  • Bases view templates now generate dynamically based on user settings
      \n
    • Task filters adapt to user's task identification method (tag or property)
    • \n
    • Property ordering reflects defaultVisibleProperties setting
    • \n
    • Uses correct YAML object notation for Bases filters
    • \n
    • Maintains backward compatibility with legacy static templates
    • \n
    \n
  • \n
  • Updated Bases CalendarView to show TaskNotes in property-based events
      \n
    • Tasks can now be visualized on calendar via any date property (dateCreated, scheduled, due, etc.)
    • \n
    • Previously all TaskNotes were filtered out from property-based events
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1022, #684) Fixed tasks randomly disappearing when Smart Connections plugin is enabled
      \n
    • Eliminated race condition caused by index synchronization delays
    • \n
    • TaskManager now reads directly from Obsidian's MetadataCache instead of maintaining separate indexes
    • \n
    • No more timing-sensitive code that could conflict with other plugins' metadata processing
    • \n
    • Tasks will always be visible regardless of other plugins' processing times
    • \n
    • Thanks to @alejandrospoz, @seepage87, @amarjt, @luckb0x, camara-tech for reporting and help debugging.
    • \n
    \n
  • \n
  • (#992) Fixed "Failed to resolve module specifier 'obsidian'" error when moving recurring task instances in calendar
      \n
    • Removed unnecessary dynamic imports that were causing module resolution failures
    • \n
    • Consolidated imports at top of calendar-core.ts module
    • \n
    • Thanks to @jalooc for reporting this issue
    • \n
    \n
  • \n
  • Fixed task dependencies not displaying on task cards
      \n
    • TaskManager now properly calculates isBlocked and isBlocking flags from dependency data
    • \n
    • Added missing property extractors and renderers in TaskCard for all dependency-related fields
    • \n
    • Dependency information now shows correctly in Bases views, task note widgets, and other views
    • \n
    • Shows "Blocked (n)" and "Blocking (n)" pills, plus detailed task links
    • \n
    \n
  • \n
  • Fixed Bases property mapping for user-configured field names
      \n
    • PropertyMappingService now correctly strips prefixes and applies FieldMapper transformations
    • \n
    • Example: User configures "state" → "status", Bases provides "note.state", now correctly maps to "status"
    • \n
    • Ensures TaskCard properly recognizes and renders user-configured properties
    • \n
    \n
  • \n
  • Fixed Bases views not respecting user-configured visible properties
      \n
    • Now prioritizes Bases 1.10.0+ public API config.getOrder() method
    • \n
    • Removed reliance on internal API paths that no longer work
    • \n
    • Filters out blocked/blocking properties when using defaults (only shown when explicitly requested via blockedBy)
    • \n
    \n
  • \n
  • Fixed MiniCalendar UTC anchoring for consistent timezone-independent date handling
  • \n
  • Fixed DateValue conversion in BasesDataAdapter
      \n
    • DateValue objects have {date: Date, time: boolean} structure
    • \n
    • Now properly checks for value.date instanceof Date before legacy conversion methods
    • \n
    • Fixes property-based events in CalendarView
    • \n
    \n
  • \n
\n","text":"Beta Release You may encounter issues. Report problems on GitHub Issues. Added# Added context menus for time entries and ICS events in calendar Time entries: Right-click shows task context menu, left-click opens time entry editor modal ICS/Google/Microsoft Calendar events: Right-click shows ICS event context menu with options to show details, create task/note, link note, and copy info Added calendar icon to ICS event titles for better visual distinction Added hover tooltips for timeblocks in calendar views Added MiniCalendar view for Bases integration Monthly calendar grid with dot indicators on days with notes Configurable date property (file.ctime, note.dateCreated, etc.) Fuzzy selector modal for selecting notes on clicked days Ctrl+click (or Cmd+click on Mac) on any day opens/creates daily note Added virtual scrolling and lazy rendering to Bases views for high-performance handling of large datasets TaskListView: Virtual scrolling for 100+ tasks in flat and grouped views with collapsible groups KanbanView: Virtual scrolling for regular columns (30+ tasks) and swimlane cells (30+ tasks per cell) Tested with up to 30,000 notes with no performance degradation Thanks to @aubreyz and @turingexmachina for their reports of performance issues and diagnosis help Changed# Refactored Bases integration to use public API and trust pre-sorted data Migrated all three views (Task List, Kanban, Calendar) to clean class-based architecture Removed legacy view files and ~500 lines of redundant sorting/grouping logic Introduced BasesDataAdapter, PropertyMappingService, and BasesViewBase abstractions Trusts Bases plugin to provide pre-sorted and pre-grouped data via public API Reduced code duplication by 40% while maintaining full feature parity Refactored calendar modules to use ES6 imports instead of lazy require() calls Removed all dynamic require() calls from calendar-core.ts and calendar-view.ts Consolidated all imports at module top level Improves code maintainability, makes dependencies explicit, and follows modern TypeScript best practices Time entry events now show task context menu on right-click (previously had no context menu) Replaced MinimalNativeCache with just-in-time TaskManager for improved reliability Removed complex index synchronization in favor of direct MetadataCache queries Eliminated 7 internal indexes (tasksByDate, tasksByStatus, overdueTasks, etc.) Added minimal DependencyCache for task dependencies and project references only Zero startup time (no index building required) Always provides fresh, accurate task data from Obsidian's MetadataCache Completed internationalization with 100% translation coverage across all supported languages Added 90 missing translation keys to English base Completed 829 translations across 6 languages (German, Spanish, French, Japanese, Russian, Chinese) All locales now have complete coverage (1745/1745 keys) Improved translation quality for migration system, calendar settings, statistics, ICS events, and filter components Migrated to i18n-state-manager CLI tool for translation management Replaced custom scripts with more robust i18n-state-manager package Added i18n-state.config.json for project-specific patterns New features: find-unused, check-duplicates, improved stale detection Hash-based state tracking and ripgrep-based scanning for performance Bases view templates now generate dynamically based on user settings Task filters adapt to user's task identification method (tag or property) Property ordering reflects defaultVisibleProperties setting Uses correct YAML object notation for Bases filters Maintains backward compatibility with legacy static templates Updated Bases CalendarView to show TaskNotes in property-based events Tasks can now be visualized on calendar via any date property (dateCreated, scheduled, due, etc.) Previously all TaskNotes were filtered out from property-based events Fixed# (#1022, #684) Fixed tasks randomly disappearing when Smart Connections plugin is enabled Eliminated race condition caused by index synchronization delays TaskManager now reads directly from Obsidian's MetadataCache instead of maintaining separate indexes No more timing-sensitive code that could conflict with other plugins' metadata processing Tasks will always be visible regardless of other plugins' processing times Thanks to @alejandrospoz, @seepage87, @amarjt, @luckb0x, camara-tech for reporting and help debugging. (#992) Fixed \"Failed to resolve module specifier 'obsidian'\" error when moving recurring task instances in calendar Removed unnecessary dynamic imports that were causing module resolution failures Consolidated imports at top of calendar-core.ts module Thanks to @jalooc for reporting this issue Fixed task dependencies not displaying on task cards TaskManager now properly calculates isBlocked and isBlocking flags from dependency data Added missing property extractors and renderers in TaskCard for all dependency-related fields Dependency information now shows correctly in Bases views, task note widgets, and other views Shows \"Blocked (n)\" and \"Blocking (n)\" pills, plus detailed task links Fixed Bases property mapping for user-configured field names PropertyMappingService now correctly strips prefixes and applies FieldMapper transformations Example: User configures \"state\" → \"status\", Bases provides \"note.state\", now correctly maps to \"status\" Ensures TaskCard properly recognizes and renders user-configured properties Fixed Bases views not respecting user-configured visible properties Now prioritizes Bases 1.10.0+ public API config.getOrder() method Removed reliance on internal API paths that no longer work Filters out blocked/blocking properties when using defaults (only shown when explicitly requested via blockedBy) Fixed MiniCalendar UTC anchoring for consistent timezone-independent date handling Fixed DateValue conversion in BasesDataAdapter DateValue objects have {date: Date, time: boolean} structure Now properly checks for value.date instanceof Date before legacy conversion methods Fixes property-based events in CalendarView"},{"route":"/obsidian/releases/4.0.0-beta.2/","title":"TaskNotes 4.0.0-beta.2","description":"Beta Release","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.0.0-beta.2.md","namespace":"obsidian","relativePath":"releases/4.0.0-beta.2.md","raw":"# TaskNotes 4.0.0-beta.2\n\n> **Beta Release**\n>\n> You may encounter issues. Report problems on [GitHub Issues](https://github.com/callumalpass/tasknotes/issues).\n\n## Added\n\n- (#1090) Portuguese (Brazil) translation\n - Full Portuguese (pt-BR) localization support\n - A big thanks to @andysteel for the contribution\n- **Configurable task modal fields** \n - New \"Modal Fields\" settings tab for complete control over task creation and edit modals\n - Configure which fields appear in creation vs edit modals independently\n - Drag-and-drop reordering of fields within groups (metadata, organization, dependencies, custom)\n - Enable/disable individual fields (including core fields like contexts, tags, time estimate)\n - Organize fields into groups \n - Automatic migration of existing user-defined fields\n - Title and details fields support visibility toggling (ordering fixed for consistency)\n- **Rich markdown editor for NLP task creation**\n - Replaced plain textarea with full CodeMirror markdown editor\n - Live preview, syntax highlighting, and wikilink support\n - Ctrl/Cmd+Enter keyboard shortcut to save task\n - Esc/Tab keyboard shortcuts for modal control\n- **Customizable NLP triggers with autocomplete**\n - Configure custom trigger characters/strings for each property type (tags, contexts, projects, status, priority)\n - Supports user-defined field triggers\n - CodeMirror-based autocomplete with keyboard navigation (arrow keys, Enter, Tab)\n - Quote support for multi-word values in user fields\n - Native tag suggester integration when using # trigger\n- **Inline task link overlay enhancements**\n - Configurable visible properties for inline task cards\n - PropertySelectorModal for selecting which properties to display\n - Improved layout: title prioritized, horizontal scrolling for metadata\n - Real-time updates when task data changes\n- **New utility services**\n - `TriggerConfigService` - manages NLP trigger configurations\n - `PropertySelectorModal` - reusable multi-select property picker\n - Property helpers for consistent property handling across views\n- Kanban column reordering via drag and drop\n - Drag column headers to reorder columns\n - Column order is saved per grouping property\n - Visual feedback during drag operations\n- Mini calendar enhancements (in progress)\n - Week numbers column\n - Heat map intensity visualization\n - Note preview tooltips on hover\n - Keyboard navigation\n- **Unified Relationships widget**\n - Consolidated project subtasks, task dependencies, and blocking relationships into a single dynamic widget\n - Four automatic tabs: Subtasks (Kanban), Projects (List), Blocked By (List), Blocking (Kanban)\n - Tabs automatically show/hide based on available relationship data\n - Bases views handle all data updates reactively - no manual refresh needed\n - Single configuration setting: show/hide and position (top/bottom)\n - Significantly reduced code complexity (430 fewer lines)\n\n## Fixed\n\n- (#1084) Fixed word wrapping in NLP preview items\n - Thanks to @maybetm for the fix\n- (#975) Fixed advanced calendar list headers not respecting theme colors\n - Thanks to @hugohil for the fix\n- (#1089) Fixed embedded task list bases growing unbounded and leaving large empty space\n - Embedded bases now scroll internally instead of expanding to show all tasks\n - Consistent behavior between task list and kanban embedded views\n - Thanks to @same774 for reporting with screenshot\n- **Bases Calendar view options now working correctly**\n - Fixed \"Highlight today\" toggle not applying - now properly adds/removes CSS class when toggled\n - Fixed calendar view type (month/week/day/etc) not being saved when changed via calendar buttons\n - View type is now persisted when users click month/week/day buttons in the calendar UI\n- (#1050) Task modal no longer adds unwanted empty contexts and projects arrays\n - FieldMapper now checks if arrays are empty before writing to frontmatter\n - Thanks to @nightroman for reporting this issue\n- **Inline task link overlay fixes**\n - Fixed layout prioritization: title now prioritized over metadata\n - Added horizontal scrolling for metadata to prevent overflow\n - Fixed real-time update listeners for task data changes\n- Fixed group collapse/expand functionality in TaskListView\n - Re-registered click event listener for group headers using Component API\n - Groups can now be properly collapsed and expanded\n- Fixed config loading race condition in KanbanView and CalendarView\n - Config is now properly loaded in onload() lifecycle method\n - Views wait for config before rendering options\n- Fixed MiniCalendarView to use direct Bases API like other views\n - Consistent use of Component lifecycle methods\n - Proper cleanup in onunload()\n\n## Changed\n\n- **NLP system overhaul**\n - Replaced `StatusSuggestionService` wrapper with direct `NaturalLanguageParser` usage\n - Consolidated trigger configuration into unified `TriggerConfigService`\n - Enhanced `NaturalLanguageParser` with full trigger and user field support\n - Removed custom # tag autocomplete in favor of Obsidian's native tag suggester (when using # trigger)\n- **Task card and editor improvements**\n - Simplified `TaskCard` interface - removed unused options (showCheckbox, showArchiveButton, groupByDate)\n - Refactored `TaskLinkWidget` to use unified `TaskCard` component for consistency\n - Added support for inline vs. block layout modes in task cards\n - Improved task card BEM CSS with better styling for inline mode\n- **Settings UI enhancements**\n - NLP triggers now configurable through Settings > Features tab\n - Added settings for inline task card visible properties\n - Improved appearance tab with property selector integration\n - Better organization of NLP-related settings\n- Refactored Bases views to use Component lifecycle properly\n - Views now extend Component and use onload()/onunload()\n - Automatic cleanup of event listeners via Component.registerDomEvent()\n - Improved state management and ephemeral state handling\n- Improved development experience\n - Converted ESLint errors to warnings for non-blocking development\n - Fixed various linting issues and unused imports\n\n## Removed\n\n- Removed `StatusSuggestionService` (functionality consolidated into `NaturalLanguageParser`)\n\n## Breaking Changes\n\n- **Relationships widget settings consolidated** (automatic migration)\n - Old settings removed: `showProjectSubtasks`, `projectSubtasksPosition`, `showTaskDependencies`, `taskDependenciesPosition`\n - New unified settings: `showRelationships`, `relationshipsPosition`\n - Widget now appears on ALL notes (tasks, projects, regular notes) - Bases filtering controls which tabs are visible\n - **Migration**: Existing users will see the new unified widget automatically. If you had project subtasks enabled, relationships widget will be enabled by default\n - **Bases file change**: The command mapping changed from `'project-subtasks': 'TaskNotes/Views/project-subtasks.base'` to `'relationships': 'TaskNotes/Views/relationships.base'`\n - Run \"Create Default Files\" in Settings > General to create the new `relationships.base` file\n\n","aliases":["/releases/4.0.0-beta.2/","/releases/4.0.0-beta.2/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"removed","text":"Removed"},{"level":2,"id":"breaking-changes","text":"Breaking Changes"}],"html":"
\n

Beta Release

\n

You may encounter issues. Report problems on GitHub Issues.

\n
\n

Added#

\n
    \n
  • (#1090) Portuguese (Brazil) translation
      \n
    • Full Portuguese (pt-BR) localization support
    • \n
    • A big thanks to @andysteel for the contribution
    • \n
    \n
  • \n
  • Configurable task modal fields
      \n
    • New "Modal Fields" settings tab for complete control over task creation and edit modals
    • \n
    • Configure which fields appear in creation vs edit modals independently
    • \n
    • Drag-and-drop reordering of fields within groups (metadata, organization, dependencies, custom)
    • \n
    • Enable/disable individual fields (including core fields like contexts, tags, time estimate)
    • \n
    • Organize fields into groups
    • \n
    • Automatic migration of existing user-defined fields
    • \n
    • Title and details fields support visibility toggling (ordering fixed for consistency)
    • \n
    \n
  • \n
  • Rich markdown editor for NLP task creation
      \n
    • Replaced plain textarea with full CodeMirror markdown editor
    • \n
    • Live preview, syntax highlighting, and wikilink support
    • \n
    • Ctrl/Cmd+Enter keyboard shortcut to save task
    • \n
    • Esc/Tab keyboard shortcuts for modal control
    • \n
    \n
  • \n
  • Customizable NLP triggers with autocomplete
      \n
    • Configure custom trigger characters/strings for each property type (tags, contexts, projects, status, priority)
    • \n
    • Supports user-defined field triggers
    • \n
    • CodeMirror-based autocomplete with keyboard navigation (arrow keys, Enter, Tab)
    • \n
    • Quote support for multi-word values in user fields
    • \n
    • Native tag suggester integration when using # trigger
    • \n
    \n
  • \n
  • Inline task link overlay enhancements
      \n
    • Configurable visible properties for inline task cards
    • \n
    • PropertySelectorModal for selecting which properties to display
    • \n
    • Improved layout: title prioritized, horizontal scrolling for metadata
    • \n
    • Real-time updates when task data changes
    • \n
    \n
  • \n
  • New utility services
      \n
    • TriggerConfigService - manages NLP trigger configurations
    • \n
    • PropertySelectorModal - reusable multi-select property picker
    • \n
    • Property helpers for consistent property handling across views
    • \n
    \n
  • \n
  • Kanban column reordering via drag and drop
      \n
    • Drag column headers to reorder columns
    • \n
    • Column order is saved per grouping property
    • \n
    • Visual feedback during drag operations
    • \n
    \n
  • \n
  • Mini calendar enhancements (in progress)
      \n
    • Week numbers column
    • \n
    • Heat map intensity visualization
    • \n
    • Note preview tooltips on hover
    • \n
    • Keyboard navigation
    • \n
    \n
  • \n
  • Unified Relationships widget
      \n
    • Consolidated project subtasks, task dependencies, and blocking relationships into a single dynamic widget
    • \n
    • Four automatic tabs: Subtasks (Kanban), Projects (List), Blocked By (List), Blocking (Kanban)
    • \n
    • Tabs automatically show/hide based on available relationship data
    • \n
    • Bases views handle all data updates reactively - no manual refresh needed
    • \n
    • Single configuration setting: show/hide and position (top/bottom)
    • \n
    • Significantly reduced code complexity (430 fewer lines)
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1084) Fixed word wrapping in NLP preview items
      \n
    • Thanks to @maybetm for the fix
    • \n
    \n
  • \n
  • (#975) Fixed advanced calendar list headers not respecting theme colors
      \n
    • Thanks to @hugohil for the fix
    • \n
    \n
  • \n
  • (#1089) Fixed embedded task list bases growing unbounded and leaving large empty space
      \n
    • Embedded bases now scroll internally instead of expanding to show all tasks
    • \n
    • Consistent behavior between task list and kanban embedded views
    • \n
    • Thanks to @same774 for reporting with screenshot
    • \n
    \n
  • \n
  • Bases Calendar view options now working correctly
      \n
    • Fixed "Highlight today" toggle not applying - now properly adds/removes CSS class when toggled
    • \n
    • Fixed calendar view type (month/week/day/etc) not being saved when changed via calendar buttons
    • \n
    • View type is now persisted when users click month/week/day buttons in the calendar UI
    • \n
    \n
  • \n
  • (#1050) Task modal no longer adds unwanted empty contexts and projects arrays
      \n
    • FieldMapper now checks if arrays are empty before writing to frontmatter
    • \n
    • Thanks to @nightroman for reporting this issue
    • \n
    \n
  • \n
  • Inline task link overlay fixes
      \n
    • Fixed layout prioritization: title now prioritized over metadata
    • \n
    • Added horizontal scrolling for metadata to prevent overflow
    • \n
    • Fixed real-time update listeners for task data changes
    • \n
    \n
  • \n
  • Fixed group collapse/expand functionality in TaskListView
      \n
    • Re-registered click event listener for group headers using Component API
    • \n
    • Groups can now be properly collapsed and expanded
    • \n
    \n
  • \n
  • Fixed config loading race condition in KanbanView and CalendarView
      \n
    • Config is now properly loaded in onload() lifecycle method
    • \n
    • Views wait for config before rendering options
    • \n
    \n
  • \n
  • Fixed MiniCalendarView to use direct Bases API like other views
      \n
    • Consistent use of Component lifecycle methods
    • \n
    • Proper cleanup in onunload()
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • NLP system overhaul
      \n
    • Replaced StatusSuggestionService wrapper with direct NaturalLanguageParser usage
    • \n
    • Consolidated trigger configuration into unified TriggerConfigService
    • \n
    • Enhanced NaturalLanguageParser with full trigger and user field support
    • \n
    • Removed custom # tag autocomplete in favor of Obsidian's native tag suggester (when using # trigger)
    • \n
    \n
  • \n
  • Task card and editor improvements
      \n
    • Simplified TaskCard interface - removed unused options (showCheckbox, showArchiveButton, groupByDate)
    • \n
    • Refactored TaskLinkWidget to use unified TaskCard component for consistency
    • \n
    • Added support for inline vs. block layout modes in task cards
    • \n
    • Improved task card BEM CSS with better styling for inline mode
    • \n
    \n
  • \n
  • Settings UI enhancements
      \n
    • NLP triggers now configurable through Settings > Features tab
    • \n
    • Added settings for inline task card visible properties
    • \n
    • Improved appearance tab with property selector integration
    • \n
    • Better organization of NLP-related settings
    • \n
    \n
  • \n
  • Refactored Bases views to use Component lifecycle properly
      \n
    • Views now extend Component and use onload()/onunload()
    • \n
    • Automatic cleanup of event listeners via Component.registerDomEvent()
    • \n
    • Improved state management and ephemeral state handling
    • \n
    \n
  • \n
  • Improved development experience
      \n
    • Converted ESLint errors to warnings for non-blocking development
    • \n
    • Fixed various linting issues and unused imports
    • \n
    \n
  • \n
\n

Removed#

\n
    \n
  • Removed StatusSuggestionService (functionality consolidated into NaturalLanguageParser)
  • \n
\n

Breaking Changes#

\n
    \n
  • Relationships widget settings consolidated (automatic migration)
      \n
    • Old settings removed: showProjectSubtasks, projectSubtasksPosition, showTaskDependencies, taskDependenciesPosition
    • \n
    • New unified settings: showRelationships, relationshipsPosition
    • \n
    • Widget now appears on ALL notes (tasks, projects, regular notes) - Bases filtering controls which tabs are visible
    • \n
    • Migration: Existing users will see the new unified widget automatically. If you had project subtasks enabled, relationships widget will be enabled by default
    • \n
    • Bases file change: The command mapping changed from 'project-subtasks': 'TaskNotes/Views/project-subtasks.base' to 'relationships': 'TaskNotes/Views/relationships.base'
    • \n
    • Run "Create Default Files" in Settings > General to create the new relationships.base file
    • \n
    \n
  • \n
\n","text":"Beta Release You may encounter issues. Report problems on GitHub Issues. Added# (#1090) Portuguese (Brazil) translation Full Portuguese (pt-BR) localization support A big thanks to @andysteel for the contribution Configurable task modal fields New \"Modal Fields\" settings tab for complete control over task creation and edit modals Configure which fields appear in creation vs edit modals independently Drag-and-drop reordering of fields within groups (metadata, organization, dependencies, custom) Enable/disable individual fields (including core fields like contexts, tags, time estimate) Organize fields into groups Automatic migration of existing user-defined fields Title and details fields support visibility toggling (ordering fixed for consistency) Rich markdown editor for NLP task creation Replaced plain textarea with full CodeMirror markdown editor Live preview, syntax highlighting, and wikilink support Ctrl/Cmd+Enter keyboard shortcut to save task Esc/Tab keyboard shortcuts for modal control Customizable NLP triggers with autocomplete Configure custom trigger characters/strings for each property type (tags, contexts, projects, status, priority) Supports user-defined field triggers CodeMirror-based autocomplete with keyboard navigation (arrow keys, Enter, Tab) Quote support for multi-word values in user fields Native tag suggester integration when using # trigger Inline task link overlay enhancements Configurable visible properties for inline task cards PropertySelectorModal for selecting which properties to display Improved layout: title prioritized, horizontal scrolling for metadata Real-time updates when task data changes New utility services TriggerConfigService - manages NLP trigger configurations PropertySelectorModal - reusable multi-select property picker Property helpers for consistent property handling across views Kanban column reordering via drag and drop Drag column headers to reorder columns Column order is saved per grouping property Visual feedback during drag operations Mini calendar enhancements (in progress) Week numbers column Heat map intensity visualization Note preview tooltips on hover Keyboard navigation Unified Relationships widget Consolidated project subtasks, task dependencies, and blocking relationships into a single dynamic widget Four automatic tabs: Subtasks (Kanban), Projects (List), Blocked By (List), Blocking (Kanban) Tabs automatically show/hide based on available relationship data Bases views handle all data updates reactively - no manual refresh needed Single configuration setting: show/hide and position (top/bottom) Significantly reduced code complexity (430 fewer lines) Fixed# (#1084) Fixed word wrapping in NLP preview items Thanks to @maybetm for the fix (#975) Fixed advanced calendar list headers not respecting theme colors Thanks to @hugohil for the fix (#1089) Fixed embedded task list bases growing unbounded and leaving large empty space Embedded bases now scroll internally instead of expanding to show all tasks Consistent behavior between task list and kanban embedded views Thanks to @same774 for reporting with screenshot Bases Calendar view options now working correctly Fixed \"Highlight today\" toggle not applying - now properly adds/removes CSS class when toggled Fixed calendar view type (month/week/day/etc) not being saved when changed via calendar buttons View type is now persisted when users click month/week/day buttons in the calendar UI (#1050) Task modal no longer adds unwanted empty contexts and projects arrays FieldMapper now checks if arrays are empty before writing to frontmatter Thanks to @nightroman for reporting this issue Inline task link overlay fixes Fixed layout prioritization: title now prioritized over metadata Added horizontal scrolling for metadata to prevent overflow Fixed real-time update listeners for task data changes Fixed group collapse/expand functionality in TaskListView Re-registered click event listener for group headers using Component API Groups can now be properly collapsed and expanded Fixed config loading race condition in KanbanView and CalendarView Config is now properly loaded in onload() lifecycle method Views wait for config before rendering options Fixed MiniCalendarView to use direct Bases API like other views Consistent use of Component lifecycle methods Proper cleanup in onunload() Changed# NLP system overhaul Replaced StatusSuggestionService wrapper with direct NaturalLanguageParser usage Consolidated trigger configuration into unified TriggerConfigService Enhanced NaturalLanguageParser with full trigger and user field support Removed custom # tag autocomplete in favor of Obsidian's native tag suggester (when using # trigger) Task card and editor improvements Simplified TaskCard interface - removed unused options (showCheckbox, showArchiveButton, groupByDate) Refactored TaskLinkWidget to use unified TaskCard component for consistency Added support for inline vs. block layout modes in task cards Improved task card BEM CSS with better styling for inline mode Settings UI enhancements NLP triggers now configurable through Settings > Features tab Added settings for inline task card visible properties Improved appearance tab with property selector integration Better organization of NLP-related settings Refactored Bases views to use Component lifecycle properly Views now extend Component and use onload()/onunload() Automatic cleanup of event listeners via Component.registerDomEvent() Improved state management and ephemeral state handling Improved development experience Converted ESLint errors to warnings for non-blocking development Fixed various linting issues and unused imports Removed# Removed StatusSuggestionService (functionality consolidated into NaturalLanguageParser) Breaking Changes# Relationships widget settings consolidated (automatic migration) Old settings removed: showProjectSubtasks, projectSubtasksPosition, showTaskDependencies, taskDependenciesPosition New unified settings: showRelationships, relationshipsPosition Widget now appears on ALL notes (tasks, projects, regular notes) - Bases filtering controls which tabs are visible Migration: Existing users will see the new unified widget automatically. If you had project subtasks enabled, relationships widget will be enabled by default Bases file change: The command mapping changed from 'project-subtasks': 'TaskNotes/Views/project-subtasks.base' to 'relationships': 'TaskNotes/Views/relationships.base' Run \"Create Default Files\" in Settings > General to create the new relationships.base file"},{"route":"/obsidian/releases/4.0.0-beta.3/","title":"TaskNotes 4.0.0-beta.3","description":"Beta Release","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.0.0-beta.3.md","namespace":"obsidian","relativePath":"releases/4.0.0-beta.3.md","raw":"# TaskNotes 4.0.0-beta.3\n\n> **Beta Release**\n>\n> You may encounter issues. Report problems on [GitHub Issues](https://github.com/callumalpass/tasknotes/issues).\n\n## Added\n\n- Updated task card styling\n - Increased status dot size from 16px to 18px\n - Added subtle shadows and transitions to card hover states\n - Updated hover effects on status and priority dots with scaling and removed glow\n - Modified metadata pills with backdrop blur and adjusted spacing\n - Added box shadows to interactive elements (dates, projects, tags) on hover\n - Updated animations to use cubic-bezier easing\n - Added gradient accents to subtask and blocking task borders\n - Fixed subtasks appearing behind parent card hover backgrounds\n - Fixed subtask click and context menu events bubbling to parent cards\n - Fixed subtasks inheriting parent priority and status colors\n\n- (#361) Added completion-based recurrence support with `recurrence_anchor` field\n - Tasks can now recur based on completion date instead of scheduled date\n - Set `recurrence_anchor: completion` in task frontmatter to enable this behavior\n - When completing a recurring task, the next occurrence will be scheduled relative to the completion date\n - The DTSTART in the RRULE automatically updates to the completion date, ensuring calendar views show future occurrences at the correct dates\n - Defaults to `scheduled` (original behavior) if not specified\n - Useful for tasks like \"Exercise weekly\" where you want the next occurrence 7 days after you actually complete it, not 7 days after it was scheduled\n - Example: Complete a weekly task 2 days late, and the next occurrence will be 7 days from the completion date (not the original scheduled date)\n - Thanks to @luciolebrillante for the original feature request, and @jhedlund, @nschenone, @BryanWall, @realJohnDoe, and @kazerniel for additional input and interest\n\n- (#416) Added support for skipped recurrence instances with `skipped_instances` field\n - Recurring tasks can now have individual instances marked as \"skipped\" without completing them\n - Skipped instances are stored in the `skipped_instances` frontmatter array (e.g., `[\"2025-11-15\", \"2025-11-22\"]`)\n - Right-click on a recurring task instance in calendar views to skip/unskip it\n - Visual styling differentiates skipped instances:\n - Calendar views: Gray background with muted appearance\n - Task cards: Strike-through text with gray styling\n - Skipped instances don't affect the recurrence pattern - future instances continue as scheduled\n - Useful for holidays, vacations, or other planned exceptions to recurring tasks\n - Thanks to @mdbraber for the suggestion to use an array similar to `complete_instances`, and @jerzy-dudzic for reporting the issue\n\n\n## Fixed\n\n- (#893) Fixed yearly recurring tasks not always updating scheduled date to next occurrence when completed\n - Increased look-ahead period for yearly recurrence from 365 days to 800 days (~2.2 years)\n - Also optimized look-ahead periods for other frequencies: daily (30 days), weekly (90 days), monthly (400 days)\n - Ensures the next occurrence is always found when completing recurring task instances\n - Thanks to @VenturaNotes for reporting\n\n- (#951) Fixed yearly recurring tasks not showing up in calendar's weekly, 3-day, or day views\n - Extended the look-ahead period for yearly recurring tasks when generating calendar instances\n - Calendar views now look ahead ~2.2 years for yearly tasks to ensure occurrences appear even in short date ranges\n - Only displays instances that fall within the actual visible calendar range\n - Weekly recurring tasks were unaffected and continued to work correctly\n - Thanks to @bespokecomp for reporting\n\n- (#889) Fixed git merge conflicts in calendar subscription metadata\n - Calendar subscription `lastFetched` and `lastError` fields are now stored in memory instead of being saved to disk\n - Prevents git conflicts when syncing vaults across multiple computers that independently fetch calendar subscriptions\n - The \"last synced\" timestamp in settings will reset on plugin reload, but subscriptions will re-fetch automatically\n - Thanks to @karlfrohlich for reporting\n\n- Fixed recurrence modal not loading DTSTART date/time when editing existing recurrence rules\n - The custom recurrence modal now correctly parses and displays the start date and time fields\n - Fixed parser that was splitting on `=` instead of `:` for DTSTART values\n\n- (#1097) Fixed custom properties and formulas not displaying in Bases views\n - Updated TaskCard to use Bases API's getValue() method for formulas and custom note properties\n - Formulas now work correctly using `formula.NAME` syntax\n - Custom note properties now work correctly using `note.PROPERTY` syntax\n - Thanks to @cathywu for reporting\n\n- (#1099) Fixed issues with default Bases file creation\n - Fixed double-prefix bug in relationships template that generated invalid filter expressions like `note.note.projects`\n - Fixed race condition where files created during plugin load wouldn't appear in file explorer\n - Default Bases files now generate with correct property paths and appear reliably in the file explorer\n - Thanks to @kmaustral for reporting\n\n- (#1110) Fixed open recurring tasks appearing crossed out in Tasks view\n - Removed stale `selectedDate` property that was never updated in v4\n - Tasks view now uses fresh UTC-anchored \"today\" for correct recurring task completion status\n - Fixes issue where tasks completed yesterday would appear crossed out today for users in positive UTC offset timezones\n - Also fixed KanbanView to use UTC-anchored dates for consistency\n - Thanks to @kmaustral for reporting\n\n- (#1118) Fixed user-defined fields not working in inline task conversion\n - User-defined fields like `>customfield value` now properly convert to frontmatter when using the \"TaskNote: Convert task to TaskNote\" command\n - Fixed fields appearing with internal IDs (e.g., `field_1761435101864`) instead of configured frontmatter key names\n - Array values are now properly joined with commas\n - Added `userFields` property to `ParsedTaskData` interface to support custom fields throughout the conversion flow\n - Thanks to @guncav for reporting\n\n- Fixed kanban column width CSS constraints not matching settings\n - Updated CSS min-width from 280px to 200px and max-width from 350px to 500px to match slider range\n - Column width slider now works correctly across the full 200-500px range\n\n- Kanban view now shows empty columns for all user-defined statuses when grouping by status\n - Empty columns appear for custom statuses defined in settings, even when no tasks have that status\n - Allows users to drag tasks into empty status columns\n - Works in both flat kanban view and swimlane mode\n - Respects the existing \"Hide empty columns\" setting\n - Thanks to @williamcheuk03 for reporting this issue\n","aliases":["/releases/4.0.0-beta.3/","/releases/4.0.0-beta.3/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"
\n

Beta Release

\n

You may encounter issues. Report problems on GitHub Issues.

\n
\n

Added#

\n
    \n
  • Updated task card styling

    \n
      \n
    • Increased status dot size from 16px to 18px
    • \n
    • Added subtle shadows and transitions to card hover states
    • \n
    • Updated hover effects on status and priority dots with scaling and removed glow
    • \n
    • Modified metadata pills with backdrop blur and adjusted spacing
    • \n
    • Added box shadows to interactive elements (dates, projects, tags) on hover
    • \n
    • Updated animations to use cubic-bezier easing
    • \n
    • Added gradient accents to subtask and blocking task borders
    • \n
    • Fixed subtasks appearing behind parent card hover backgrounds
    • \n
    • Fixed subtask click and context menu events bubbling to parent cards
    • \n
    • Fixed subtasks inheriting parent priority and status colors
    • \n
    \n
  • \n
  • (#361) Added completion-based recurrence support with recurrence_anchor field

    \n
      \n
    • Tasks can now recur based on completion date instead of scheduled date
    • \n
    • Set recurrence_anchor: completion in task frontmatter to enable this behavior
    • \n
    • When completing a recurring task, the next occurrence will be scheduled relative to the completion date
    • \n
    • The DTSTART in the RRULE automatically updates to the completion date, ensuring calendar views show future occurrences at the correct dates
    • \n
    • Defaults to scheduled (original behavior) if not specified
    • \n
    • Useful for tasks like "Exercise weekly" where you want the next occurrence 7 days after you actually complete it, not 7 days after it was scheduled
    • \n
    • Example: Complete a weekly task 2 days late, and the next occurrence will be 7 days from the completion date (not the original scheduled date)
    • \n
    • Thanks to @luciolebrillante for the original feature request, and @jhedlund, @nschenone, @BryanWall, @realJohnDoe, and @kazerniel for additional input and interest
    • \n
    \n
  • \n
  • (#416) Added support for skipped recurrence instances with skipped_instances field

    \n
      \n
    • Recurring tasks can now have individual instances marked as "skipped" without completing them
    • \n
    • Skipped instances are stored in the skipped_instances frontmatter array (e.g., ["2025-11-15", "2025-11-22"])
    • \n
    • Right-click on a recurring task instance in calendar views to skip/unskip it
    • \n
    • Visual styling differentiates skipped instances:
        \n
      • Calendar views: Gray background with muted appearance
      • \n
      • Task cards: Strike-through text with gray styling
      • \n
      \n
    • \n
    • Skipped instances don't affect the recurrence pattern - future instances continue as scheduled
    • \n
    • Useful for holidays, vacations, or other planned exceptions to recurring tasks
    • \n
    • Thanks to @mdbraber for the suggestion to use an array similar to complete_instances, and @jerzy-dudzic for reporting the issue
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#893) Fixed yearly recurring tasks not always updating scheduled date to next occurrence when completed

    \n
      \n
    • Increased look-ahead period for yearly recurrence from 365 days to 800 days (~2.2 years)
    • \n
    • Also optimized look-ahead periods for other frequencies: daily (30 days), weekly (90 days), monthly (400 days)
    • \n
    • Ensures the next occurrence is always found when completing recurring task instances
    • \n
    • Thanks to @VenturaNotes for reporting
    • \n
    \n
  • \n
  • (#951) Fixed yearly recurring tasks not showing up in calendar's weekly, 3-day, or day views

    \n
      \n
    • Extended the look-ahead period for yearly recurring tasks when generating calendar instances
    • \n
    • Calendar views now look ahead ~2.2 years for yearly tasks to ensure occurrences appear even in short date ranges
    • \n
    • Only displays instances that fall within the actual visible calendar range
    • \n
    • Weekly recurring tasks were unaffected and continued to work correctly
    • \n
    • Thanks to @bespokecomp for reporting
    • \n
    \n
  • \n
  • (#889) Fixed git merge conflicts in calendar subscription metadata

    \n
      \n
    • Calendar subscription lastFetched and lastError fields are now stored in memory instead of being saved to disk
    • \n
    • Prevents git conflicts when syncing vaults across multiple computers that independently fetch calendar subscriptions
    • \n
    • The "last synced" timestamp in settings will reset on plugin reload, but subscriptions will re-fetch automatically
    • \n
    • Thanks to @karlfrohlich for reporting
    • \n
    \n
  • \n
  • Fixed recurrence modal not loading DTSTART date/time when editing existing recurrence rules

    \n
      \n
    • The custom recurrence modal now correctly parses and displays the start date and time fields
    • \n
    • Fixed parser that was splitting on = instead of : for DTSTART values
    • \n
    \n
  • \n
  • (#1097) Fixed custom properties and formulas not displaying in Bases views

    \n
      \n
    • Updated TaskCard to use Bases API's getValue() method for formulas and custom note properties
    • \n
    • Formulas now work correctly using formula.NAME syntax
    • \n
    • Custom note properties now work correctly using note.PROPERTY syntax
    • \n
    • Thanks to @cathywu for reporting
    • \n
    \n
  • \n
  • (#1099) Fixed issues with default Bases file creation

    \n
      \n
    • Fixed double-prefix bug in relationships template that generated invalid filter expressions like note.note.projects
    • \n
    • Fixed race condition where files created during plugin load wouldn't appear in file explorer
    • \n
    • Default Bases files now generate with correct property paths and appear reliably in the file explorer
    • \n
    • Thanks to @kmaustral for reporting
    • \n
    \n
  • \n
  • (#1110) Fixed open recurring tasks appearing crossed out in Tasks view

    \n
      \n
    • Removed stale selectedDate property that was never updated in v4
    • \n
    • Tasks view now uses fresh UTC-anchored "today" for correct recurring task completion status
    • \n
    • Fixes issue where tasks completed yesterday would appear crossed out today for users in positive UTC offset timezones
    • \n
    • Also fixed KanbanView to use UTC-anchored dates for consistency
    • \n
    • Thanks to @kmaustral for reporting
    • \n
    \n
  • \n
  • (#1118) Fixed user-defined fields not working in inline task conversion

    \n
      \n
    • User-defined fields like >customfield value now properly convert to frontmatter when using the "TaskNote: Convert task to TaskNote" command
    • \n
    • Fixed fields appearing with internal IDs (e.g., field_1761435101864) instead of configured frontmatter key names
    • \n
    • Array values are now properly joined with commas
    • \n
    • Added userFields property to ParsedTaskData interface to support custom fields throughout the conversion flow
    • \n
    • Thanks to @guncav for reporting
    • \n
    \n
  • \n
  • Fixed kanban column width CSS constraints not matching settings

    \n
      \n
    • Updated CSS min-width from 280px to 200px and max-width from 350px to 500px to match slider range
    • \n
    • Column width slider now works correctly across the full 200-500px range
    • \n
    \n
  • \n
  • Kanban view now shows empty columns for all user-defined statuses when grouping by status

    \n
      \n
    • Empty columns appear for custom statuses defined in settings, even when no tasks have that status
    • \n
    • Allows users to drag tasks into empty status columns
    • \n
    • Works in both flat kanban view and swimlane mode
    • \n
    • Respects the existing "Hide empty columns" setting
    • \n
    • Thanks to @williamcheuk03 for reporting this issue
    • \n
    \n
  • \n
\n","text":"Beta Release You may encounter issues. Report problems on GitHub Issues. Added# Updated task card styling Increased status dot size from 16px to 18px Added subtle shadows and transitions to card hover states Updated hover effects on status and priority dots with scaling and removed glow Modified metadata pills with backdrop blur and adjusted spacing Added box shadows to interactive elements (dates, projects, tags) on hover Updated animations to use cubic-bezier easing Added gradient accents to subtask and blocking task borders Fixed subtasks appearing behind parent card hover backgrounds Fixed subtask click and context menu events bubbling to parent cards Fixed subtasks inheriting parent priority and status colors (#361) Added completion-based recurrence support with recurrence_anchor field Tasks can now recur based on completion date instead of scheduled date Set recurrence_anchor: completion in task frontmatter to enable this behavior When completing a recurring task, the next occurrence will be scheduled relative to the completion date The DTSTART in the RRULE automatically updates to the completion date, ensuring calendar views show future occurrences at the correct dates Defaults to scheduled (original behavior) if not specified Useful for tasks like \"Exercise weekly\" where you want the next occurrence 7 days after you actually complete it, not 7 days after it was scheduled Example: Complete a weekly task 2 days late, and the next occurrence will be 7 days from the completion date (not the original scheduled date) Thanks to @luciolebrillante for the original feature request, and @jhedlund, @nschenone, @BryanWall, @realJohnDoe, and @kazerniel for additional input and interest (#416) Added support for skipped recurrence instances with skipped_instances field Recurring tasks can now have individual instances marked as \"skipped\" without completing them Skipped instances are stored in the skipped_instances frontmatter array (e.g., [\"2025-11-15\", \"2025-11-22\"]) Right-click on a recurring task instance in calendar views to skip/unskip it Visual styling differentiates skipped instances: Calendar views: Gray background with muted appearance Task cards: Strike-through text with gray styling Skipped instances don't affect the recurrence pattern - future instances continue as scheduled Useful for holidays, vacations, or other planned exceptions to recurring tasks Thanks to @mdbraber for the suggestion to use an array similar to complete_instances, and @jerzy-dudzic for reporting the issue Fixed# (#893) Fixed yearly recurring tasks not always updating scheduled date to next occurrence when completed Increased look-ahead period for yearly recurrence from 365 days to 800 days (~2.2 years) Also optimized look-ahead periods for other frequencies: daily (30 days), weekly (90 days), monthly (400 days) Ensures the next occurrence is always found when completing recurring task instances Thanks to @VenturaNotes for reporting (#951) Fixed yearly recurring tasks not showing up in calendar's weekly, 3-day, or day views Extended the look-ahead period for yearly recurring tasks when generating calendar instances Calendar views now look ahead ~2.2 years for yearly tasks to ensure occurrences appear even in short date ranges Only displays instances that fall within the actual visible calendar range Weekly recurring tasks were unaffected and continued to work correctly Thanks to @bespokecomp for reporting (#889) Fixed git merge conflicts in calendar subscription metadata Calendar subscription lastFetched and lastError fields are now stored in memory instead of being saved to disk Prevents git conflicts when syncing vaults across multiple computers that independently fetch calendar subscriptions The \"last synced\" timestamp in settings will reset on plugin reload, but subscriptions will re-fetch automatically Thanks to @karlfrohlich for reporting Fixed recurrence modal not loading DTSTART date/time when editing existing recurrence rules The custom recurrence modal now correctly parses and displays the start date and time fields Fixed parser that was splitting on = instead of : for DTSTART values (#1097) Fixed custom properties and formulas not displaying in Bases views Updated TaskCard to use Bases API's getValue() method for formulas and custom note properties Formulas now work correctly using formula.NAME syntax Custom note properties now work correctly using note.PROPERTY syntax Thanks to @cathywu for reporting (#1099) Fixed issues with default Bases file creation Fixed double-prefix bug in relationships template that generated invalid filter expressions like note.note.projects Fixed race condition where files created during plugin load wouldn't appear in file explorer Default Bases files now generate with correct property paths and appear reliably in the file explorer Thanks to @kmaustral for reporting (#1110) Fixed open recurring tasks appearing crossed out in Tasks view Removed stale selectedDate property that was never updated in v4 Tasks view now uses fresh UTC-anchored \"today\" for correct recurring task completion status Fixes issue where tasks completed yesterday would appear crossed out today for users in positive UTC offset timezones Also fixed KanbanView to use UTC-anchored dates for consistency Thanks to @kmaustral for reporting (#1118) Fixed user-defined fields not working in inline task conversion User-defined fields like >customfield value now properly convert to frontmatter when using the \"TaskNote: Convert task to TaskNote\" command Fixed fields appearing with internal IDs (e.g., field_1761435101864) instead of configured frontmatter key names Array values are now properly joined with commas Added userFields property to ParsedTaskData interface to support custom fields throughout the conversion flow Thanks to @guncav for reporting Fixed kanban column width CSS constraints not matching settings Updated CSS min-width from 280px to 200px and max-width from 350px to 500px to match slider range Column width slider now works correctly across the full 200-500px range Kanban view now shows empty columns for all user-defined statuses when grouping by status Empty columns appear for custom statuses defined in settings, even when no tasks have that status Allows users to drag tasks into empty status columns Works in both flat kanban view and swimlane mode Respects the existing \"Hide empty columns\" setting Thanks to @williamcheuk03 for reporting this issue"},{"route":"/obsidian/releases/4.0.1/","title":"TaskNotes 4","description":"TaskNotes 4.0.1 is a stability-focused major release that finishes the migration to Obsidian's Bases core plugin. Every task-facing view (Task List, Kanban, Calendar, Agenda...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.0.1.md","namespace":"obsidian","relativePath":"releases/4.0.1.md","raw":"# TaskNotes 4\n\nTaskNotes 4.0.1 is a stability-focused major release that finishes the migration to Obsidian's Bases core plugin. Every task-facing view (Task List, Kanban, Calendar, Agenda, Mini Calendar, and the embedded Relationships widget) now runs on `.base` files. This refactor simplifies the plugin codebase, removes bespoke UI logic, and lets workflows feel native to Obsidian—views are just files in your vault.\n\n## Highlights\n\n**New features and improvements:**\n\n- Performance improvements\n - Virtual scrolling in Task List and Kanban views handles **30,000+ tasks** without performance degradation\n- **OAuth calendar integration**\n - Google Calendar and Microsoft Outlook bi-directional sync\n - Drag calendar events in the TaskNotes calendar to update them online\n- **Configurable modals and NLP**\n - New Modal Fields settings tab for moving, hiding, or requiring fields in create/edit modals\n - Rich markdown editor and customizable NLP triggers, including autocomplete for user fields\n- **Time management features**\n - Time Entry Editor Modal \n - Improved Timeblock creation and management\n - Completion-based recurrence with `recurrence_anchor` field\n - Skippable recurrence instances\n\n**Bases architecture changes:**\n\n- **Bases-first architecture**\n - Task views ship as `.base` files inside `TaskNotes/Views/`\n - Commands and ribbon buttons now open files you control\n - Filtering/grouping/sorting uses Bases YAML instead of TaskNotes-specific UI\n - Agenda is a dedicated list-mode calendar `.base` file for fast daily/weekly reviews\n- **Inline workflows stay in sync**\n - Unified Relationships widget embeds a Bases view so project subtasks, dependencies, and blocking tasks stay in one place\n - Task cards inside notes honor the same Bases filtering/grouping rules as standalone views\n\n## Why Bases?\n\nMoving everything to Bases allowed us to delete thousands of lines of bespoke filtering logic, state management, and widget code. The plugin now leans on Obsidian's supported API, which:\n\n- Reduces maintenance overhead and improves reliability\n- Lets advanced users version-control and audit their view definitions\n- Makes saved views portable between vaults\n- Keeps TaskNotes behavior consistent with other Obsidian-native workflows\n\n## Upgrade Notes\n\n- Obsidian **1.10.1 or later** is required (Bases public API with group-by support)\n- Enable the **Bases** core plugin before opening TaskNotes views\n- Run **Settings → TaskNotes → General → Create Default Files** if you need fresh `.base` files\n- Use **Export All Saved Views to Bases** to convert any legacy FilterBar saved views into `.base` files\n- The Relationships widget uses `TaskNotes/Views/relationships.base`; adjust that file to change what appears inside notes\n\n## Breaking Changes\n\n- The old FilterBar UI has been removed—all filtering and saved views live in `.base` files\n- Legacy widget settings (`showProjectSubtasks`, `showTaskDependencies`, etc.) were replaced with `showRelationships` and `relationshipsPosition`\n- Task view commands now fail if their mapped `.base` file is missing; configure paths under **Settings → TaskNotes → General → View Commands**\n- **Priority sorting now uses alphabetical order instead of custom weights**\n - In v3, TaskNotes used priority \"weights\" to determine sort order (higher weight = higher priority)\n - In v4, Obsidian's Bases plugin sorts priorities alphabetically by their value\n - The weight field has been removed from the settings UI\n - **Workaround**: Name your priority values to sort alphabetically in your desired order\n - Example: `1-urgent`, `2-high`, `3-medium`, `4-normal`, `5-low`\n - Or: `a-urgent`, `b-high`, `c-medium`, `d-normal`, `e-low`\n- Agenda view has been replaced by the list view in Calendar\n - Grouping is not supported in this view, so the \"Overdue\" group is no longer provided\n - A separate \"Overdue\" view is available in the \"Task List\" base file\n\n## Known Issues\n\n- Users upgrading from versions prior to 3.x should export saved views to Bases before deleting old plugin data\n- Embedded Bases views still require the Bases plugin to remain enabled; disabling Bases will hide TaskNotes task views\n\n## Details\n\n### Added\n\n- Virtual scrolling and lazy rendering to Bases views for handling thousands of notes without performance degradation - Thanks to @aubreyz and @turingexmachina for reporting performance issues and help with diagnosis\n- Google Calendar and Microsoft Outlook integration via OAuth 2.0 with automatic syncing\n- Time Entry Editor Modal for managing time entries (Alt-drag on calendar to create)\n- Kanban Swimlane Layout with horizontal grouping and configurable column widths\n- Saved View Converter button in settings to convert v3 saved filter views to `.base` files\n- Context menus for time entries and ICS events in calendar views\n- Calendar icon to ICS event titles for better visual distinction\n- Hover tooltips for timeblocks in calendar views\n- MiniCalendar view for Bases integration with monthly grid and dot indicators - Thanks to @aubreyz and @turingexmachina for reporting performance issues and help with diagnosis\n- (#1090) Portuguese (Brazil) translation - Thanks to @andysteel for the contribution\n- Configurable task modal fields with drag-and-drop reordering in new \"Modal Fields\" settings tab\n- Rich markdown editor for NLP task creation with syntax highlighting and wikilink support\n- Customizable NLP triggers with autocomplete and keyboard navigation\n- Inline task link overlay enhancements with configurable visible properties\n- Kanban column reordering via drag and drop with saved order per grouping property\n- Mini calendar enhancements including week numbers, heat map visualization, note preview tooltips, and keyboard navigation\n- Unified Relationships widget consolidating project subtasks, dependencies, and blocking relationships with automatic tabs\n- Updated task card styling with improved hover effects, shadows, and gradient accents\n- (#361) Completion-based recurrence support with `recurrence_anchor` field for tasks that recur based on completion date - Thanks to @luciolebrillante for the original feature request, and @jhedlund, @nschenone, @BryanWall, @realJohnDoe, and @kazerniel for additional input and interest\n- (#416) Support for skipped recurrence instances with `skipped_instances` field and right-click skip/unskip in calendar - Thanks to @mdbraber for suggesting the array approach and @jerzy-dudzic for reporting the issue\n- Sub-grouping support to Bases Task List view with nested grouping by any property and collapsible groups\n- Documentation for default Bases templates showing all default `.base` file templates with examples\n\n### Changed\n\n- All views (Calendar, MiniCalendar, Kanban, Tasks, Agenda, Project Subtasks) now use Bases architecture with `.base` files\n- Calendar sources (Google, Microsoft, ICS events) can be toggled independently with improved timezone handling\n- Reorganized settings tabs with OAuth calendar settings in Integrations tab\n- Refactored Bases integration to use public API and trust pre-sorted data\n- Refactored calendar modules to use ES6 imports instead of lazy require() calls\n- Time entry events now show task context menu on right-click\n- Replaced MinimalNativeCache with just-in-time TaskManager for zero startup time and always-fresh task data\n- Completed internationalization with 100% translation coverage across all 6 supported languages\n- Migrated to i18n-state-manager CLI tool for improved translation management\n- Bases view templates now generate dynamically based on user settings with adaptive task filters\n- Updated Bases CalendarView to show TaskNotes in property-based events\n- NLP system overhaul with consolidated trigger configuration and direct NaturalLanguageParser usage\n- Simplified TaskCard interface and refactored TaskLinkWidget for consistency\n- Settings UI enhancements with NLP triggers configurable through Features tab\n- Refactored Bases views to use Component lifecycle properly with automatic cleanup\n- Improved development experience by converting ESLint errors to warnings\n- Renamed \"Advanced Calendar\" to \"Calendar\" throughout the UI\n- Improved timeblock visual styling in calendar views with reduced border width and softer shadows\n- Updated \"Export All Views\" button to \"Export V3 Views\" to clarify it migrates v3 saved views\n- Improved internationalization (i18n) support in General settings tab with all Bases integration settings using translation keys\n- Changed default Tasks List template view order with \"All Tasks\" first and added \"Unscheduled\" view\n\n### Fixed\n\n- (#843) Fixed task tag being added when \"Identify tasks by\" is set to \"Property\" - Thanks to @jack2game for reporting\n- Fixed dark mode calendar borders\n- Fixed Bases Kanban column ordering - Thanks to @mweichert for reporting\n- Fixed state management bug in FilterSettingsComponent\n- Fixed timezone handling for recurring events\n- (#1022, #684) Fixed tasks randomly disappearing when Smart Connections plugin is enabled by eliminating race condition - Thanks to @alejandrospoz, @seepage87, @amarjt, @luckb0x, and camara-tech for reporting and help debugging\n- (#992) Fixed \"Failed to resolve module specifier 'obsidian'\" error when moving recurring task instances in calendar - Thanks to @jalooc for reporting\n- Fixed task dependencies not displaying on task cards with proper isBlocked and isBlocking flags\n- Fixed Bases property mapping for user-configured field names\n- Fixed Bases views not respecting user-configured visible properties\n- Fixed MiniCalendar UTC anchoring for consistent timezone-independent date handling\n- Fixed DateValue conversion in BasesDataAdapter for property-based events in CalendarView\n- (#1084) Fixed word wrapping in NLP preview items - Thanks to @maybetm for the fix\n- (#975) Fixed advanced calendar list headers not respecting theme colors - Thanks to @hugohil for the fix\n- (#1089) Fixed embedded task list bases growing unbounded and leaving large empty space - Thanks to @same774 for reporting with screenshot\n- Fixed \"Highlight today\" toggle and calendar view type persistence in Bases Calendar view options\n- (#1050) Fixed task modal adding unwanted empty contexts and projects arrays - Thanks to @nightroman for reporting\n- Fixed inline task link overlay layout prioritization and horizontal scrolling for metadata\n- Fixed group collapse/expand functionality in TaskListView\n- Fixed config loading race condition in KanbanView and CalendarView\n- Fixed MiniCalendarView to use direct Bases API like other views\n- (#893) Fixed yearly recurring tasks not always updating scheduled date to next occurrence when completed - Thanks to @VenturaNotes for reporting\n- (#951) Fixed yearly recurring tasks not showing up in calendar's weekly, 3-day, or day views - Thanks to @bespokecomp for reporting\n- (#889) Fixed git merge conflicts in calendar subscription metadata by storing in memory instead of disk - Thanks to @karlfrohlich for reporting\n- Fixed recurrence modal not loading DTSTART date/time when editing existing recurrence rules\n- (#1097) Fixed custom properties and formulas not displaying in Bases views using getValue() method - Thanks to @cathywu for reporting\n- (#1099) Fixed issues with default Bases file creation including double-prefix bug and race condition - Thanks to @kmaustral for reporting\n- (#1110) Fixed open recurring tasks appearing crossed out in Tasks view by using UTC-anchored dates - Thanks to @kmaustral for reporting\n- (#1118) Fixed user-defined fields not working in inline task conversion to TaskNote - Thanks to @guncav for reporting\n- Fixed kanban column width CSS constraints not matching settings slider range\n- Fixed Kanban view showing empty columns for all user-defined statuses when grouping by status - Thanks to @williamcheuk03 for reporting\n- (#1103) Fixed TaskNotes/Views folder being created unnecessarily on startup - Thanks to @Wayment9504 for reporting\n- (#1133) Fixed empty priority columns not showing in Kanban view when \"Hide empty columns\" is disabled - Thanks to @luckb0x for reporting\n- Fixed OAuth calendar cards showing \"Unknown account\" by removing non-functional Account field - Thanks to @Oblique for reporting\n- Fixed incorrect Bases syntax in default template files with correct parameter naming\n- Fixed incorrect Bases syntax in \"Export V3 Views\" feature with correct YAML structure\n- (#1127) Fixed custom priority colors not being respected in Task List and Subtasks sections - Thanks to @HPmattsloper for reporting\n- (#1043) Fixed inability to set \"at time of event\" (0 offset) as default reminder in settings - Thanks to @dblinnikov for reporting\n- (#1055) Fixed break sessions being logged as `type: work` when started via command/hotkey - Thanks to @0-BSCode for reporting and debugging\n- (#1024) Fixed date/time picker immediately closing when selecting time on iPhone by refactoring to native Modal components - Thanks to @3zra47 for reporting\n- (#1122) Fixed inline task titles being truncated too aggressively with increased max-width - Thanks to @jacorvillo for reporting\n- Fixed Obsidian crashes when invalid time values entered in Bases calendar view configuration\n- (#1120) Fixed custom field mappings not being respected throughout the application - Thanks to @kmaustral for reporting\n- (#1121) Fixed custom user fields being saved with auto-generated IDs instead of user-defined property keys - Thanks to @guncav for reporting\n- (#1123) Fixed relationships widget only displaying on task notes, now appears on both task and project notes - Thanks to @dblinnikov for reporting\n- Fixed time entries not showing in calendar view for tasks without scheduled or due dates\n- (#1091) Fixed task card and relationships widgets appearing inside footnote editors - Thanks to @3zra47 for reporting\n- (#1086) Fixed calendar \"+more\" popover showing white text on white background in dark mode - Thanks to @same774 for reporting\n- (#1076) Fixed inability to create timeblocks ending at midnight (00:00) - Thanks to @skoove for reporting\n- (#958) Fixed cursor jumping and layout shifts when typing near task card or relationships widgets in live preview - Thanks to @thesmithmode for detailed debugging information\n- (#513) Fixed task card and relationships widgets not appearing in reading mode and fixed critical memory leak - Thanks to @berzernberg for reporting\n\n### Removed\n\n- Removed StatusSuggestionService (functionality consolidated into NaturalLanguageParser)\n- Removed legacy FilterBar UI - all filtering now lives in `.base` files\n- Removed legacy views\n\n","aliases":["/releases/4.0.1/","/releases/4.0.1/"],"toc":[{"level":2,"id":"highlights","text":"Highlights"},{"level":2,"id":"why-bases","text":"Why Bases?"},{"level":2,"id":"upgrade-notes","text":"Upgrade Notes"},{"level":2,"id":"breaking-changes","text":"Breaking Changes"},{"level":2,"id":"known-issues","text":"Known Issues"},{"level":2,"id":"details","text":"Details"},{"level":3,"id":"added","text":"Added"},{"level":3,"id":"changed","text":"Changed"},{"level":3,"id":"fixed","text":"Fixed"},{"level":3,"id":"removed","text":"Removed"}],"html":"

TaskNotes 4.0.1 is a stability-focused major release that finishes the migration to Obsidian's Bases core plugin. Every task-facing view (Task List, Kanban, Calendar, Agenda, Mini Calendar, and the embedded Relationships widget) now runs on .base files. This refactor simplifies the plugin codebase, removes bespoke UI logic, and lets workflows feel native to Obsidian—views are just files in your vault.

\n

Highlights#

\n

New features and improvements:

\n
    \n
  • Performance improvements
      \n
    • Virtual scrolling in Task List and Kanban views handles 30,000+ tasks without performance degradation
    • \n
    \n
  • \n
  • OAuth calendar integration
      \n
    • Google Calendar and Microsoft Outlook bi-directional sync
    • \n
    • Drag calendar events in the TaskNotes calendar to update them online
    • \n
    \n
  • \n
  • Configurable modals and NLP
      \n
    • New Modal Fields settings tab for moving, hiding, or requiring fields in create/edit modals
    • \n
    • Rich markdown editor and customizable NLP triggers, including autocomplete for user fields
    • \n
    \n
  • \n
  • Time management features
      \n
    • Time Entry Editor Modal
    • \n
    • Improved Timeblock creation and management
    • \n
    • Completion-based recurrence with recurrence_anchor field
    • \n
    • Skippable recurrence instances
    • \n
    \n
  • \n
\n

Bases architecture changes:

\n
    \n
  • Bases-first architecture
      \n
    • Task views ship as .base files inside TaskNotes/Views/
    • \n
    • Commands and ribbon buttons now open files you control
    • \n
    • Filtering/grouping/sorting uses Bases YAML instead of TaskNotes-specific UI
    • \n
    • Agenda is a dedicated list-mode calendar .base file for fast daily/weekly reviews
    • \n
    \n
  • \n
  • Inline workflows stay in sync
      \n
    • Unified Relationships widget embeds a Bases view so project subtasks, dependencies, and blocking tasks stay in one place
    • \n
    • Task cards inside notes honor the same Bases filtering/grouping rules as standalone views
    • \n
    \n
  • \n
\n

Why Bases?#

\n

Moving everything to Bases allowed us to delete thousands of lines of bespoke filtering logic, state management, and widget code. The plugin now leans on Obsidian's supported API, which:

\n
    \n
  • Reduces maintenance overhead and improves reliability
  • \n
  • Lets advanced users version-control and audit their view definitions
  • \n
  • Makes saved views portable between vaults
  • \n
  • Keeps TaskNotes behavior consistent with other Obsidian-native workflows
  • \n
\n

Upgrade Notes#

\n
    \n
  • Obsidian 1.10.1 or later is required (Bases public API with group-by support)
  • \n
  • Enable the Bases core plugin before opening TaskNotes views
  • \n
  • Run Settings → TaskNotes → General → Create Default Files if you need fresh .base files
  • \n
  • Use Export All Saved Views to Bases to convert any legacy FilterBar saved views into .base files
  • \n
  • The Relationships widget uses TaskNotes/Views/relationships.base; adjust that file to change what appears inside notes
  • \n
\n

Breaking Changes#

\n
    \n
  • The old FilterBar UI has been removed—all filtering and saved views live in .base files
  • \n
  • Legacy widget settings (showProjectSubtasks, showTaskDependencies, etc.) were replaced with showRelationships and relationshipsPosition
  • \n
  • Task view commands now fail if their mapped .base file is missing; configure paths under Settings → TaskNotes → General → View Commands
  • \n
  • Priority sorting now uses alphabetical order instead of custom weights
      \n
    • In v3, TaskNotes used priority "weights" to determine sort order (higher weight = higher priority)
    • \n
    • In v4, Obsidian's Bases plugin sorts priorities alphabetically by their value
    • \n
    • The weight field has been removed from the settings UI
    • \n
    • Workaround: Name your priority values to sort alphabetically in your desired order
        \n
      • Example: 1-urgent, 2-high, 3-medium, 4-normal, 5-low
      • \n
      • Or: a-urgent, b-high, c-medium, d-normal, e-low
      • \n
      \n
    • \n
    \n
  • \n
  • Agenda view has been replaced by the list view in Calendar
      \n
    • Grouping is not supported in this view, so the "Overdue" group is no longer provided
    • \n
    • A separate "Overdue" view is available in the "Task List" base file
    • \n
    \n
  • \n
\n

Known Issues#

\n
    \n
  • Users upgrading from versions prior to 3.x should export saved views to Bases before deleting old plugin data
  • \n
  • Embedded Bases views still require the Bases plugin to remain enabled; disabling Bases will hide TaskNotes task views
  • \n
\n

Details#

\n

Added#

\n
    \n
  • Virtual scrolling and lazy rendering to Bases views for handling thousands of notes without performance degradation - Thanks to @aubreyz and @turingexmachina for reporting performance issues and help with diagnosis
  • \n
  • Google Calendar and Microsoft Outlook integration via OAuth 2.0 with automatic syncing
  • \n
  • Time Entry Editor Modal for managing time entries (Alt-drag on calendar to create)
  • \n
  • Kanban Swimlane Layout with horizontal grouping and configurable column widths
  • \n
  • Saved View Converter button in settings to convert v3 saved filter views to .base files
  • \n
  • Context menus for time entries and ICS events in calendar views
  • \n
  • Calendar icon to ICS event titles for better visual distinction
  • \n
  • Hover tooltips for timeblocks in calendar views
  • \n
  • MiniCalendar view for Bases integration with monthly grid and dot indicators - Thanks to @aubreyz and @turingexmachina for reporting performance issues and help with diagnosis
  • \n
  • (#1090) Portuguese (Brazil) translation - Thanks to @andysteel for the contribution
  • \n
  • Configurable task modal fields with drag-and-drop reordering in new "Modal Fields" settings tab
  • \n
  • Rich markdown editor for NLP task creation with syntax highlighting and wikilink support
  • \n
  • Customizable NLP triggers with autocomplete and keyboard navigation
  • \n
  • Inline task link overlay enhancements with configurable visible properties
  • \n
  • Kanban column reordering via drag and drop with saved order per grouping property
  • \n
  • Mini calendar enhancements including week numbers, heat map visualization, note preview tooltips, and keyboard navigation
  • \n
  • Unified Relationships widget consolidating project subtasks, dependencies, and blocking relationships with automatic tabs
  • \n
  • Updated task card styling with improved hover effects, shadows, and gradient accents
  • \n
  • (#361) Completion-based recurrence support with recurrence_anchor field for tasks that recur based on completion date - Thanks to @luciolebrillante for the original feature request, and @jhedlund, @nschenone, @BryanWall, @realJohnDoe, and @kazerniel for additional input and interest
  • \n
  • (#416) Support for skipped recurrence instances with skipped_instances field and right-click skip/unskip in calendar - Thanks to @mdbraber for suggesting the array approach and @jerzy-dudzic for reporting the issue
  • \n
  • Sub-grouping support to Bases Task List view with nested grouping by any property and collapsible groups
  • \n
  • Documentation for default Bases templates showing all default .base file templates with examples
  • \n
\n

Changed#

\n
    \n
  • All views (Calendar, MiniCalendar, Kanban, Tasks, Agenda, Project Subtasks) now use Bases architecture with .base files
  • \n
  • Calendar sources (Google, Microsoft, ICS events) can be toggled independently with improved timezone handling
  • \n
  • Reorganized settings tabs with OAuth calendar settings in Integrations tab
  • \n
  • Refactored Bases integration to use public API and trust pre-sorted data
  • \n
  • Refactored calendar modules to use ES6 imports instead of lazy require() calls
  • \n
  • Time entry events now show task context menu on right-click
  • \n
  • Replaced MinimalNativeCache with just-in-time TaskManager for zero startup time and always-fresh task data
  • \n
  • Completed internationalization with 100% translation coverage across all 6 supported languages
  • \n
  • Migrated to i18n-state-manager CLI tool for improved translation management
  • \n
  • Bases view templates now generate dynamically based on user settings with adaptive task filters
  • \n
  • Updated Bases CalendarView to show TaskNotes in property-based events
  • \n
  • NLP system overhaul with consolidated trigger configuration and direct NaturalLanguageParser usage
  • \n
  • Simplified TaskCard interface and refactored TaskLinkWidget for consistency
  • \n
  • Settings UI enhancements with NLP triggers configurable through Features tab
  • \n
  • Refactored Bases views to use Component lifecycle properly with automatic cleanup
  • \n
  • Improved development experience by converting ESLint errors to warnings
  • \n
  • Renamed "Advanced Calendar" to "Calendar" throughout the UI
  • \n
  • Improved timeblock visual styling in calendar views with reduced border width and softer shadows
  • \n
  • Updated "Export All Views" button to "Export V3 Views" to clarify it migrates v3 saved views
  • \n
  • Improved internationalization (i18n) support in General settings tab with all Bases integration settings using translation keys
  • \n
  • Changed default Tasks List template view order with "All Tasks" first and added "Unscheduled" view
  • \n
\n

Fixed#

\n
    \n
  • (#843) Fixed task tag being added when "Identify tasks by" is set to "Property" - Thanks to @jack2game for reporting
  • \n
  • Fixed dark mode calendar borders
  • \n
  • Fixed Bases Kanban column ordering - Thanks to @mweichert for reporting
  • \n
  • Fixed state management bug in FilterSettingsComponent
  • \n
  • Fixed timezone handling for recurring events
  • \n
  • (#1022, #684) Fixed tasks randomly disappearing when Smart Connections plugin is enabled by eliminating race condition - Thanks to @alejandrospoz, @seepage87, @amarjt, @luckb0x, and camara-tech for reporting and help debugging
  • \n
  • (#992) Fixed "Failed to resolve module specifier 'obsidian'" error when moving recurring task instances in calendar - Thanks to @jalooc for reporting
  • \n
  • Fixed task dependencies not displaying on task cards with proper isBlocked and isBlocking flags
  • \n
  • Fixed Bases property mapping for user-configured field names
  • \n
  • Fixed Bases views not respecting user-configured visible properties
  • \n
  • Fixed MiniCalendar UTC anchoring for consistent timezone-independent date handling
  • \n
  • Fixed DateValue conversion in BasesDataAdapter for property-based events in CalendarView
  • \n
  • (#1084) Fixed word wrapping in NLP preview items - Thanks to @maybetm for the fix
  • \n
  • (#975) Fixed advanced calendar list headers not respecting theme colors - Thanks to @hugohil for the fix
  • \n
  • (#1089) Fixed embedded task list bases growing unbounded and leaving large empty space - Thanks to @same774 for reporting with screenshot
  • \n
  • Fixed "Highlight today" toggle and calendar view type persistence in Bases Calendar view options
  • \n
  • (#1050) Fixed task modal adding unwanted empty contexts and projects arrays - Thanks to @nightroman for reporting
  • \n
  • Fixed inline task link overlay layout prioritization and horizontal scrolling for metadata
  • \n
  • Fixed group collapse/expand functionality in TaskListView
  • \n
  • Fixed config loading race condition in KanbanView and CalendarView
  • \n
  • Fixed MiniCalendarView to use direct Bases API like other views
  • \n
  • (#893) Fixed yearly recurring tasks not always updating scheduled date to next occurrence when completed - Thanks to @VenturaNotes for reporting
  • \n
  • (#951) Fixed yearly recurring tasks not showing up in calendar's weekly, 3-day, or day views - Thanks to @bespokecomp for reporting
  • \n
  • (#889) Fixed git merge conflicts in calendar subscription metadata by storing in memory instead of disk - Thanks to @karlfrohlich for reporting
  • \n
  • Fixed recurrence modal not loading DTSTART date/time when editing existing recurrence rules
  • \n
  • (#1097) Fixed custom properties and formulas not displaying in Bases views using getValue() method - Thanks to @cathywu for reporting
  • \n
  • (#1099) Fixed issues with default Bases file creation including double-prefix bug and race condition - Thanks to @kmaustral for reporting
  • \n
  • (#1110) Fixed open recurring tasks appearing crossed out in Tasks view by using UTC-anchored dates - Thanks to @kmaustral for reporting
  • \n
  • (#1118) Fixed user-defined fields not working in inline task conversion to TaskNote - Thanks to @guncav for reporting
  • \n
  • Fixed kanban column width CSS constraints not matching settings slider range
  • \n
  • Fixed Kanban view showing empty columns for all user-defined statuses when grouping by status - Thanks to @williamcheuk03 for reporting
  • \n
  • (#1103) Fixed TaskNotes/Views folder being created unnecessarily on startup - Thanks to @Wayment9504 for reporting
  • \n
  • (#1133) Fixed empty priority columns not showing in Kanban view when "Hide empty columns" is disabled - Thanks to @luckb0x for reporting
  • \n
  • Fixed OAuth calendar cards showing "Unknown account" by removing non-functional Account field - Thanks to @Oblique for reporting
  • \n
  • Fixed incorrect Bases syntax in default template files with correct parameter naming
  • \n
  • Fixed incorrect Bases syntax in "Export V3 Views" feature with correct YAML structure
  • \n
  • (#1127) Fixed custom priority colors not being respected in Task List and Subtasks sections - Thanks to @HPmattsloper for reporting
  • \n
  • (#1043) Fixed inability to set "at time of event" (0 offset) as default reminder in settings - Thanks to @dblinnikov for reporting
  • \n
  • (#1055) Fixed break sessions being logged as type: work when started via command/hotkey - Thanks to @0-BSCode for reporting and debugging
  • \n
  • (#1024) Fixed date/time picker immediately closing when selecting time on iPhone by refactoring to native Modal components - Thanks to @3zra47 for reporting
  • \n
  • (#1122) Fixed inline task titles being truncated too aggressively with increased max-width - Thanks to @jacorvillo for reporting
  • \n
  • Fixed Obsidian crashes when invalid time values entered in Bases calendar view configuration
  • \n
  • (#1120) Fixed custom field mappings not being respected throughout the application - Thanks to @kmaustral for reporting
  • \n
  • (#1121) Fixed custom user fields being saved with auto-generated IDs instead of user-defined property keys - Thanks to @guncav for reporting
  • \n
  • (#1123) Fixed relationships widget only displaying on task notes, now appears on both task and project notes - Thanks to @dblinnikov for reporting
  • \n
  • Fixed time entries not showing in calendar view for tasks without scheduled or due dates
  • \n
  • (#1091) Fixed task card and relationships widgets appearing inside footnote editors - Thanks to @3zra47 for reporting
  • \n
  • (#1086) Fixed calendar "+more" popover showing white text on white background in dark mode - Thanks to @same774 for reporting
  • \n
  • (#1076) Fixed inability to create timeblocks ending at midnight (00:00) - Thanks to @skoove for reporting
  • \n
  • (#958) Fixed cursor jumping and layout shifts when typing near task card or relationships widgets in live preview - Thanks to @thesmithmode for detailed debugging information
  • \n
  • (#513) Fixed task card and relationships widgets not appearing in reading mode and fixed critical memory leak - Thanks to @berzernberg for reporting
  • \n
\n

Removed#

\n
    \n
  • Removed StatusSuggestionService (functionality consolidated into NaturalLanguageParser)
  • \n
  • Removed legacy FilterBar UI - all filtering now lives in .base files
  • \n
  • Removed legacy views
  • \n
\n","text":"TaskNotes 4.0.1 is a stability-focused major release that finishes the migration to Obsidian's Bases core plugin. Every task-facing view (Task List, Kanban, Calendar, Agenda, Mini Calendar, and the embedded Relationships widget) now runs on .base files. This refactor simplifies the plugin codebase, removes bespoke UI logic, and lets workflows feel native to Obsidian—views are just files in your vault. Highlights# New features and improvements: Performance improvements Virtual scrolling in Task List and Kanban views handles 30,000+ tasks without performance degradation OAuth calendar integration Google Calendar and Microsoft Outlook bi-directional sync Drag calendar events in the TaskNotes calendar to update them online Configurable modals and NLP New Modal Fields settings tab for moving, hiding, or requiring fields in create/edit modals Rich markdown editor and customizable NLP triggers, including autocomplete for user fields Time management features Time Entry Editor Modal Improved Timeblock creation and management Completion-based recurrence with recurrence_anchor field Skippable recurrence instances Bases architecture changes: Bases-first architecture Task views ship as .base files inside TaskNotes/Views/ Commands and ribbon buttons now open files you control Filtering/grouping/sorting uses Bases YAML instead of TaskNotes-specific UI Agenda is a dedicated list-mode calendar .base file for fast daily/weekly reviews Inline workflows stay in sync Unified Relationships widget embeds a Bases view so project subtasks, dependencies, and blocking tasks stay in one place Task cards inside notes honor the same Bases filtering/grouping rules as standalone views Why Bases?# Moving everything to Bases allowed us to delete thousands of lines of bespoke filtering logic, state management, and widget code. The plugin now leans on Obsidian's supported API, which: Reduces maintenance overhead and improves reliability Lets advanced users version-control and audit their view definitions Makes saved views portable between vaults Keeps TaskNotes behavior consistent with other Obsidian-native workflows Upgrade Notes# Obsidian 1.10.1 or later is required (Bases public API with group-by support) Enable the Bases core plugin before opening TaskNotes views Run Settings → TaskNotes → General → Create Default Files if you need fresh .base files Use Export All Saved Views to Bases to convert any legacy FilterBar saved views into .base files The Relationships widget uses TaskNotes/Views/relationships.base; adjust that file to change what appears inside notes Breaking Changes# The old FilterBar UI has been removed—all filtering and saved views live in .base files Legacy widget settings (showProjectSubtasks, showTaskDependencies, etc.) were replaced with showRelationships and relationshipsPosition Task view commands now fail if their mapped .base file is missing; configure paths under Settings → TaskNotes → General → View Commands Priority sorting now uses alphabetical order instead of custom weights In v3, TaskNotes used priority \"weights\" to determine sort order (higher weight = higher priority) In v4, Obsidian's Bases plugin sorts priorities alphabetically by their value The weight field has been removed from the settings UI Workaround: Name your priority values to sort alphabetically in your desired order Example: 1-urgent, 2-high, 3-medium, 4-normal, 5-low Or: a-urgent, b-high, c-medium, d-normal, e-low Agenda view has been replaced by the list view in Calendar Grouping is not supported in this view, so the \"Overdue\" group is no longer provided A separate \"Overdue\" view is available in the \"Task List\" base file Known Issues# Users upgrading from versions prior to 3.x should export saved views to Bases before deleting old plugin data Embedded Bases views still require the Bases plugin to remain enabled; disabling Bases will hide TaskNotes task views Details# Added# Virtual scrolling and lazy rendering to Bases views for handling thousands of notes without performance degradation - Thanks to @aubreyz and @turingexmachina for reporting performance issues and help with diagnosis Google Calendar and Microsoft Outlook integration via OAuth 2.0 with automatic syncing Time Entry Editor Modal for managing time entries (Alt-drag on calendar to create) Kanban Swimlane Layout with horizontal grouping and configurable column widths Saved View Converter button in settings to convert v3 saved filter views to .base files Context menus for time entries and ICS events in calendar views Calendar icon to ICS event titles for better visual distinction Hover tooltips for timeblocks in calendar views MiniCalendar view for Bases integration with monthly grid and dot indicators - Thanks to @aubreyz and @turingexmachina for reporting performance issues and help with diagnosis (#1090) Portuguese (Brazil) translation - Thanks to @andysteel for the contribution Configurable task modal fields with drag-and-drop reordering in new \"Modal Fields\" settings tab Rich markdown editor for NLP task creation with syntax highlighting and wikilink support Customizable NLP triggers with autocomplete and keyboard navigation Inline task link overlay enhancements with configurable visible properties Kanban column reordering via drag and drop with saved order per grouping property Mini calendar enhancements including week numbers, heat map visualization, note preview tooltips, and keyboard navigation Unified Relationships widget consolidating project subtasks, dependencies, and blocking relationships with automatic tabs Updated task card styling with improved hover effects, shadows, and gradient accents (#361) Completion-based recurrence support with recurrence_anchor field for tasks that recur based on completion date - Thanks to @luciolebrillante for the original feature request, and @jhedlund, @nschenone, @BryanWall, @realJohnDoe, and @kazerniel for additional input and interest (#416) Support for skipped recurrence instances with skipped_instances field and right-click skip/unskip in calendar - Thanks to @mdbraber for suggesting the array approach and @jerzy-dudzic for reporting the issue Sub-grouping support to Bases Task List view with nested grouping by any property and collapsible groups Documentation for default Bases templates showing all default .base file templates with examples Changed# All views (Calendar, MiniCalendar, Kanban, Tasks, Agenda, Project Subtasks) now use Bases architecture with .base files Calendar sources (Google, Microsoft, ICS events) can be toggled independently with improved timezone handling Reorganized settings tabs with OAuth calendar settings in Integrations tab Refactored Bases integration to use public API and trust pre-sorted data Refactored calendar modules to use ES6 imports instead of lazy require() calls Time entry events now show task context menu on right-click Replaced MinimalNativeCache with just-in-time TaskManager for zero startup time and always-fresh task data Completed internationalization with 100% translation coverage across all 6 supported languages Migrated to i18n-state-manager CLI tool for improved translation management Bases view templates now generate dynamically based on user settings with adaptive task filters Updated Bases CalendarView to show TaskNotes in property-based events NLP system overhaul with consolidated trigger configuration and direct NaturalLanguageParser usage Simplified TaskCard interface and refactored TaskLinkWidget for consistency Settings UI enhancements with NLP triggers configurable through Features tab Refactored Bases views to use Component lifecycle properly with automatic cleanup Improved development experience by converting ESLint errors to warnings Renamed \"Advanced Calendar\" to \"Calendar\" throughout the UI Improved timeblock visual styling in calendar views with reduced border width and softer shadows Updated \"Export All Views\" button to \"Export V3 Views\" to clarify it migrates v3 saved views Improved internationalization (i18n) support in General settings tab with all Bases integration settings using translation keys Changed default Tasks List template view order with \"All Tasks\" first and added \"Unscheduled\" view Fixed# (#843) Fixed task tag being added when \"Identify tasks by\" is set to \"Property\" - Thanks to @jack2game for reporting Fixed dark mode calendar borders Fixed Bases Kanban column ordering - Thanks to @mweichert for reporting Fixed state management bug in FilterSettingsComponent Fixed timezone handling for recurring events (#1022, #684) Fixed tasks randomly disappearing when Smart Connections plugin is enabled by eliminating race condition - Thanks to @alejandrospoz, @seepage87, @amarjt, @luckb0x, and camara-tech for reporting and help debugging (#992) Fixed \"Failed to resolve module specifier 'obsidian'\" error when moving recurring task instances in calendar - Thanks to @jalooc for reporting Fixed task dependencies not displaying on task cards with proper isBlocked and isBlocking flags Fixed Bases property mapping for user-configured field names Fixed Bases views not respecting user-configured visible properties Fixed MiniCalendar UTC anchoring for consistent timezone-independent date handling Fixed DateValue conversion in BasesDataAdapter for property-based events in CalendarView (#1084) Fixed word wrapping in NLP preview items - Thanks to @maybetm for the fix (#975) Fixed advanced calendar list headers not respecting theme colors - Thanks to @hugohil for the fix (#1089) Fixed embedded task list bases growing unbounded and leaving large empty space - Thanks to @same774 for reporting with screenshot Fixed \"Highlight today\" toggle and calendar view type persistence in Bases Calendar view options (#1050) Fixed task modal adding unwanted empty contexts and projects arrays - Thanks to @nightroman for reporting Fixed inline task link overlay layout prioritization and horizontal scrolling for metadata Fixed group collapse/expand functionality in TaskListView Fixed config loading race condition in KanbanView and CalendarView Fixed MiniCalendarView to use direct Bases API like other views (#893) Fixed yearly recurring tasks not always updating scheduled date to next occurrence when completed - Thanks to @VenturaNotes for reporting (#951) Fixed yearly recurring tasks not showing up in calendar's weekly, 3-day, or day views - Thanks to @bespokecomp for reporting (#889) Fixed git merge conflicts in calendar subscription metadata by storing in memory instead of disk - Thanks to @karlfrohlich for reporting Fixed recurrence modal not loading DTSTART date/time when editing existing recurrence rules (#1097) Fixed custom properties and formulas not displaying in Bases views using getValue() method - Thanks to @cathywu for reporting (#1099) Fixed issues with default Bases file creation including double-prefix bug and race condition - Thanks to @kmaustral for reporting (#1110) Fixed open recurring tasks appearing crossed out in Tasks view by using UTC-anchored dates - Thanks to @kmaustral for reporting (#1118) Fixed user-defined fields not working in inline task conversion to TaskNote - Thanks to @guncav for reporting Fixed kanban column width CSS constraints not matching settings slider range Fixed Kanban view showing empty columns for all user-defined statuses when grouping by status - Thanks to @williamcheuk03 for reporting (#1103) Fixed TaskNotes/Views folder being created unnecessarily on startup - Thanks to @Wayment9504 for reporting (#1133) Fixed empty priority columns not showing in Kanban view when \"Hide empty columns\" is disabled - Thanks to @luckb0x for reporting Fixed OAuth calendar cards showing \"Unknown account\" by removing non-functional Account field - Thanks to @Oblique for reporting Fixed incorrect Bases syntax in default template files with correct parameter naming Fixed incorrect Bases syntax in \"Export V3 Views\" feature with correct YAML structure (#1127) Fixed custom priority colors not being respected in Task List and Subtasks sections - Thanks to @HPmattsloper for reporting (#1043) Fixed inability to set \"at time of event\" (0 offset) as default reminder in settings - Thanks to @dblinnikov for reporting (#1055) Fixed break sessions being logged as type: work when started via command/hotkey - Thanks to @0-BSCode for reporting and debugging (#1024) Fixed date/time picker immediately closing when selecting time on iPhone by refactoring to native Modal components - Thanks to @3zra47 for reporting (#1122) Fixed inline task titles being truncated too aggressively with increased max-width - Thanks to @jacorvillo for reporting Fixed Obsidian crashes when invalid time values entered in Bases calendar view configuration (#1120) Fixed custom field mappings not being respected throughout the application - Thanks to @kmaustral for reporting (#1121) Fixed custom user fields being saved with auto-generated IDs instead of user-defined property keys - Thanks to @guncav for reporting (#1123) Fixed relationships widget only displaying on task notes, now appears on both task and project notes - Thanks to @dblinnikov for reporting Fixed time entries not showing in calendar view for tasks without scheduled or due dates (#1091) Fixed task card and relationships widgets appearing inside footnote editors - Thanks to @3zra47 for reporting (#1086) Fixed calendar \"+more\" popover showing white text on white background in dark mode - Thanks to @same774 for reporting (#1076) Fixed inability to create timeblocks ending at midnight (00:00) - Thanks to @skoove for reporting (#958) Fixed cursor jumping and layout shifts when typing near task card or relationships widgets in live preview - Thanks to @thesmithmode for detailed debugging information (#513) Fixed task card and relationships widgets not appearing in reading mode and fixed critical memory leak - Thanks to @berzernberg for reporting Removed# Removed StatusSuggestionService (functionality consolidated into NaturalLanguageParser) Removed legacy FilterBar UI - all filtering now lives in .base files Removed legacy views"},{"route":"/obsidian/releases/4.0.2/","title":"TaskNotes 4.0.2","description":"This release fixes some of the more urgent (and easy-to-fix) bugs that were introduced in the v4 major release. Thanks to everyone for your patience, and to those who have repor...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.0.2.md","namespace":"obsidian","relativePath":"releases/4.0.2.md","raw":"# TaskNotes 4.0.2\n\nThis release fixes some of the more urgent (and easy-to-fix) bugs that were introduced in the v4 major release. Thanks to everyone for your patience, and to those who have reported issues, for taking the time to do so. There will be more releases over the coming weeks to iron out some of v4's kinks.\n\n## Added\n\n- Added \"Not Blocked\" view to default task list template\n - Shows incomplete tasks that are ready to work on (not blocked by incomplete dependencies)\n - Uses Bases `list.filter()` to check completion status of each blocking task\n - This new view can be accessed by regenerating the Task List view, or by copying the filters from the [default base templates documentation](https://tasknotes.dev/views/default-base-templates)\n\n## Fixed\n\n- (#1145, #1156) Fixed default Kanban view requiring manual 'Group by' configuration\n - Default Kanban template now automatically includes `groupBy` property set to status\n - Resolves \"Kanban requires a 'Group by' property to be configured\" error on first use\n - Users no longer need to manually configure grouping through the Sort menu\n - Thanks to @randomness42 and @seepage87 for reporting\n- Fixed user-defined custom fields appearing as `user:field_xxx` in generated base templates\n - Custom fields now use their actual property names (e.g., `effort` instead of `user:field_1761435303709`)\n - Ensures Bases can properly query user-defined properties\n - Also fixed `totalTrackedTime` to correctly map to the configured `timeEntries` property name\n- (#1145) Improved Kanban error message when no 'Group by' property is configured\n - Now includes instructions: \"Click the 'Sort' button and select a property under 'Group by'\"\n - Thanks to @randomness42 for the suggestion\n- (#1139, #1141) Fixed relationships widget not appearing in project notes\n - Project references are now resolved to full file paths when indexing\n - Uses Obsidian's link resolution API to handle wikilinks, markdown links, and relative paths\n - Restores v3.x behavior where subtasks appear in parent project notes\n - Thanks to @jhedlund, @n1njaznutz, and @luckb0x for reporting and testing\n- Fixed dependency blocking status to be status-aware\n - \"Blocked (x)\" pill now only appears when tasks have **incomplete** blocking dependencies\n - Tasks with all completed blocking dependencies no longer show as blocked\n- Fixed cache invalidation bug causing blocking/blocked pills to disappear when editing tasks\n - When a task is modified, only forward dependencies are cleared (stored in its frontmatter)\n - Reverse dependencies are preserved (stored in other tasks' frontmatter)\n\n## Changed\n\n- Removed custom TaskNotes icon from task modals\n - Task creation and edit modals now use Obsidian's standard title styling \n - Thanks to @kepano for the suggestion\n- Moved default base templates documentation to `docs/views/`\n - Location: `docs/views/default-base-templates.md`\n - Added cross-references to official Obsidian Bases documentation\n - Updated code comments to reference new documentation path\n- Fixed incorrect quote escaping in default base templates documentation\n - YAML examples now use proper single quotes for strings containing double quotes\n","aliases":["/releases/4.0.2/","/releases/4.0.2/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"changed","text":"Changed"}],"html":"

This release fixes some of the more urgent (and easy-to-fix) bugs that were introduced in the v4 major release. Thanks to everyone for your patience, and to those who have reported issues, for taking the time to do so. There will be more releases over the coming weeks to iron out some of v4's kinks.

\n

Added#

\n
    \n
  • Added "Not Blocked" view to default task list template
      \n
    • Shows incomplete tasks that are ready to work on (not blocked by incomplete dependencies)
    • \n
    • Uses Bases list.filter() to check completion status of each blocking task
    • \n
    • This new view can be accessed by regenerating the Task List view, or by copying the filters from the default base templates documentation
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1145, #1156) Fixed default Kanban view requiring manual 'Group by' configuration
      \n
    • Default Kanban template now automatically includes groupBy property set to status
    • \n
    • Resolves "Kanban requires a 'Group by' property to be configured" error on first use
    • \n
    • Users no longer need to manually configure grouping through the Sort menu
    • \n
    • Thanks to @randomness42 and @seepage87 for reporting
    • \n
    \n
  • \n
  • Fixed user-defined custom fields appearing as user:field_xxx in generated base templates
      \n
    • Custom fields now use their actual property names (e.g., effort instead of user:field_1761435303709)
    • \n
    • Ensures Bases can properly query user-defined properties
    • \n
    • Also fixed totalTrackedTime to correctly map to the configured timeEntries property name
    • \n
    \n
  • \n
  • (#1145) Improved Kanban error message when no 'Group by' property is configured
      \n
    • Now includes instructions: "Click the 'Sort' button and select a property under 'Group by'"
    • \n
    • Thanks to @randomness42 for the suggestion
    • \n
    \n
  • \n
  • (#1139, #1141) Fixed relationships widget not appearing in project notes
      \n
    • Project references are now resolved to full file paths when indexing
    • \n
    • Uses Obsidian's link resolution API to handle wikilinks, markdown links, and relative paths
    • \n
    • Restores v3.x behavior where subtasks appear in parent project notes
    • \n
    • Thanks to @jhedlund, @n1njaznutz, and @luckb0x for reporting and testing
    • \n
    \n
  • \n
  • Fixed dependency blocking status to be status-aware
      \n
    • "Blocked (x)" pill now only appears when tasks have incomplete blocking dependencies
    • \n
    • Tasks with all completed blocking dependencies no longer show as blocked
    • \n
    \n
  • \n
  • Fixed cache invalidation bug causing blocking/blocked pills to disappear when editing tasks
      \n
    • When a task is modified, only forward dependencies are cleared (stored in its frontmatter)
    • \n
    • Reverse dependencies are preserved (stored in other tasks' frontmatter)
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Removed custom TaskNotes icon from task modals
      \n
    • Task creation and edit modals now use Obsidian's standard title styling
    • \n
    • Thanks to @kepano for the suggestion
    • \n
    \n
  • \n
  • Moved default base templates documentation to docs/views/
      \n
    • Location: docs/views/default-base-templates.md
    • \n
    • Added cross-references to official Obsidian Bases documentation
    • \n
    • Updated code comments to reference new documentation path
    • \n
    \n
  • \n
  • Fixed incorrect quote escaping in default base templates documentation
      \n
    • YAML examples now use proper single quotes for strings containing double quotes
    • \n
    \n
  • \n
\n","text":"This release fixes some of the more urgent (and easy-to-fix) bugs that were introduced in the v4 major release. Thanks to everyone for your patience, and to those who have reported issues, for taking the time to do so. There will be more releases over the coming weeks to iron out some of v4's kinks. Added# Added \"Not Blocked\" view to default task list template Shows incomplete tasks that are ready to work on (not blocked by incomplete dependencies) Uses Bases list.filter() to check completion status of each blocking task This new view can be accessed by regenerating the Task List view, or by copying the filters from the default base templates documentation Fixed# (#1145, #1156) Fixed default Kanban view requiring manual 'Group by' configuration Default Kanban template now automatically includes groupBy property set to status Resolves \"Kanban requires a 'Group by' property to be configured\" error on first use Users no longer need to manually configure grouping through the Sort menu Thanks to @randomness42 and @seepage87 for reporting Fixed user-defined custom fields appearing as user:field_xxx in generated base templates Custom fields now use their actual property names (e.g., effort instead of user:field_1761435303709) Ensures Bases can properly query user-defined properties Also fixed totalTrackedTime to correctly map to the configured timeEntries property name (#1145) Improved Kanban error message when no 'Group by' property is configured Now includes instructions: \"Click the 'Sort' button and select a property under 'Group by'\" Thanks to @randomness42 for the suggestion (#1139, #1141) Fixed relationships widget not appearing in project notes Project references are now resolved to full file paths when indexing Uses Obsidian's link resolution API to handle wikilinks, markdown links, and relative paths Restores v3.x behavior where subtasks appear in parent project notes Thanks to @jhedlund, @n1njaznutz, and @luckb0x for reporting and testing Fixed dependency blocking status to be status-aware \"Blocked (x)\" pill now only appears when tasks have incomplete blocking dependencies Tasks with all completed blocking dependencies no longer show as blocked Fixed cache invalidation bug causing blocking/blocked pills to disappear when editing tasks When a task is modified, only forward dependencies are cleared (stored in its frontmatter) Reverse dependencies are preserved (stored in other tasks' frontmatter) Changed# Removed custom TaskNotes icon from task modals Task creation and edit modals now use Obsidian's standard title styling Thanks to @kepano for the suggestion Moved default base templates documentation to docs/views/ Location: docs/views/default-base-templates.md Added cross-references to official Obsidian Bases documentation Updated code comments to reference new documentation path Fixed incorrect quote escaping in default base templates documentation YAML examples now use proper single quotes for strings containing double quotes"},{"route":"/obsidian/releases/4.0.3/","title":"TaskNotes 4.0.3","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.0.3.md","namespace":"obsidian","relativePath":"releases/4.0.3.md","raw":"# TaskNotes 4.0.3\n\n## Fixed\n\n- (#1157) Fixed task embeds appearing on new line instead of inline with bullets in lists\n - Changed inline task cards to use span elements instead of divs for proper inline flow\n - Added max-width constraint to prevent wrapping when tasks are wider than editor\n - Task embeds now display correctly inline with bullet points during live preview\n - Thanks to @3zra47 for reporting\n- (#1168) Fixed mini calendar stealing focus every few seconds when pinned to sidebar\n - Thanks to @DearHaruHaru for reporting\n- (#1161, #1162) Fixed \"unexpected scalar\" YAML parsing error in generated tasks-default.base template\n - Changed nested quotes in \"Not Blocked\" filter from double to single quotes\n - Thanks to @benschifman and @InterstellarRaccoon for reporting, @GarrettKaupp for identifying the fix\n\n## Changed\n\n- Updated task modal UI to use native Obsidian patterns for better theme compatibility\n - Thanks to @kepano for feedback\n\n","aliases":["/releases/4.0.3/","/releases/4.0.3/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"changed","text":"Changed"}],"html":"

Fixed#

\n
    \n
  • (#1157) Fixed task embeds appearing on new line instead of inline with bullets in lists
      \n
    • Changed inline task cards to use span elements instead of divs for proper inline flow
    • \n
    • Added max-width constraint to prevent wrapping when tasks are wider than editor
    • \n
    • Task embeds now display correctly inline with bullet points during live preview
    • \n
    • Thanks to @3zra47 for reporting
    • \n
    \n
  • \n
  • (#1168) Fixed mini calendar stealing focus every few seconds when pinned to sidebar
      \n
    • Thanks to @DearHaruHaru for reporting
    • \n
    \n
  • \n
  • (#1161, #1162) Fixed "unexpected scalar" YAML parsing error in generated tasks-default.base template
      \n
    • Changed nested quotes in "Not Blocked" filter from double to single quotes
    • \n
    • Thanks to @benschifman and @InterstellarRaccoon for reporting, @GarrettKaupp for identifying the fix
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Updated task modal UI to use native Obsidian patterns for better theme compatibility
      \n
    • Thanks to @kepano for feedback
    • \n
    \n
  • \n
\n","text":"Fixed# (#1157) Fixed task embeds appearing on new line instead of inline with bullets in lists Changed inline task cards to use span elements instead of divs for proper inline flow Added max-width constraint to prevent wrapping when tasks are wider than editor Task embeds now display correctly inline with bullet points during live preview Thanks to @3zra47 for reporting (#1168) Fixed mini calendar stealing focus every few seconds when pinned to sidebar Thanks to @DearHaruHaru for reporting (#1161, #1162) Fixed \"unexpected scalar\" YAML parsing error in generated tasks-default.base template Changed nested quotes in \"Not Blocked\" filter from double to single quotes Thanks to @benschifman and @InterstellarRaccoon for reporting, @GarrettKaupp for identifying the fix Changed# Updated task modal UI to use native Obsidian patterns for better theme compatibility Thanks to @kepano for feedback"},{"route":"/obsidian/releases/4.0.4/","title":"TaskNotes 4.0.4","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.0.4.md","namespace":"obsidian","relativePath":"releases/4.0.4.md","raw":"# TaskNotes 4.0.4\n\n## Added\n\n- (#1134, #779) Added CMD+Enter (Mac) / Ctrl+Enter (Windows/Linux) keyboard shortcut support for saving in all modals\n - Works from any input field in task creation, task edit, time entry, timeblock, and property selector modals\n - Thanks to @luckb0x, @hamlim and @nightroman for the feature requests\n\n## Fixed\n\n- (#1181) Fixed vertical overflow in Kanban view columns with fewer than 15 tasks\n - Prevents cards from extending beyond column boundaries before virtualization activates\n - Thanks to @lomarcanys for reporting\n- (#1177) Bases views now anchor recurring completion and calendar navigation to the right date\n - Recurring completion from Bases Task List/Kanban uses the task's scheduled/due date instead of \"today\" (fixes complete_instances)\n - Bases calendar navigation and property-based events use UTC anchors to avoid previous-day jumps\n - Thanks to @nslee123 for flagging the issue\n- Bases calendar navigation now respects UTC-anchored dates to avoid landing on the previous day\n - Corrected all-day end date calculation to prevent off-by-one spans\n - Added regression test for the UTC anchor behavior\n - Thanks to KaCii for [flagging the issue](https://discord.com/channels/686053708261228577/1433165116702199880/1439757826380660767)\n\n## Changed\n\n- Refactored plugin styling to better align with Obsidian's native UI conventions\n - Replaced all `cursor: pointer` with `cursor: var(--cursor)` (100+ instances) to follow Obsidian's cursor convention\n - Removed forced `border: none; box-shadow: none` rules that were fighting against Obsidian's native button styling\n - Scoped custom `.tn-btn` button system to settings modal only (`.mod-settings`), allowing Obsidian's native button styles to work elsewhere\n - Thanks to @kepano for guidance\n","aliases":["/releases/4.0.4/","/releases/4.0.4/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"changed","text":"Changed"}],"html":"

Added#

\n
    \n
  • (#1134, #779) Added CMD+Enter (Mac) / Ctrl+Enter (Windows/Linux) keyboard shortcut support for saving in all modals
      \n
    • Works from any input field in task creation, task edit, time entry, timeblock, and property selector modals
    • \n
    • Thanks to @luckb0x, @hamlim and @nightroman for the feature requests
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1181) Fixed vertical overflow in Kanban view columns with fewer than 15 tasks
      \n
    • Prevents cards from extending beyond column boundaries before virtualization activates
    • \n
    • Thanks to @lomarcanys for reporting
    • \n
    \n
  • \n
  • (#1177) Bases views now anchor recurring completion and calendar navigation to the right date
      \n
    • Recurring completion from Bases Task List/Kanban uses the task's scheduled/due date instead of "today" (fixes complete_instances)
    • \n
    • Bases calendar navigation and property-based events use UTC anchors to avoid previous-day jumps
    • \n
    • Thanks to @nslee123 for flagging the issue
    • \n
    \n
  • \n
  • Bases calendar navigation now respects UTC-anchored dates to avoid landing on the previous day
      \n
    • Corrected all-day end date calculation to prevent off-by-one spans
    • \n
    • Added regression test for the UTC anchor behavior
    • \n
    • Thanks to KaCii for flagging the issue
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Refactored plugin styling to better align with Obsidian's native UI conventions
      \n
    • Replaced all cursor: pointer with cursor: var(--cursor) (100+ instances) to follow Obsidian's cursor convention
    • \n
    • Removed forced border: none; box-shadow: none rules that were fighting against Obsidian's native button styling
    • \n
    • Scoped custom .tn-btn button system to settings modal only (.mod-settings), allowing Obsidian's native button styles to work elsewhere
    • \n
    • Thanks to @kepano for guidance
    • \n
    \n
  • \n
\n","text":"Added# (#1134, #779) Added CMD+Enter (Mac) / Ctrl+Enter (Windows/Linux) keyboard shortcut support for saving in all modals Works from any input field in task creation, task edit, time entry, timeblock, and property selector modals Thanks to @luckb0x, @hamlim and @nightroman for the feature requests Fixed# (#1181) Fixed vertical overflow in Kanban view columns with fewer than 15 tasks Prevents cards from extending beyond column boundaries before virtualization activates Thanks to @lomarcanys for reporting (#1177) Bases views now anchor recurring completion and calendar navigation to the right date Recurring completion from Bases Task List/Kanban uses the task's scheduled/due date instead of \"today\" (fixes complete_instances) Bases calendar navigation and property-based events use UTC anchors to avoid previous-day jumps Thanks to @nslee123 for flagging the issue Bases calendar navigation now respects UTC-anchored dates to avoid landing on the previous day Corrected all-day end date calculation to prevent off-by-one spans Added regression test for the UTC anchor behavior Thanks to KaCii for flagging the issue Changed# Refactored plugin styling to better align with Obsidian's native UI conventions Replaced all cursor: pointer with cursor: var(--cursor) (100+ instances) to follow Obsidian's cursor convention Removed forced border: none; box-shadow: none rules that were fighting against Obsidian's native button styling Scoped custom .tn-btn button system to settings modal only (.mod-settings), allowing Obsidian's native button styles to work elsewhere Thanks to @kepano for guidance"},{"route":"/obsidian/releases/4.0.5/","title":"TaskNotes 4.0.5","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.0.5.md","namespace":"obsidian","relativePath":"releases/4.0.5.md","raw":"# TaskNotes 4.0.5\n\n## Changed\n\n- (#790) Task edit modal now shows unresolved project links with appropriate styling\n\t- Similar to how dependencies are displayed, unresolved projects now appear with visual indication\n\t- Hovering over an unresolved project shows a tooltip explaining it couldn't be resolved\n\t- Thanks to @aubreyz for reporting\n\n## Fixed\n\n- (#1011) Fixed chevrons incorrectly showing on tasks with no subtasks\n\t- Project index was incorrectly adding all linked files instead of only files referenced in the projects field\n\t- Now properly parses the projects field and only indexes those specific files as projects\n\t- Also fixed alias handling in project and dependency links - aliases are now correctly stripped before link resolution\n\t- Thanks to @craziedde for reporting\n- (#1200) Fixed kanban drag & drop not updating task properties correctly\n\t- Dragging tasks to different columns now properly triggers business logic (completedDate, auto-archive, webhooks)\n\t- Previously, kanban updates bypassed `updateProperty` and directly modified frontmatter\n\t- Thanks very much to @tvoklov for the PR\n- (#1203) Fixed autocomplete dropdown being clipped inside NLP field boundaries\n\t- Configure CodeMirror tooltips to render in document.body instead of constrained editor container\n\t- Prevents suggestion dropdown from being hidden when it extends beyond the NLP field height\n\t- Thanks to @Andrei-Ioda for reporting\n- (#1172) Fixed task lists and checkboxes rendering incorrectly in task details editor\n\t- Remove padding-left override on `.cm-line` to allow CodeMirror decorations (checkboxes, indentation) to render properly\n\t- Content padding is now handled by `.cm-content` while `.cm-line` uses natural spacing\n\t- Thanks to @nightroman for reporting\n- Fixed relationships widget not appearing on project notes without frontmatter\n\t- Widget now correctly shows on any note referenced as a project by tasks, regardless of whether the note has frontmatter\n- Fixed task card and relationships widgets not appearing when opening notes in source mode\n\t- Removed live preview mode restriction to allow widgets to render in both source and live preview modes\n- (#901) Fixed calendar view toolbar buttons overflowing on narrow screens\n - Added `flex-wrap: wrap` to calendar header toolbar to allow buttons to wrap to multiple lines\n - Thanks to @RumiaKitinari for reporting\n- (#1193), (#1194), (#1185) Fixed new calendar views not respecting user's default calendar settings\n\t- Previously, new Bases calendar views used hardcoded inline defaults instead of user-configured preferences\n\t- Calendar view initialization now correctly uses `plugin.settings.calendarViewSettings` as the fallback\n\t- Thanks @ki5ck, @minchinweb and @ThamirysOlv for reporting \n- Fixed calendar to ensure that it respects user's locale\n - Tries to use calendar locale, then tries UI language, then system language, then falls back to English\n- (#1043) Fixed default reminders with \"at time of event\" (0 offset) not being applied to tasks\n\t- UI was displaying \"1\" instead of \"0\" for zero-offset reminders in settings\n\t- Thanks to @dblinnikov for reporting\n- (#1206) Fixed NLP status parsing regressions with trigger prefixes and temporal keywords\n\t- Manually typing status trigger + label now correctly parses (e.g., `*Done` when label is `Done`)\n\t- Status values containing temporal keywords no longer misparsed as dates (e.g., `Expedite = Now`)\n\t- Thanks very much to @renatomen for the PR\n- (#1212) Fixed \"Show release notes on update\" toggle not saving correctly\n - Thanks to @Jon-dog for reporting\n- (#1197) Add Portuguese language to list of translations in general tab settings\n - Allows users to select the Portuguese translation option\n - Thanks to @andysteel for the PR\n- Fixed file properties displaying incorrectly in Bases views\n\t- File properties like `file.name`, `file.basename`, `file.size`, etc. were showing as \"Title\" or returning null\n\t- Now correctly extracts and displays all file properties from Obsidian's file metadata\n\t- Supports both direct TFile properties (name, basename, extension, path, size, ctime, mtime) and computed properties (links, embeds, tags, backlinks, aliases)\n","aliases":["/releases/4.0.5/","/releases/4.0.5/"],"toc":[{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Changed#

\n
    \n
  • (#790) Task edit modal now shows unresolved project links with appropriate styling
      \n
    • Similar to how dependencies are displayed, unresolved projects now appear with visual indication
    • \n
    • Hovering over an unresolved project shows a tooltip explaining it couldn't be resolved
    • \n
    • Thanks to @aubreyz for reporting
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1011) Fixed chevrons incorrectly showing on tasks with no subtasks
      \n
    • Project index was incorrectly adding all linked files instead of only files referenced in the projects field
    • \n
    • Now properly parses the projects field and only indexes those specific files as projects
    • \n
    • Also fixed alias handling in project and dependency links - aliases are now correctly stripped before link resolution
    • \n
    • Thanks to @craziedde for reporting
    • \n
    \n
  • \n
  • (#1200) Fixed kanban drag & drop not updating task properties correctly
      \n
    • Dragging tasks to different columns now properly triggers business logic (completedDate, auto-archive, webhooks)
    • \n
    • Previously, kanban updates bypassed updateProperty and directly modified frontmatter
    • \n
    • Thanks very much to @tvoklov for the PR
    • \n
    \n
  • \n
  • (#1203) Fixed autocomplete dropdown being clipped inside NLP field boundaries
      \n
    • Configure CodeMirror tooltips to render in document.body instead of constrained editor container
    • \n
    • Prevents suggestion dropdown from being hidden when it extends beyond the NLP field height
    • \n
    • Thanks to @Andrei-Ioda for reporting
    • \n
    \n
  • \n
  • (#1172) Fixed task lists and checkboxes rendering incorrectly in task details editor
      \n
    • Remove padding-left override on .cm-line to allow CodeMirror decorations (checkboxes, indentation) to render properly
    • \n
    • Content padding is now handled by .cm-content while .cm-line uses natural spacing
    • \n
    • Thanks to @nightroman for reporting
    • \n
    \n
  • \n
  • Fixed relationships widget not appearing on project notes without frontmatter
      \n
    • Widget now correctly shows on any note referenced as a project by tasks, regardless of whether the note has frontmatter
    • \n
    \n
  • \n
  • Fixed task card and relationships widgets not appearing when opening notes in source mode
      \n
    • Removed live preview mode restriction to allow widgets to render in both source and live preview modes
    • \n
    \n
  • \n
  • (#901) Fixed calendar view toolbar buttons overflowing on narrow screens
      \n
    • Added flex-wrap: wrap to calendar header toolbar to allow buttons to wrap to multiple lines
    • \n
    • Thanks to @RumiaKitinari for reporting
    • \n
    \n
  • \n
  • (#1193), (#1194), (#1185) Fixed new calendar views not respecting user's default calendar settings
      \n
    • Previously, new Bases calendar views used hardcoded inline defaults instead of user-configured preferences
    • \n
    • Calendar view initialization now correctly uses plugin.settings.calendarViewSettings as the fallback
    • \n
    • Thanks @ki5ck, @minchinweb and @ThamirysOlv for reporting
    • \n
    \n
  • \n
  • Fixed calendar to ensure that it respects user's locale
      \n
    • Tries to use calendar locale, then tries UI language, then system language, then falls back to English
    • \n
    \n
  • \n
  • (#1043) Fixed default reminders with "at time of event" (0 offset) not being applied to tasks
      \n
    • UI was displaying "1" instead of "0" for zero-offset reminders in settings
    • \n
    • Thanks to @dblinnikov for reporting
    • \n
    \n
  • \n
  • (#1206) Fixed NLP status parsing regressions with trigger prefixes and temporal keywords
      \n
    • Manually typing status trigger + label now correctly parses (e.g., *Done when label is Done)
    • \n
    • Status values containing temporal keywords no longer misparsed as dates (e.g., Expedite = Now)
    • \n
    • Thanks very much to @renatomen for the PR
    • \n
    \n
  • \n
  • (#1212) Fixed "Show release notes on update" toggle not saving correctly
      \n
    • Thanks to @Jon-dog for reporting
    • \n
    \n
  • \n
  • (#1197) Add Portuguese language to list of translations in general tab settings
      \n
    • Allows users to select the Portuguese translation option
    • \n
    • Thanks to @andysteel for the PR
    • \n
    \n
  • \n
  • Fixed file properties displaying incorrectly in Bases views
      \n
    • File properties like file.name, file.basename, file.size, etc. were showing as "Title" or returning null
    • \n
    • Now correctly extracts and displays all file properties from Obsidian's file metadata
    • \n
    • Supports both direct TFile properties (name, basename, extension, path, size, ctime, mtime) and computed properties (links, embeds, tags, backlinks, aliases)
    • \n
    \n
  • \n
\n","text":"Changed# (#790) Task edit modal now shows unresolved project links with appropriate styling Similar to how dependencies are displayed, unresolved projects now appear with visual indication Hovering over an unresolved project shows a tooltip explaining it couldn't be resolved Thanks to @aubreyz for reporting Fixed# (#1011) Fixed chevrons incorrectly showing on tasks with no subtasks Project index was incorrectly adding all linked files instead of only files referenced in the projects field Now properly parses the projects field and only indexes those specific files as projects Also fixed alias handling in project and dependency links - aliases are now correctly stripped before link resolution Thanks to @craziedde for reporting (#1200) Fixed kanban drag & drop not updating task properties correctly Dragging tasks to different columns now properly triggers business logic (completedDate, auto-archive, webhooks) Previously, kanban updates bypassed updateProperty and directly modified frontmatter Thanks very much to @tvoklov for the PR (#1203) Fixed autocomplete dropdown being clipped inside NLP field boundaries Configure CodeMirror tooltips to render in document.body instead of constrained editor container Prevents suggestion dropdown from being hidden when it extends beyond the NLP field height Thanks to @Andrei-Ioda for reporting (#1172) Fixed task lists and checkboxes rendering incorrectly in task details editor Remove padding-left override on .cm-line to allow CodeMirror decorations (checkboxes, indentation) to render properly Content padding is now handled by .cm-content while .cm-line uses natural spacing Thanks to @nightroman for reporting Fixed relationships widget not appearing on project notes without frontmatter Widget now correctly shows on any note referenced as a project by tasks, regardless of whether the note has frontmatter Fixed task card and relationships widgets not appearing when opening notes in source mode Removed live preview mode restriction to allow widgets to render in both source and live preview modes (#901) Fixed calendar view toolbar buttons overflowing on narrow screens Added flex-wrap: wrap to calendar header toolbar to allow buttons to wrap to multiple lines Thanks to @RumiaKitinari for reporting (#1193), (#1194), (#1185) Fixed new calendar views not respecting user's default calendar settings Previously, new Bases calendar views used hardcoded inline defaults instead of user-configured preferences Calendar view initialization now correctly uses plugin.settings.calendarViewSettings as the fallback Thanks @ki5ck, @minchinweb and @ThamirysOlv for reporting Fixed calendar to ensure that it respects user's locale Tries to use calendar locale, then tries UI language, then system language, then falls back to English (#1043) Fixed default reminders with \"at time of event\" (0 offset) not being applied to tasks UI was displaying \"1\" instead of \"0\" for zero-offset reminders in settings Thanks to @dblinnikov for reporting (#1206) Fixed NLP status parsing regressions with trigger prefixes and temporal keywords Manually typing status trigger + label now correctly parses (e.g., *Done when label is Done) Status values containing temporal keywords no longer misparsed as dates (e.g., Expedite = Now) Thanks very much to @renatomen for the PR (#1212) Fixed \"Show release notes on update\" toggle not saving correctly Thanks to @Jon-dog for reporting (#1197) Add Portuguese language to list of translations in general tab settings Allows users to select the Portuguese translation option Thanks to @andysteel for the PR Fixed file properties displaying incorrectly in Bases views File properties like file.name, file.basename, file.size, etc. were showing as \"Title\" or returning null Now correctly extracts and displays all file properties from Obsidian's file metadata Supports both direct TFile properties (name, basename, extension, path, size, ctime, mtime) and computed properties (links, embeds, tags, backlinks, aliases)"},{"route":"/obsidian/releases/4.1.0/","title":"TaskNotes 4.1.0","description":"(#1245), (#793) Added custom icon support for task statuses","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.1.0.md","namespace":"obsidian","relativePath":"releases/4.1.0.md","raw":"# TaskNotes 4.1.0\n\n## Added\n\n- (#1245), (#793) Added custom icon support for task statuses\n - Configure a Lucide icon name (e.g., `check`, `circle`, `clock`) per status in Settings → Task Properties → Task Statuses\n - Icons display instead of the colored dot, inheriting the status color\n - Browse available icons at [lucide.dev](https://lucide.dev)\n - Improves accessibility by allowing shape-based status differentiation\n - Thanks to @3Fish for the feature request and @Raonmir2, @aubreyz, @prayidae, and @anareaty for the discussion on accessibility and icon-based indicators\n\n- (#1259) Added [Property Types Reference](../settings/property-types-reference.md) documentation\n - Documents expected data types (text, list, date, number) for all frontmatter properties\n - Includes format specifications, examples, and a complete YAML reference\n - Thanks to @Oblique82 for the suggestion\n\n- (#1248) Added formula property support for sub-grouping in Bases Task List view\n - Formula properties (e.g., `formula.myFormula`) now appear in the Sub-group by dropdown\n - Supports all Bases Value types including strings, numbers, booleans, dates, and lists\n - Thanks to @prayidae for the feature request\n\n- (#1070) Added formula property support for swimlanes in Bases Kanban view\n - Formula properties now appear in the Swim Lane dropdown\n - Fixed swimlanes displaying empty when grouping by formula properties\n - Note: Dragging tasks between formula-based columns/swimlanes is disabled (formulas are computed values)\n - Thanks to @cathywu for reporting\n\n- (#1010), (#1126) Added batch task selection and editing in Task List and Kanban views\n - Shift+click to select multiple tasks\n - Right-click selected tasks to open batch context menu\n - Batch operations: change status, priority, due date, scheduled date, archive, delete\n - Drag multiple selected cards in Kanban to move them together\n - Click the selection count indicator to clear selection\n - Thanks to @jalooc and @solidabstract for the feature requests\n\n- (#1207) Added inline search box to Bases views (Task List, Kanban, Calendar)\n - Enable via \"Enable search box\" toggle in view settings\n - Searches across title, status, priority, tags, contexts, projects, and visible custom properties\n - Press Escape or click × to clear search\n - Thanks to @renatomen for the PR\n\n- (#363) Added \"Create or open task\" command with NLP-based quick task creation\n - Open via command palette or assign a hotkey\n - Search existing tasks or type natural language to create new tasks (e.g., \"Buy groceries tomorrow #shopping\")\n - Press Enter to select an existing task, Shift+Enter to create a new task\n - Real-time preview shows parsed title, due date, priority, tags, and other metadata\n - Can be used when adding sub-tasks to create sub-tasks on-the-fly\n - Thanks to @luciolebrillante for the feature request\n\n- (#1044), (#1222) Added unsaved changes confirmation when closing task edit modal\n - Detects modifications to any field (title, dates, priority, tags, etc.)\n - Shows confirmation dialog with Save/Discard/Keep Editing options\n - Prevents accidental data loss from clicking outside the modal or pressing Escape\n - Thanks to @renatomen for the PR and @0-BSCode for the feature request\n\n- (#904) Added visual highlighting for overdue and past dates on task cards\n - Overdue due dates now display in red text\n - Past scheduled dates now display in blue text\n - Thanks to @ras0q for the suggestion\n\n- (#1164) Added `priorityWeight` formula to all default Bases templates for priority-based sorting\n - Formula maps each priority value to a numeric weight based on your custom priority configuration\n - Sort by `formula.priorityWeight` in ascending order to get highest priority tasks first\n - Example: `if(priority==\"high\",0,if(priority==\"normal\",1,if(priority==\"low\",2,999)))`\n - Thanks to @jhedlund for the suggestion\n\n- (#1257), (#1064) Added configurable event stacking options for Bases Calendar view\n - **Allow events to overlap**: Toggle whether timed events visually overlap or display side-by-side in week/day views\n - **Max stacked events**: Limit horizontal event stacking in week/day views (0 = unlimited)\n - **Max events per day**: Limit events shown per day cell in month view (0 = auto based on cell height)\n - **Max event rows per day**: Limit event rows per day cell in month view (0 = unlimited)\n - Configure per-view in the Bases Calendar view settings under Layout\n - Thanks to @3zra47 and @hasanyilmaz for the feature requests\n\n## Changed\n\n- Improved inline task conversion to merge TasksPlugin and NLP parsing results\n - Previously, if a task had hashtags (e.g., `- [ ] Buy milk tomorrow #groceries`), NLP parsing was skipped entirely\n - Now NLP always parses the clean title to extract dates/times, then merges with TasksPlugin-extracted metadata\n - TasksPlugin explicit values (emoji dates like 📅) take priority over NLP-inferred values\n - Tags, contexts, and projects from both sources are combined and deduplicated\n\n- Polished task card styling for a more native Obsidian look\n - Simplified hover and focus states to use native Obsidian colors\n - Removed blur filter and shadows from metadata pills\n - Fixed subtask chevron vertical alignment with status dot\n - Reduced swimlane label column width in Kanban view\n\n- (#1151) Increased mini calendar heatmap color intensity for better visibility\n - Days with notes now show more noticeable colors, especially with low note counts\n - Intensity levels increased from 10/25/45/65% to 25/40/55/70%\n - Thanks to @arreme for the suggestion\n\n## Fixed\n\n- (#1271) Fixed custom user fields not appearing in task modals after creation\n - New custom fields are now automatically added to both creation and edit modals\n - Deleting a custom field also removes it from modal configuration\n - Updating a field's display name syncs to the modal configuration\n - Thanks to @craziedde for reporting\n\n- (#1256) Fixed links in custom properties not rendering as clickable in task cards\n - Wikilinks (`[[Note]]`) now render correctly in Bases views\n - Markdown links (`[text](url)`) now render correctly in all views\n - Links in list-type properties are also properly rendered\n - Thanks to @3zra47 for reporting\n\n- (#1157) Fixed inline task embeds breaking layout when placed in indented bullet lists\n - Task titles now wrap naturally within line boundaries instead of forcing the entire card to a new line\n - Metadata (dates, tags, etc.) stays inline when space permits, with horizontal scrolling on hover when needed\n - Thanks to @3zra47 for reporting\n\n- (#1241) Fixed deleting custom priorities in settings removing the wrong priority when multiple priorities exist\n - Thanks to @Anthonyhunter100 for reporting\n\n- (#1165) Fixed Kanban view grouping by list properties (contexts, tags, projects) treating multiple values as a single combined column\n - Tasks with multiple values now appear in each individual column (e.g., a task with `contexts: [work, call]` appears in both \"work\" and \"call\" columns)\n - Added \"Show items in multiple columns\" option (enabled by default) to control this behavior\n - Fixed drag-and-drop to properly add/remove individual values instead of replacing the entire list\n - Fixed swimlane mode to also respect list property explosion\n - Thanks to @dictionarymouse for reporting\n\n- (#1217) Fixed inconsistent Ctrl+Click/Cmd+Click behavior for opening notes in new tabs\n - Note cards and internal links now properly support Ctrl/Cmd+Click to open in new tab\n - Added middle-click support for opening in new tab\n - Thanks to @diegomarzaa for reporting\n\n- (#1265) Fixed task edit modal corrupting markdown-style project links on save\n - Links like `[Project Name](path.md)` were being wrapped in extra brackets: `[[[Project Name](path.md)]]`\n - Plain text project names are now preserved as-is instead of being converted to wikilinks\n - Markdown-style project links now resolve properly and display as linked (not orange/unresolved)\n - Thanks to @minchinweb for reporting\n\n- (#1266) Fixed Kanban view scroll position resetting to top of column after any change\n - Clicking status dots, priority, or other task properties no longer jumps the column back to top\n - Scroll position is now preserved for both regular columns and swimlane cells\n - Thanks to @essouflenfer for reporting\n\n- (#485), (#1221), (#1262) Fixed NLP parser not recognizing non-ASCII characters in tags, contexts, and projects\n - Tags like `#investigación` were being truncated at accented characters (e.g., `#investigaci`)\n - Non-Latin scripts (Chinese, Cyrillic, Japanese, etc.) were not recognized at all (e.g., `@家`, `#杂事`, `@ознакомиться`)\n - Parser now uses Unicode-aware regex patterns to support all languages and scripts\n - Thanks to @Arachnidai, @fidelaznar, and @qian1ing for reporting\n\n- (#1249) Fixed project preview in task creation modal showing quadruple brackets (`[[[[Project]]]]`)\n - Projects selected from autocomplete were being wrapped in extra wikilink brackets in the preview display\n - Thanks to @2vzqwz8tvg-png for reporting\n\n- (#1249) Fixed custom priority ordering in settings being unclear and non-intuitive\n - Priority cards are now draggable to reorder (like statuses)\n - Priorities are displayed in weight order (lowest to highest priority)\n - New priorities are added at the end (highest priority) instead of with a fixed weight\n - Thanks to @2vzqwz8tvg-png for reporting\n\n- (#1272) Fixed recurrence anchor not being saved when set to \"completion\" during task creation\n - Selecting \"completion\" as the recurrence anchor now correctly persists to the task frontmatter\n - Thanks to @blaxcky for reporting\n\n- (#1128) Fixed NLP parser not allowing slashes in context names\n - Contexts like `@shopping/groceries` were being split into `@shopping` and `/groceries`\n - Hierarchical context names now work the same as tags and projects\n - Thanks to @wealthychef1 for reporting\n\n- (#1170) Fixed `dateCreated` and `dateModified` not using custom property names when creating notes from calendar events\n - Notes created from ICS events now respect the field mapping configured in settings\n - Thanks to @maddie-m for reporting\n\n- (#1171) Fixed calendar event toggles not responding to changes after initial load\n - Toggling \"Show scheduled tasks\", \"Show due tasks\", and other event filters now correctly updates the calendar\n - Previously, changing these toggles had no effect until the view was reloaded\n - Thanks to @hangryscribe3 for reporting\n\n- (#1198) Fixed project links being created relative to the wrong file when editing from Bases views\n - Relative paths in project links are now correctly resolved relative to the task note file\n - Previously, editing a task from a Bases view would create project links relative to the `.base` file\n - Thanks to @minchinweb for reporting\n\n","aliases":["/releases/4.1.0/","/releases/4.1.0/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • (#1245), (#793) Added custom icon support for task statuses

    \n
      \n
    • Configure a Lucide icon name (e.g., check, circle, clock) per status in Settings → Task Properties → Task Statuses
    • \n
    • Icons display instead of the colored dot, inheriting the status color
    • \n
    • Browse available icons at lucide.dev
    • \n
    • Improves accessibility by allowing shape-based status differentiation
    • \n
    • Thanks to @3Fish for the feature request and @Raonmir2, @aubreyz, @prayidae, and @anareaty for the discussion on accessibility and icon-based indicators
    • \n
    \n
  • \n
  • (#1259) Added Property Types Reference documentation

    \n
      \n
    • Documents expected data types (text, list, date, number) for all frontmatter properties
    • \n
    • Includes format specifications, examples, and a complete YAML reference
    • \n
    • Thanks to @Oblique82 for the suggestion
    • \n
    \n
  • \n
  • (#1248) Added formula property support for sub-grouping in Bases Task List view

    \n
      \n
    • Formula properties (e.g., formula.myFormula) now appear in the Sub-group by dropdown
    • \n
    • Supports all Bases Value types including strings, numbers, booleans, dates, and lists
    • \n
    • Thanks to @prayidae for the feature request
    • \n
    \n
  • \n
  • (#1070) Added formula property support for swimlanes in Bases Kanban view

    \n
      \n
    • Formula properties now appear in the Swim Lane dropdown
    • \n
    • Fixed swimlanes displaying empty when grouping by formula properties
    • \n
    • Note: Dragging tasks between formula-based columns/swimlanes is disabled (formulas are computed values)
    • \n
    • Thanks to @cathywu for reporting
    • \n
    \n
  • \n
  • (#1010), (#1126) Added batch task selection and editing in Task List and Kanban views

    \n
      \n
    • Shift+click to select multiple tasks
    • \n
    • Right-click selected tasks to open batch context menu
    • \n
    • Batch operations: change status, priority, due date, scheduled date, archive, delete
    • \n
    • Drag multiple selected cards in Kanban to move them together
    • \n
    • Click the selection count indicator to clear selection
    • \n
    • Thanks to @jalooc and @solidabstract for the feature requests
    • \n
    \n
  • \n
  • (#1207) Added inline search box to Bases views (Task List, Kanban, Calendar)

    \n
      \n
    • Enable via "Enable search box" toggle in view settings
    • \n
    • Searches across title, status, priority, tags, contexts, projects, and visible custom properties
    • \n
    • Press Escape or click × to clear search
    • \n
    • Thanks to @renatomen for the PR
    • \n
    \n
  • \n
  • (#363) Added "Create or open task" command with NLP-based quick task creation

    \n
      \n
    • Open via command palette or assign a hotkey
    • \n
    • Search existing tasks or type natural language to create new tasks (e.g., "Buy groceries tomorrow #shopping")
    • \n
    • Press Enter to select an existing task, Shift+Enter to create a new task
    • \n
    • Real-time preview shows parsed title, due date, priority, tags, and other metadata
    • \n
    • Can be used when adding sub-tasks to create sub-tasks on-the-fly
    • \n
    • Thanks to @luciolebrillante for the feature request
    • \n
    \n
  • \n
  • (#1044), (#1222) Added unsaved changes confirmation when closing task edit modal

    \n
      \n
    • Detects modifications to any field (title, dates, priority, tags, etc.)
    • \n
    • Shows confirmation dialog with Save/Discard/Keep Editing options
    • \n
    • Prevents accidental data loss from clicking outside the modal or pressing Escape
    • \n
    • Thanks to @renatomen for the PR and @0-BSCode for the feature request
    • \n
    \n
  • \n
  • (#904) Added visual highlighting for overdue and past dates on task cards

    \n
      \n
    • Overdue due dates now display in red text
    • \n
    • Past scheduled dates now display in blue text
    • \n
    • Thanks to @ras0q for the suggestion
    • \n
    \n
  • \n
  • (#1164) Added priorityWeight formula to all default Bases templates for priority-based sorting

    \n
      \n
    • Formula maps each priority value to a numeric weight based on your custom priority configuration
    • \n
    • Sort by formula.priorityWeight in ascending order to get highest priority tasks first
    • \n
    • Example: if(priority=="high",0,if(priority=="normal",1,if(priority=="low",2,999)))
    • \n
    • Thanks to @jhedlund for the suggestion
    • \n
    \n
  • \n
  • (#1257), (#1064) Added configurable event stacking options for Bases Calendar view

    \n
      \n
    • Allow events to overlap: Toggle whether timed events visually overlap or display side-by-side in week/day views
    • \n
    • Max stacked events: Limit horizontal event stacking in week/day views (0 = unlimited)
    • \n
    • Max events per day: Limit events shown per day cell in month view (0 = auto based on cell height)
    • \n
    • Max event rows per day: Limit event rows per day cell in month view (0 = unlimited)
    • \n
    • Configure per-view in the Bases Calendar view settings under Layout
    • \n
    • Thanks to @3zra47 and @hasanyilmaz for the feature requests
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Improved inline task conversion to merge TasksPlugin and NLP parsing results

    \n
      \n
    • Previously, if a task had hashtags (e.g., - [ ] Buy milk tomorrow #groceries), NLP parsing was skipped entirely
    • \n
    • Now NLP always parses the clean title to extract dates/times, then merges with TasksPlugin-extracted metadata
    • \n
    • TasksPlugin explicit values (emoji dates like 📅) take priority over NLP-inferred values
    • \n
    • Tags, contexts, and projects from both sources are combined and deduplicated
    • \n
    \n
  • \n
  • Polished task card styling for a more native Obsidian look

    \n
      \n
    • Simplified hover and focus states to use native Obsidian colors
    • \n
    • Removed blur filter and shadows from metadata pills
    • \n
    • Fixed subtask chevron vertical alignment with status dot
    • \n
    • Reduced swimlane label column width in Kanban view
    • \n
    \n
  • \n
  • (#1151) Increased mini calendar heatmap color intensity for better visibility

    \n
      \n
    • Days with notes now show more noticeable colors, especially with low note counts
    • \n
    • Intensity levels increased from 10/25/45/65% to 25/40/55/70%
    • \n
    • Thanks to @arreme for the suggestion
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1271) Fixed custom user fields not appearing in task modals after creation

    \n
      \n
    • New custom fields are now automatically added to both creation and edit modals
    • \n
    • Deleting a custom field also removes it from modal configuration
    • \n
    • Updating a field's display name syncs to the modal configuration
    • \n
    • Thanks to @craziedde for reporting
    • \n
    \n
  • \n
  • (#1256) Fixed links in custom properties not rendering as clickable in task cards

    \n
      \n
    • Wikilinks ([[Note]]) now render correctly in Bases views
    • \n
    • Markdown links ([text](url)) now render correctly in all views
    • \n
    • Links in list-type properties are also properly rendered
    • \n
    • Thanks to @3zra47 for reporting
    • \n
    \n
  • \n
  • (#1157) Fixed inline task embeds breaking layout when placed in indented bullet lists

    \n
      \n
    • Task titles now wrap naturally within line boundaries instead of forcing the entire card to a new line
    • \n
    • Metadata (dates, tags, etc.) stays inline when space permits, with horizontal scrolling on hover when needed
    • \n
    • Thanks to @3zra47 for reporting
    • \n
    \n
  • \n
  • (#1241) Fixed deleting custom priorities in settings removing the wrong priority when multiple priorities exist

    \n
      \n
    • Thanks to @Anthonyhunter100 for reporting
    • \n
    \n
  • \n
  • (#1165) Fixed Kanban view grouping by list properties (contexts, tags, projects) treating multiple values as a single combined column

    \n
      \n
    • Tasks with multiple values now appear in each individual column (e.g., a task with contexts: [work, call] appears in both "work" and "call" columns)
    • \n
    • Added "Show items in multiple columns" option (enabled by default) to control this behavior
    • \n
    • Fixed drag-and-drop to properly add/remove individual values instead of replacing the entire list
    • \n
    • Fixed swimlane mode to also respect list property explosion
    • \n
    • Thanks to @dictionarymouse for reporting
    • \n
    \n
  • \n
  • (#1217) Fixed inconsistent Ctrl+Click/Cmd+Click behavior for opening notes in new tabs

    \n
      \n
    • Note cards and internal links now properly support Ctrl/Cmd+Click to open in new tab
    • \n
    • Added middle-click support for opening in new tab
    • \n
    • Thanks to @diegomarzaa for reporting
    • \n
    \n
  • \n
  • (#1265) Fixed task edit modal corrupting markdown-style project links on save

    \n
      \n
    • Links like [Project Name](path.md) were being wrapped in extra brackets: [[[Project Name](path.md)]]
    • \n
    • Plain text project names are now preserved as-is instead of being converted to wikilinks
    • \n
    • Markdown-style project links now resolve properly and display as linked (not orange/unresolved)
    • \n
    • Thanks to @minchinweb for reporting
    • \n
    \n
  • \n
  • (#1266) Fixed Kanban view scroll position resetting to top of column after any change

    \n
      \n
    • Clicking status dots, priority, or other task properties no longer jumps the column back to top
    • \n
    • Scroll position is now preserved for both regular columns and swimlane cells
    • \n
    • Thanks to @essouflenfer for reporting
    • \n
    \n
  • \n
  • (#485), (#1221), (#1262) Fixed NLP parser not recognizing non-ASCII characters in tags, contexts, and projects

    \n
      \n
    • Tags like #investigación were being truncated at accented characters (e.g., #investigaci)
    • \n
    • Non-Latin scripts (Chinese, Cyrillic, Japanese, etc.) were not recognized at all (e.g., @家, #杂事, @ознакомиться)
    • \n
    • Parser now uses Unicode-aware regex patterns to support all languages and scripts
    • \n
    • Thanks to @Arachnidai, @fidelaznar, and @qian1ing for reporting
    • \n
    \n
  • \n
  • (#1249) Fixed project preview in task creation modal showing quadruple brackets ([[[[Project]]]])

    \n
      \n
    • Projects selected from autocomplete were being wrapped in extra wikilink brackets in the preview display
    • \n
    • Thanks to @2vzqwz8tvg-png for reporting
    • \n
    \n
  • \n
  • (#1249) Fixed custom priority ordering in settings being unclear and non-intuitive

    \n
      \n
    • Priority cards are now draggable to reorder (like statuses)
    • \n
    • Priorities are displayed in weight order (lowest to highest priority)
    • \n
    • New priorities are added at the end (highest priority) instead of with a fixed weight
    • \n
    • Thanks to @2vzqwz8tvg-png for reporting
    • \n
    \n
  • \n
  • (#1272) Fixed recurrence anchor not being saved when set to "completion" during task creation

    \n
      \n
    • Selecting "completion" as the recurrence anchor now correctly persists to the task frontmatter
    • \n
    • Thanks to @blaxcky for reporting
    • \n
    \n
  • \n
  • (#1128) Fixed NLP parser not allowing slashes in context names

    \n
      \n
    • Contexts like @shopping/groceries were being split into @shopping and /groceries
    • \n
    • Hierarchical context names now work the same as tags and projects
    • \n
    • Thanks to @wealthychef1 for reporting
    • \n
    \n
  • \n
  • (#1170) Fixed dateCreated and dateModified not using custom property names when creating notes from calendar events

    \n
      \n
    • Notes created from ICS events now respect the field mapping configured in settings
    • \n
    • Thanks to @maddie-m for reporting
    • \n
    \n
  • \n
  • (#1171) Fixed calendar event toggles not responding to changes after initial load

    \n
      \n
    • Toggling "Show scheduled tasks", "Show due tasks", and other event filters now correctly updates the calendar
    • \n
    • Previously, changing these toggles had no effect until the view was reloaded
    • \n
    • Thanks to @hangryscribe3 for reporting
    • \n
    \n
  • \n
  • (#1198) Fixed project links being created relative to the wrong file when editing from Bases views

    \n
      \n
    • Relative paths in project links are now correctly resolved relative to the task note file
    • \n
    • Previously, editing a task from a Bases view would create project links relative to the .base file
    • \n
    • Thanks to @minchinweb for reporting
    • \n
    \n
  • \n
\n","text":"Added# (#1245), (#793) Added custom icon support for task statuses Configure a Lucide icon name (e.g., check, circle, clock) per status in Settings → Task Properties → Task Statuses Icons display instead of the colored dot, inheriting the status color Browse available icons at lucide.dev Improves accessibility by allowing shape-based status differentiation Thanks to @3Fish for the feature request and @Raonmir2, @aubreyz, @prayidae, and @anareaty for the discussion on accessibility and icon-based indicators (#1259) Added Property Types Reference documentation Documents expected data types (text, list, date, number) for all frontmatter properties Includes format specifications, examples, and a complete YAML reference Thanks to @Oblique82 for the suggestion (#1248) Added formula property support for sub-grouping in Bases Task List view Formula properties (e.g., formula.myFormula) now appear in the Sub-group by dropdown Supports all Bases Value types including strings, numbers, booleans, dates, and lists Thanks to @prayidae for the feature request (#1070) Added formula property support for swimlanes in Bases Kanban view Formula properties now appear in the Swim Lane dropdown Fixed swimlanes displaying empty when grouping by formula properties Note: Dragging tasks between formula-based columns/swimlanes is disabled (formulas are computed values) Thanks to @cathywu for reporting (#1010), (#1126) Added batch task selection and editing in Task List and Kanban views Shift+click to select multiple tasks Right-click selected tasks to open batch context menu Batch operations: change status, priority, due date, scheduled date, archive, delete Drag multiple selected cards in Kanban to move them together Click the selection count indicator to clear selection Thanks to @jalooc and @solidabstract for the feature requests (#1207) Added inline search box to Bases views (Task List, Kanban, Calendar) Enable via \"Enable search box\" toggle in view settings Searches across title, status, priority, tags, contexts, projects, and visible custom properties Press Escape or click × to clear search Thanks to @renatomen for the PR (#363) Added \"Create or open task\" command with NLP-based quick task creation Open via command palette or assign a hotkey Search existing tasks or type natural language to create new tasks (e.g., \"Buy groceries tomorrow #shopping\") Press Enter to select an existing task, Shift+Enter to create a new task Real-time preview shows parsed title, due date, priority, tags, and other metadata Can be used when adding sub-tasks to create sub-tasks on-the-fly Thanks to @luciolebrillante for the feature request (#1044), (#1222) Added unsaved changes confirmation when closing task edit modal Detects modifications to any field (title, dates, priority, tags, etc.) Shows confirmation dialog with Save/Discard/Keep Editing options Prevents accidental data loss from clicking outside the modal or pressing Escape Thanks to @renatomen for the PR and @0-BSCode for the feature request (#904) Added visual highlighting for overdue and past dates on task cards Overdue due dates now display in red text Past scheduled dates now display in blue text Thanks to @ras0q for the suggestion (#1164) Added priorityWeight formula to all default Bases templates for priority-based sorting Formula maps each priority value to a numeric weight based on your custom priority configuration Sort by formula.priorityWeight in ascending order to get highest priority tasks first Example: if(priority==\"high\",0,if(priority==\"normal\",1,if(priority==\"low\",2,999))) Thanks to @jhedlund for the suggestion (#1257), (#1064) Added configurable event stacking options for Bases Calendar view Allow events to overlap: Toggle whether timed events visually overlap or display side-by-side in week/day views Max stacked events: Limit horizontal event stacking in week/day views (0 = unlimited) Max events per day: Limit events shown per day cell in month view (0 = auto based on cell height) Max event rows per day: Limit event rows per day cell in month view (0 = unlimited) Configure per-view in the Bases Calendar view settings under Layout Thanks to @3zra47 and @hasanyilmaz for the feature requests Changed# Improved inline task conversion to merge TasksPlugin and NLP parsing results Previously, if a task had hashtags (e.g., - [ ] Buy milk tomorrow #groceries), NLP parsing was skipped entirely Now NLP always parses the clean title to extract dates/times, then merges with TasksPlugin-extracted metadata TasksPlugin explicit values (emoji dates like 📅) take priority over NLP-inferred values Tags, contexts, and projects from both sources are combined and deduplicated Polished task card styling for a more native Obsidian look Simplified hover and focus states to use native Obsidian colors Removed blur filter and shadows from metadata pills Fixed subtask chevron vertical alignment with status dot Reduced swimlane label column width in Kanban view (#1151) Increased mini calendar heatmap color intensity for better visibility Days with notes now show more noticeable colors, especially with low note counts Intensity levels increased from 10/25/45/65% to 25/40/55/70% Thanks to @arreme for the suggestion Fixed# (#1271) Fixed custom user fields not appearing in task modals after creation New custom fields are now automatically added to both creation and edit modals Deleting a custom field also removes it from modal configuration Updating a field's display name syncs to the modal configuration Thanks to @craziedde for reporting (#1256) Fixed links in custom properties not rendering as clickable in task cards Wikilinks ([[Note]]) now render correctly in Bases views Markdown links ([text](url)) now render correctly in all views Links in list-type properties are also properly rendered Thanks to @3zra47 for reporting (#1157) Fixed inline task embeds breaking layout when placed in indented bullet lists Task titles now wrap naturally within line boundaries instead of forcing the entire card to a new line Metadata (dates, tags, etc.) stays inline when space permits, with horizontal scrolling on hover when needed Thanks to @3zra47 for reporting (#1241) Fixed deleting custom priorities in settings removing the wrong priority when multiple priorities exist Thanks to @Anthonyhunter100 for reporting (#1165) Fixed Kanban view grouping by list properties (contexts, tags, projects) treating multiple values as a single combined column Tasks with multiple values now appear in each individual column (e.g., a task with contexts: [work, call] appears in both \"work\" and \"call\" columns) Added \"Show items in multiple columns\" option (enabled by default) to control this behavior Fixed drag-and-drop to properly add/remove individual values instead of replacing the entire list Fixed swimlane mode to also respect list property explosion Thanks to @dictionarymouse for reporting (#1217) Fixed inconsistent Ctrl+Click/Cmd+Click behavior for opening notes in new tabs Note cards and internal links now properly support Ctrl/Cmd+Click to open in new tab Added middle-click support for opening in new tab Thanks to @diegomarzaa for reporting (#1265) Fixed task edit modal corrupting markdown-style project links on save Links like [Project Name](path.md) were being wrapped in extra brackets: [[[Project Name](path.md)]] Plain text project names are now preserved as-is instead of being converted to wikilinks Markdown-style project links now resolve properly and display as linked (not orange/unresolved) Thanks to @minchinweb for reporting (#1266) Fixed Kanban view scroll position resetting to top of column after any change Clicking status dots, priority, or other task properties no longer jumps the column back to top Scroll position is now preserved for both regular columns and swimlane cells Thanks to @essouflenfer for reporting (#485), (#1221), (#1262) Fixed NLP parser not recognizing non-ASCII characters in tags, contexts, and projects Tags like #investigación were being truncated at accented characters (e.g., #investigaci) Non-Latin scripts (Chinese, Cyrillic, Japanese, etc.) were not recognized at all (e.g., @家, #杂事, @ознакомиться) Parser now uses Unicode-aware regex patterns to support all languages and scripts Thanks to @Arachnidai, @fidelaznar, and @qian1ing for reporting (#1249) Fixed project preview in task creation modal showing quadruple brackets ([[[[Project]]]]) Projects selected from autocomplete were being wrapped in extra wikilink brackets in the preview display Thanks to @2vzqwz8tvg-png for reporting (#1249) Fixed custom priority ordering in settings being unclear and non-intuitive Priority cards are now draggable to reorder (like statuses) Priorities are displayed in weight order (lowest to highest priority) New priorities are added at the end (highest priority) instead of with a fixed weight Thanks to @2vzqwz8tvg-png for reporting (#1272) Fixed recurrence anchor not being saved when set to \"completion\" during task creation Selecting \"completion\" as the recurrence anchor now correctly persists to the task frontmatter Thanks to @blaxcky for reporting (#1128) Fixed NLP parser not allowing slashes in context names Contexts like @shopping/groceries were being split into @shopping and /groceries Hierarchical context names now work the same as tags and projects Thanks to @wealthychef1 for reporting (#1170) Fixed dateCreated and dateModified not using custom property names when creating notes from calendar events Notes created from ICS events now respect the field mapping configured in settings Thanks to @maddie-m for reporting (#1171) Fixed calendar event toggles not responding to changes after initial load Toggling \"Show scheduled tasks\", \"Show due tasks\", and other event filters now correctly updates the calendar Previously, changing these toggles had no effect until the view was reloaded Thanks to @hangryscribe3 for reporting (#1198) Fixed project links being created relative to the wrong file when editing from Bases views Relative paths in project links are now correctly resolved relative to the task note file Previously, editing a task from a Bases view would create project links relative to the .base file Thanks to @minchinweb for reporting"},{"route":"/obsidian/releases/4.1.1/","title":"TaskNotes 4.1.1","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.1.1.md","namespace":"obsidian","relativePath":"releases/4.1.1.md","raw":"# TaskNotes 4.1.1\n\n## Added\n\n- (#1277) Icon autosuggestion for custom status settings\n - Type to search through all available Lucide icons\n - Thanks to @Arachnidai for the suggestion\n- New formula properties in default Base templates\n - **Date calculations**: `daysUntilDue`, `daysUntilScheduled`, `daysSinceCreated`, `daysSinceModified`\n - **Boolean helpers**: `isOverdue`, `isDueToday`, `isDueThisWeek`, `isScheduledToday`, `isRecurring`, `hasTimeEstimate`\n - **Time tracking**: `timeRemaining`, `efficiencyRatio`, `timeTrackedThisWeek`, `timeTrackedToday`, `timeTrackedFormatted`\n - **Grouping**: `dueMonth`, `dueWeek`, `scheduledMonth`, `scheduledWeek`, `dueDateCategory`, `timeEstimateCategory`, `ageCategory`, `createdMonth`, `modifiedMonth`, `priorityCategory`, `projectCount`, `contextCount`, `trackingStatus`\n - **Combined due/scheduled**: `nextDate`, `daysUntilNext`, `hasDate`, `isToday`, `isThisWeek`, `nextDateCategory`, `nextDateMonth`, `nextDateWeek` - work with whichever date comes first\n - **Sorting**: `priorityWeight`, `urgencyScore` (combines priority with date proximity)\n - **Display**: `dueDateDisplay` (relative dates like \"Today\", \"Tomorrow\", \"3d ago\")\n - Action-oriented views (Not Blocked, Today, Overdue, This Week) now sort by urgency score, showing most important tasks first\n - See [Default Base Templates documentation](https://tasknotes.dev/views/default-base-templates) for full details\n - **Note**: To get these new formulas, either copy them from the documentation, or delete your `.base` files in `TaskNotes/Views/` and restart Obsidian to regenerate them\n\n## Changed\n\n- (#1282) Added spacing between task title and metadata in inline task widgets for improved readability\n - Thanks to @3zra47 for the suggestion\n- Custom status icons now display in all context menus (task context menu, batch operations menu, and task creation/edit modals)\n- Added embedded video guide for Google Calendar OAuth setup in documentation\n - Thanks to [@antoneheyward](https://www.youtube.com/@antoneheyward) for the tutorial\n\n## Fixed\n\n- (#1279) Fixed Kanban column width setting not being respected on mobile devices\n - Thanks to @guncav for reporting\n- (#1026), (#1177) Fixed recurring task completion from Base views recording the wrong date for users in negative UTC offset timezones (e.g., PST/PDT) when completing tasks in the evening\n - The bug caused `complete_instances` to record the next day instead of the user's current calendar day\n - Thanks to @3zra47 and @nslee123 for reporting and providing detailed reproduction steps\n\n","aliases":["/releases/4.1.1/","/releases/4.1.1/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • (#1277) Icon autosuggestion for custom status settings
      \n
    • Type to search through all available Lucide icons
    • \n
    • Thanks to @Arachnidai for the suggestion
    • \n
    \n
  • \n
  • New formula properties in default Base templates
      \n
    • Date calculations: daysUntilDue, daysUntilScheduled, daysSinceCreated, daysSinceModified
    • \n
    • Boolean helpers: isOverdue, isDueToday, isDueThisWeek, isScheduledToday, isRecurring, hasTimeEstimate
    • \n
    • Time tracking: timeRemaining, efficiencyRatio, timeTrackedThisWeek, timeTrackedToday, timeTrackedFormatted
    • \n
    • Grouping: dueMonth, dueWeek, scheduledMonth, scheduledWeek, dueDateCategory, timeEstimateCategory, ageCategory, createdMonth, modifiedMonth, priorityCategory, projectCount, contextCount, trackingStatus
    • \n
    • Combined due/scheduled: nextDate, daysUntilNext, hasDate, isToday, isThisWeek, nextDateCategory, nextDateMonth, nextDateWeek - work with whichever date comes first
    • \n
    • Sorting: priorityWeight, urgencyScore (combines priority with date proximity)
    • \n
    • Display: dueDateDisplay (relative dates like "Today", "Tomorrow", "3d ago")
    • \n
    • Action-oriented views (Not Blocked, Today, Overdue, This Week) now sort by urgency score, showing most important tasks first
    • \n
    • See Default Base Templates documentation for full details
    • \n
    • Note: To get these new formulas, either copy them from the documentation, or delete your .base files in TaskNotes/Views/ and restart Obsidian to regenerate them
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • (#1282) Added spacing between task title and metadata in inline task widgets for improved readability
      \n
    • Thanks to @3zra47 for the suggestion
    • \n
    \n
  • \n
  • Custom status icons now display in all context menus (task context menu, batch operations menu, and task creation/edit modals)
  • \n
  • Added embedded video guide for Google Calendar OAuth setup in documentation\n
  • \n
\n

Fixed#

\n
    \n
  • (#1279) Fixed Kanban column width setting not being respected on mobile devices
      \n
    • Thanks to @guncav for reporting
    • \n
    \n
  • \n
  • (#1026), (#1177) Fixed recurring task completion from Base views recording the wrong date for users in negative UTC offset timezones (e.g., PST/PDT) when completing tasks in the evening
      \n
    • The bug caused complete_instances to record the next day instead of the user's current calendar day
    • \n
    • Thanks to @3zra47 and @nslee123 for reporting and providing detailed reproduction steps
    • \n
    \n
  • \n
\n","text":"Added# (#1277) Icon autosuggestion for custom status settings Type to search through all available Lucide icons Thanks to @Arachnidai for the suggestion New formula properties in default Base templates Date calculations: daysUntilDue, daysUntilScheduled, daysSinceCreated, daysSinceModified Boolean helpers: isOverdue, isDueToday, isDueThisWeek, isScheduledToday, isRecurring, hasTimeEstimate Time tracking: timeRemaining, efficiencyRatio, timeTrackedThisWeek, timeTrackedToday, timeTrackedFormatted Grouping: dueMonth, dueWeek, scheduledMonth, scheduledWeek, dueDateCategory, timeEstimateCategory, ageCategory, createdMonth, modifiedMonth, priorityCategory, projectCount, contextCount, trackingStatus Combined due/scheduled: nextDate, daysUntilNext, hasDate, isToday, isThisWeek, nextDateCategory, nextDateMonth, nextDateWeek - work with whichever date comes first Sorting: priorityWeight, urgencyScore (combines priority with date proximity) Display: dueDateDisplay (relative dates like \"Today\", \"Tomorrow\", \"3d ago\") Action-oriented views (Not Blocked, Today, Overdue, This Week) now sort by urgency score, showing most important tasks first See Default Base Templates documentation for full details Note: To get these new formulas, either copy them from the documentation, or delete your .base files in TaskNotes/Views/ and restart Obsidian to regenerate them Changed# (#1282) Added spacing between task title and metadata in inline task widgets for improved readability Thanks to @3zra47 for the suggestion Custom status icons now display in all context menus (task context menu, batch operations menu, and task creation/edit modals) Added embedded video guide for Google Calendar OAuth setup in documentation Thanks to @antoneheyward for the tutorial Fixed# (#1279) Fixed Kanban column width setting not being respected on mobile devices Thanks to @guncav for reporting (#1026), (#1177) Fixed recurring task completion from Base views recording the wrong date for users in negative UTC offset timezones (e.g., PST/PDT) when completing tasks in the evening The bug caused complete_instances to record the next day instead of the user's current calendar day Thanks to @3zra47 and @nslee123 for reporting and providing detailed reproduction steps"},{"route":"/obsidian/releases/4.1.2/","title":"TaskNotes 4.1.2","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.1.2.md","namespace":"obsidian","relativePath":"releases/4.1.2.md","raw":"# TaskNotes 4.1.2\n\n## Fixed\n\n- Significant performance improvements for Bases views (TaskList, Kanban, Calendar)\n - Reduced `extractDataItems` time from ~4 seconds to ~5-10ms for large vaults (6000+ tasks)\n - Computed file properties (`file.backlinks`, `file.links`, etc.) are now fetched lazily during render instead of upfront\n - Only visible items (with virtualization) trigger expensive property computations\n - Added debouncing to `onDataUpdated` to prevent UI freezes during typing\n - Timeblock generation now uses Obsidian's metadataCache instead of file reads\n - Added date range filtering for calendar events to skip events outside visible range\n - (#1285) Calendar view uses 5-second debounce to prevent flickering while typing\n\t - Thanks to @steven-murray for reporting\n- Calendar view switching (month/week/day/list) is now much faster\n - View type is now saved on unload instead of on every change\n- Fixed task edit modal archive button being too narrow on mobile devices\n- (#1319) Added missing properties to Field Mapping settings\n - `recurrence_anchor` - now in Settings > Task Properties > Task Details\n - `skipped_instances` - now in Settings > Task Properties > Metadata Properties\n - Thanks to @kazerniel for reporting\n- (#1310) Fixed inline task conversion deleting text when task title exceeds filename limits\n - Text that cannot fit in the filename is now preserved in the task note's body\n - Thanks to @prayidae for reporting\n- (#1301) Fixed inline task wikilinks leaving blank space when no metadata properties are visible\n - Thanks to @Richard-UMPV for reporting\n- (#1317) Fixed project autosuggest filters not working correctly when only \"Required Property Key\" is configured\n - NLP `+` trigger now properly filters by property existence when no property value is specified\n - Modal \"Add to project\" button now shows consistent results with inline autosuggest\n - Thanks to @JacksonMcDonaldDev for reporting\n- (#1287), (#1307) The \"New\" button in Bases views now opens the TaskNotes creation modal\n - Tasks created from Bases views now respect default properties (status, priority, etc.)\n - Tasks are now created in the configured default folder instead of the views folder\n - Thanks to @anareaty and @sylvainfct-dot for reporting\n- (#1291) Fixed Microsoft Calendar OAuth documentation using wrong redirect URI\n - Added instructions for configuring via Azure manifest editor\n - Thanks to @PlecotusAustriacus for reporting\n\n## Added\n\n- (#803) New command \"Convert current note to task\" to add task properties to an existing note\n - Thanks to @GardarikanetS and @diegomarzaa for suggesting\n- (#1080) Custom user fields now support default values\n - Each field type has an appropriate input: text field, number input, toggle, date preset dropdown, or comma-separated list\n - Defaults are applied when creating tasks via modal, instant conversion, \"Create or open task\" command, or HTTP API\n - Thanks to @bradyrx for suggesting\n\n## Changed\n\n- Added documentation link to settings panel (links to tasknotes.dev)\n- Reorganized settings panel for improved discoverability\n - Removed \"Defaults\" tab - default values are now configured alongside each property in the Task Properties tab\n - Moved task filename format settings to the Title property section\n - Moved project autosuggest settings to the Projects property section\n - Body template setting moved to the Features tab\n - Added descriptions to each property explaining its purpose\n - Moved \"Folder for converted tasks\" setting to General tab under Task Storage for better discoverability\n - Updated setting description to clarify that leaving empty uses the default tasks folder\n\n","aliases":["/releases/4.1.2/","/releases/4.1.2/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"}],"html":"

Fixed#

\n
    \n
  • Significant performance improvements for Bases views (TaskList, Kanban, Calendar)
      \n
    • Reduced extractDataItems time from ~4 seconds to ~5-10ms for large vaults (6000+ tasks)
    • \n
    • Computed file properties (file.backlinks, file.links, etc.) are now fetched lazily during render instead of upfront
    • \n
    • Only visible items (with virtualization) trigger expensive property computations
    • \n
    • Added debouncing to onDataUpdated to prevent UI freezes during typing
    • \n
    • Timeblock generation now uses Obsidian's metadataCache instead of file reads
    • \n
    • Added date range filtering for calendar events to skip events outside visible range
    • \n
    • (#1285) Calendar view uses 5-second debounce to prevent flickering while typing
        \n
      • Thanks to @steven-murray for reporting
      • \n
      \n
    • \n
    \n
  • \n
  • Calendar view switching (month/week/day/list) is now much faster
      \n
    • View type is now saved on unload instead of on every change
    • \n
    \n
  • \n
  • Fixed task edit modal archive button being too narrow on mobile devices
  • \n
  • (#1319) Added missing properties to Field Mapping settings
      \n
    • recurrence_anchor - now in Settings > Task Properties > Task Details
    • \n
    • skipped_instances - now in Settings > Task Properties > Metadata Properties
    • \n
    • Thanks to @kazerniel for reporting
    • \n
    \n
  • \n
  • (#1310) Fixed inline task conversion deleting text when task title exceeds filename limits
      \n
    • Text that cannot fit in the filename is now preserved in the task note's body
    • \n
    • Thanks to @prayidae for reporting
    • \n
    \n
  • \n
  • (#1301) Fixed inline task wikilinks leaving blank space when no metadata properties are visible
      \n
    • Thanks to @Richard-UMPV for reporting
    • \n
    \n
  • \n
  • (#1317) Fixed project autosuggest filters not working correctly when only "Required Property Key" is configured
      \n
    • NLP + trigger now properly filters by property existence when no property value is specified
    • \n
    • Modal "Add to project" button now shows consistent results with inline autosuggest
    • \n
    • Thanks to @JacksonMcDonaldDev for reporting
    • \n
    \n
  • \n
  • (#1287), (#1307) The "New" button in Bases views now opens the TaskNotes creation modal
      \n
    • Tasks created from Bases views now respect default properties (status, priority, etc.)
    • \n
    • Tasks are now created in the configured default folder instead of the views folder
    • \n
    • Thanks to @anareaty and @sylvainfct-dot for reporting
    • \n
    \n
  • \n
  • (#1291) Fixed Microsoft Calendar OAuth documentation using wrong redirect URI
      \n
    • Added instructions for configuring via Azure manifest editor
    • \n
    • Thanks to @PlecotusAustriacus for reporting
    • \n
    \n
  • \n
\n

Added#

\n
    \n
  • (#803) New command "Convert current note to task" to add task properties to an existing note
      \n
    • Thanks to @GardarikanetS and @diegomarzaa for suggesting
    • \n
    \n
  • \n
  • (#1080) Custom user fields now support default values
      \n
    • Each field type has an appropriate input: text field, number input, toggle, date preset dropdown, or comma-separated list
    • \n
    • Defaults are applied when creating tasks via modal, instant conversion, "Create or open task" command, or HTTP API
    • \n
    • Thanks to @bradyrx for suggesting
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Added documentation link to settings panel (links to tasknotes.dev)
  • \n
  • Reorganized settings panel for improved discoverability
      \n
    • Removed "Defaults" tab - default values are now configured alongside each property in the Task Properties tab
    • \n
    • Moved task filename format settings to the Title property section
    • \n
    • Moved project autosuggest settings to the Projects property section
    • \n
    • Body template setting moved to the Features tab
    • \n
    • Added descriptions to each property explaining its purpose
    • \n
    • Moved "Folder for converted tasks" setting to General tab under Task Storage for better discoverability
    • \n
    • Updated setting description to clarify that leaving empty uses the default tasks folder
    • \n
    \n
  • \n
\n","text":"Fixed# Significant performance improvements for Bases views (TaskList, Kanban, Calendar) Reduced extractDataItems time from ~4 seconds to ~5-10ms for large vaults (6000+ tasks) Computed file properties (file.backlinks, file.links, etc.) are now fetched lazily during render instead of upfront Only visible items (with virtualization) trigger expensive property computations Added debouncing to onDataUpdated to prevent UI freezes during typing Timeblock generation now uses Obsidian's metadataCache instead of file reads Added date range filtering for calendar events to skip events outside visible range (#1285) Calendar view uses 5-second debounce to prevent flickering while typing Thanks to @steven-murray for reporting Calendar view switching (month/week/day/list) is now much faster View type is now saved on unload instead of on every change Fixed task edit modal archive button being too narrow on mobile devices (#1319) Added missing properties to Field Mapping settings recurrence_anchor - now in Settings > Task Properties > Task Details skipped_instances - now in Settings > Task Properties > Metadata Properties Thanks to @kazerniel for reporting (#1310) Fixed inline task conversion deleting text when task title exceeds filename limits Text that cannot fit in the filename is now preserved in the task note's body Thanks to @prayidae for reporting (#1301) Fixed inline task wikilinks leaving blank space when no metadata properties are visible Thanks to @Richard-UMPV for reporting (#1317) Fixed project autosuggest filters not working correctly when only \"Required Property Key\" is configured NLP + trigger now properly filters by property existence when no property value is specified Modal \"Add to project\" button now shows consistent results with inline autosuggest Thanks to @JacksonMcDonaldDev for reporting (#1287), (#1307) The \"New\" button in Bases views now opens the TaskNotes creation modal Tasks created from Bases views now respect default properties (status, priority, etc.) Tasks are now created in the configured default folder instead of the views folder Thanks to @anareaty and @sylvainfct-dot for reporting (#1291) Fixed Microsoft Calendar OAuth documentation using wrong redirect URI Added instructions for configuring via Azure manifest editor Thanks to @PlecotusAustriacus for reporting Added# (#803) New command \"Convert current note to task\" to add task properties to an existing note Thanks to @GardarikanetS and @diegomarzaa for suggesting (#1080) Custom user fields now support default values Each field type has an appropriate input: text field, number input, toggle, date preset dropdown, or comma-separated list Defaults are applied when creating tasks via modal, instant conversion, \"Create or open task\" command, or HTTP API Thanks to @bradyrx for suggesting Changed# Added documentation link to settings panel (links to tasknotes.dev) Reorganized settings panel for improved discoverability Removed \"Defaults\" tab - default values are now configured alongside each property in the Task Properties tab Moved task filename format settings to the Title property section Moved project autosuggest settings to the Projects property section Body template setting moved to the Features tab Added descriptions to each property explaining its purpose Moved \"Folder for converted tasks\" setting to General tab under Task Storage for better discoverability Updated setting description to clarify that leaving empty uses the default tasks folder"},{"route":"/obsidian/releases/4.1.3/","title":"TaskNotes 4.1.3","description":"This patch fixes a critical performance issue affecting the Calendar views. As a bonus, it adds a configurable \"split\" view to the task creation/edit modals.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.1.3.md","namespace":"obsidian","relativePath":"releases/4.1.3.md","raw":"# TaskNotes 4.1.3\n\nThis patch fixes a critical performance issue affecting the Calendar views. As a bonus, it adds a configurable \"split\" view to the task creation/edit modals. \n\n## Added\n\n- Split layout for task modals on wide screens (900px+)\n - Details editor appears in a dedicated right column when the modal is expanded\n - New setting \"Split layout on wide screens\" in Modal Fields settings tab to toggle this behavior\n - Improves usability by showing form fields and details side-by-side\n\n## Fixed\n\n- (#1330) Fixed calendar view regression taking 5 seconds to load and respond to user interactions\n - Initial calendar load is now immediate again\n - User interactions (drag/drop, creating timeblocks, etc.) respond instantly\n - Removed redundant date filtering (FullCalendar handles this more efficiently)\n - Thanks to @ysafonov, @kmaustral, @sunjiawe, @Мизгирь, and @FiliusIcari for reporting\n","aliases":["/releases/4.1.3/","/releases/4.1.3/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

This patch fixes a critical performance issue affecting the Calendar views. As a bonus, it adds a configurable "split" view to the task creation/edit modals.

\n

Added#

\n
    \n
  • Split layout for task modals on wide screens (900px+)
      \n
    • Details editor appears in a dedicated right column when the modal is expanded
    • \n
    • New setting "Split layout on wide screens" in Modal Fields settings tab to toggle this behavior
    • \n
    • Improves usability by showing form fields and details side-by-side
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1330) Fixed calendar view regression taking 5 seconds to load and respond to user interactions
      \n
    • Initial calendar load is now immediate again
    • \n
    • User interactions (drag/drop, creating timeblocks, etc.) respond instantly
    • \n
    • Removed redundant date filtering (FullCalendar handles this more efficiently)
    • \n
    • Thanks to @ysafonov, @kmaustral, @sunjiawe, @Мизгирь, and @FiliusIcari for reporting
    • \n
    \n
  • \n
\n","text":"This patch fixes a critical performance issue affecting the Calendar views. As a bonus, it adds a configurable \"split\" view to the task creation/edit modals. Added# Split layout for task modals on wide screens (900px+) Details editor appears in a dedicated right column when the modal is expanded New setting \"Split layout on wide screens\" in Modal Fields settings tab to toggle this behavior Improves usability by showing form fields and details side-by-side Fixed# (#1330) Fixed calendar view regression taking 5 seconds to load and respond to user interactions Initial calendar load is now immediate again User interactions (drag/drop, creating timeblocks, etc.) respond instantly Removed redundant date filtering (FullCalendar handles this more efficiently) Thanks to @ysafonov, @kmaustral, @sunjiawe, @Мизгирь, and @FiliusIcari for reporting"},{"route":"/obsidian/releases/4.10.0/","title":"TaskNotes 4.10.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.10.0.md","namespace":"obsidian","relativePath":"releases/4.10.0.md","raw":"# TaskNotes 4.10.0\n\n## Added\n\n- **New companion plugin:** TaskNotes Workflows adds Markdown-defined automation for TaskNotes tasks, events, schedules, and manual commands. It keeps automation workflows outside TaskNotes core while using the runtime API for safe task reads, writes, queries, events, and relationship resolution. See [TaskNotes Workflows](https://tasknotes.dev/companion-plugins/tasknotes-workflows/).\n - (#1530) `Auto-start time tracking` starts a timer when a task moves into active work. Thanks to @Jendrik0 and @benmartinek for the request and follow-up.\n - (#222, #184) `Stop time tracking on complete` stops active timers when a task is completed. Thanks to @bcohen44 and @cathywu for the requests, and @amarjt for the follow-up.\n - (#265) `Stamp started timestamp` records a custom started timestamp when a task first moves into active work. Thanks to @cathywu, @digitaldoctors, and @Leo310 for the request and discussion.\n - (#1703) `Clear scheduled when started` clears the scheduled date when a task moves into active work. Thanks to @kmaustral for the request.\n - (#1293) `Rollover overdue scheduled tasks` moves incomplete tasks with past scheduled dates back to today. Thanks to @grosserfrank for the request.\n - (#1896) `Escalate upcoming due tasks` raises priority as due dates approach. Thanks to @Neptune-Illusion for the request.\n - (#214, #518, #1785, #1855) The subtask inheritance workflows can copy parent contexts, tags, priority, planning dates, and dependencies into new subtasks. Thanks to @timfidd, @bepolymathe, @AndyEveritt, @lindsaylearns, @tomsymonds, @wedgen, @poulpoulsen, and @misolex for the related requests and discussion.\n - (#1166) `Blocked task review` provides a reminder-style review for blocked tasks without automatically deleting dependency links. Thanks to @jpmoo and @jortscity for the request and follow-up.\n- Added a versioned TaskNotes JavaScript runtime API for companion plugins, with namespaced model validation, canonical task query validation/normalization/explain helpers, catalogs, query/support helpers, lifecycle events, typed errors/results, task, time-tracking, Pomodoro, recurring-task, settings, NLP, event, and extension-registry surfaces. Runtime API mutations carry source and correlation metadata so companion plugins can debug and coordinate workflow runs. See [JavaScript API](https://tasknotes.dev/javascript-api/).\n- Added documentation for the companion-plugin model. See [Companion Plugins](https://tasknotes.dev/companion-plugins/).\n- (#288, #345, #361, #523, #573, #703, #925, #929, #1115, #1137, #1260, #1303, #1324, #1394, #1445, #1509, #1735, #1736, #1743, #1780, #1874, #1951, #1974) Added support for TaskNotes spec 0.2.0 materialized occurrences, including recurrence parent/date fields, generated mdbase schema roles, parent reconciliation when occurrence notes are completed, occurrence notes that inherit parent planning metadata without copying history, occurrence note controls in task, calendar, and edit-modal completion menus, and visible occurrence identity on task cards. This gives recurring tasks a concrete occurrence-note path for per-instance state, related notes, subtasks, templates, scheduling changes, completion history, and calendar behavior without forcing every recurring task to create files. See [Recurring Tasks](https://tasknotes.dev/features/recurring-tasks/#materialized-occurrence-notes) and [Property Types Reference](https://tasknotes.dev/settings/property-types-reference/#materialized-occurrence-properties). Thanks to @LuxBetancourt, @jerzy-dudzic, @luciolebrillante, @BryanWall, @jhedlund, @kazerniel, @nschenone, @realJohnDoe, @cathywu, @Lorite, @EllenGYY, @JcMinarro, @gsssr, @slipstyle, @3zra47, @Leonard-44, @ak-42, @RumiaKitinari, @atos2212-blip, @kmaustral, @eugenedefox, @notDavid, @zitongcharliedeng, and @Jomo94 for the related recurrence, occurrence, completion, and calendar requests.\n- (#1951) Added Calendar support for recurring tasks stretched between scheduled and due dates when the existing stretch option is enabled. Date-only ranges stay as all-day spans, and timed ranges render once per day in the range. Thanks to @atos2212-blip for the request.\n- (#1751, #1792, #1969) Added a Task List and Kanban view option to hide top-level subtasks when their parent task is also in the filtered view, while still allowing inherited expanded relationships to show the subtasks under the parent. Thanks to @Glint-Eye and @Proxybat for the request and follow-up, and @stanley-910 and @Spencerduran for the earlier PRs.\n\n## Changed\n\n- Moved core TaskNotes model behavior for field mapping, dates, recurrence, time-tracking, and adapter operation planning into a shared package used by the plugin and companion tooling.\n- Calendar views now coalesce materialized occurrence notes with their matching virtual recurring instances. Dragging a materialized occurrence reschedules that occurrence note without changing the parent recurrence rule or the note's `occurrence_date` identity. See [Recurring Tasks](https://tasknotes.dev/features/recurring-tasks/#calendar-drag-and-drop).\n- Improved the Calendar Bases View Options menu by splitting settings into clearer groups and hiding view-specific controls until they apply to the selected calendar mode.\n\n## Fixed\n\n- (#1976) Fixed embedded Calendar and Agenda Bases so \"Navigate to date from property\" can use the containing note's date property when the Base rows do not have that property. Thanks to @matesvecenik for reporting this.\n- (#1977) Fixed Calendar and Agenda views showing duplicate all-day entries when a task's scheduled date and due date are the same day. Timed due dates on the same day still show as separate deadline markers. Thanks to @pdgBC for reporting this.\n- Fixed the release notes view using cramped interface typography instead of regular reading typography.\n- (#216) Improved inline conversion for Tasks plugin task lines, including Dataview-style fields, priority markers, recurrence text, date aliases, block links, and safer trailing-field parsing. Thanks to @ksdavidc for the request, @natleahh for the Dataview example, and @hangryscribe3 and @nayatiuh for the discussion.\n- (#1974) Stopped Calendar and Agenda property-based events from logging date parse errors for entries that do not have the selected date property. Thanks to @Jomo94 for suggesting completed-date Agenda events.\n- (#1973) Reduced unnecessary Calendar view recreations when external calendar providers are reported in a different order, and preserved Calendar scroll position when a config-driven refresh has to recreate the view. Thanks to @e-zz for reporting this.\n- (#1972) Fixed ICS calendar event related notes so standalone events with similar numeric IDs no longer show unrelated notes or tasks on every event. Thanks to @ks-studio-net for reporting this.\n- (#1970) Fixed generated default Base filters so updating default files applies configured excluded folders to TaskNotes task views. Thanks to @henrim01 for reporting that templates could still appear in regenerated views.\n- (#1968) Fixed inline task link overlays collapsing on Obsidian mobile, which could hide the task title and leave a tall empty gap after the widget. Thanks to @renatomen for reporting and diagnosing the containment issue.\n","aliases":["/releases/4.10.0/","/releases/4.10.0/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • New companion plugin: TaskNotes Workflows adds Markdown-defined automation for TaskNotes tasks, events, schedules, and manual commands. It keeps automation workflows outside TaskNotes core while using the runtime API for safe task reads, writes, queries, events, and relationship resolution. See TaskNotes Workflows.
      \n
    • (#1530) Auto-start time tracking starts a timer when a task moves into active work. Thanks to @Jendrik0 and @benmartinek for the request and follow-up.
    • \n
    • (#222, #184) Stop time tracking on complete stops active timers when a task is completed. Thanks to @bcohen44 and @cathywu for the requests, and @amarjt for the follow-up.
    • \n
    • (#265) Stamp started timestamp records a custom started timestamp when a task first moves into active work. Thanks to @cathywu, @digitaldoctors, and @Leo310 for the request and discussion.
    • \n
    • (#1703) Clear scheduled when started clears the scheduled date when a task moves into active work. Thanks to @kmaustral for the request.
    • \n
    • (#1293) Rollover overdue scheduled tasks moves incomplete tasks with past scheduled dates back to today. Thanks to @grosserfrank for the request.
    • \n
    • (#1896) Escalate upcoming due tasks raises priority as due dates approach. Thanks to @Neptune-Illusion for the request.
    • \n
    • (#214, #518, #1785, #1855) The subtask inheritance workflows can copy parent contexts, tags, priority, planning dates, and dependencies into new subtasks. Thanks to @timfidd, @bepolymathe, @AndyEveritt, @lindsaylearns, @tomsymonds, @wedgen, @poulpoulsen, and @misolex for the related requests and discussion.
    • \n
    • (#1166) Blocked task review provides a reminder-style review for blocked tasks without automatically deleting dependency links. Thanks to @jpmoo and @jortscity for the request and follow-up.
    • \n
    \n
  • \n
  • Added a versioned TaskNotes JavaScript runtime API for companion plugins, with namespaced model validation, canonical task query validation/normalization/explain helpers, catalogs, query/support helpers, lifecycle events, typed errors/results, task, time-tracking, Pomodoro, recurring-task, settings, NLP, event, and extension-registry surfaces. Runtime API mutations carry source and correlation metadata so companion plugins can debug and coordinate workflow runs. See JavaScript API.
  • \n
  • Added documentation for the companion-plugin model. See Companion Plugins.
  • \n
  • (#288, #345, #361, #523, #573, #703, #925, #929, #1115, #1137, #1260, #1303, #1324, #1394, #1445, #1509, #1735, #1736, #1743, #1780, #1874, #1951, #1974) Added support for TaskNotes spec 0.2.0 materialized occurrences, including recurrence parent/date fields, generated mdbase schema roles, parent reconciliation when occurrence notes are completed, occurrence notes that inherit parent planning metadata without copying history, occurrence note controls in task, calendar, and edit-modal completion menus, and visible occurrence identity on task cards. This gives recurring tasks a concrete occurrence-note path for per-instance state, related notes, subtasks, templates, scheduling changes, completion history, and calendar behavior without forcing every recurring task to create files. See Recurring Tasks and Property Types Reference. Thanks to @LuxBetancourt, @jerzy-dudzic, @luciolebrillante, @BryanWall, @jhedlund, @kazerniel, @nschenone, @realJohnDoe, @cathywu, @Lorite, @EllenGYY, @JcMinarro, @gsssr, @slipstyle, @3zra47, @Leonard-44, @ak-42, @RumiaKitinari, @atos2212-blip, @kmaustral, @eugenedefox, @notDavid, @zitongcharliedeng, and @Jomo94 for the related recurrence, occurrence, completion, and calendar requests.
  • \n
  • (#1951) Added Calendar support for recurring tasks stretched between scheduled and due dates when the existing stretch option is enabled. Date-only ranges stay as all-day spans, and timed ranges render once per day in the range. Thanks to @atos2212-blip for the request.
  • \n
  • (#1751, #1792, #1969) Added a Task List and Kanban view option to hide top-level subtasks when their parent task is also in the filtered view, while still allowing inherited expanded relationships to show the subtasks under the parent. Thanks to @Glint-Eye and @Proxybat for the request and follow-up, and @stanley-910 and @Spencerduran for the earlier PRs.
  • \n
\n

Changed#

\n
    \n
  • Moved core TaskNotes model behavior for field mapping, dates, recurrence, time-tracking, and adapter operation planning into a shared package used by the plugin and companion tooling.
  • \n
  • Calendar views now coalesce materialized occurrence notes with their matching virtual recurring instances. Dragging a materialized occurrence reschedules that occurrence note without changing the parent recurrence rule or the note's occurrence_date identity. See Recurring Tasks.
  • \n
  • Improved the Calendar Bases View Options menu by splitting settings into clearer groups and hiding view-specific controls until they apply to the selected calendar mode.
  • \n
\n

Fixed#

\n
    \n
  • (#1976) Fixed embedded Calendar and Agenda Bases so "Navigate to date from property" can use the containing note's date property when the Base rows do not have that property. Thanks to @matesvecenik for reporting this.
  • \n
  • (#1977) Fixed Calendar and Agenda views showing duplicate all-day entries when a task's scheduled date and due date are the same day. Timed due dates on the same day still show as separate deadline markers. Thanks to @pdgBC for reporting this.
  • \n
  • Fixed the release notes view using cramped interface typography instead of regular reading typography.
  • \n
  • (#216) Improved inline conversion for Tasks plugin task lines, including Dataview-style fields, priority markers, recurrence text, date aliases, block links, and safer trailing-field parsing. Thanks to @ksdavidc for the request, @natleahh for the Dataview example, and @hangryscribe3 and @nayatiuh for the discussion.
  • \n
  • (#1974) Stopped Calendar and Agenda property-based events from logging date parse errors for entries that do not have the selected date property. Thanks to @Jomo94 for suggesting completed-date Agenda events.
  • \n
  • (#1973) Reduced unnecessary Calendar view recreations when external calendar providers are reported in a different order, and preserved Calendar scroll position when a config-driven refresh has to recreate the view. Thanks to @e-zz for reporting this.
  • \n
  • (#1972) Fixed ICS calendar event related notes so standalone events with similar numeric IDs no longer show unrelated notes or tasks on every event. Thanks to @ks-studio-net for reporting this.
  • \n
  • (#1970) Fixed generated default Base filters so updating default files applies configured excluded folders to TaskNotes task views. Thanks to @henrim01 for reporting that templates could still appear in regenerated views.
  • \n
  • (#1968) Fixed inline task link overlays collapsing on Obsidian mobile, which could hide the task title and leave a tall empty gap after the widget. Thanks to @renatomen for reporting and diagnosing the containment issue.
  • \n
\n","text":"Added# New companion plugin: TaskNotes Workflows adds Markdown-defined automation for TaskNotes tasks, events, schedules, and manual commands. It keeps automation workflows outside TaskNotes core while using the runtime API for safe task reads, writes, queries, events, and relationship resolution. See TaskNotes Workflows. (#1530) Auto-start time tracking starts a timer when a task moves into active work. Thanks to @Jendrik0 and @benmartinek for the request and follow-up. (#222, #184) Stop time tracking on complete stops active timers when a task is completed. Thanks to @bcohen44 and @cathywu for the requests, and @amarjt for the follow-up. (#265) Stamp started timestamp records a custom started timestamp when a task first moves into active work. Thanks to @cathywu, @digitaldoctors, and @Leo310 for the request and discussion. (#1703) Clear scheduled when started clears the scheduled date when a task moves into active work. Thanks to @kmaustral for the request. (#1293) Rollover overdue scheduled tasks moves incomplete tasks with past scheduled dates back to today. Thanks to @grosserfrank for the request. (#1896) Escalate upcoming due tasks raises priority as due dates approach. Thanks to @Neptune-Illusion for the request. (#214, #518, #1785, #1855) The subtask inheritance workflows can copy parent contexts, tags, priority, planning dates, and dependencies into new subtasks. Thanks to @timfidd, @bepolymathe, @AndyEveritt, @lindsaylearns, @tomsymonds, @wedgen, @poulpoulsen, and @misolex for the related requests and discussion. (#1166) Blocked task review provides a reminder-style review for blocked tasks without automatically deleting dependency links. Thanks to @jpmoo and @jortscity for the request and follow-up. Added a versioned TaskNotes JavaScript runtime API for companion plugins, with namespaced model validation, canonical task query validation/normalization/explain helpers, catalogs, query/support helpers, lifecycle events, typed errors/results, task, time-tracking, Pomodoro, recurring-task, settings, NLP, event, and extension-registry surfaces. Runtime API mutations carry source and correlation metadata so companion plugins can debug and coordinate workflow runs. See JavaScript API. Added documentation for the companion-plugin model. See Companion Plugins. (#288, #345, #361, #523, #573, #703, #925, #929, #1115, #1137, #1260, #1303, #1324, #1394, #1445, #1509, #1735, #1736, #1743, #1780, #1874, #1951, #1974) Added support for TaskNotes spec 0.2.0 materialized occurrences, including recurrence parent/date fields, generated mdbase schema roles, parent reconciliation when occurrence notes are completed, occurrence notes that inherit parent planning metadata without copying history, occurrence note controls in task, calendar, and edit-modal completion menus, and visible occurrence identity on task cards. This gives recurring tasks a concrete occurrence-note path for per-instance state, related notes, subtasks, templates, scheduling changes, completion history, and calendar behavior without forcing every recurring task to create files. See Recurring Tasks and Property Types Reference. Thanks to @LuxBetancourt, @jerzy-dudzic, @luciolebrillante, @BryanWall, @jhedlund, @kazerniel, @nschenone, @realJohnDoe, @cathywu, @Lorite, @EllenGYY, @JcMinarro, @gsssr, @slipstyle, @3zra47, @Leonard-44, @ak-42, @RumiaKitinari, @atos2212-blip, @kmaustral, @eugenedefox, @notDavid, @zitongcharliedeng, and @Jomo94 for the related recurrence, occurrence, completion, and calendar requests. (#1951) Added Calendar support for recurring tasks stretched between scheduled and due dates when the existing stretch option is enabled. Date-only ranges stay as all-day spans, and timed ranges render once per day in the range. Thanks to @atos2212-blip for the request. (#1751, #1792, #1969) Added a Task List and Kanban view option to hide top-level subtasks when their parent task is also in the filtered view, while still allowing inherited expanded relationships to show the subtasks under the parent. Thanks to @Glint-Eye and @Proxybat for the request and follow-up, and @stanley-910 and @Spencerduran for the earlier PRs. Changed# Moved core TaskNotes model behavior for field mapping, dates, recurrence, time-tracking, and adapter operation planning into a shared package used by the plugin and companion tooling. Calendar views now coalesce materialized occurrence notes with their matching virtual recurring instances. Dragging a materialized occurrence reschedules that occurrence note without changing the parent recurrence rule or the note's occurrence_date identity. See Recurring Tasks. Improved the Calendar Bases View Options menu by splitting settings into clearer groups and hiding view-specific controls until they apply to the selected calendar mode. Fixed# (#1976) Fixed embedded Calendar and Agenda Bases so \"Navigate to date from property\" can use the containing note's date property when the Base rows do not have that property. Thanks to @matesvecenik for reporting this. (#1977) Fixed Calendar and Agenda views showing duplicate all-day entries when a task's scheduled date and due date are the same day. Timed due dates on the same day still show as separate deadline markers. Thanks to @pdgBC for reporting this. Fixed the release notes view using cramped interface typography instead of regular reading typography. (#216) Improved inline conversion for Tasks plugin task lines, including Dataview-style fields, priority markers, recurrence text, date aliases, block links, and safer trailing-field parsing. Thanks to @ksdavidc for the request, @natleahh for the Dataview example, and @hangryscribe3 and @nayatiuh for the discussion. (#1974) Stopped Calendar and Agenda property-based events from logging date parse errors for entries that do not have the selected date property. Thanks to @Jomo94 for suggesting completed-date Agenda events. (#1973) Reduced unnecessary Calendar view recreations when external calendar providers are reported in a different order, and preserved Calendar scroll position when a config-driven refresh has to recreate the view. Thanks to @e-zz for reporting this. (#1972) Fixed ICS calendar event related notes so standalone events with similar numeric IDs no longer show unrelated notes or tasks on every event. Thanks to @ks-studio-net for reporting this. (#1970) Fixed generated default Base filters so updating default files applies configured excluded folders to TaskNotes task views. Thanks to @henrim01 for reporting that templates could still appear in regenerated views. (#1968) Fixed inline task link overlays collapsing on Obsidian mobile, which could hide the task title and leave a tall empty gap after the widget. Thanks to @renatomen for reporting and diagnosing the containment issue."},{"route":"/obsidian/releases/4.10.1/","title":"TaskNotes 4.10.1","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.10.1.md","namespace":"obsidian","relativePath":"releases/4.10.1.md","raw":"# TaskNotes 4.10.1\n\n## Added\n\n- Added a startup check for new compatible TaskNotes releases. When a new release is available, TaskNotes shows a notice that opens the TaskNotes entry in Obsidian's Community Plugins browser.\n- (#1989) Added a command-palette action plus runtime and HTTP API actions for updating configured default `.base` files from the current TaskNotes templates. Thanks to @businessBoris for the request.\n- (#1115) Added API and MCP support for creating materialized occurrence notes from recurring tasks, and made headless recurring-instance completion respect occurrence notes when the parent uses Create next after completion. Thanks to @gsssr for the original request, @slipstyle for the follow-up, and @martin-forge for identifying the API/MCP gap.\n\n## Fixed\n\n- (#1985) Fixed embedded Calendar and Agenda time-grid views drifting out of alignment inside callouts and Reading mode. Thanks to @matesvecenik for reporting and sharing screenshots.\n- (#1986) Fixed the local HTTP API rejecting requests from the TaskNotes browser extension's Chrome extension origin. Thanks to @n1njaznutz for reporting this.\n- (#1980) Added mobile bottom spacing to Agenda Calendar views so the last visible tasks can scroll above Obsidian's bottom navigation bar. Thanks to @Jomo94 for reporting and sharing the screenshot.\n- (#1984) Fixed mobile task link overlays hiding configured inline task card properties such as scheduled date, due date, contexts, and projects. Thanks to @stil-sudo for reporting.\n- (#1979) Kept the left-positioned subtask chevron from overlapping the task status control on mobile task cards. Thanks to @Jomo94 for reporting and sharing the screenshot.\n- (#1903) Reduced the Edit Task modal's mobile action-button footer so Open note, Archive, Delete, Save, and Cancel take two rows instead of three on iPhone-sized screens. Thanks to @3zra47 for the original report and @krzyfu for the follow-up about the button area crowding the editor.\n- (#1982) Preserved scroll position in TaskNotes Bases after task edits and data refreshes, avoiding jumps back to the top on mobile. Thanks to @3zra47 for reporting.\n- (#1978) Restored Obsidian editor shortcuts such as insert link, headings, and list toggles inside the Edit Task modal's Details editor. Thanks to @krzyfu for reporting this.\n","aliases":["/releases/4.10.1/","/releases/4.10.1/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • Added a startup check for new compatible TaskNotes releases. When a new release is available, TaskNotes shows a notice that opens the TaskNotes entry in Obsidian's Community Plugins browser.
  • \n
  • (#1989) Added a command-palette action plus runtime and HTTP API actions for updating configured default .base files from the current TaskNotes templates. Thanks to @businessBoris for the request.
  • \n
  • (#1115) Added API and MCP support for creating materialized occurrence notes from recurring tasks, and made headless recurring-instance completion respect occurrence notes when the parent uses Create next after completion. Thanks to @gsssr for the original request, @slipstyle for the follow-up, and @martin-forge for identifying the API/MCP gap.
  • \n
\n

Fixed#

\n
    \n
  • (#1985) Fixed embedded Calendar and Agenda time-grid views drifting out of alignment inside callouts and Reading mode. Thanks to @matesvecenik for reporting and sharing screenshots.
  • \n
  • (#1986) Fixed the local HTTP API rejecting requests from the TaskNotes browser extension's Chrome extension origin. Thanks to @n1njaznutz for reporting this.
  • \n
  • (#1980) Added mobile bottom spacing to Agenda Calendar views so the last visible tasks can scroll above Obsidian's bottom navigation bar. Thanks to @Jomo94 for reporting and sharing the screenshot.
  • \n
  • (#1984) Fixed mobile task link overlays hiding configured inline task card properties such as scheduled date, due date, contexts, and projects. Thanks to @stil-sudo for reporting.
  • \n
  • (#1979) Kept the left-positioned subtask chevron from overlapping the task status control on mobile task cards. Thanks to @Jomo94 for reporting and sharing the screenshot.
  • \n
  • (#1903) Reduced the Edit Task modal's mobile action-button footer so Open note, Archive, Delete, Save, and Cancel take two rows instead of three on iPhone-sized screens. Thanks to @3zra47 for the original report and @krzyfu for the follow-up about the button area crowding the editor.
  • \n
  • (#1982) Preserved scroll position in TaskNotes Bases after task edits and data refreshes, avoiding jumps back to the top on mobile. Thanks to @3zra47 for reporting.
  • \n
  • (#1978) Restored Obsidian editor shortcuts such as insert link, headings, and list toggles inside the Edit Task modal's Details editor. Thanks to @krzyfu for reporting this.
  • \n
\n","text":"Added# Added a startup check for new compatible TaskNotes releases. When a new release is available, TaskNotes shows a notice that opens the TaskNotes entry in Obsidian's Community Plugins browser. (#1989) Added a command-palette action plus runtime and HTTP API actions for updating configured default .base files from the current TaskNotes templates. Thanks to @businessBoris for the request. (#1115) Added API and MCP support for creating materialized occurrence notes from recurring tasks, and made headless recurring-instance completion respect occurrence notes when the parent uses Create next after completion. Thanks to @gsssr for the original request, @slipstyle for the follow-up, and @martin-forge for identifying the API/MCP gap. Fixed# (#1985) Fixed embedded Calendar and Agenda time-grid views drifting out of alignment inside callouts and Reading mode. Thanks to @matesvecenik for reporting and sharing screenshots. (#1986) Fixed the local HTTP API rejecting requests from the TaskNotes browser extension's Chrome extension origin. Thanks to @n1njaznutz for reporting this. (#1980) Added mobile bottom spacing to Agenda Calendar views so the last visible tasks can scroll above Obsidian's bottom navigation bar. Thanks to @Jomo94 for reporting and sharing the screenshot. (#1984) Fixed mobile task link overlays hiding configured inline task card properties such as scheduled date, due date, contexts, and projects. Thanks to @stil-sudo for reporting. (#1979) Kept the left-positioned subtask chevron from overlapping the task status control on mobile task cards. Thanks to @Jomo94 for reporting and sharing the screenshot. (#1903) Reduced the Edit Task modal's mobile action-button footer so Open note, Archive, Delete, Save, and Cancel take two rows instead of three on iPhone-sized screens. Thanks to @3zra47 for the original report and @krzyfu for the follow-up about the button area crowding the editor. (#1982) Preserved scroll position in TaskNotes Bases after task edits and data refreshes, avoiding jumps back to the top on mobile. Thanks to @3zra47 for reporting. (#1978) Restored Obsidian editor shortcuts such as insert link, headings, and list toggles inside the Edit Task modal's Details editor. Thanks to @krzyfu for reporting this."},{"route":"/obsidian/releases/4.10.2/","title":"TaskNotes 4.10.2","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.10.2.md","namespace":"obsidian","relativePath":"releases/4.10.2.md","raw":"# TaskNotes 4.10.2\n\n## Fixed\n\n- (#1995) Fixed Bases Calendar views showing both a materialized occurrence note and its matching virtual recurring task instance. Thanks to @rdefaccio for reporting this.\n- (Discussion #1994) Fixed timed recurring tasks failing to advance their due dates when due-date offset preservation is enabled. Thanks to @mgrecar for raising this.\n","aliases":["/releases/4.10.2/","/releases/4.10.2/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Fixed#

\n
    \n
  • (#1995) Fixed Bases Calendar views showing both a materialized occurrence note and its matching virtual recurring task instance. Thanks to @rdefaccio for reporting this.
  • \n
  • (Discussion #1994) Fixed timed recurring tasks failing to advance their due dates when due-date offset preservation is enabled. Thanks to @mgrecar for raising this.
  • \n
\n","text":"Fixed# (#1995) Fixed Bases Calendar views showing both a materialized occurrence note and its matching virtual recurring task instance. Thanks to @rdefaccio for reporting this. (Discussion #1994) Fixed timed recurring tasks failing to advance their due dates when due-date offset preservation is enabled. Thanks to @mgrecar for raising this."},{"route":"/obsidian/releases/4.11.0/","title":"TaskNotes 4.11.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.11.0.md","namespace":"obsidian","relativePath":"releases/4.11.0.md","raw":"# TaskNotes 4.11.0\n\n## Added\n\n- (#730, #1897, #1942, #1998) Added [Canvas Bases](https://github.com/callumalpass/canvas-bases), an optional companion plugin that turns Obsidian Bases views into canvas-style boards and reusable JSON Canvas snapshots, with TaskNotes badges, task menus, dependency and subtask edges, and assignment zones for supported TaskNotes actions. See [Canvas Bases](https://tasknotes.dev/companion-plugins/canvas-bases/) for setup details. Thanks to @DillPickle80, @BradGaddis, @Hyadhuad, and @AlinaWithAFace for the visual planning requests, and to @renatomen, @prayidae, and @maranqz for the related discussion.\n- Added a TaskNotes starter note that is created and opened automatically on first install to introduce task creation, inline conversion, and embedded Bases views.\n- Added a runtime API surface for companion plugins to show or populate the standard TaskNotes task context menu.\n- (#2000) Added separate settings for using the active note as a project during normal task creation and during inline task creation or instant conversion. Thanks to @BlueScreen32 for suggesting the split.\n- (#1303, #2001) Added separate templates for materialized occurrence notes, including parent-level `occurrence_template` support and a global fallback setting. Thanks to @BrucePlumb for suggesting a separate occurrence-note template and @ak-42 for the related per-recurrence template request.\n- (#2006) Added the projected local finish time beside the remaining duration while a Pomodoro is running. See [Pomodoro View](https://tasknotes.dev/views/pomodoro-view/) for the timer behavior. Thanks to @abbiefalls90 for suggesting this.\n- (#2016) Added a setting for recurring external calendar event related notes, so Google, Microsoft, and ICS recurrences can either share notes across the series or keep notes limited to the selected instance. See [Integrations Settings](https://tasknotes.dev/settings/integrations/#calendar-subscriptions-ics) for the setting. Thanks to @akhtsang for reporting this, and to @cathywu and @mdbraber for the earlier series-linking discussion.\n\n## Changed\n\n- (#1737) Clarified that changing the task tag does not automatically update existing Base view filters. Thanks to @goldorak00 for reporting this, and to @Domcoppinger and @imsuck for the first-time setup feedback.\n- (#2005) Excluded archived task notes and archived project-note references from Task & Project Statistics. Thanks to @Xiarno for suggesting this.\n- Added a local review-type lint check that catches dependency-resolution warnings from Obsidian's online review before submission.\n- Improved dependency and project relationship cache updates so ordinary note edits avoid unnecessary relationship recalculation, while blocked and blocking state stays current when dependency status changes.\n- Improved filter and view query caching so filter options update immediately after relevant task-field changes while large Task List, Kanban, and Calendar queries avoid repeated vault scans.\n- Extended the in-app release notes bundle to include the current major release, with collapsed versions rendered only when opened.\n\n## Fixed\n\n- (#2015) Fixed Google Calendar events from the previous six months disappearing from Calendar and Mini Calendar views after a fresh sync. Thanks to @akhtsang for reporting this.\n- (#2013) Fixed task-card status and priority dots becoming oversized on touch-capable desktop devices. Thanks to @RumiaKitinari for reporting this.\n- (#2009) Restored Tab and Shift+Tab focus movement in the Create new task modal's natural language input instead of letting the markdown editor indent the title. Thanks to @prepare4robots for reporting this.\n- (#2007) Fixed status autocomplete in the task creation modal leaving status value fragments in the task title when the editor auto-paired the status trigger. Thanks to @prepare4robots for reporting this.\n- (#2004) Fixed the Pomodoro start command forgetting the selected task after it was completed, so reopening the task lets it be picked up again. Thanks to @MPourjam for reporting this.\n- (#1996) Made Kanban card drag-and-drop show a clear drop slot marker while cards are being repositioned, so the landing position remains visible during sorting. Thanks to @phillipadsmith for reporting this.\n- Fixed runtime API dependency removal so removing the last dependency from a task also clears the mapped `blockedBy` property from the note.\n","aliases":["/releases/4.11.0/","/releases/4.11.0/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • (#730, #1897, #1942, #1998) Added Canvas Bases, an optional companion plugin that turns Obsidian Bases views into canvas-style boards and reusable JSON Canvas snapshots, with TaskNotes badges, task menus, dependency and subtask edges, and assignment zones for supported TaskNotes actions. See Canvas Bases for setup details. Thanks to @DillPickle80, @BradGaddis, @Hyadhuad, and @AlinaWithAFace for the visual planning requests, and to @renatomen, @prayidae, and @maranqz for the related discussion.
  • \n
  • Added a TaskNotes starter note that is created and opened automatically on first install to introduce task creation, inline conversion, and embedded Bases views.
  • \n
  • Added a runtime API surface for companion plugins to show or populate the standard TaskNotes task context menu.
  • \n
  • (#2000) Added separate settings for using the active note as a project during normal task creation and during inline task creation or instant conversion. Thanks to @BlueScreen32 for suggesting the split.
  • \n
  • (#1303, #2001) Added separate templates for materialized occurrence notes, including parent-level occurrence_template support and a global fallback setting. Thanks to @BrucePlumb for suggesting a separate occurrence-note template and @ak-42 for the related per-recurrence template request.
  • \n
  • (#2006) Added the projected local finish time beside the remaining duration while a Pomodoro is running. See Pomodoro View for the timer behavior. Thanks to @abbiefalls90 for suggesting this.
  • \n
  • (#2016) Added a setting for recurring external calendar event related notes, so Google, Microsoft, and ICS recurrences can either share notes across the series or keep notes limited to the selected instance. See Integrations Settings for the setting. Thanks to @akhtsang for reporting this, and to @cathywu and @mdbraber for the earlier series-linking discussion.
  • \n
\n

Changed#

\n
    \n
  • (#1737) Clarified that changing the task tag does not automatically update existing Base view filters. Thanks to @goldorak00 for reporting this, and to @Domcoppinger and @imsuck for the first-time setup feedback.
  • \n
  • (#2005) Excluded archived task notes and archived project-note references from Task & Project Statistics. Thanks to @Xiarno for suggesting this.
  • \n
  • Added a local review-type lint check that catches dependency-resolution warnings from Obsidian's online review before submission.
  • \n
  • Improved dependency and project relationship cache updates so ordinary note edits avoid unnecessary relationship recalculation, while blocked and blocking state stays current when dependency status changes.
  • \n
  • Improved filter and view query caching so filter options update immediately after relevant task-field changes while large Task List, Kanban, and Calendar queries avoid repeated vault scans.
  • \n
  • Extended the in-app release notes bundle to include the current major release, with collapsed versions rendered only when opened.
  • \n
\n

Fixed#

\n
    \n
  • (#2015) Fixed Google Calendar events from the previous six months disappearing from Calendar and Mini Calendar views after a fresh sync. Thanks to @akhtsang for reporting this.
  • \n
  • (#2013) Fixed task-card status and priority dots becoming oversized on touch-capable desktop devices. Thanks to @RumiaKitinari for reporting this.
  • \n
  • (#2009) Restored Tab and Shift+Tab focus movement in the Create new task modal's natural language input instead of letting the markdown editor indent the title. Thanks to @prepare4robots for reporting this.
  • \n
  • (#2007) Fixed status autocomplete in the task creation modal leaving status value fragments in the task title when the editor auto-paired the status trigger. Thanks to @prepare4robots for reporting this.
  • \n
  • (#2004) Fixed the Pomodoro start command forgetting the selected task after it was completed, so reopening the task lets it be picked up again. Thanks to @MPourjam for reporting this.
  • \n
  • (#1996) Made Kanban card drag-and-drop show a clear drop slot marker while cards are being repositioned, so the landing position remains visible during sorting. Thanks to @phillipadsmith for reporting this.
  • \n
  • Fixed runtime API dependency removal so removing the last dependency from a task also clears the mapped blockedBy property from the note.
  • \n
\n","text":"Added# (#730, #1897, #1942, #1998) Added Canvas Bases, an optional companion plugin that turns Obsidian Bases views into canvas-style boards and reusable JSON Canvas snapshots, with TaskNotes badges, task menus, dependency and subtask edges, and assignment zones for supported TaskNotes actions. See Canvas Bases for setup details. Thanks to @DillPickle80, @BradGaddis, @Hyadhuad, and @AlinaWithAFace for the visual planning requests, and to @renatomen, @prayidae, and @maranqz for the related discussion. Added a TaskNotes starter note that is created and opened automatically on first install to introduce task creation, inline conversion, and embedded Bases views. Added a runtime API surface for companion plugins to show or populate the standard TaskNotes task context menu. (#2000) Added separate settings for using the active note as a project during normal task creation and during inline task creation or instant conversion. Thanks to @BlueScreen32 for suggesting the split. (#1303, #2001) Added separate templates for materialized occurrence notes, including parent-level occurrence_template support and a global fallback setting. Thanks to @BrucePlumb for suggesting a separate occurrence-note template and @ak-42 for the related per-recurrence template request. (#2006) Added the projected local finish time beside the remaining duration while a Pomodoro is running. See Pomodoro View for the timer behavior. Thanks to @abbiefalls90 for suggesting this. (#2016) Added a setting for recurring external calendar event related notes, so Google, Microsoft, and ICS recurrences can either share notes across the series or keep notes limited to the selected instance. See Integrations Settings for the setting. Thanks to @akhtsang for reporting this, and to @cathywu and @mdbraber for the earlier series-linking discussion. Changed# (#1737) Clarified that changing the task tag does not automatically update existing Base view filters. Thanks to @goldorak00 for reporting this, and to @Domcoppinger and @imsuck for the first-time setup feedback. (#2005) Excluded archived task notes and archived project-note references from Task & Project Statistics. Thanks to @Xiarno for suggesting this. Added a local review-type lint check that catches dependency-resolution warnings from Obsidian's online review before submission. Improved dependency and project relationship cache updates so ordinary note edits avoid unnecessary relationship recalculation, while blocked and blocking state stays current when dependency status changes. Improved filter and view query caching so filter options update immediately after relevant task-field changes while large Task List, Kanban, and Calendar queries avoid repeated vault scans. Extended the in-app release notes bundle to include the current major release, with collapsed versions rendered only when opened. Fixed# (#2015) Fixed Google Calendar events from the previous six months disappearing from Calendar and Mini Calendar views after a fresh sync. Thanks to @akhtsang for reporting this. (#2013) Fixed task-card status and priority dots becoming oversized on touch-capable desktop devices. Thanks to @RumiaKitinari for reporting this. (#2009) Restored Tab and Shift+Tab focus movement in the Create new task modal's natural language input instead of letting the markdown editor indent the title. Thanks to @prepare4robots for reporting this. (#2007) Fixed status autocomplete in the task creation modal leaving status value fragments in the task title when the editor auto-paired the status trigger. Thanks to @prepare4robots for reporting this. (#2004) Fixed the Pomodoro start command forgetting the selected task after it was completed, so reopening the task lets it be picked up again. Thanks to @MPourjam for reporting this. (#1996) Made Kanban card drag-and-drop show a clear drop slot marker while cards are being repositioned, so the landing position remains visible during sorting. Thanks to @phillipadsmith for reporting this. Fixed runtime API dependency removal so removing the last dependency from a task also clears the mapped blockedBy property from the note."},{"route":"/obsidian/releases/4.11.1/","title":"TaskNotes 4.11.1","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.11.1.md","namespace":"obsidian","relativePath":"releases/4.11.1.md","raw":"# TaskNotes 4.11.1\n\n## Added\n\n- (#2024) Added materialized occurrence notes to the Relationships widget, so recurring parent task notes can show their occurrence notes in an **Occurrences** tab. See [Relationships Widget](https://tasknotes.dev/features/inline-tasks/#relationships-widget). Thanks to @3zra47 for requesting this.\n- (#2022) Added a **Skip instance** / **Unskip instance** action to the recurring task edit modal's completion calendar, so skipped dates can be adjusted from the same date menu as completions. See [Recurring Tasks](https://tasknotes.dev/features/recurring-tasks/#completion-tracking). Thanks to @AmonAmarthFTW for requesting this.\n- (#2048) Added current due and scheduled dates to the edit modal's task information. Thanks to @1activegeek for requesting this.\n- (#2058, #2059) Added natural-language parsing and the full date picker to date-type custom fields. Thanks to @chmac for requesting this.\n- (#2060) Added date-type custom fields to the task right-click menu under **Custom dates**. Thanks to @chmac for requesting this.\n- (#2067) Added an **Edit task** action to the task card context menu, including inline task cards. Thanks to @DarkCellar for requesting this.\n- (#2068) Added `reminders` input support to the MCP `tasknotes_create_task` and `tasknotes_update_task` tools. Thanks to @Spirit597 for requesting this.\n- (#2069) Added an **Add project** action to the Quick Actions palette. Thanks to @chmac for requesting this.\n\n## Fixed\n\n- (#2007) Fixed a remaining task creation autocomplete case where a status value containing another status label could leave status fragments in the task title. Thanks to @prepare4robots for the follow-up report.\n- (#2031) Fixed quick task creation failing when natural language input created a recurring task with a scheduled time. Thanks to @rdefaccio for reporting this.\n- (#2034) Fixed Advanced Calendar timed events switching to a high-contrast mobile fill when Obsidian is narrowed or split on desktop. Thanks to @RumiaKitinari for reporting this.\n- (#2039) Fixed broken images on the Workflows and Calendar Setup documentation pages. Thanks to @chmac for reporting this.\n- (#2045) Fixed custom modal fields assigned to Basic Information not appearing in task creation or edit modals. Thanks to @chmac for reporting this.\n- (#2063) Fixed project autocomplete storing ambiguous project links without the selected note's folder path. Thanks to @chmac for reporting this.\n- (#2072) Fixed inline task links to headings so they show both the task title and heading instead of only the heading. Thanks to @spasche for reporting this.\n- (#2075) Fixed multiday Calendar events being clipped to one day when a Base is embedded in Reading view. Thanks to @ddevaal for reporting this.\n- (#2079) Fixed the reminder modal's **Absolute** tab so it switches from relative fields to absolute date and time fields. Thanks to @JunwonYoon for reporting this and identifying the CSS specificity issue.\n\n## Changed\n\n- Improved local review checks so unsafe direct `Object.prototype` method access is caught before submission.\n","aliases":["/releases/4.11.1/","/releases/4.11.1/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"changed","text":"Changed"}],"html":"

Added#

\n
    \n
  • (#2024) Added materialized occurrence notes to the Relationships widget, so recurring parent task notes can show their occurrence notes in an Occurrences tab. See Relationships Widget. Thanks to @3zra47 for requesting this.
  • \n
  • (#2022) Added a Skip instance / Unskip instance action to the recurring task edit modal's completion calendar, so skipped dates can be adjusted from the same date menu as completions. See Recurring Tasks. Thanks to @AmonAmarthFTW for requesting this.
  • \n
  • (#2048) Added current due and scheduled dates to the edit modal's task information. Thanks to @1activegeek for requesting this.
  • \n
  • (#2058, #2059) Added natural-language parsing and the full date picker to date-type custom fields. Thanks to @chmac for requesting this.
  • \n
  • (#2060) Added date-type custom fields to the task right-click menu under Custom dates. Thanks to @chmac for requesting this.
  • \n
  • (#2067) Added an Edit task action to the task card context menu, including inline task cards. Thanks to @DarkCellar for requesting this.
  • \n
  • (#2068) Added reminders input support to the MCP tasknotes_create_task and tasknotes_update_task tools. Thanks to @Spirit597 for requesting this.
  • \n
  • (#2069) Added an Add project action to the Quick Actions palette. Thanks to @chmac for requesting this.
  • \n
\n

Fixed#

\n
    \n
  • (#2007) Fixed a remaining task creation autocomplete case where a status value containing another status label could leave status fragments in the task title. Thanks to @prepare4robots for the follow-up report.
  • \n
  • (#2031) Fixed quick task creation failing when natural language input created a recurring task with a scheduled time. Thanks to @rdefaccio for reporting this.
  • \n
  • (#2034) Fixed Advanced Calendar timed events switching to a high-contrast mobile fill when Obsidian is narrowed or split on desktop. Thanks to @RumiaKitinari for reporting this.
  • \n
  • (#2039) Fixed broken images on the Workflows and Calendar Setup documentation pages. Thanks to @chmac for reporting this.
  • \n
  • (#2045) Fixed custom modal fields assigned to Basic Information not appearing in task creation or edit modals. Thanks to @chmac for reporting this.
  • \n
  • (#2063) Fixed project autocomplete storing ambiguous project links without the selected note's folder path. Thanks to @chmac for reporting this.
  • \n
  • (#2072) Fixed inline task links to headings so they show both the task title and heading instead of only the heading. Thanks to @spasche for reporting this.
  • \n
  • (#2075) Fixed multiday Calendar events being clipped to one day when a Base is embedded in Reading view. Thanks to @ddevaal for reporting this.
  • \n
  • (#2079) Fixed the reminder modal's Absolute tab so it switches from relative fields to absolute date and time fields. Thanks to @JunwonYoon for reporting this and identifying the CSS specificity issue.
  • \n
\n

Changed#

\n
    \n
  • Improved local review checks so unsafe direct Object.prototype method access is caught before submission.
  • \n
\n","text":"Added# (#2024) Added materialized occurrence notes to the Relationships widget, so recurring parent task notes can show their occurrence notes in an Occurrences tab. See Relationships Widget. Thanks to @3zra47 for requesting this. (#2022) Added a Skip instance / Unskip instance action to the recurring task edit modal's completion calendar, so skipped dates can be adjusted from the same date menu as completions. See Recurring Tasks. Thanks to @AmonAmarthFTW for requesting this. (#2048) Added current due and scheduled dates to the edit modal's task information. Thanks to @1activegeek for requesting this. (#2058, #2059) Added natural-language parsing and the full date picker to date-type custom fields. Thanks to @chmac for requesting this. (#2060) Added date-type custom fields to the task right-click menu under Custom dates. Thanks to @chmac for requesting this. (#2067) Added an Edit task action to the task card context menu, including inline task cards. Thanks to @DarkCellar for requesting this. (#2068) Added reminders input support to the MCP tasknotes_create_task and tasknotes_update_task tools. Thanks to @Spirit597 for requesting this. (#2069) Added an Add project action to the Quick Actions palette. Thanks to @chmac for requesting this. Fixed# (#2007) Fixed a remaining task creation autocomplete case where a status value containing another status label could leave status fragments in the task title. Thanks to @prepare4robots for the follow-up report. (#2031) Fixed quick task creation failing when natural language input created a recurring task with a scheduled time. Thanks to @rdefaccio for reporting this. (#2034) Fixed Advanced Calendar timed events switching to a high-contrast mobile fill when Obsidian is narrowed or split on desktop. Thanks to @RumiaKitinari for reporting this. (#2039) Fixed broken images on the Workflows and Calendar Setup documentation pages. Thanks to @chmac for reporting this. (#2045) Fixed custom modal fields assigned to Basic Information not appearing in task creation or edit modals. Thanks to @chmac for reporting this. (#2063) Fixed project autocomplete storing ambiguous project links without the selected note's folder path. Thanks to @chmac for reporting this. (#2072) Fixed inline task links to headings so they show both the task title and heading instead of only the heading. Thanks to @spasche for reporting this. (#2075) Fixed multiday Calendar events being clipped to one day when a Base is embedded in Reading view. Thanks to @ddevaal for reporting this. (#2079) Fixed the reminder modal's Absolute tab so it switches from relative fields to absolute date and time fields. Thanks to @JunwonYoon for reporting this and identifying the CSS specificity issue. Changed# Improved local review checks so unsafe direct Object.prototype method access is caught before submission."},{"route":"/obsidian/releases/4.12.0/","title":"TaskNotes 4.12.0","description":"[!info] TaskNotes v5 beta","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.12.0.md","namespace":"obsidian","relativePath":"releases/4.12.0.md","raw":"# TaskNotes 4.12.0\n\n> [!info] TaskNotes v5 beta\n>\n> [TaskNotes v5](https://github.com/callumalpass/tasknotes/releases/tag/5.0.0-beta.0) is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release.\n>\n> The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the [TaskNotes app](https://app.tasknotes.dev/), which is also available in beta, so the same tasks can be managed through either interface.\n>\n> TaskNotes collections are built on [mdbase](https://mdbase.dev/), a Markdown-native collection format. [mdbase Connect](https://mdbase.dev/connect/) provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand.\n>\n> TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and [report any problems you encounter](https://github.com/callumalpass/tasknotes/issues).\n\n## Security\n\n- Calendar OAuth credentials and account tokens are now stored in Obsidian Secret Storage instead of TaskNotes' `data.json`, with automatic migration for existing connections. See [Calendar Integration](https://tasknotes.dev/features/calendar-integration/).\n - Thanks to @mcuste for the contribution\n- Updated bundled HTTP, address parsing, and schema validation dependencies to\n versions containing their current security fixes.\n\n## Added\n\n- Added portable task attachment references. Attachments now round-trip as an\n ordered `attachments` link list in task frontmatter and are exposed through\n the TaskNotes model and runtime API. These are collection-file references\n only; attachment bytes and binary metadata remain owned by the host.\n- (#2142) MCP `tasknotes_create_task` and `tasknotes_update_task` now accept\n `customProperties` for configured TaskNotes user fields. Thanks to\n @phillipadsmith for suggesting this.\n- (#2126, #2134) Added optional filename templates for materialized recurring\n occurrence notes, with explicit date, ISO week, month, year, and month-name\n variables plus per-parent overrides. Existing naming remains unchanged until a\n template is configured. See [Recurring Tasks](https://tasknotes.dev/features/recurring-tasks/#occurrence-filenames).\n Thanks to @raphaelfaouakhiri for reporting and implementing this.\n- (#2105) Added `{{projectFolder}}` and `{{projectFolders}}` folder template\n variables for storing tasks alongside linked project notes. See\n [Template Variables](https://tasknotes.dev/features/template-variables/).\n Thanks to @carypruitt for this contribution.\n\n## Changed\n\n- Generated TaskNotes type contracts now include configured natural-language\n capture triggers, allowing compatible clients to offer the same field\n suggestions.\n- Rebuilt the TaskNotes documentation with\n reorganized navigation, full-text search, mobile and accessibility\n improvements, and references generated from the current commands, settings,\n compatibility metadata, HTTP routes, and default Bases. Added practical\n guides for adopting TaskNotes in an existing vault, mobile use, custom Bases,\n and backup and recovery. See the\n [TaskNotes documentation](https://tasknotes.dev/).\n- (#2088) Convert current note to task now uses your default scheduled date when\n the note does not already have `scheduled` frontmatter, while the **None**\n default still leaves converted notes unscheduled. See\n [Task Properties](https://tasknotes.dev/settings/task-properties/#scheduled-date).\n Thanks to @e-zz for suggesting this.\n\n## Fixed\n\n- Plugin settings now recover when Obsidian briefly returns no data while\n reloading an externally changed settings file, preventing a post-reload error\n without overwriting the existing settings.\n- (#2194) Pomodoro task selection suggestions now keep rich task cards at the\n menu width, preventing task titles from wrapping one letter per line. Thanks\n to @Evilgenee for reporting this.\n- (#2196) Drag-to-reorder now works for Task List Bases embedded in Live Preview\n notes, matching the behavior of directly opened Bases and Reading mode embeds.\n Thanks to @jimbo108108 for reporting this.\n- (#2198) Agenda Bases can now show overdue scheduled or due tasks on today's\n row with `showOverdueOnToday`, and regenerated default Agenda files enable\n that behavior by default. Thanks to @vicrdguez for reporting this.\n- (#2182) Checklist progress on task cards now excludes cancelled markdown\n checklist items such as `[-]` from the completed/total count. Thanks to\n @ctrl-q for reporting this.\n- (#2180) Inline task cards in Live Preview now keep their click and context menu\n handlers active on Obsidian 1.13, so clicking a rendered task link opens the\n edit modal instead of revealing the raw wikilink. Thanks to @npondel for the\n detailed diagnosis and @minchinweb for confirming the issue.\n- (#2171) Stopped recurring\n notification and status-bar scans from reading unindexed notes directly from\n disk while preserving the fallback for direct task lookups. Thanks to\n @tgrosinger for identifying and diagnosing the excessive vault reads.\n- (#2174) **Open or create occurrence note** from Quick Actions now uses the\n recurring task's scheduled occurrence date, preventing duplicate occurrence\n notes keyed to the day the action was run. Thanks to @chmac for reporting\n this.\n- (#2169) Regenerated default Base views now include tasks whose identifying\n property is stored as a list containing the configured task value. Thanks to\n @GlebYavorski for reporting this.\n- (#2166) Fixed Task List views configured to start collapsed so the first\n chevron click expands only the selected group instead of expanding every\n other group. Thanks to @renatomen for reporting and fixing this.\n- (#2165) **Convert current note to task** now reads configured field mappings,\n including list-valued title fields such as `aliases`, and preserves an\n existing aliases list when the title is unchanged. Thanks to @jkuball for\n reporting this.\n- (#2164) Flat Kanban boards now clear stale swimlane layout state when they\n rerender, preventing columns from occasionally stacking into one vertical\n strip after switching tabs. Thanks to @brienna for reporting this.\n- (#2160, #2161) Generated Kanban Bases now use the correct TaskNotes status\n property and configuration block. Rich Bases status values render as their\n configured labels, while pinned columns and saved column order are honored.\n Thanks to @kevin-4c for the detailed reports and diagnosis.\n- (#2111, #2159) Recurring task instances now remain visible through the final\n day of Calendar and Agenda ranges in positive-offset time zones, regardless\n of the configured first day of the week. Thanks to @Arachnidai and @odxn0803\n for reporting this.\n- (#2155) Regenerated default Calendar Bases now inherit the app-level time slot\n duration instead of hardcoding 30 minutes. Existing per-Base time settings\n remain intentional overrides. Thanks to @SZZ504232 for reporting this.\n- (#2154) Timed ICS events without a `TZID` now preserve their floating wall\n time in the user's local timezone instead of being interpreted as UTC. Thanks\n to @cloesophia for the reproducible calendar sample.\n- (#2152) Fixed paginated Google Calendar refreshes for calendars with many\n events so secondary calendars do not disappear after Google returns a second\n page. Thanks to @wobafett for reporting and diagnosing this.\n- (#2141) Fixed Task List groups for tasks without scheduled or due dates showing\n a raw Bases icon object instead of **None**. Thanks to @ks-studio-net for\n reporting this.\n- (#2140) The edit task modal now shows saved task-identification tags when\n hiding identification tags is disabled. Thanks to @3zra47 for reporting this.\n- (#2148) Empty list-like frontmatter values no longer become literal `\"null\"`\n entries when tasks are edited. Thanks to @minchinweb for reporting this.\n- (#2120, #2135) Long all-day event titles in Calendar week and day views now\n truncate instead of stretching the all-day row. Thanks to @same774 and\n @ks-studio-net for reporting this.\n- (#2124) Fixed a Kanban crash when opening or closing the edit modal immediately\n after moving a task between list-valued swimlanes such as contexts. Thanks to\n @Decia-C for reporting this.\n- (#2114) Completing a rescheduled occurrence for a scheduled-anchored recurring\n task now advances the parent from the moved occurrence date instead of an\n earlier original occurrence date. Thanks to @chrabia for reporting this.\n- (#2113) Failed Google Calendar manual refreshes no longer make the next\n immediate refresh show a misleading success notice. Thanks to @JohWQ for\n reporting this.\n- (#2109) TaskNotes no longer injects instant-conversion controls into embedded\n or detached Markdown editors, preventing checkbox notes opened from unrelated\n Bases from freezing Obsidian on mobile. Thanks to @jmartinmcfly for the clear\n reproduction and recording.\n- (#2107, #2108) Creating tasks with **Store title in filename** enabled now\n handles duplicate or case-variant titles without failing or replacing the task\n title with a suffixed filename. Thanks to @AdmiralClackington for reporting and\n diagnosing this.\n- (#2106) Regenerated default Calendar Base files now use your configured first\n day of the week instead of forcing Sunday. Thanks to @atos2212-blip, @cweekly,\n @idontcode34, and @hikatamika for reporting this.\n- (#2100) Tags added while creating a task now keep the same frontmatter order as\n tags added later from the task context menu. Thanks to @mgrecar for reporting\n this.\n- (#2092) New non-recurring tasks created directly in a completed status now get\n a completed date, so completed-date views can find them immediately. Thanks\n to @Crell for reporting this.\n- (#2096) Fixed TaskNotes Kanban swimlanes falling back to **None** when the\n swimlane used a Bases formula that was not already cached by Bases. Thanks to\n @ddevaal for reporting this.\n- (#2093) TaskNotes now retries custom Bases view registration when the Bases\n core plugin is enabled after TaskNotes, preventing default views from showing\n **Unknown view type** until TaskNotes is reloaded. Thanks to @yaye-work for\n reporting this.\n- (#2084) The Relationships widget no longer prevents editor text selection from\n autoscrolling when dragging below the bottom edge of a task note. Thanks to\n @lostwildland for reporting this.\n- (#2081, #2103) Kept task card and relationships widgets visible in reading mode\n when Obsidian scroll or preview updates remove their DOM, and refreshed visible\n widgets promptly after metadata changes. Thanks to @mukhozhuk for reporting and\n debugging this and @martin-forge for fixing it.\n- (#2064, #2066) Recurring tasks now advance correctly after their next\n scheduled date is manually adjusted, preserving due-date offsets and times\n without jumping back to an earlier occurrence. Thanks to @chmac for reporting\n and fixing this.\n- (#2018) Fixed **Hide empty columns** in Kanban views with swimlanes so columns\n with no visible tasks are hidden while pinned columns remain. Thanks to\n @scottTomaszewski for reporting and fixing this.\n- Fixed recurring all-day ICS subscription events keeping the original end date\n on later instances, which could cause calendar list views to show events under\n the wrong day. Thanks to @abbiefalls90.\n- (#2033) Fixed the project folder badge on task cards so, when expandable\n subtasks are enabled, it expands or collapses inline subtasks instead of\n showing an unavailable-action notice. Thanks to @abbiefalls90 for the fix and\n @scottkodai for the follow-up feedback.\n- (#2040, #2041) Stopped newly created tasks from filling the Google Calendar\n retry queue when calendar export is disabled. Thanks to @chmac for reporting\n and fixing this.\n- (#2046, #2051) The date and time picker now focuses the natural-language input\n when it is enabled, making keyboard-driven quick actions ready for immediate\n typing. Thanks to @DevOps-Toast for reporting this and @ther12k for fixing it.\n- (#2125, #2129) Materialized recurring occurrence notes now record the date\n they were actually completed, while the parent recurring task continues to\n track the occurrence date. Thanks to @raphaelfaouakhiri for reporting and\n fixing this.\n- (#2173, #2175) Completion-anchored recurring tasks with materialized\n occurrence notes now schedule the next occurrence from the day the occurrence\n was actually completed. Thanks to @chmac for reporting and fixing this.\n- (#1982) Preserved the Task List's own scroll position during Bases refreshes so\n long mobile lists do not jump back to the top after task updates. Thanks to\n @3zra47 for the follow-up report.\n- (#1863) Microsoft Calendar event updates now accept opaque Exchange calendar\n IDs instead of failing local validation before contacting Microsoft Graph.\n Thanks to @fmacondray for reporting this and providing the follow-up stack\n trace.\n","aliases":["/releases/4.12.0/","/releases/4.12.0/"],"toc":[{"level":2,"id":"security","text":"Security"},{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"
\n

[!info] TaskNotes v5 beta

\n

TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release.

\n

The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface.

\n

TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand.

\n

TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter.

\n
\n

Security#

\n
    \n
  • Calendar OAuth credentials and account tokens are now stored in Obsidian Secret Storage instead of TaskNotes' data.json, with automatic migration for existing connections. See Calendar Integration.
      \n
    • Thanks to @mcuste for the contribution
    • \n
    \n
  • \n
  • Updated bundled HTTP, address parsing, and schema validation dependencies to\nversions containing their current security fixes.
  • \n
\n

Added#

\n
    \n
  • Added portable task attachment references. Attachments now round-trip as an\nordered attachments link list in task frontmatter and are exposed through\nthe TaskNotes model and runtime API. These are collection-file references\nonly; attachment bytes and binary metadata remain owned by the host.
  • \n
  • (#2142) MCP tasknotes_create_task and tasknotes_update_task now accept\ncustomProperties for configured TaskNotes user fields. Thanks to\n@phillipadsmith for suggesting this.
  • \n
  • (#2126, #2134) Added optional filename templates for materialized recurring\noccurrence notes, with explicit date, ISO week, month, year, and month-name\nvariables plus per-parent overrides. Existing naming remains unchanged until a\ntemplate is configured. See Recurring Tasks.\nThanks to @raphaelfaouakhiri for reporting and implementing this.
  • \n
  • (#2105) Added {{projectFolder}} and {{projectFolders}} folder template\nvariables for storing tasks alongside linked project notes. See\nTemplate Variables.\nThanks to @carypruitt for this contribution.
  • \n
\n

Changed#

\n
    \n
  • Generated TaskNotes type contracts now include configured natural-language\ncapture triggers, allowing compatible clients to offer the same field\nsuggestions.
  • \n
  • Rebuilt the TaskNotes documentation with\nreorganized navigation, full-text search, mobile and accessibility\nimprovements, and references generated from the current commands, settings,\ncompatibility metadata, HTTP routes, and default Bases. Added practical\nguides for adopting TaskNotes in an existing vault, mobile use, custom Bases,\nand backup and recovery. See the\nTaskNotes documentation.
  • \n
  • (#2088) Convert current note to task now uses your default scheduled date when\nthe note does not already have scheduled frontmatter, while the None\ndefault still leaves converted notes unscheduled. See\nTask Properties.\nThanks to @e-zz for suggesting this.
  • \n
\n

Fixed#

\n
    \n
  • Plugin settings now recover when Obsidian briefly returns no data while\nreloading an externally changed settings file, preventing a post-reload error\nwithout overwriting the existing settings.
  • \n
  • (#2194) Pomodoro task selection suggestions now keep rich task cards at the\nmenu width, preventing task titles from wrapping one letter per line. Thanks\nto @Evilgenee for reporting this.
  • \n
  • (#2196) Drag-to-reorder now works for Task List Bases embedded in Live Preview\nnotes, matching the behavior of directly opened Bases and Reading mode embeds.\nThanks to @jimbo108108 for reporting this.
  • \n
  • (#2198) Agenda Bases can now show overdue scheduled or due tasks on today's\nrow with showOverdueOnToday, and regenerated default Agenda files enable\nthat behavior by default. Thanks to @vicrdguez for reporting this.
  • \n
  • (#2182) Checklist progress on task cards now excludes cancelled markdown\nchecklist items such as [-] from the completed/total count. Thanks to\n@ctrl-q for reporting this.
  • \n
  • (#2180) Inline task cards in Live Preview now keep their click and context menu\nhandlers active on Obsidian 1.13, so clicking a rendered task link opens the\nedit modal instead of revealing the raw wikilink. Thanks to @npondel for the\ndetailed diagnosis and @minchinweb for confirming the issue.
  • \n
  • (#2171) Stopped recurring\nnotification and status-bar scans from reading unindexed notes directly from\ndisk while preserving the fallback for direct task lookups. Thanks to\n@tgrosinger for identifying and diagnosing the excessive vault reads.
  • \n
  • (#2174) Open or create occurrence note from Quick Actions now uses the\nrecurring task's scheduled occurrence date, preventing duplicate occurrence\nnotes keyed to the day the action was run. Thanks to @chmac for reporting\nthis.
  • \n
  • (#2169) Regenerated default Base views now include tasks whose identifying\nproperty is stored as a list containing the configured task value. Thanks to\n@GlebYavorski for reporting this.
  • \n
  • (#2166) Fixed Task List views configured to start collapsed so the first\nchevron click expands only the selected group instead of expanding every\nother group. Thanks to @renatomen for reporting and fixing this.
  • \n
  • (#2165) Convert current note to task now reads configured field mappings,\nincluding list-valued title fields such as aliases, and preserves an\nexisting aliases list when the title is unchanged. Thanks to @jkuball for\nreporting this.
  • \n
  • (#2164) Flat Kanban boards now clear stale swimlane layout state when they\nrerender, preventing columns from occasionally stacking into one vertical\nstrip after switching tabs. Thanks to @brienna for reporting this.
  • \n
  • (#2160, #2161) Generated Kanban Bases now use the correct TaskNotes status\nproperty and configuration block. Rich Bases status values render as their\nconfigured labels, while pinned columns and saved column order are honored.\nThanks to @kevin-4c for the detailed reports and diagnosis.
  • \n
  • (#2111, #2159) Recurring task instances now remain visible through the final\nday of Calendar and Agenda ranges in positive-offset time zones, regardless\nof the configured first day of the week. Thanks to @Arachnidai and @odxn0803\nfor reporting this.
  • \n
  • (#2155) Regenerated default Calendar Bases now inherit the app-level time slot\nduration instead of hardcoding 30 minutes. Existing per-Base time settings\nremain intentional overrides. Thanks to @SZZ504232 for reporting this.
  • \n
  • (#2154) Timed ICS events without a TZID now preserve their floating wall\ntime in the user's local timezone instead of being interpreted as UTC. Thanks\nto @cloesophia for the reproducible calendar sample.
  • \n
  • (#2152) Fixed paginated Google Calendar refreshes for calendars with many\nevents so secondary calendars do not disappear after Google returns a second\npage. Thanks to @wobafett for reporting and diagnosing this.
  • \n
  • (#2141) Fixed Task List groups for tasks without scheduled or due dates showing\na raw Bases icon object instead of None. Thanks to @ks-studio-net for\nreporting this.
  • \n
  • (#2140) The edit task modal now shows saved task-identification tags when\nhiding identification tags is disabled. Thanks to @3zra47 for reporting this.
  • \n
  • (#2148) Empty list-like frontmatter values no longer become literal "null"\nentries when tasks are edited. Thanks to @minchinweb for reporting this.
  • \n
  • (#2120, #2135) Long all-day event titles in Calendar week and day views now\ntruncate instead of stretching the all-day row. Thanks to @same774 and\n@ks-studio-net for reporting this.
  • \n
  • (#2124) Fixed a Kanban crash when opening or closing the edit modal immediately\nafter moving a task between list-valued swimlanes such as contexts. Thanks to\n@Decia-C for reporting this.
  • \n
  • (#2114) Completing a rescheduled occurrence for a scheduled-anchored recurring\ntask now advances the parent from the moved occurrence date instead of an\nearlier original occurrence date. Thanks to @chrabia for reporting this.
  • \n
  • (#2113) Failed Google Calendar manual refreshes no longer make the next\nimmediate refresh show a misleading success notice. Thanks to @JohWQ for\nreporting this.
  • \n
  • (#2109) TaskNotes no longer injects instant-conversion controls into embedded\nor detached Markdown editors, preventing checkbox notes opened from unrelated\nBases from freezing Obsidian on mobile. Thanks to @jmartinmcfly for the clear\nreproduction and recording.
  • \n
  • (#2107, #2108) Creating tasks with Store title in filename enabled now\nhandles duplicate or case-variant titles without failing or replacing the task\ntitle with a suffixed filename. Thanks to @AdmiralClackington for reporting and\ndiagnosing this.
  • \n
  • (#2106) Regenerated default Calendar Base files now use your configured first\nday of the week instead of forcing Sunday. Thanks to @atos2212-blip, @cweekly,\n@idontcode34, and @hikatamika for reporting this.
  • \n
  • (#2100) Tags added while creating a task now keep the same frontmatter order as\ntags added later from the task context menu. Thanks to @mgrecar for reporting\nthis.
  • \n
  • (#2092) New non-recurring tasks created directly in a completed status now get\na completed date, so completed-date views can find them immediately. Thanks\nto @Crell for reporting this.
  • \n
  • (#2096) Fixed TaskNotes Kanban swimlanes falling back to None when the\nswimlane used a Bases formula that was not already cached by Bases. Thanks to\n@ddevaal for reporting this.
  • \n
  • (#2093) TaskNotes now retries custom Bases view registration when the Bases\ncore plugin is enabled after TaskNotes, preventing default views from showing\nUnknown view type until TaskNotes is reloaded. Thanks to @yaye-work for\nreporting this.
  • \n
  • (#2084) The Relationships widget no longer prevents editor text selection from\nautoscrolling when dragging below the bottom edge of a task note. Thanks to\n@lostwildland for reporting this.
  • \n
  • (#2081, #2103) Kept task card and relationships widgets visible in reading mode\nwhen Obsidian scroll or preview updates remove their DOM, and refreshed visible\nwidgets promptly after metadata changes. Thanks to @mukhozhuk for reporting and\ndebugging this and @martin-forge for fixing it.
  • \n
  • (#2064, #2066) Recurring tasks now advance correctly after their next\nscheduled date is manually adjusted, preserving due-date offsets and times\nwithout jumping back to an earlier occurrence. Thanks to @chmac for reporting\nand fixing this.
  • \n
  • (#2018) Fixed Hide empty columns in Kanban views with swimlanes so columns\nwith no visible tasks are hidden while pinned columns remain. Thanks to\n@scottTomaszewski for reporting and fixing this.
  • \n
  • Fixed recurring all-day ICS subscription events keeping the original end date\non later instances, which could cause calendar list views to show events under\nthe wrong day. Thanks to @abbiefalls90.
  • \n
  • (#2033) Fixed the project folder badge on task cards so, when expandable\nsubtasks are enabled, it expands or collapses inline subtasks instead of\nshowing an unavailable-action notice. Thanks to @abbiefalls90 for the fix and\n@scottkodai for the follow-up feedback.
  • \n
  • (#2040, #2041) Stopped newly created tasks from filling the Google Calendar\nretry queue when calendar export is disabled. Thanks to @chmac for reporting\nand fixing this.
  • \n
  • (#2046, #2051) The date and time picker now focuses the natural-language input\nwhen it is enabled, making keyboard-driven quick actions ready for immediate\ntyping. Thanks to @DevOps-Toast for reporting this and @ther12k for fixing it.
  • \n
  • (#2125, #2129) Materialized recurring occurrence notes now record the date\nthey were actually completed, while the parent recurring task continues to\ntrack the occurrence date. Thanks to @raphaelfaouakhiri for reporting and\nfixing this.
  • \n
  • (#2173, #2175) Completion-anchored recurring tasks with materialized\noccurrence notes now schedule the next occurrence from the day the occurrence\nwas actually completed. Thanks to @chmac for reporting and fixing this.
  • \n
  • (#1982) Preserved the Task List's own scroll position during Bases refreshes so\nlong mobile lists do not jump back to the top after task updates. Thanks to\n@3zra47 for the follow-up report.
  • \n
  • (#1863) Microsoft Calendar event updates now accept opaque Exchange calendar\nIDs instead of failing local validation before contacting Microsoft Graph.\nThanks to @fmacondray for reporting this and providing the follow-up stack\ntrace.
  • \n
\n","text":"[!info] TaskNotes v5 beta TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release. The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface. TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand. TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter. Security# Calendar OAuth credentials and account tokens are now stored in Obsidian Secret Storage instead of TaskNotes' data.json, with automatic migration for existing connections. See Calendar Integration. Thanks to @mcuste for the contribution Updated bundled HTTP, address parsing, and schema validation dependencies to versions containing their current security fixes. Added# Added portable task attachment references. Attachments now round-trip as an ordered attachments link list in task frontmatter and are exposed through the TaskNotes model and runtime API. These are collection-file references only; attachment bytes and binary metadata remain owned by the host. (#2142) MCP tasknotes_create_task and tasknotes_update_task now accept customProperties for configured TaskNotes user fields. Thanks to @phillipadsmith for suggesting this. (#2126, #2134) Added optional filename templates for materialized recurring occurrence notes, with explicit date, ISO week, month, year, and month-name variables plus per-parent overrides. Existing naming remains unchanged until a template is configured. See Recurring Tasks. Thanks to @raphaelfaouakhiri for reporting and implementing this. (#2105) Added {{projectFolder}} and {{projectFolders}} folder template variables for storing tasks alongside linked project notes. See Template Variables. Thanks to @carypruitt for this contribution. Changed# Generated TaskNotes type contracts now include configured natural-language capture triggers, allowing compatible clients to offer the same field suggestions. Rebuilt the TaskNotes documentation with reorganized navigation, full-text search, mobile and accessibility improvements, and references generated from the current commands, settings, compatibility metadata, HTTP routes, and default Bases. Added practical guides for adopting TaskNotes in an existing vault, mobile use, custom Bases, and backup and recovery. See the TaskNotes documentation. (#2088) Convert current note to task now uses your default scheduled date when the note does not already have scheduled frontmatter, while the None default still leaves converted notes unscheduled. See Task Properties. Thanks to @e-zz for suggesting this. Fixed# Plugin settings now recover when Obsidian briefly returns no data while reloading an externally changed settings file, preventing a post-reload error without overwriting the existing settings. (#2194) Pomodoro task selection suggestions now keep rich task cards at the menu width, preventing task titles from wrapping one letter per line. Thanks to @Evilgenee for reporting this. (#2196) Drag-to-reorder now works for Task List Bases embedded in Live Preview notes, matching the behavior of directly opened Bases and Reading mode embeds. Thanks to @jimbo108108 for reporting this. (#2198) Agenda Bases can now show overdue scheduled or due tasks on today's row with showOverdueOnToday, and regenerated default Agenda files enable that behavior by default. Thanks to @vicrdguez for reporting this. (#2182) Checklist progress on task cards now excludes cancelled markdown checklist items such as [-] from the completed/total count. Thanks to @ctrl-q for reporting this. (#2180) Inline task cards in Live Preview now keep their click and context menu handlers active on Obsidian 1.13, so clicking a rendered task link opens the edit modal instead of revealing the raw wikilink. Thanks to @npondel for the detailed diagnosis and @minchinweb for confirming the issue. (#2171) Stopped recurring notification and status-bar scans from reading unindexed notes directly from disk while preserving the fallback for direct task lookups. Thanks to @tgrosinger for identifying and diagnosing the excessive vault reads. (#2174) Open or create occurrence note from Quick Actions now uses the recurring task's scheduled occurrence date, preventing duplicate occurrence notes keyed to the day the action was run. Thanks to @chmac for reporting this. (#2169) Regenerated default Base views now include tasks whose identifying property is stored as a list containing the configured task value. Thanks to @GlebYavorski for reporting this. (#2166) Fixed Task List views configured to start collapsed so the first chevron click expands only the selected group instead of expanding every other group. Thanks to @renatomen for reporting and fixing this. (#2165) Convert current note to task now reads configured field mappings, including list-valued title fields such as aliases, and preserves an existing aliases list when the title is unchanged. Thanks to @jkuball for reporting this. (#2164) Flat Kanban boards now clear stale swimlane layout state when they rerender, preventing columns from occasionally stacking into one vertical strip after switching tabs. Thanks to @brienna for reporting this. (#2160, #2161) Generated Kanban Bases now use the correct TaskNotes status property and configuration block. Rich Bases status values render as their configured labels, while pinned columns and saved column order are honored. Thanks to @kevin-4c for the detailed reports and diagnosis. (#2111, #2159) Recurring task instances now remain visible through the final day of Calendar and Agenda ranges in positive-offset time zones, regardless of the configured first day of the week. Thanks to @Arachnidai and @odxn0803 for reporting this. (#2155) Regenerated default Calendar Bases now inherit the app-level time slot duration instead of hardcoding 30 minutes. Existing per-Base time settings remain intentional overrides. Thanks to @SZZ504232 for reporting this. (#2154) Timed ICS events without a TZID now preserve their floating wall time in the user's local timezone instead of being interpreted as UTC. Thanks to @cloesophia for the reproducible calendar sample. (#2152) Fixed paginated Google Calendar refreshes for calendars with many events so secondary calendars do not disappear after Google returns a second page. Thanks to @wobafett for reporting and diagnosing this. (#2141) Fixed Task List groups for tasks without scheduled or due dates showing a raw Bases icon object instead of None. Thanks to @ks-studio-net for reporting this. (#2140) The edit task modal now shows saved task-identification tags when hiding identification tags is disabled. Thanks to @3zra47 for reporting this. (#2148) Empty list-like frontmatter values no longer become literal \"null\" entries when tasks are edited. Thanks to @minchinweb for reporting this. (#2120, #2135) Long all-day event titles in Calendar week and day views now truncate instead of stretching the all-day row. Thanks to @same774 and @ks-studio-net for reporting this. (#2124) Fixed a Kanban crash when opening or closing the edit modal immediately after moving a task between list-valued swimlanes such as contexts. Thanks to @Decia-C for reporting this. (#2114) Completing a rescheduled occurrence for a scheduled-anchored recurring task now advances the parent from the moved occurrence date instead of an earlier original occurrence date. Thanks to @chrabia for reporting this. (#2113) Failed Google Calendar manual refreshes no longer make the next immediate refresh show a misleading success notice. Thanks to @JohWQ for reporting this. (#2109) TaskNotes no longer injects instant-conversion controls into embedded or detached Markdown editors, preventing checkbox notes opened from unrelated Bases from freezing Obsidian on mobile. Thanks to @jmartinmcfly for the clear reproduction and recording. (#2107, #2108) Creating tasks with Store title in filename enabled now handles duplicate or case-variant titles without failing or replacing the task title with a suffixed filename. Thanks to @AdmiralClackington for reporting and diagnosing this. (#2106) Regenerated default Calendar Base files now use your configured first day of the week instead of forcing Sunday. Thanks to @atos2212-blip, @cweekly, @idontcode34, and @hikatamika for reporting this. (#2100) Tags added while creating a task now keep the same frontmatter order as tags added later from the task context menu. Thanks to @mgrecar for reporting this. (#2092) New non-recurring tasks created directly in a completed status now get a completed date, so completed-date views can find them immediately. Thanks to @Crell for reporting this. (#2096) Fixed TaskNotes Kanban swimlanes falling back to None when the swimlane used a Bases formula that was not already cached by Bases. Thanks to @ddevaal for reporting this. (#2093) TaskNotes now retries custom Bases view registration when the Bases core plugin is enabled after TaskNotes, preventing default views from showing Unknown view type until TaskNotes is reloaded. Thanks to @yaye-work for reporting this. (#2084) The Relationships widget no longer prevents editor text selection from autoscrolling when dragging below the bottom edge of a task note. Thanks to @lostwildland for reporting this. (#2081, #2103) Kept task card and relationships widgets visible in reading mode when Obsidian scroll or preview updates remove their DOM, and refreshed visible widgets promptly after metadata changes. Thanks to @mukhozhuk for reporting and debugging this and @martin-forge for fixing it. (#2064, #2066) Recurring tasks now advance correctly after their next scheduled date is manually adjusted, preserving due-date offsets and times without jumping back to an earlier occurrence. Thanks to @chmac for reporting and fixing this. (#2018) Fixed Hide empty columns in Kanban views with swimlanes so columns with no visible tasks are hidden while pinned columns remain. Thanks to @scottTomaszewski for reporting and fixing this. Fixed recurring all-day ICS subscription events keeping the original end date on later instances, which could cause calendar list views to show events under the wrong day. Thanks to @abbiefalls90. (#2033) Fixed the project folder badge on task cards so, when expandable subtasks are enabled, it expands or collapses inline subtasks instead of showing an unavailable-action notice. Thanks to @abbiefalls90 for the fix and @scottkodai for the follow-up feedback. (#2040, #2041) Stopped newly created tasks from filling the Google Calendar retry queue when calendar export is disabled. Thanks to @chmac for reporting and fixing this. (#2046, #2051) The date and time picker now focuses the natural-language input when it is enabled, making keyboard-driven quick actions ready for immediate typing. Thanks to @DevOps-Toast for reporting this and @ther12k for fixing it. (#2125, #2129) Materialized recurring occurrence notes now record the date they were actually completed, while the parent recurring task continues to track the occurrence date. Thanks to @raphaelfaouakhiri for reporting and fixing this. (#2173, #2175) Completion-anchored recurring tasks with materialized occurrence notes now schedule the next occurrence from the day the occurrence was actually completed. Thanks to @chmac for reporting and fixing this. (#1982) Preserved the Task List's own scroll position during Bases refreshes so long mobile lists do not jump back to the top after task updates. Thanks to @3zra47 for the follow-up report. (#1863) Microsoft Calendar event updates now accept opaque Exchange calendar IDs instead of failing local validation before contacting Microsoft Graph. Thanks to @fmacondray for reporting this and providing the follow-up stack trace."},{"route":"/obsidian/releases/4.12.1/","title":"TaskNotes 4.12.1","description":"[!info] TaskNotes v5 beta","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.12.1.md","namespace":"obsidian","relativePath":"releases/4.12.1.md","raw":"# TaskNotes 4.12.1\n\n> [!info] TaskNotes v5 beta\n>\n> [TaskNotes v5](https://github.com/callumalpass/tasknotes/releases/tag/5.0.0-beta.0) is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release.\n>\n> The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the [TaskNotes app](https://app.tasknotes.dev/), which is also available in beta, so the same tasks can be managed through either interface.\n>\n> TaskNotes collections are built on [mdbase](https://mdbase.dev/), a Markdown-native collection format. [mdbase Connect](https://mdbase.dev/connect/) provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand.\n>\n> TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and [report any problems you encounter](https://github.com/callumalpass/tasknotes/issues).\n\n## Changed\n\n- (#2204) Public documentation is now published from the dedicated `tasknotes.dev` repository. Plugin release notes and internal documentation remain in this repository.\n- Updated compatibility with Obsidian's current plugin review and settings search.\n\n## Fixed\n\n- Fixed TaskNotes interface elements sometimes appearing in the wrong window when using Obsidian pop-out windows.\n- Improved confirmation dialogs, icons, and modal styling to use Obsidian's current interface APIs.\n","aliases":["/releases/4.12.1/","/releases/4.12.1/"],"toc":[{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"
\n

[!info] TaskNotes v5 beta

\n

TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release.

\n

The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface.

\n

TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand.

\n

TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter.

\n
\n

Changed#

\n
    \n
  • (#2204) Public documentation is now published from the dedicated tasknotes.dev repository. Plugin release notes and internal documentation remain in this repository.
  • \n
  • Updated compatibility with Obsidian's current plugin review and settings search.
  • \n
\n

Fixed#

\n
    \n
  • Fixed TaskNotes interface elements sometimes appearing in the wrong window when using Obsidian pop-out windows.
  • \n
  • Improved confirmation dialogs, icons, and modal styling to use Obsidian's current interface APIs.
  • \n
\n","text":"[!info] TaskNotes v5 beta TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release. The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface. TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand. TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter. Changed# (#2204) Public documentation is now published from the dedicated tasknotes.dev repository. Plugin release notes and internal documentation remain in this repository. Updated compatibility with Obsidian's current plugin review and settings search. Fixed# Fixed TaskNotes interface elements sometimes appearing in the wrong window when using Obsidian pop-out windows. Improved confirmation dialogs, icons, and modal styling to use Obsidian's current interface APIs."},{"route":"/obsidian/releases/4.12.2/","title":"TaskNotes 4.12.2","description":"[!info] TaskNotes v5 beta","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.12.2.md","namespace":"obsidian","relativePath":"releases/4.12.2.md","raw":"# TaskNotes 4.12.2\n\n> [!info] TaskNotes v5 beta\n>\n> [TaskNotes v5](https://github.com/callumalpass/tasknotes/releases/tag/5.0.0-beta.0) is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release.\n>\n> The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the [TaskNotes app](https://app.tasknotes.dev/), which is also available in beta, so the same tasks can be managed through either interface.\n>\n> TaskNotes collections are built on [mdbase](https://mdbase.dev/), a Markdown-native collection format. [mdbase Connect](https://mdbase.dev/connect/) provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand.\n>\n> TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and [report any problems you encounter](https://github.com/callumalpass/tasknotes/issues).\n\n## Fixed\n\n- (#2212) Fixed TaskNotes settings sections appearing pushed across the Obsidian settings pane on desktop. Thanks to @RafaQNunes for reporting this.\n","aliases":["/releases/4.12.2/","/releases/4.12.2/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"}],"html":"
\n

[!info] TaskNotes v5 beta

\n

TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release.

\n

The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface.

\n

TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand.

\n

TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter.

\n
\n

Fixed#

\n
    \n
  • (#2212) Fixed TaskNotes settings sections appearing pushed across the Obsidian settings pane on desktop. Thanks to @RafaQNunes for reporting this.
  • \n
\n","text":"[!info] TaskNotes v5 beta TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release. The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface. TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand. TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter. Fixed# (#2212) Fixed TaskNotes settings sections appearing pushed across the Obsidian settings pane on desktop. Thanks to @RafaQNunes for reporting this."},{"route":"/obsidian/releases/4.12.3/","title":"TaskNotes 4.12.3","description":"[!info] TaskNotes v5 beta","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.12.3.md","namespace":"obsidian","relativePath":"releases/4.12.3.md","raw":"# TaskNotes 4.12.3\n\n> [!info] TaskNotes v5 beta\n>\n> [TaskNotes v5](https://github.com/callumalpass/tasknotes/releases/tag/5.0.0-beta.0) is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release.\n>\n> The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the [TaskNotes app](https://app.tasknotes.dev/), which is also available in beta, so the same tasks can be managed through either interface.\n>\n> TaskNotes collections are built on [mdbase](https://mdbase.dev/), a Markdown-native collection format. [mdbase Connect](https://mdbase.dev/connect/) provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand.\n>\n> TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and [report any problems you encounter](https://github.com/callumalpass/tasknotes/issues).\n\n## Fixed\n\n- (#2212) Fixed TaskNotes settings sections appearing offscreen or blank on\n Obsidian 1.13 desktop. Thanks to @RafaQNunes for reporting this, and to\n @m4to-3pe and @matthewrishii for confirming it remained in 4.12.2.\n- (#2213) Runtime plugin-data updates now avoid writing when Obsidian cannot\n safely read an existing TaskNotes `data.json`, preventing calendar sync,\n Pomodoro, ICS, or auto-archive state writes from replacing saved settings.\n Thanks to @3zra47 for the follow-up details and file-history evidence.\n- (#2216) Fixed updated default Kanban Bases grouping every task into the\n `None` column when grouping by status. The generated Kanban templates now use\n the real status property, and existing Kanban files using `task.status` keep\n grouping from TaskNotes task data. Thanks to @Esvorst for reporting this.\n- (#2120, #2135) Long all-day event titles in Calendar week and day views now\n truncate in the all-day row instead of stretching it vertically. Thanks to\n @same774 and @ks-studio-net for reporting this, and to @Admorei for confirming\n it remained in 4.12.2.\n","aliases":["/releases/4.12.3/","/releases/4.12.3/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"}],"html":"
\n

[!info] TaskNotes v5 beta

\n

TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release.

\n

The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface.

\n

TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand.

\n

TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter.

\n
\n

Fixed#

\n
    \n
  • (#2212) Fixed TaskNotes settings sections appearing offscreen or blank on\nObsidian 1.13 desktop. Thanks to @RafaQNunes for reporting this, and to\n@m4to-3pe and @matthewrishii for confirming it remained in 4.12.2.
  • \n
  • (#2213) Runtime plugin-data updates now avoid writing when Obsidian cannot\nsafely read an existing TaskNotes data.json, preventing calendar sync,\nPomodoro, ICS, or auto-archive state writes from replacing saved settings.\nThanks to @3zra47 for the follow-up details and file-history evidence.
  • \n
  • (#2216) Fixed updated default Kanban Bases grouping every task into the\nNone column when grouping by status. The generated Kanban templates now use\nthe real status property, and existing Kanban files using task.status keep\ngrouping from TaskNotes task data. Thanks to @Esvorst for reporting this.
  • \n
  • (#2120, #2135) Long all-day event titles in Calendar week and day views now\ntruncate in the all-day row instead of stretching it vertically. Thanks to\n@same774 and @ks-studio-net for reporting this, and to @Admorei for confirming\nit remained in 4.12.2.
  • \n
\n","text":"[!info] TaskNotes v5 beta TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release. The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface. TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand. TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter. Fixed# (#2212) Fixed TaskNotes settings sections appearing offscreen or blank on Obsidian 1.13 desktop. Thanks to @RafaQNunes for reporting this, and to @m4to-3pe and @matthewrishii for confirming it remained in 4.12.2. (#2213) Runtime plugin-data updates now avoid writing when Obsidian cannot safely read an existing TaskNotes data.json, preventing calendar sync, Pomodoro, ICS, or auto-archive state writes from replacing saved settings. Thanks to @3zra47 for the follow-up details and file-history evidence. (#2216) Fixed updated default Kanban Bases grouping every task into the None column when grouping by status. The generated Kanban templates now use the real status property, and existing Kanban files using task.status keep grouping from TaskNotes task data. Thanks to @Esvorst for reporting this. (#2120, #2135) Long all-day event titles in Calendar week and day views now truncate in the all-day row instead of stretching it vertically. Thanks to @same774 and @ks-studio-net for reporting this, and to @Admorei for confirming it remained in 4.12.2."},{"route":"/obsidian/releases/4.12.4/","title":"TaskNotes 4.12.4","description":"[!info] TaskNotes v5 beta","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.12.4.md","namespace":"obsidian","relativePath":"releases/4.12.4.md","raw":"# TaskNotes 4.12.4\n\n> [!info] TaskNotes v5 beta\n>\n> [TaskNotes v5](https://github.com/callumalpass/tasknotes/releases/tag/5.0.0-beta.0) is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release.\n>\n> The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the [TaskNotes app](https://app.tasknotes.dev/), which is also available in beta, so the same tasks can be managed through either interface.\n>\n> TaskNotes collections are built on [mdbase](https://mdbase.dev/), a Markdown-native collection format. [mdbase Connect](https://mdbase.dev/connect/) provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand.\n>\n> TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and [report any problems you encounter](https://github.com/callumalpass/tasknotes/issues).\n\n## Changed\n\n- (#2187) Improved TaskNotes startup performance by allowing Bases registration to finish asynchronously. Thanks to @tgrosinger for the contribution.\n\n## Fixed\n\n- (#2232) Opening an occurrence note from a completion-anchored recurring task now\n uses the task's scheduled occurrence date instead of defaulting to today. Thanks\n to @chmac for reporting this.\n- (#2247) Creating a new inline task now removes nested wikilink and Markdown-link\n markup from the inserted task link's display text. Thanks to @bgk0018 for\n reporting this.\n- (#2231) Fixed Agenda views with `showOverdueOnToday` showing the same task twice\n when both its scheduled and due dates were overdue. Thanks to @takashit16833 for\n reporting this.\n- (#2206) The time entry editor now opens much faster for tasks with many tracked\n sessions by delaying the heavier description editor setup until a description\n field is focused. Thanks to @Sapere-Kyle for reporting this.\n- (#2239) Fixed Task List Bases embedded in mobile notes leaving a large blank gap\n after the final task card. Thanks to @same774 for reporting this and @prethrive\n for sharing a workaround.\n- (#2238) The Relationships widget now stays below long Live Preview Dataview\n tables and no longer appears twice after switching to Reading mode. Thanks to\n @Romek1769 for reporting this.\n- (#2250) Hardened Google Calendar task metadata updates: duplicate Google\n Calendar fields are now repaired atomically without replacing concurrent task\n edits, and synchronization finishing after a disconnect no longer writes stale\n event metadata. Thanks to @3zra47 for reporting the corrupted task data that\n prompted this review.\n- (#2229) Google Calendar OAuth authorization now opens in the system browser\n instead of Obsidian's Web Viewer, avoiding Google's 401 malformed-request\n page in the in-app browser. Thanks to @prethrive for reporting this and\n confirming the workaround.\n- Skipping a recurring task instance from Task List or Kanban now records the\n task's occurrence date instead of the view's current date. Thanks to\n @renatomen for the contribution.\n- (#2130) Tasks added by external sync while Obsidian is closed are now exported\n to Google Calendar after TaskNotes starts. Thanks to @seththepeacock for\n reporting this and @raphaelfaouakhiri for the contribution.\n- (#2246) Fixed materialized recurring occurrences hiding occurrence-template filename suffixes in TaskNotes views. Thanks to @raphaelfaouakhiri for reporting and fixing this issue.\n- (#2221) Fixed `PUT /api/tasks/:id` ignoring empty arrays for `contexts` and `blockedBy`: sending `{\"contexts\": []}` or `{\"blockedBy\": []}` now clears the corresponding frontmatter field instead of silently leaving the previous value in place. The deletion pass previously fired only on a literal `undefined`, which JSON cannot express, so HTTP clients had no way to clear these fields. Thanks to @tgrosinger for the contribution.\n- (#2191) Completing or skipping a recurring occurrence that was moved earlier\n than its original date no longer schedules that original date again. Thanks to\n @martin-forge for the contribution.\n- (#2193) Google Calendar event descriptions written with formatting now read as\n plain text in event details, copied text, and generated notes, instead of\n showing raw HTML tags. Paragraph breaks, list structure, and link addresses are\n kept. Thanks to @martin-forge for the contribution.\n- (#2192) Agenda and list cards for Google and Microsoft calendar events now\n show the name of the calendar the event belongs to, instead of the generic\n \"Calendar\" label. Thanks to @martin-forge for the contribution.\n","aliases":["/releases/4.12.4/","/releases/4.12.4/"],"toc":[{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"
\n

[!info] TaskNotes v5 beta

\n

TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release.

\n

The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface.

\n

TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand.

\n

TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter.

\n
\n

Changed#

\n
    \n
  • (#2187) Improved TaskNotes startup performance by allowing Bases registration to finish asynchronously. Thanks to @tgrosinger for the contribution.
  • \n
\n

Fixed#

\n
    \n
  • (#2232) Opening an occurrence note from a completion-anchored recurring task now\nuses the task's scheduled occurrence date instead of defaulting to today. Thanks\nto @chmac for reporting this.
  • \n
  • (#2247) Creating a new inline task now removes nested wikilink and Markdown-link\nmarkup from the inserted task link's display text. Thanks to @bgk0018 for\nreporting this.
  • \n
  • (#2231) Fixed Agenda views with showOverdueOnToday showing the same task twice\nwhen both its scheduled and due dates were overdue. Thanks to @takashit16833 for\nreporting this.
  • \n
  • (#2206) The time entry editor now opens much faster for tasks with many tracked\nsessions by delaying the heavier description editor setup until a description\nfield is focused. Thanks to @Sapere-Kyle for reporting this.
  • \n
  • (#2239) Fixed Task List Bases embedded in mobile notes leaving a large blank gap\nafter the final task card. Thanks to @same774 for reporting this and @prethrive\nfor sharing a workaround.
  • \n
  • (#2238) The Relationships widget now stays below long Live Preview Dataview\ntables and no longer appears twice after switching to Reading mode. Thanks to\n@Romek1769 for reporting this.
  • \n
  • (#2250) Hardened Google Calendar task metadata updates: duplicate Google\nCalendar fields are now repaired atomically without replacing concurrent task\nedits, and synchronization finishing after a disconnect no longer writes stale\nevent metadata. Thanks to @3zra47 for reporting the corrupted task data that\nprompted this review.
  • \n
  • (#2229) Google Calendar OAuth authorization now opens in the system browser\ninstead of Obsidian's Web Viewer, avoiding Google's 401 malformed-request\npage in the in-app browser. Thanks to @prethrive for reporting this and\nconfirming the workaround.
  • \n
  • Skipping a recurring task instance from Task List or Kanban now records the\ntask's occurrence date instead of the view's current date. Thanks to\n@renatomen for the contribution.
  • \n
  • (#2130) Tasks added by external sync while Obsidian is closed are now exported\nto Google Calendar after TaskNotes starts. Thanks to @seththepeacock for\nreporting this and @raphaelfaouakhiri for the contribution.
  • \n
  • (#2246) Fixed materialized recurring occurrences hiding occurrence-template filename suffixes in TaskNotes views. Thanks to @raphaelfaouakhiri for reporting and fixing this issue.
  • \n
  • (#2221) Fixed PUT /api/tasks/:id ignoring empty arrays for contexts and blockedBy: sending {"contexts": []} or {"blockedBy": []} now clears the corresponding frontmatter field instead of silently leaving the previous value in place. The deletion pass previously fired only on a literal undefined, which JSON cannot express, so HTTP clients had no way to clear these fields. Thanks to @tgrosinger for the contribution.
  • \n
  • (#2191) Completing or skipping a recurring occurrence that was moved earlier\nthan its original date no longer schedules that original date again. Thanks to\n@martin-forge for the contribution.
  • \n
  • (#2193) Google Calendar event descriptions written with formatting now read as\nplain text in event details, copied text, and generated notes, instead of\nshowing raw HTML tags. Paragraph breaks, list structure, and link addresses are\nkept. Thanks to @martin-forge for the contribution.
  • \n
  • (#2192) Agenda and list cards for Google and Microsoft calendar events now\nshow the name of the calendar the event belongs to, instead of the generic\n"Calendar" label. Thanks to @martin-forge for the contribution.
  • \n
\n","text":"[!info] TaskNotes v5 beta TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release. The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface. TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand. TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter. Changed# (#2187) Improved TaskNotes startup performance by allowing Bases registration to finish asynchronously. Thanks to @tgrosinger for the contribution. Fixed# (#2232) Opening an occurrence note from a completion-anchored recurring task now uses the task's scheduled occurrence date instead of defaulting to today. Thanks to @chmac for reporting this. (#2247) Creating a new inline task now removes nested wikilink and Markdown-link markup from the inserted task link's display text. Thanks to @bgk0018 for reporting this. (#2231) Fixed Agenda views with showOverdueOnToday showing the same task twice when both its scheduled and due dates were overdue. Thanks to @takashit16833 for reporting this. (#2206) The time entry editor now opens much faster for tasks with many tracked sessions by delaying the heavier description editor setup until a description field is focused. Thanks to @Sapere-Kyle for reporting this. (#2239) Fixed Task List Bases embedded in mobile notes leaving a large blank gap after the final task card. Thanks to @same774 for reporting this and @prethrive for sharing a workaround. (#2238) The Relationships widget now stays below long Live Preview Dataview tables and no longer appears twice after switching to Reading mode. Thanks to @Romek1769 for reporting this. (#2250) Hardened Google Calendar task metadata updates: duplicate Google Calendar fields are now repaired atomically without replacing concurrent task edits, and synchronization finishing after a disconnect no longer writes stale event metadata. Thanks to @3zra47 for reporting the corrupted task data that prompted this review. (#2229) Google Calendar OAuth authorization now opens in the system browser instead of Obsidian's Web Viewer, avoiding Google's 401 malformed-request page in the in-app browser. Thanks to @prethrive for reporting this and confirming the workaround. Skipping a recurring task instance from Task List or Kanban now records the task's occurrence date instead of the view's current date. Thanks to @renatomen for the contribution. (#2130) Tasks added by external sync while Obsidian is closed are now exported to Google Calendar after TaskNotes starts. Thanks to @seththepeacock for reporting this and @raphaelfaouakhiri for the contribution. (#2246) Fixed materialized recurring occurrences hiding occurrence-template filename suffixes in TaskNotes views. Thanks to @raphaelfaouakhiri for reporting and fixing this issue. (#2221) Fixed PUT /api/tasks/:id ignoring empty arrays for contexts and blockedBy: sending {\"contexts\": []} or {\"blockedBy\": []} now clears the corresponding frontmatter field instead of silently leaving the previous value in place. The deletion pass previously fired only on a literal undefined, which JSON cannot express, so HTTP clients had no way to clear these fields. Thanks to @tgrosinger for the contribution. (#2191) Completing or skipping a recurring occurrence that was moved earlier than its original date no longer schedules that original date again. Thanks to @martin-forge for the contribution. (#2193) Google Calendar event descriptions written with formatting now read as plain text in event details, copied text, and generated notes, instead of showing raw HTML tags. Paragraph breaks, list structure, and link addresses are kept. Thanks to @martin-forge for the contribution. (#2192) Agenda and list cards for Google and Microsoft calendar events now show the name of the calendar the event belongs to, instead of the generic \"Calendar\" label. Thanks to @martin-forge for the contribution."},{"route":"/obsidian/releases/4.12.5/","title":"TaskNotes 4.12.5","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.12.5.md","namespace":"obsidian","relativePath":"releases/4.12.5.md","raw":"# TaskNotes 4.12.5\n\n## Fixed\n\n- (#2255) Notes with an in-note task card no longer jump while scrolling in reading mode. The card is now restored only after scrolling settles instead of being re-injected every frame against Obsidian's virtualised reading view. Thanks to @logicelf for the detailed diagnosis.\n- (#2256) Kanban swimlane order now follows the view's sort configuration again: with a formula or property sort applied, the swimlane holding the top-sorted task floats to the top of the board as it did before the swimlane ordering option was introduced. Thanks to @tsweezy for reporting this.\n- (#2222) The TaskNotes settings tab bar now wraps to a second line instead of clipping the Integrations tab beside the documentation link on narrow settings panes. Thanks to @nextstitch and @YongcaiHuang for reporting this.\n","aliases":["/releases/4.12.5/","/releases/4.12.5/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Fixed#

\n
    \n
  • (#2255) Notes with an in-note task card no longer jump while scrolling in reading mode. The card is now restored only after scrolling settles instead of being re-injected every frame against Obsidian's virtualised reading view. Thanks to @logicelf for the detailed diagnosis.
  • \n
  • (#2256) Kanban swimlane order now follows the view's sort configuration again: with a formula or property sort applied, the swimlane holding the top-sorted task floats to the top of the board as it did before the swimlane ordering option was introduced. Thanks to @tsweezy for reporting this.
  • \n
  • (#2222) The TaskNotes settings tab bar now wraps to a second line instead of clipping the Integrations tab beside the documentation link on narrow settings panes. Thanks to @nextstitch and @YongcaiHuang for reporting this.
  • \n
\n","text":"Fixed# (#2255) Notes with an in-note task card no longer jump while scrolling in reading mode. The card is now restored only after scrolling settles instead of being re-injected every frame against Obsidian's virtualised reading view. Thanks to @logicelf for the detailed diagnosis. (#2256) Kanban swimlane order now follows the view's sort configuration again: with a formula or property sort applied, the swimlane holding the top-sorted task floats to the top of the board as it did before the swimlane ordering option was introduced. Thanks to @tsweezy for reporting this. (#2222) The TaskNotes settings tab bar now wraps to a second line instead of clipping the Integrations tab beside the documentation link on narrow settings panes. Thanks to @nextstitch and @YongcaiHuang for reporting this."},{"route":"/obsidian/releases/4.13.0/","title":"TaskNotes 4.13.0","description":"HTTP API and MCP clients now require authentication. If you previously connected without a token, copy the API token from Settings → TaskNotes → Integrations into your client...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.13.0.md","namespace":"obsidian","relativePath":"releases/4.13.0.md","raw":"# TaskNotes 4.13.0\n\n## Before updating\n\n**HTTP API and MCP clients now require authentication.** If you previously connected without a token, copy the API token from **Settings → TaskNotes → Integrations** into your client's authentication settings. Requests must include `Authorization: Bearer `. If the token is empty when the server starts, TaskNotes generates and saves one; leaving it empty no longer disables authentication. See [HTTP API](https://tasknotes.dev/HTTP_API/).\n\n## Security\n\n- (#2292) Required authentication for local API/MCP listeners. OAuth callbacks now use an OS-assigned loopback port, accept each authorization state only once, and return fixed pages without reflecting callback text. Thanks to @martin-forge for the hardening.\n\n## Added\n\n- Added a dedicated TaskNotes v5 and app beta section to the plugin's release notes, including instructions for joining the Android test. The announcement appears once rather than repeating inside individual versions.\n- (#2147) Added context-menu actions for recording task completion today, on the scheduled date, on the due date, or on a chosen date. The actions can be grouped in a submenu from Appearance settings. See [Completing Tasks](https://tasknotes.dev/features/task-management/#completing-tasks).\n - Rescheduling a recurring task can reactivate affected completed or skipped instances after confirmation. See [Recurring Tasks](https://tasknotes.dev/features/recurring-tasks/).\n - Completion-date actions, submenu settings, and rescheduling confirmations are translated into all supported languages.\n - Thanks to @renatomen for the contribution.\n\n## Fixed\n\n- (#2291) Preserved background task updates when saving an older task edit window, including recurring completion history and properties changed or removed elsewhere. Thanks to @martin-forge for the fix.\n- (#2294) Stopped plugin startup when an existing settings file cannot be read, preserving it for recovery instead of starting services with default settings. Thanks to @GGlider for reporting settings loss in #1591 and @martin-forge for the fix.\n- (#2322) Fixed metadata edits deleting the saved title when a filename cannot represent it, such as for long titles. Existing title properties are preserved on unrelated edits; this does not recover previously deleted titles. Thanks to @1dezer1 for reporting.\n- (#2255, #2300) Fixed task cards repeatedly disappearing and being restored while scrolling in Reading mode, which could pull the note down to the bottom. Thanks to @logicelf for the diagnosis and @nelsonlove for the fix.\n- (#2318) Kept calendar events chronological when a Base sort is configured, using Base order for tasks at the same time. Thanks to @ky1ejs for reporting #1411 and @martin-forge for the fix.\n- (#2319) Avoided duplicate recurring-task projections when TaskNotes has recorded the original occurrence date of a calendar move. Completion and skip history remain visible when requested. Other move cases are unchanged. Thanks to @martin-forge for the fix.\n- (#2309) Fixed Google calendars enabled through the `primary` alias using the wrong color, ignoring visibility toggles, or losing their calendar name on event cards and linked notes. Thanks to @martin-forge for the fix.\n- (#2279) Fixed Google Calendar authorization stalling when the system browser opens but does not report back that it launched. Authorization now completes or times out independently, and overlapping attempts cannot stop the active connection attempt. Thanks to @DamienDLR for the diagnosis.\n- (#2298, #2299) Kept timed recurrence anchors when saving custom recurrence or completing a completion-anchored instance. Timed anchors are written with `Z` and retain their time, including seconds, without a device-timezone conversion. Date-only rules and scheduled-anchor completion are unchanged. See [Recurring Tasks](https://tasknotes.dev/features/recurring-tasks/). Thanks to @wellsbk1 for reporting.\n- (#2043, #2055) Fixed tasks created with the default Subtasks view's **+** button missing their project and immediately disappearing from the view. Thanks to @kudrmax for reporting and @ther12k for the initial fix.\n- (#2284) Prevented repeated activation of instant checkbox conversion from creating duplicate TaskNotes while the first conversion is still in progress. Thanks to @doyoonear for reporting.\n- (#2314) Fixed rescheduled ICS recurring events appearing at their original time and cancelled occurrences remaining visible. Thanks to @benschifman for reporting.\n- (#1849) Fixed context menus stacking on top of each other. Only one menu stays open at a time, and clicking the same indicator again closes its menu. This previously applied to date fields only, and now covers priority, status, recurrence, reminders, task, ICS event, and batch menus. Thanks to @3zra47 for reporting and @YBKF for the contribution.\n- (#2303) Removed the extra space after inline task links on desktop while retaining the task menu on touch devices. Thanks to @nelsonlove for the fix.\n\n## Changed\n\n- (#2316) Clarified the Google OAuth Desktop app setup and redirect-mismatch troubleshooting, including why fixed Web application redirect URLs are not reliable with dynamic callback ports. See [Calendar Setup](https://tasknotes.dev/calendar-setup/). Thanks to @TomaszGaweda for reporting and following up.\n","aliases":["/releases/4.13.0/","/releases/4.13.0/"],"toc":[{"level":2,"id":"before-updating","text":"Before updating"},{"level":2,"id":"security","text":"Security"},{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"changed","text":"Changed"}],"html":"

Before updating#

\n

HTTP API and MCP clients now require authentication. If you previously connected without a token, copy the API token from Settings → TaskNotes → Integrations into your client's authentication settings. Requests must include Authorization: Bearer <token>. If the token is empty when the server starts, TaskNotes generates and saves one; leaving it empty no longer disables authentication. See HTTP API.

\n

Security#

\n
    \n
  • (#2292) Required authentication for local API/MCP listeners. OAuth callbacks now use an OS-assigned loopback port, accept each authorization state only once, and return fixed pages without reflecting callback text. Thanks to @martin-forge for the hardening.
  • \n
\n

Added#

\n
    \n
  • Added a dedicated TaskNotes v5 and app beta section to the plugin's release notes, including instructions for joining the Android test. The announcement appears once rather than repeating inside individual versions.
  • \n
  • (#2147) Added context-menu actions for recording task completion today, on the scheduled date, on the due date, or on a chosen date. The actions can be grouped in a submenu from Appearance settings. See Completing Tasks.
      \n
    • Rescheduling a recurring task can reactivate affected completed or skipped instances after confirmation. See Recurring Tasks.
    • \n
    • Completion-date actions, submenu settings, and rescheduling confirmations are translated into all supported languages.
    • \n
    • Thanks to @renatomen for the contribution.
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#2291) Preserved background task updates when saving an older task edit window, including recurring completion history and properties changed or removed elsewhere. Thanks to @martin-forge for the fix.
  • \n
  • (#2294) Stopped plugin startup when an existing settings file cannot be read, preserving it for recovery instead of starting services with default settings. Thanks to @GGlider for reporting settings loss in #1591 and @martin-forge for the fix.
  • \n
  • (#2322) Fixed metadata edits deleting the saved title when a filename cannot represent it, such as for long titles. Existing title properties are preserved on unrelated edits; this does not recover previously deleted titles. Thanks to @1dezer1 for reporting.
  • \n
  • (#2255, #2300) Fixed task cards repeatedly disappearing and being restored while scrolling in Reading mode, which could pull the note down to the bottom. Thanks to @logicelf for the diagnosis and @nelsonlove for the fix.
  • \n
  • (#2318) Kept calendar events chronological when a Base sort is configured, using Base order for tasks at the same time. Thanks to @ky1ejs for reporting #1411 and @martin-forge for the fix.
  • \n
  • (#2319) Avoided duplicate recurring-task projections when TaskNotes has recorded the original occurrence date of a calendar move. Completion and skip history remain visible when requested. Other move cases are unchanged. Thanks to @martin-forge for the fix.
  • \n
  • (#2309) Fixed Google calendars enabled through the primary alias using the wrong color, ignoring visibility toggles, or losing their calendar name on event cards and linked notes. Thanks to @martin-forge for the fix.
  • \n
  • (#2279) Fixed Google Calendar authorization stalling when the system browser opens but does not report back that it launched. Authorization now completes or times out independently, and overlapping attempts cannot stop the active connection attempt. Thanks to @DamienDLR for the diagnosis.
  • \n
  • (#2298, #2299) Kept timed recurrence anchors when saving custom recurrence or completing a completion-anchored instance. Timed anchors are written with Z and retain their time, including seconds, without a device-timezone conversion. Date-only rules and scheduled-anchor completion are unchanged. See Recurring Tasks. Thanks to @wellsbk1 for reporting.
  • \n
  • (#2043, #2055) Fixed tasks created with the default Subtasks view's + button missing their project and immediately disappearing from the view. Thanks to @kudrmax for reporting and @ther12k for the initial fix.
  • \n
  • (#2284) Prevented repeated activation of instant checkbox conversion from creating duplicate TaskNotes while the first conversion is still in progress. Thanks to @doyoonear for reporting.
  • \n
  • (#2314) Fixed rescheduled ICS recurring events appearing at their original time and cancelled occurrences remaining visible. Thanks to @benschifman for reporting.
  • \n
  • (#1849) Fixed context menus stacking on top of each other. Only one menu stays open at a time, and clicking the same indicator again closes its menu. This previously applied to date fields only, and now covers priority, status, recurrence, reminders, task, ICS event, and batch menus. Thanks to @3zra47 for reporting and @YBKF for the contribution.
  • \n
  • (#2303) Removed the extra space after inline task links on desktop while retaining the task menu on touch devices. Thanks to @nelsonlove for the fix.
  • \n
\n

Changed#

\n
    \n
  • (#2316) Clarified the Google OAuth Desktop app setup and redirect-mismatch troubleshooting, including why fixed Web application redirect URLs are not reliable with dynamic callback ports. See Calendar Setup. Thanks to @TomaszGaweda for reporting and following up.
  • \n
\n","text":"Before updating# HTTP API and MCP clients now require authentication. If you previously connected without a token, copy the API token from Settings → TaskNotes → Integrations into your client's authentication settings. Requests must include Authorization: Bearer . If the token is empty when the server starts, TaskNotes generates and saves one; leaving it empty no longer disables authentication. See HTTP API. Security# (#2292) Required authentication for local API/MCP listeners. OAuth callbacks now use an OS-assigned loopback port, accept each authorization state only once, and return fixed pages without reflecting callback text. Thanks to @martin-forge for the hardening. Added# Added a dedicated TaskNotes v5 and app beta section to the plugin's release notes, including instructions for joining the Android test. The announcement appears once rather than repeating inside individual versions. (#2147) Added context-menu actions for recording task completion today, on the scheduled date, on the due date, or on a chosen date. The actions can be grouped in a submenu from Appearance settings. See Completing Tasks. Rescheduling a recurring task can reactivate affected completed or skipped instances after confirmation. See Recurring Tasks. Completion-date actions, submenu settings, and rescheduling confirmations are translated into all supported languages. Thanks to @renatomen for the contribution. Fixed# (#2291) Preserved background task updates when saving an older task edit window, including recurring completion history and properties changed or removed elsewhere. Thanks to @martin-forge for the fix. (#2294) Stopped plugin startup when an existing settings file cannot be read, preserving it for recovery instead of starting services with default settings. Thanks to @GGlider for reporting settings loss in #1591 and @martin-forge for the fix. (#2322) Fixed metadata edits deleting the saved title when a filename cannot represent it, such as for long titles. Existing title properties are preserved on unrelated edits; this does not recover previously deleted titles. Thanks to @1dezer1 for reporting. (#2255, #2300) Fixed task cards repeatedly disappearing and being restored while scrolling in Reading mode, which could pull the note down to the bottom. Thanks to @logicelf for the diagnosis and @nelsonlove for the fix. (#2318) Kept calendar events chronological when a Base sort is configured, using Base order for tasks at the same time. Thanks to @ky1ejs for reporting #1411 and @martin-forge for the fix. (#2319) Avoided duplicate recurring-task projections when TaskNotes has recorded the original occurrence date of a calendar move. Completion and skip history remain visible when requested. Other move cases are unchanged. Thanks to @martin-forge for the fix. (#2309) Fixed Google calendars enabled through the primary alias using the wrong color, ignoring visibility toggles, or losing their calendar name on event cards and linked notes. Thanks to @martin-forge for the fix. (#2279) Fixed Google Calendar authorization stalling when the system browser opens but does not report back that it launched. Authorization now completes or times out independently, and overlapping attempts cannot stop the active connection attempt. Thanks to @DamienDLR for the diagnosis. (#2298, #2299) Kept timed recurrence anchors when saving custom recurrence or completing a completion-anchored instance. Timed anchors are written with Z and retain their time, including seconds, without a device-timezone conversion. Date-only rules and scheduled-anchor completion are unchanged. See Recurring Tasks. Thanks to @wellsbk1 for reporting. (#2043, #2055) Fixed tasks created with the default Subtasks view's + button missing their project and immediately disappearing from the view. Thanks to @kudrmax for reporting and @ther12k for the initial fix. (#2284) Prevented repeated activation of instant checkbox conversion from creating duplicate TaskNotes while the first conversion is still in progress. Thanks to @doyoonear for reporting. (#2314) Fixed rescheduled ICS recurring events appearing at their original time and cancelled occurrences remaining visible. Thanks to @benschifman for reporting. (#1849) Fixed context menus stacking on top of each other. Only one menu stays open at a time, and clicking the same indicator again closes its menu. This previously applied to date fields only, and now covers priority, status, recurrence, reminders, task, ICS event, and batch menus. Thanks to @3zra47 for reporting and @YBKF for the contribution. (#2303) Removed the extra space after inline task links on desktop while retaining the task menu on touch devices. Thanks to @nelsonlove for the fix. Changed# (#2316) Clarified the Google OAuth Desktop app setup and redirect-mismatch troubleshooting, including why fixed Web application redirect URLs are not reliable with dynamic callback ports. See Calendar Setup. Thanks to @TomaszGaweda for reporting and following up."},{"route":"/obsidian/releases/4.2.0/","title":"TaskNotes 4.2.0","description":"Added Korean (한국어) language support","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.2.0.md","namespace":"obsidian","relativePath":"releases/4.2.0.md","raw":"# TaskNotes 4.2.0\n\n## Added\n\n- Added Korean (한국어) language support\n - Full translation of all 1911 localization keys\n - Korean language option now available in Settings → General → Language\n\n- Adopted Obsidian 1.11.0 API features with backwards compatibility\n - Settings tab now displays TaskNotes icon in the sidebar (Obsidian 1.11.0+)\n - Settings sections now use native `SettingGroup` for improved visual grouping (Obsidian 1.11.0+)\n - Falls back gracefully to traditional section headers on older Obsidian versions\n\n- (#59) Added `shortYear` template variable for custom filename and folder templates\n - Use `{shortYear}` in filename templates (e.g., \"25\" for 2025)\n - Use `{{shortYear}}` in folder templates\n - Thanks to @Pixeltica for the feature request\n\n- (#1393) Option to prevent auto-creation of default Base view files on startup\n - New \"Auto-create default files\" toggle in Settings → Integrations → Bases Integration\n - When disabled, deleted sample Base files will not be recreated on plugin load\n - The manual \"Create Default Files\" button remains available for on-demand recreation\n - Thanks to @wealthychef1 for the feature request\n\n- (#1408) Shift+click on status icon to cycle backwards through statuses\n - Normal click cycles forward through status order\n - Shift+click cycles in reverse order\n - Thanks to @JerryLu086 for the feature request\n\n- (#1410) Task creation modal now starts in vim insert mode when vim keybindings are enabled\n - Previously required pressing 'i' before typing when Obsidian vim mode was active\n - The modal now automatically enters insert mode on focus, allowing immediate typing\n - Thanks to @Leo310 for the feature request\n\n- Added button tooltips to calendar view toolbar\n - Hovering over navigation and view buttons now shows descriptive hints\n - Buttons include: Today, Previous, Next, Month, Week, Day, Year, List\n\n- Added tooltips to task modal action icons\n - Icon buttons for status, date, project, priority, recurrence, and reminder now show tooltips on hover\n - Improves discoverability for new users\n\n- (#503) Settings now sync automatically across devices via Obsidian Sync\n - Changes to custom statuses, priorities, and other settings apply immediately without restart\n - Thanks to @jhedlund for the feature request and @l-mb for the implementation\n\n- (#1403) Kanban view option to consolidate status icons in column headers\n - New \"Show status icon in column header only\" toggle in Kanban view settings (disabled by default)\n - When enabled and grouped by status, shows the icon in the column header and hides it on cards\n - Reduces visual redundancy when the column already indicates the status\n - Thanks to @l-mb for the feature request and implementation\n\n- (#1401) Calendar view option to span tasks between scheduled and due dates\n - New \"Span tasks between scheduled and due dates\" toggle in Calendar view Layout settings\n - When enabled, tasks with both scheduled and due dates display as multi-day bars\n - Provides Gantt chart-style visualization for project planning\n - Thanks to @0atman for the feature request\n\n- (#1334) `{{currentNotePath}}` now works for \"Create new inline task\" command\n - The inline task folder setting with `{{currentNotePath}}` previously only worked for checkbox conversion\n - Now also applies when using the \"Create new inline task\" command from the command palette\n - Thanks to @kmaustral for the feature request\n\n- (#1264) Option to open Pomodoro timer in mobile sidebar instead of note panel\n - New \"Mobile sidebar\" setting in Settings → Features → Pomodoro Timer\n - Choose between: Note panel (default tab behavior), Left sidebar, or Right sidebar\n - Allows quick swipe access to the timer without switching notes on mobile devices\n - Thanks to @Evthestrike for the feature request\n\n- (#1220) Option to use ICS event end time as task due date\n - New \"Use ICS event end time as task due date\" toggle in Settings → Integrations → Calendar Subscriptions\n - When enabled, tasks created from calendar events will have their due date set to the event's end time\n - For all-day events, uses the event date (not the ICS container end date which is the next day per ICS spec)\n - For timed events, includes the exact end time\n - Defaults to disabled to preserve existing behavior\n - Thanks to @MiserMagus for the feature request\n\n- (#1108) Option to use task duration instead of due date for ICS calendar export\n - New \"Use task duration for event length\" toggle in Settings → Integrations → Automatic ICS Export\n - When enabled, exported calendar events use scheduled date + time estimate as DTSTART/DTEND\n - This aligns with GTD workflows where scheduled + duration represents work planning, while due date represents deadlines\n - When disabled (default), preserves existing behavior using due date as DTEND\n - Thanks to @bepolymathe for the feature request\n\n## Fixed\n\n- (#1421) Fixed natural language parser only capturing one date when both scheduled and due dates are specified\n - Input like \"Task scheduled for tomorrow due next week\" now correctly sets both scheduled and due dates\n - Previously the parser would return early after finding the first date trigger, ignoring any subsequent triggers\n - Thanks to @wealthychef1 for reporting\n\n- (#1384) Fixed title being sanitized even when \"Store Task Title in Filename\" is disabled\n - Characters like `?`, `<`, `>`, `:`, etc. are now preserved in task titles when they won't be used in filenames\n - When `storeTitleInFilename` is false, only minimal sanitization (whitespace normalization, control character removal) is applied\n - Thanks to @allison-casey for reporting\n\n- (#1028), (#1140), (#1152), (#1354), (#1362) Fixed duplicate task entries appearing in Agenda view\n - Tasks were shown twice: once as TaskNotes events and again as property-based events with a file icon\n - Changed default Agenda template to disable property-based events (`showPropertyBasedEvents: false`)\n - Users can re-enable property-based events in view settings if needed for non-task date properties\n - Thanks to @YIRU69, @jhedlund, @dblinnikov, @Snakiest, @WeiYiAcc, @JacksonMcDonaldDev, @jimbo108108, and @krelltunez for reporting\n\n- (#1386) Fixed `timeEstimateCategory` formula showing \"Long (>2h)\" instead of \"No estimate\" for new tasks\n - The condition didn't properly handle null values when `timeEstimate` property is unset\n - Also fixed the same issue in `trackingStatus` formula\n - Thanks to @nicou for reporting and @osxisl for the PR\n\n- (#1397) Fixed Bases views (Kanban, Calendar, Task List) resetting to Calendar view after a few minutes\n - Also fixed CalendarView corrupting other view files when saving state on unload\n - Thanks to @music-soul1-1 for reporting\n\n- (#1398) Fixed overdue strikethrough showing on completed tasks\n - Completed tasks with past due dates no longer display overdue styling \n - Respects the \"Hide completed from overdue\" setting which defaults to true\n\n- (#1363) Fixed calendar view showing nothing when a task has an invalid date format\n - Tasks with malformed dates (e.g., \"262025-12-16\" instead of \"2025-12-16\") no longer crash the entire calendar\n - Invalid tasks are now skipped with a console warning, allowing other events to display normally\n - Thanks to @Erelen for reporting\n\n- Fixed today column in week/day calendar views using FullCalendar's default yellow instead of theme accent\n - Today's column now uses a tint of the theme accent color for consistent styling\n\n- (#1399) Fixed drag-and-drop not working in Kanban view on mobile\n - Cards and columns can now be dragged using long-press gesture on touch devices\n - Includes haptic feedback and auto-scroll when dragging near edges\n - Thanks to @l-mb for reporting and the fix\n\n- (#1381) Fixed Pomodoro \"Change Task\" menu not showing newly created tasks\n - Tasks created while the Pomodoro view was open would not appear in the task selector\n - Improved metadata cache synchronization to properly wait for new files to be indexed\n - Thanks to @Ghosthael for reporting\n\n- (#1344) Fixed \"Unsaved Changes\" popup appearing randomly when closing task edit modal\n - The popup would appear even when no changes were made to the task\n - Caused by inconsistent trailing whitespace normalization when comparing details content\n - Thanks to @hasanyilmaz for reporting\n\n- (#1402) Fixed Kanban swimlane view showing tasks in wrong column when grouped by formula\n - After editing task metadata, cards would jump to \"None\" column until Obsidian reload\n - Column assignment now uses Bases' computed grouping instead of cached formula outputs\n - Thanks to @bailob for the fix\n\n- (#1352) Fixed date context menu not preserving time when using increment options\n - Using +1 day, -1 day, +1 week, or -1 week on a task with a time (e.g., `2025-12-10T16:00`) now preserves the time\n - Previously the time would be stripped, changing `2025-12-10T16:00` to `2025-12-11` instead of `2025-12-11T16:00`\n - Thanks to @cathywu for the feature request\n\n- Fixed v3 saved views exporting incorrectly to Bases format\n - Title filters now correctly use `file.name` instead of `note.title`\n - Archived filters now generate valid boolean expressions instead of malformed comparisons\n - \"Is Blocked\" filters now generate correct expressions with proper operator precedence\n\n- (#1036) Due dates can now be dragged in the calendar view\n - Previously only scheduled dates were draggable; due dates were locked in place\n - Dragging a due event now updates the task's due date property\n - Thanks to @same774 for reporting\n\n- Improved calendar view responsiveness for user interactions\n - Task creation, editing, timeblock changes, and view option toggles now update immediately\n - Previously these actions waited 5 seconds due to the debounce intended for external file changes\n - The 5-second debounce is now bypassed for direct user actions while still preventing flicker during typing\n\n- Improved visual affordance for Pomodoro timer duration adjustment buttons\n - The +/- buttons below the timer now have visible backgrounds and borders\n - Hover states show accent color border for clearer interactivity feedback\n - Previously buttons were nearly invisible with transparent backgrounds\n\n- (#1409), (#1214), (#979) Improved Calendar, Agenda, Kanban, and Stats views in pop-out windows\n - Drag-and-drop in Kanban view now works correctly when the view is in a new window\n - Context menus (status, priority, task) now work correctly in pop-out windows\n - Stats view drill-down modal now appears in the correct window\n - Search boxes, task cards, and grouped task lists render correctly\n - Root cause: Code was using global `document` and standard `instanceof` checks which fail across windows\n - Solution: Use `ownerDocument` for DOM operations and Obsidian's cross-window `instanceOf()` method\n - **Known limitation**: Calendar event dragging does not work in pop-out windows due to FullCalendar library using global `document` for mouse event listeners. Use context menus or edit modals as a workaround.\n - Updated FullCalendar to v6.1.20\n - Thanks to @Snakiest, @same774, and @3zra47 for reporting\n\n- (#1337) Fixed \"Convert current note to task\" hotkey not applying default values from settings\n - When user configured default status/priority as \"None\", the modal would show \"Open\" and \"Normal\" instead\n - Root cause: Task edit modal was refreshing data from file and overwriting user-configured defaults\n - Now preserves constructor-provided task data when converting non-task files\n - Thanks to @guihasparyk for reporting\n\n- (#1304) Fixed \"Cannot find function map on type Link\" error in Blocking view\n - Error occurred when embedding the Relationships base and opening the Blocking view\n - Root cause: When `blockedBy` contained a single dependency, Bases returned it as a Link object without a `.map()` method\n - Fixed by wrapping `blockedBy` with `list()` before calling `.map()`, consistent with the Blocked By view\n - Thanks to @prayidae for reporting\n\n- (#1295) Fixed missing navigation link to Default Base Templates page on tasknotes.dev\n - The page existed but was not accessible from the site navigation\n - Thanks to @Arachnidai for reporting\n\n- (#1223) Fixed \"Go to today's note\" command opening wrong date in positive UTC offset timezones\n - In timezones like Japan (UTC+9), early morning use of this command opened yesterday's note\n - Root cause: Incorrectly extracting UTC date components instead of local timezone date\n - Thanks to @BrucePlumb for reporting\n","aliases":["/releases/4.2.0/","/releases/4.2.0/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • Added Korean (한국어) language support

    \n
      \n
    • Full translation of all 1911 localization keys
    • \n
    • Korean language option now available in Settings → General → Language
    • \n
    \n
  • \n
  • Adopted Obsidian 1.11.0 API features with backwards compatibility

    \n
      \n
    • Settings tab now displays TaskNotes icon in the sidebar (Obsidian 1.11.0+)
    • \n
    • Settings sections now use native SettingGroup for improved visual grouping (Obsidian 1.11.0+)
    • \n
    • Falls back gracefully to traditional section headers on older Obsidian versions
    • \n
    \n
  • \n
  • (#59) Added shortYear template variable for custom filename and folder templates

    \n
      \n
    • Use {shortYear} in filename templates (e.g., "25" for 2025)
    • \n
    • Use {{shortYear}} in folder templates
    • \n
    • Thanks to @Pixeltica for the feature request
    • \n
    \n
  • \n
  • (#1393) Option to prevent auto-creation of default Base view files on startup

    \n
      \n
    • New "Auto-create default files" toggle in Settings → Integrations → Bases Integration
    • \n
    • When disabled, deleted sample Base files will not be recreated on plugin load
    • \n
    • The manual "Create Default Files" button remains available for on-demand recreation
    • \n
    • Thanks to @wealthychef1 for the feature request
    • \n
    \n
  • \n
  • (#1408) Shift+click on status icon to cycle backwards through statuses

    \n
      \n
    • Normal click cycles forward through status order
    • \n
    • Shift+click cycles in reverse order
    • \n
    • Thanks to @JerryLu086 for the feature request
    • \n
    \n
  • \n
  • (#1410) Task creation modal now starts in vim insert mode when vim keybindings are enabled

    \n
      \n
    • Previously required pressing 'i' before typing when Obsidian vim mode was active
    • \n
    • The modal now automatically enters insert mode on focus, allowing immediate typing
    • \n
    • Thanks to @Leo310 for the feature request
    • \n
    \n
  • \n
  • Added button tooltips to calendar view toolbar

    \n
      \n
    • Hovering over navigation and view buttons now shows descriptive hints
    • \n
    • Buttons include: Today, Previous, Next, Month, Week, Day, Year, List
    • \n
    \n
  • \n
  • Added tooltips to task modal action icons

    \n
      \n
    • Icon buttons for status, date, project, priority, recurrence, and reminder now show tooltips on hover
    • \n
    • Improves discoverability for new users
    • \n
    \n
  • \n
  • (#503) Settings now sync automatically across devices via Obsidian Sync

    \n
      \n
    • Changes to custom statuses, priorities, and other settings apply immediately without restart
    • \n
    • Thanks to @jhedlund for the feature request and @l-mb for the implementation
    • \n
    \n
  • \n
  • (#1403) Kanban view option to consolidate status icons in column headers

    \n
      \n
    • New "Show status icon in column header only" toggle in Kanban view settings (disabled by default)
    • \n
    • When enabled and grouped by status, shows the icon in the column header and hides it on cards
    • \n
    • Reduces visual redundancy when the column already indicates the status
    • \n
    • Thanks to @l-mb for the feature request and implementation
    • \n
    \n
  • \n
  • (#1401) Calendar view option to span tasks between scheduled and due dates

    \n
      \n
    • New "Span tasks between scheduled and due dates" toggle in Calendar view Layout settings
    • \n
    • When enabled, tasks with both scheduled and due dates display as multi-day bars
    • \n
    • Provides Gantt chart-style visualization for project planning
    • \n
    • Thanks to @0atman for the feature request
    • \n
    \n
  • \n
  • (#1334) {{currentNotePath}} now works for "Create new inline task" command

    \n
      \n
    • The inline task folder setting with {{currentNotePath}} previously only worked for checkbox conversion
    • \n
    • Now also applies when using the "Create new inline task" command from the command palette
    • \n
    • Thanks to @kmaustral for the feature request
    • \n
    \n
  • \n
  • (#1264) Option to open Pomodoro timer in mobile sidebar instead of note panel

    \n
      \n
    • New "Mobile sidebar" setting in Settings → Features → Pomodoro Timer
    • \n
    • Choose between: Note panel (default tab behavior), Left sidebar, or Right sidebar
    • \n
    • Allows quick swipe access to the timer without switching notes on mobile devices
    • \n
    • Thanks to @Evthestrike for the feature request
    • \n
    \n
  • \n
  • (#1220) Option to use ICS event end time as task due date

    \n
      \n
    • New "Use ICS event end time as task due date" toggle in Settings → Integrations → Calendar Subscriptions
    • \n
    • When enabled, tasks created from calendar events will have their due date set to the event's end time
    • \n
    • For all-day events, uses the event date (not the ICS container end date which is the next day per ICS spec)
    • \n
    • For timed events, includes the exact end time
    • \n
    • Defaults to disabled to preserve existing behavior
    • \n
    • Thanks to @MiserMagus for the feature request
    • \n
    \n
  • \n
  • (#1108) Option to use task duration instead of due date for ICS calendar export

    \n
      \n
    • New "Use task duration for event length" toggle in Settings → Integrations → Automatic ICS Export
    • \n
    • When enabled, exported calendar events use scheduled date + time estimate as DTSTART/DTEND
    • \n
    • This aligns with GTD workflows where scheduled + duration represents work planning, while due date represents deadlines
    • \n
    • When disabled (default), preserves existing behavior using due date as DTEND
    • \n
    • Thanks to @bepolymathe for the feature request
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1421) Fixed natural language parser only capturing one date when both scheduled and due dates are specified

    \n
      \n
    • Input like "Task scheduled for tomorrow due next week" now correctly sets both scheduled and due dates
    • \n
    • Previously the parser would return early after finding the first date trigger, ignoring any subsequent triggers
    • \n
    • Thanks to @wealthychef1 for reporting
    • \n
    \n
  • \n
  • (#1384) Fixed title being sanitized even when "Store Task Title in Filename" is disabled

    \n
      \n
    • Characters like ?, <, >, :, etc. are now preserved in task titles when they won't be used in filenames
    • \n
    • When storeTitleInFilename is false, only minimal sanitization (whitespace normalization, control character removal) is applied
    • \n
    • Thanks to @allison-casey for reporting
    • \n
    \n
  • \n
  • (#1028), (#1140), (#1152), (#1354), (#1362) Fixed duplicate task entries appearing in Agenda view

    \n
      \n
    • Tasks were shown twice: once as TaskNotes events and again as property-based events with a file icon
    • \n
    • Changed default Agenda template to disable property-based events (showPropertyBasedEvents: false)
    • \n
    • Users can re-enable property-based events in view settings if needed for non-task date properties
    • \n
    • Thanks to @YIRU69, @jhedlund, @dblinnikov, @Snakiest, @WeiYiAcc, @JacksonMcDonaldDev, @jimbo108108, and @krelltunez for reporting
    • \n
    \n
  • \n
  • (#1386) Fixed timeEstimateCategory formula showing "Long (>2h)" instead of "No estimate" for new tasks

    \n
      \n
    • The condition didn't properly handle null values when timeEstimate property is unset
    • \n
    • Also fixed the same issue in trackingStatus formula
    • \n
    • Thanks to @nicou for reporting and @osxisl for the PR
    • \n
    \n
  • \n
  • (#1397) Fixed Bases views (Kanban, Calendar, Task List) resetting to Calendar view after a few minutes

    \n
      \n
    • Also fixed CalendarView corrupting other view files when saving state on unload
    • \n
    • Thanks to @music-soul1-1 for reporting
    • \n
    \n
  • \n
  • (#1398) Fixed overdue strikethrough showing on completed tasks

    \n
      \n
    • Completed tasks with past due dates no longer display overdue styling
    • \n
    • Respects the "Hide completed from overdue" setting which defaults to true
    • \n
    \n
  • \n
  • (#1363) Fixed calendar view showing nothing when a task has an invalid date format

    \n
      \n
    • Tasks with malformed dates (e.g., "262025-12-16" instead of "2025-12-16") no longer crash the entire calendar
    • \n
    • Invalid tasks are now skipped with a console warning, allowing other events to display normally
    • \n
    • Thanks to @Erelen for reporting
    • \n
    \n
  • \n
  • Fixed today column in week/day calendar views using FullCalendar's default yellow instead of theme accent

    \n
      \n
    • Today's column now uses a tint of the theme accent color for consistent styling
    • \n
    \n
  • \n
  • (#1399) Fixed drag-and-drop not working in Kanban view on mobile

    \n
      \n
    • Cards and columns can now be dragged using long-press gesture on touch devices
    • \n
    • Includes haptic feedback and auto-scroll when dragging near edges
    • \n
    • Thanks to @l-mb for reporting and the fix
    • \n
    \n
  • \n
  • (#1381) Fixed Pomodoro "Change Task" menu not showing newly created tasks

    \n
      \n
    • Tasks created while the Pomodoro view was open would not appear in the task selector
    • \n
    • Improved metadata cache synchronization to properly wait for new files to be indexed
    • \n
    • Thanks to @Ghosthael for reporting
    • \n
    \n
  • \n
  • (#1344) Fixed "Unsaved Changes" popup appearing randomly when closing task edit modal

    \n
      \n
    • The popup would appear even when no changes were made to the task
    • \n
    • Caused by inconsistent trailing whitespace normalization when comparing details content
    • \n
    • Thanks to @hasanyilmaz for reporting
    • \n
    \n
  • \n
  • (#1402) Fixed Kanban swimlane view showing tasks in wrong column when grouped by formula

    \n
      \n
    • After editing task metadata, cards would jump to "None" column until Obsidian reload
    • \n
    • Column assignment now uses Bases' computed grouping instead of cached formula outputs
    • \n
    • Thanks to @bailob for the fix
    • \n
    \n
  • \n
  • (#1352) Fixed date context menu not preserving time when using increment options

    \n
      \n
    • Using +1 day, -1 day, +1 week, or -1 week on a task with a time (e.g., 2025-12-10T16:00) now preserves the time
    • \n
    • Previously the time would be stripped, changing 2025-12-10T16:00 to 2025-12-11 instead of 2025-12-11T16:00
    • \n
    • Thanks to @cathywu for the feature request
    • \n
    \n
  • \n
  • Fixed v3 saved views exporting incorrectly to Bases format

    \n
      \n
    • Title filters now correctly use file.name instead of note.title
    • \n
    • Archived filters now generate valid boolean expressions instead of malformed comparisons
    • \n
    • "Is Blocked" filters now generate correct expressions with proper operator precedence
    • \n
    \n
  • \n
  • (#1036) Due dates can now be dragged in the calendar view

    \n
      \n
    • Previously only scheduled dates were draggable; due dates were locked in place
    • \n
    • Dragging a due event now updates the task's due date property
    • \n
    • Thanks to @same774 for reporting
    • \n
    \n
  • \n
  • Improved calendar view responsiveness for user interactions

    \n
      \n
    • Task creation, editing, timeblock changes, and view option toggles now update immediately
    • \n
    • Previously these actions waited 5 seconds due to the debounce intended for external file changes
    • \n
    • The 5-second debounce is now bypassed for direct user actions while still preventing flicker during typing
    • \n
    \n
  • \n
  • Improved visual affordance for Pomodoro timer duration adjustment buttons

    \n
      \n
    • The +/- buttons below the timer now have visible backgrounds and borders
    • \n
    • Hover states show accent color border for clearer interactivity feedback
    • \n
    • Previously buttons were nearly invisible with transparent backgrounds
    • \n
    \n
  • \n
  • (#1409), (#1214), (#979) Improved Calendar, Agenda, Kanban, and Stats views in pop-out windows

    \n
      \n
    • Drag-and-drop in Kanban view now works correctly when the view is in a new window
    • \n
    • Context menus (status, priority, task) now work correctly in pop-out windows
    • \n
    • Stats view drill-down modal now appears in the correct window
    • \n
    • Search boxes, task cards, and grouped task lists render correctly
    • \n
    • Root cause: Code was using global document and standard instanceof checks which fail across windows
    • \n
    • Solution: Use ownerDocument for DOM operations and Obsidian's cross-window instanceOf() method
    • \n
    • Known limitation: Calendar event dragging does not work in pop-out windows due to FullCalendar library using global document for mouse event listeners. Use context menus or edit modals as a workaround.
    • \n
    • Updated FullCalendar to v6.1.20
    • \n
    • Thanks to @Snakiest, @same774, and @3zra47 for reporting
    • \n
    \n
  • \n
  • (#1337) Fixed "Convert current note to task" hotkey not applying default values from settings

    \n
      \n
    • When user configured default status/priority as "None", the modal would show "Open" and "Normal" instead
    • \n
    • Root cause: Task edit modal was refreshing data from file and overwriting user-configured defaults
    • \n
    • Now preserves constructor-provided task data when converting non-task files
    • \n
    • Thanks to @guihasparyk for reporting
    • \n
    \n
  • \n
  • (#1304) Fixed "Cannot find function map on type Link" error in Blocking view

    \n
      \n
    • Error occurred when embedding the Relationships base and opening the Blocking view
    • \n
    • Root cause: When blockedBy contained a single dependency, Bases returned it as a Link object without a .map() method
    • \n
    • Fixed by wrapping blockedBy with list() before calling .map(), consistent with the Blocked By view
    • \n
    • Thanks to @prayidae for reporting
    • \n
    \n
  • \n
  • (#1295) Fixed missing navigation link to Default Base Templates page on tasknotes.dev

    \n
      \n
    • The page existed but was not accessible from the site navigation
    • \n
    • Thanks to @Arachnidai for reporting
    • \n
    \n
  • \n
  • (#1223) Fixed "Go to today's note" command opening wrong date in positive UTC offset timezones

    \n
      \n
    • In timezones like Japan (UTC+9), early morning use of this command opened yesterday's note
    • \n
    • Root cause: Incorrectly extracting UTC date components instead of local timezone date
    • \n
    • Thanks to @BrucePlumb for reporting
    • \n
    \n
  • \n
\n","text":"Added# Added Korean (한국어) language support Full translation of all 1911 localization keys Korean language option now available in Settings → General → Language Adopted Obsidian 1.11.0 API features with backwards compatibility Settings tab now displays TaskNotes icon in the sidebar (Obsidian 1.11.0+) Settings sections now use native SettingGroup for improved visual grouping (Obsidian 1.11.0+) Falls back gracefully to traditional section headers on older Obsidian versions (#59) Added shortYear template variable for custom filename and folder templates Use {shortYear} in filename templates (e.g., \"25\" for 2025) Use {{shortYear}} in folder templates Thanks to @Pixeltica for the feature request (#1393) Option to prevent auto-creation of default Base view files on startup New \"Auto-create default files\" toggle in Settings → Integrations → Bases Integration When disabled, deleted sample Base files will not be recreated on plugin load The manual \"Create Default Files\" button remains available for on-demand recreation Thanks to @wealthychef1 for the feature request (#1408) Shift+click on status icon to cycle backwards through statuses Normal click cycles forward through status order Shift+click cycles in reverse order Thanks to @JerryLu086 for the feature request (#1410) Task creation modal now starts in vim insert mode when vim keybindings are enabled Previously required pressing 'i' before typing when Obsidian vim mode was active The modal now automatically enters insert mode on focus, allowing immediate typing Thanks to @Leo310 for the feature request Added button tooltips to calendar view toolbar Hovering over navigation and view buttons now shows descriptive hints Buttons include: Today, Previous, Next, Month, Week, Day, Year, List Added tooltips to task modal action icons Icon buttons for status, date, project, priority, recurrence, and reminder now show tooltips on hover Improves discoverability for new users (#503) Settings now sync automatically across devices via Obsidian Sync Changes to custom statuses, priorities, and other settings apply immediately without restart Thanks to @jhedlund for the feature request and @l-mb for the implementation (#1403) Kanban view option to consolidate status icons in column headers New \"Show status icon in column header only\" toggle in Kanban view settings (disabled by default) When enabled and grouped by status, shows the icon in the column header and hides it on cards Reduces visual redundancy when the column already indicates the status Thanks to @l-mb for the feature request and implementation (#1401) Calendar view option to span tasks between scheduled and due dates New \"Span tasks between scheduled and due dates\" toggle in Calendar view Layout settings When enabled, tasks with both scheduled and due dates display as multi-day bars Provides Gantt chart-style visualization for project planning Thanks to @0atman for the feature request (#1334) {{currentNotePath}} now works for \"Create new inline task\" command The inline task folder setting with {{currentNotePath}} previously only worked for checkbox conversion Now also applies when using the \"Create new inline task\" command from the command palette Thanks to @kmaustral for the feature request (#1264) Option to open Pomodoro timer in mobile sidebar instead of note panel New \"Mobile sidebar\" setting in Settings → Features → Pomodoro Timer Choose between: Note panel (default tab behavior), Left sidebar, or Right sidebar Allows quick swipe access to the timer without switching notes on mobile devices Thanks to @Evthestrike for the feature request (#1220) Option to use ICS event end time as task due date New \"Use ICS event end time as task due date\" toggle in Settings → Integrations → Calendar Subscriptions When enabled, tasks created from calendar events will have their due date set to the event's end time For all-day events, uses the event date (not the ICS container end date which is the next day per ICS spec) For timed events, includes the exact end time Defaults to disabled to preserve existing behavior Thanks to @MiserMagus for the feature request (#1108) Option to use task duration instead of due date for ICS calendar export New \"Use task duration for event length\" toggle in Settings → Integrations → Automatic ICS Export When enabled, exported calendar events use scheduled date + time estimate as DTSTART/DTEND This aligns with GTD workflows where scheduled + duration represents work planning, while due date represents deadlines When disabled (default), preserves existing behavior using due date as DTEND Thanks to @bepolymathe for the feature request Fixed# (#1421) Fixed natural language parser only capturing one date when both scheduled and due dates are specified Input like \"Task scheduled for tomorrow due next week\" now correctly sets both scheduled and due dates Previously the parser would return early after finding the first date trigger, ignoring any subsequent triggers Thanks to @wealthychef1 for reporting (#1384) Fixed title being sanitized even when \"Store Task Title in Filename\" is disabled Characters like ?, <, >, :, etc. are now preserved in task titles when they won't be used in filenames When storeTitleInFilename is false, only minimal sanitization (whitespace normalization, control character removal) is applied Thanks to @allison-casey for reporting (#1028), (#1140), (#1152), (#1354), (#1362) Fixed duplicate task entries appearing in Agenda view Tasks were shown twice: once as TaskNotes events and again as property-based events with a file icon Changed default Agenda template to disable property-based events (showPropertyBasedEvents: false) Users can re-enable property-based events in view settings if needed for non-task date properties Thanks to @YIRU69, @jhedlund, @dblinnikov, @Snakiest, @WeiYiAcc, @JacksonMcDonaldDev, @jimbo108108, and @krelltunez for reporting (#1386) Fixed timeEstimateCategory formula showing \"Long (>2h)\" instead of \"No estimate\" for new tasks The condition didn't properly handle null values when timeEstimate property is unset Also fixed the same issue in trackingStatus formula Thanks to @nicou for reporting and @osxisl for the PR (#1397) Fixed Bases views (Kanban, Calendar, Task List) resetting to Calendar view after a few minutes Also fixed CalendarView corrupting other view files when saving state on unload Thanks to @music-soul1-1 for reporting (#1398) Fixed overdue strikethrough showing on completed tasks Completed tasks with past due dates no longer display overdue styling Respects the \"Hide completed from overdue\" setting which defaults to true (#1363) Fixed calendar view showing nothing when a task has an invalid date format Tasks with malformed dates (e.g., \"262025-12-16\" instead of \"2025-12-16\") no longer crash the entire calendar Invalid tasks are now skipped with a console warning, allowing other events to display normally Thanks to @Erelen for reporting Fixed today column in week/day calendar views using FullCalendar's default yellow instead of theme accent Today's column now uses a tint of the theme accent color for consistent styling (#1399) Fixed drag-and-drop not working in Kanban view on mobile Cards and columns can now be dragged using long-press gesture on touch devices Includes haptic feedback and auto-scroll when dragging near edges Thanks to @l-mb for reporting and the fix (#1381) Fixed Pomodoro \"Change Task\" menu not showing newly created tasks Tasks created while the Pomodoro view was open would not appear in the task selector Improved metadata cache synchronization to properly wait for new files to be indexed Thanks to @Ghosthael for reporting (#1344) Fixed \"Unsaved Changes\" popup appearing randomly when closing task edit modal The popup would appear even when no changes were made to the task Caused by inconsistent trailing whitespace normalization when comparing details content Thanks to @hasanyilmaz for reporting (#1402) Fixed Kanban swimlane view showing tasks in wrong column when grouped by formula After editing task metadata, cards would jump to \"None\" column until Obsidian reload Column assignment now uses Bases' computed grouping instead of cached formula outputs Thanks to @bailob for the fix (#1352) Fixed date context menu not preserving time when using increment options Using +1 day, -1 day, +1 week, or -1 week on a task with a time (e.g., 2025-12-10T16:00) now preserves the time Previously the time would be stripped, changing 2025-12-10T16:00 to 2025-12-11 instead of 2025-12-11T16:00 Thanks to @cathywu for the feature request Fixed v3 saved views exporting incorrectly to Bases format Title filters now correctly use file.name instead of note.title Archived filters now generate valid boolean expressions instead of malformed comparisons \"Is Blocked\" filters now generate correct expressions with proper operator precedence (#1036) Due dates can now be dragged in the calendar view Previously only scheduled dates were draggable; due dates were locked in place Dragging a due event now updates the task's due date property Thanks to @same774 for reporting Improved calendar view responsiveness for user interactions Task creation, editing, timeblock changes, and view option toggles now update immediately Previously these actions waited 5 seconds due to the debounce intended for external file changes The 5-second debounce is now bypassed for direct user actions while still preventing flicker during typing Improved visual affordance for Pomodoro timer duration adjustment buttons The +/- buttons below the timer now have visible backgrounds and borders Hover states show accent color border for clearer interactivity feedback Previously buttons were nearly invisible with transparent backgrounds (#1409), (#1214), (#979) Improved Calendar, Agenda, Kanban, and Stats views in pop-out windows Drag-and-drop in Kanban view now works correctly when the view is in a new window Context menus (status, priority, task) now work correctly in pop-out windows Stats view drill-down modal now appears in the correct window Search boxes, task cards, and grouped task lists render correctly Root cause: Code was using global document and standard instanceof checks which fail across windows Solution: Use ownerDocument for DOM operations and Obsidian's cross-window instanceOf() method Known limitation: Calendar event dragging does not work in pop-out windows due to FullCalendar library using global document for mouse event listeners. Use context menus or edit modals as a workaround. Updated FullCalendar to v6.1.20 Thanks to @Snakiest, @same774, and @3zra47 for reporting (#1337) Fixed \"Convert current note to task\" hotkey not applying default values from settings When user configured default status/priority as \"None\", the modal would show \"Open\" and \"Normal\" instead Root cause: Task edit modal was refreshing data from file and overwriting user-configured defaults Now preserves constructor-provided task data when converting non-task files Thanks to @guihasparyk for reporting (#1304) Fixed \"Cannot find function map on type Link\" error in Blocking view Error occurred when embedding the Relationships base and opening the Blocking view Root cause: When blockedBy contained a single dependency, Bases returned it as a Link object without a .map() method Fixed by wrapping blockedBy with list() before calling .map(), consistent with the Blocked By view Thanks to @prayidae for reporting (#1295) Fixed missing navigation link to Default Base Templates page on tasknotes.dev The page existed but was not accessible from the site navigation Thanks to @Arachnidai for reporting (#1223) Fixed \"Go to today's note\" command opening wrong date in positive UTC offset timezones In timezones like Japan (UTC+9), early morning use of this command opened yesterday's note Root cause: Incorrectly extracting UTC date components instead of local timezone date Thanks to @BrucePlumb for reporting"},{"route":"/obsidian/releases/4.2.1/","title":"TaskNotes 4.2.1","description":"(#1424) Fixed \"Create New Task\" command creating tasks in active folder instead of default folder","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.2.1.md","namespace":"obsidian","relativePath":"releases/4.2.1.md","raw":"# TaskNotes 4.2.1\n\n## Added\n\n- New Calendars API endpoint for access to calendar data\n - Access calendar provider information and connection status\n - Query events from Google Calendar, Microsoft Calendar, and ICS subscriptions\n - Filter events by date range\n - [`tasknotes-cli`](https://github.com/callumalpass/tasknotes-cli) has been updated to make use of this endpoint\n\n## Fixed\n\n- (#1424) Fixed \"Create New Task\" command creating tasks in active folder instead of default folder\n - \"Create New Task\" now correctly uses the configured default task folder\n - \"Create New Inline Task\" continues to use the inline task folder setting\n - Thanks to @Gogo-XD for reporting and @TonyAtlas for confirming\n\n- (#1421), (#1042) Fixed natural language parser only setting one date when both scheduled and due dates are specified\n - Entering something like \"task due Jan 9 at Jan 9\" now correctly sets both the due date and scheduled date\n - Thanks to @wealthychef1 and @dblinnikov for reporting\n\n- (#1410) Fixed vim insert mode not activating in task creation modal\n - The modal now correctly enters insert mode when vim keybindings are enabled\n - Thanks to @Leo310 for the feature request\n\n- (#1422) Fixed tags with dashes not being parsed correctly\n - Tags like `#my-tag` were being truncated to `#my`\n - Thanks to @JerryLu086 for reporting\n\n- (#1419) Fixed custom statuses and priorities not saving in settings\n - Values entered in text fields were sometimes lost when closing the settings modal\n - Thanks to @s33a for reporting\n","aliases":["/releases/4.2.1/","/releases/4.2.1/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • New Calendars API endpoint for access to calendar data
      \n
    • Access calendar provider information and connection status
    • \n
    • Query events from Google Calendar, Microsoft Calendar, and ICS subscriptions
    • \n
    • Filter events by date range
    • \n
    • tasknotes-cli has been updated to make use of this endpoint
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1424) Fixed "Create New Task" command creating tasks in active folder instead of default folder

    \n
      \n
    • "Create New Task" now correctly uses the configured default task folder
    • \n
    • "Create New Inline Task" continues to use the inline task folder setting
    • \n
    • Thanks to @Gogo-XD for reporting and @TonyAtlas for confirming
    • \n
    \n
  • \n
  • (#1421), (#1042) Fixed natural language parser only setting one date when both scheduled and due dates are specified

    \n
      \n
    • Entering something like "task due Jan 9 at Jan 9" now correctly sets both the due date and scheduled date
    • \n
    • Thanks to @wealthychef1 and @dblinnikov for reporting
    • \n
    \n
  • \n
  • (#1410) Fixed vim insert mode not activating in task creation modal

    \n
      \n
    • The modal now correctly enters insert mode when vim keybindings are enabled
    • \n
    • Thanks to @Leo310 for the feature request
    • \n
    \n
  • \n
  • (#1422) Fixed tags with dashes not being parsed correctly

    \n
      \n
    • Tags like #my-tag were being truncated to #my
    • \n
    • Thanks to @JerryLu086 for reporting
    • \n
    \n
  • \n
  • (#1419) Fixed custom statuses and priorities not saving in settings

    \n
      \n
    • Values entered in text fields were sometimes lost when closing the settings modal
    • \n
    • Thanks to @s33a for reporting
    • \n
    \n
  • \n
\n","text":"Added# New Calendars API endpoint for access to calendar data Access calendar provider information and connection status Query events from Google Calendar, Microsoft Calendar, and ICS subscriptions Filter events by date range tasknotes-cli has been updated to make use of this endpoint Fixed# (#1424) Fixed \"Create New Task\" command creating tasks in active folder instead of default folder \"Create New Task\" now correctly uses the configured default task folder \"Create New Inline Task\" continues to use the inline task folder setting Thanks to @Gogo-XD for reporting and @TonyAtlas for confirming (#1421), (#1042) Fixed natural language parser only setting one date when both scheduled and due dates are specified Entering something like \"task due Jan 9 at Jan 9\" now correctly sets both the due date and scheduled date Thanks to @wealthychef1 and @dblinnikov for reporting (#1410) Fixed vim insert mode not activating in task creation modal The modal now correctly enters insert mode when vim keybindings are enabled Thanks to @Leo310 for the feature request (#1422) Fixed tags with dashes not being parsed correctly Tags like #my-tag were being truncated to #my Thanks to @JerryLu086 for reporting (#1419) Fixed custom statuses and priorities not saving in settings Values entered in text fields were sometimes lost when closing the settings modal Thanks to @s33a for reporting"},{"route":"/obsidian/releases/4.3.0/","title":"TaskNotes 4.3.0","description":"(#1361) Option to disable inline task overlay for aliased wikilinks","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.3.0.md","namespace":"obsidian","relativePath":"releases/4.3.0.md","raw":"# TaskNotes 4.3.0\n\n## Changed\n\n- (#1437) Unified template variable syntax and available variables across filename and body templates\n - Both systems now use double-brace `{{variable}}` syntax consistently\n - Single-brace `{variable}` syntax remains supported for backwards compatibility but is deprecated\n - Settings UI shows a warning when deprecated single-brace syntax is detected\n - Filename templates gain body template variables: `{{contexts}}`, `{{tags}}`, `{{hashtags}}`, `{{timeEstimate}}`, `{{details}}`, `{{parentNote}}`\n - Body templates gain filename template variables: `{{zettel}}`, `{{nano}}`, and all extended date/time variables\n - Thanks to @23maverick23 for reporting\n\n## Added\n\n- (#1361) Option to disable inline task overlay for aliased wikilinks\n - New setting in Features → Inline Tasks: \"Disable overlay for aliased links\"\n - When enabled, links with aliases like `[[Task|Check Status]]` render as plain links\n - Links without aliases continue to show the interactive task widget\n - Useful when embedding tasks in prose where the widget would be disruptive\n - Thanks to @diegomarzaa for the contribution and @jldiaz for proposing this feature in #1117\n\n- (#1199, #1205) Google Calendar export for tasks\n - Sync tasks to Google Calendar based on scheduled or due dates\n - Automatic sync on task create, update, complete, and delete\n - Configurable event title templates with placeholders (`{{title}}`, `{{status}}`, `{{priority}}`, etc.)\n - Event descriptions include task metadata and optional Obsidian deep link\n - Support for all-day or timed events with customizable duration\n - Event color customization using Google Calendar's color palette\n - Default reminder setting for popup notifications\n - Bulk sync and unlink actions in settings\n - Task-event linking stored in frontmatter (`googleCalendarEventId`)\n - Recurring tasks sync as Google Calendar recurring events\n - Completed or skipped recurring instances are automatically excluded\n - Thanks to @someromans and @Leonard-44 for requesting this feature, and @dmantisk, @farangkao, @rayvermey, and @rdpr for their input\n\n## Fixed\n\n- (#1413) Fixed angle-bracket links and project title display\n - Angle-bracket links like `[Spec]()` now resolve correctly\n - Project links display frontmatter `title` instead of raw filename/path when available\n - Dependency values normalize consistently across wikilinks, markdown links, and angle-bracket variants\n - Many thanks to @normenmueller for the contribution\n\n- (#1414) Kanban column headers now display configured priority labels instead of raw values\n - Many thanks to @normenmueller for the contribution\n\n- (#1416) Fixed property-based task identification mutating tags unexpectedly\n - Tags are only written when explicitly changed by the user\n - Task tag is only added in tag-based identification mode\n - Fixes #1391\n - Thanks to @loukandr for reporting and @normenmueller for the fix\n\n- (#1187) Fixed \"Unknown view types\" error when opening Bases views after upgrading from pre-V4\n - Users who had disabled Bases support in earlier versions could not open Bases views after upgrading\n - Settings migration now automatically re-enables Bases support since the toggle was removed in V4\n - Thanks to @MiracleXYZ for reporting\n\n- (#1144) Fixed relationships.base showing empty views for Projects, Blocked By, and Blocking tabs\n - The top-level task filter was excluding non-task files from the Projects view\n - Projects can be any file type (not just tasks), so the filter is now applied per-view\n - Subtasks, Blocked By, and Blocking views retain the task filter; Projects view does not\n - Users with existing relationships.base files should delete and regenerate them to get the fix\n - Thanks to @needo37 for reporting, and @n1njaznutz, @nestor50, and @IvyDliu for investigating and confirming the solution\n\n- Fixed calendar view type not persisting or applying when changed\n - View type changes via header buttons (week/day/month) are now saved to the .base file\n - View type changes via Bases settings panel now apply immediately without reload\n\n- (#1441) Fixed task dragging broken with \"Span tasks between scheduled and due dates\" enabled\n - Span events can now be dragged to move tasks in time\n - Dragging shifts both scheduled and due dates proportionally, preserving the span duration\n - Previously, dragging span events would cause a visual/data mismatch where the calendar showed the wrong position\n - Thanks to @Peeeet for reporting\n","aliases":["/releases/4.3.0/","/releases/4.3.0/"],"toc":[{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Changed#

\n
    \n
  • (#1437) Unified template variable syntax and available variables across filename and body templates
      \n
    • Both systems now use double-brace {{variable}} syntax consistently
    • \n
    • Single-brace {variable} syntax remains supported for backwards compatibility but is deprecated
    • \n
    • Settings UI shows a warning when deprecated single-brace syntax is detected
    • \n
    • Filename templates gain body template variables: {{contexts}}, {{tags}}, {{hashtags}}, {{timeEstimate}}, {{details}}, {{parentNote}}
    • \n
    • Body templates gain filename template variables: {{zettel}}, {{nano}}, and all extended date/time variables
    • \n
    • Thanks to @23maverick23 for reporting
    • \n
    \n
  • \n
\n

Added#

\n
    \n
  • (#1361) Option to disable inline task overlay for aliased wikilinks

    \n
      \n
    • New setting in Features → Inline Tasks: "Disable overlay for aliased links"
    • \n
    • When enabled, links with aliases like [[Task|Check Status]] render as plain links
    • \n
    • Links without aliases continue to show the interactive task widget
    • \n
    • Useful when embedding tasks in prose where the widget would be disruptive
    • \n
    • Thanks to @diegomarzaa for the contribution and @jldiaz for proposing this feature in #1117
    • \n
    \n
  • \n
  • (#1199, #1205) Google Calendar export for tasks

    \n
      \n
    • Sync tasks to Google Calendar based on scheduled or due dates
    • \n
    • Automatic sync on task create, update, complete, and delete
    • \n
    • Configurable event title templates with placeholders ({{title}}, {{status}}, {{priority}}, etc.)
    • \n
    • Event descriptions include task metadata and optional Obsidian deep link
    • \n
    • Support for all-day or timed events with customizable duration
    • \n
    • Event color customization using Google Calendar's color palette
    • \n
    • Default reminder setting for popup notifications
    • \n
    • Bulk sync and unlink actions in settings
    • \n
    • Task-event linking stored in frontmatter (googleCalendarEventId)
    • \n
    • Recurring tasks sync as Google Calendar recurring events
    • \n
    • Completed or skipped recurring instances are automatically excluded
    • \n
    • Thanks to @someromans and @Leonard-44 for requesting this feature, and @dmantisk, @farangkao, @rayvermey, and @rdpr for their input
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1413) Fixed angle-bracket links and project title display

    \n
      \n
    • Angle-bracket links like [Spec](<Projects/Client X/Spec.md>) now resolve correctly
    • \n
    • Project links display frontmatter title instead of raw filename/path when available
    • \n
    • Dependency values normalize consistently across wikilinks, markdown links, and angle-bracket variants
    • \n
    • Many thanks to @normenmueller for the contribution
    • \n
    \n
  • \n
  • (#1414) Kanban column headers now display configured priority labels instead of raw values

    \n
      \n
    • Many thanks to @normenmueller for the contribution
    • \n
    \n
  • \n
  • (#1416) Fixed property-based task identification mutating tags unexpectedly

    \n
      \n
    • Tags are only written when explicitly changed by the user
    • \n
    • Task tag is only added in tag-based identification mode
    • \n
    • Fixes #1391
    • \n
    • Thanks to @loukandr for reporting and @normenmueller for the fix
    • \n
    \n
  • \n
  • (#1187) Fixed "Unknown view types" error when opening Bases views after upgrading from pre-V4

    \n
      \n
    • Users who had disabled Bases support in earlier versions could not open Bases views after upgrading
    • \n
    • Settings migration now automatically re-enables Bases support since the toggle was removed in V4
    • \n
    • Thanks to @MiracleXYZ for reporting
    • \n
    \n
  • \n
  • (#1144) Fixed relationships.base showing empty views for Projects, Blocked By, and Blocking tabs

    \n
      \n
    • The top-level task filter was excluding non-task files from the Projects view
    • \n
    • Projects can be any file type (not just tasks), so the filter is now applied per-view
    • \n
    • Subtasks, Blocked By, and Blocking views retain the task filter; Projects view does not
    • \n
    • Users with existing relationships.base files should delete and regenerate them to get the fix
    • \n
    • Thanks to @needo37 for reporting, and @n1njaznutz, @nestor50, and @IvyDliu for investigating and confirming the solution
    • \n
    \n
  • \n
  • Fixed calendar view type not persisting or applying when changed

    \n
      \n
    • View type changes via header buttons (week/day/month) are now saved to the .base file
    • \n
    • View type changes via Bases settings panel now apply immediately without reload
    • \n
    \n
  • \n
  • (#1441) Fixed task dragging broken with "Span tasks between scheduled and due dates" enabled

    \n
      \n
    • Span events can now be dragged to move tasks in time
    • \n
    • Dragging shifts both scheduled and due dates proportionally, preserving the span duration
    • \n
    • Previously, dragging span events would cause a visual/data mismatch where the calendar showed the wrong position
    • \n
    • Thanks to @Peeeet for reporting
    • \n
    \n
  • \n
\n","text":"Changed# (#1437) Unified template variable syntax and available variables across filename and body templates Both systems now use double-brace {{variable}} syntax consistently Single-brace {variable} syntax remains supported for backwards compatibility but is deprecated Settings UI shows a warning when deprecated single-brace syntax is detected Filename templates gain body template variables: {{contexts}}, {{tags}}, {{hashtags}}, {{timeEstimate}}, {{details}}, {{parentNote}} Body templates gain filename template variables: {{zettel}}, {{nano}}, and all extended date/time variables Thanks to @23maverick23 for reporting Added# (#1361) Option to disable inline task overlay for aliased wikilinks New setting in Features → Inline Tasks: \"Disable overlay for aliased links\" When enabled, links with aliases like [[Task|Check Status]] render as plain links Links without aliases continue to show the interactive task widget Useful when embedding tasks in prose where the widget would be disruptive Thanks to @diegomarzaa for the contribution and @jldiaz for proposing this feature in #1117 (#1199, #1205) Google Calendar export for tasks Sync tasks to Google Calendar based on scheduled or due dates Automatic sync on task create, update, complete, and delete Configurable event title templates with placeholders ({{title}}, {{status}}, {{priority}}, etc.) Event descriptions include task metadata and optional Obsidian deep link Support for all-day or timed events with customizable duration Event color customization using Google Calendar's color palette Default reminder setting for popup notifications Bulk sync and unlink actions in settings Task-event linking stored in frontmatter (googleCalendarEventId) Recurring tasks sync as Google Calendar recurring events Completed or skipped recurring instances are automatically excluded Thanks to @someromans and @Leonard-44 for requesting this feature, and @dmantisk, @farangkao, @rayvermey, and @rdpr for their input Fixed# (#1413) Fixed angle-bracket links and project title display Angle-bracket links like [Spec]() now resolve correctly Project links display frontmatter title instead of raw filename/path when available Dependency values normalize consistently across wikilinks, markdown links, and angle-bracket variants Many thanks to @normenmueller for the contribution (#1414) Kanban column headers now display configured priority labels instead of raw values Many thanks to @normenmueller for the contribution (#1416) Fixed property-based task identification mutating tags unexpectedly Tags are only written when explicitly changed by the user Task tag is only added in tag-based identification mode Fixes #1391 Thanks to @loukandr for reporting and @normenmueller for the fix (#1187) Fixed \"Unknown view types\" error when opening Bases views after upgrading from pre-V4 Users who had disabled Bases support in earlier versions could not open Bases views after upgrading Settings migration now automatically re-enables Bases support since the toggle was removed in V4 Thanks to @MiracleXYZ for reporting (#1144) Fixed relationships.base showing empty views for Projects, Blocked By, and Blocking tabs The top-level task filter was excluding non-task files from the Projects view Projects can be any file type (not just tasks), so the filter is now applied per-view Subtasks, Blocked By, and Blocking views retain the task filter; Projects view does not Users with existing relationships.base files should delete and regenerate them to get the fix Thanks to @needo37 for reporting, and @n1njaznutz, @nestor50, and @IvyDliu for investigating and confirming the solution Fixed calendar view type not persisting or applying when changed View type changes via header buttons (week/day/month) are now saved to the .base file View type changes via Bases settings panel now apply immediately without reload (#1441) Fixed task dragging broken with \"Span tasks between scheduled and due dates\" enabled Span events can now be dragged to move tasks in time Dragging shifts both scheduled and due dates proportionally, preserving the span duration Previously, dragging span events would cause a visual/data mismatch where the calendar showed the wrong position Thanks to @Peeeet for reporting"},{"route":"/obsidian/releases/4.3.1/","title":"TaskNotes 4.3.1","description":"(#1546) Added sticky kanban column headers that remain visible while scrolling","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.3.1.md","namespace":"obsidian","relativePath":"releases/4.3.1.md","raw":"# TaskNotes 4.3.1\n\n## Added\n\n- (#1546) Added sticky kanban column headers that remain visible while scrolling\n - Thanks to @normenmueller for the contribution\n\n- (#1458) Added CSS color classes to context tags for custom styling\n - Each context tag now receives a unique CSS class based on its name (e.g., `context-tag--color-0` through `context-tag--color-19`)\n - Enables styling individual contexts via CSS snippets\n - Thanks to @phortx for the contribution\n\n- Added [mdbase-spec](https://mdbase.dev) type definition generation\n - New setting in Integrations tab to generate mdbase-spec v0.2.0 type definition files (`mdbase.yaml` and `_types/task.md`) at the vault root\n - Type definitions are derived from TaskNotes settings (statuses, priorities, field mappings, user fields) and regenerated automatically when settings change\n - Enables interoperability with other tools that support the mdbase-spec format\n\n## Fixed\n\n- (#1472) Fixed task dependencies not being stored as wikilinks in frontmatter\n - Dependencies now retain their `[[wikilink]]` format when saved, preventing them from breaking on file rename\n - Thanks to @renekalff for reporting\n\n- (#1443) Fixed default status/priority not updating when the referenced custom value is deleted\n - Deleting a custom status or priority that was set as the default now resets the default to the first available value\n - Thanks to @l-mb for the contribution\n\n- (#1448) Fixed project removals not persisting from the task edit modal\n - Removing all projects from a task now correctly clears the projects field\n - Different link formats (e.g., markdown links vs wikilinks) no longer cause false change detection\n - Thanks to @normenmueller for the contribution\n\n- (#1514), (#1517) Fixed task reminders not syncing to Google Calendar\n - Task-specific reminders (both relative and absolute) now sync to Google Calendar\n - Previously only the global default reminder setting was used, ignoring per-task reminders\n - Thanks to @christenbc for the contribution\n\n- (#1525), (#1531) Fixed subtask status dot not refreshing visually when clicked\n - Status dot, checkbox, and card styling now update instantly when cycling status\n - Thanks to @christenbc for the contribution\n\n- (#1537) Fixed Google Calendar errors during bulk sync\n - Added rate limiting to space out API calls, preventing errors when syncing many tasks at once\n - Thanks to @Lorite for the contribution\n\n- (#1515), (#1540) Fixed time loss when setting recurrence and recurrence not clearing from Google Calendar\n - Setting recurrence on a task with a scheduled time now preserves the time, preventing Google Calendar events from appearing as all-day\n - Clearing recurrence from a task now also removes it from the synced Google Calendar event\n - Thanks to @christenbc for the contribution\n\n- (#1428), (#1559) Fixed hierarchical tags with slashes (e.g., `#project/sub-project`) being truncated in link text\n - Tags containing slashes, hyphens, and Unicode characters now render correctly\n - Thanks to @normenmueller for the contribution and @ysafonov for reporting\n\n- (#1565) Fixed Google Calendar target calendar dropdown appearing empty after app restart\n - The dropdown now re-populates once calendars are fetched during startup\n - Thanks to @N-HEDGER for reporting\n\n- (#1567) Fixed inline task card widgets disappearing momentarily\n - When the task cache is temporarily cleared (e.g., during Smart Connections processing), the previously-rendered widget is now preserved instead of reverting to a plain wiki link\n - Thanks to @scztt for reporting\n\n- (#1568) Fixed deleted tasks not being removed from Google Calendar\n - When a task file is deleted outside of TaskNotes (e.g., via Obsidian's file manager), the synced Google Calendar event is now cleaned up automatically\n - Thanks to @kmaustral for reporting\n\n- Fixed Integrations tab spacing and layout issues\n - Improved positioning of buttons and status indicators across Google Calendar, ICS, and Webhooks sections\n","aliases":["/releases/4.3.1/","/releases/4.3.1/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • (#1546) Added sticky kanban column headers that remain visible while scrolling

    \n
      \n
    • Thanks to @normenmueller for the contribution
    • \n
    \n
  • \n
  • (#1458) Added CSS color classes to context tags for custom styling

    \n
      \n
    • Each context tag now receives a unique CSS class based on its name (e.g., context-tag--color-0 through context-tag--color-19)
    • \n
    • Enables styling individual contexts via CSS snippets
    • \n
    • Thanks to @phortx for the contribution
    • \n
    \n
  • \n
  • Added mdbase-spec type definition generation

    \n
      \n
    • New setting in Integrations tab to generate mdbase-spec v0.2.0 type definition files (mdbase.yaml and _types/task.md) at the vault root
    • \n
    • Type definitions are derived from TaskNotes settings (statuses, priorities, field mappings, user fields) and regenerated automatically when settings change
    • \n
    • Enables interoperability with other tools that support the mdbase-spec format
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1472) Fixed task dependencies not being stored as wikilinks in frontmatter

    \n
      \n
    • Dependencies now retain their [[wikilink]] format when saved, preventing them from breaking on file rename
    • \n
    • Thanks to @renekalff for reporting
    • \n
    \n
  • \n
  • (#1443) Fixed default status/priority not updating when the referenced custom value is deleted

    \n
      \n
    • Deleting a custom status or priority that was set as the default now resets the default to the first available value
    • \n
    • Thanks to @l-mb for the contribution
    • \n
    \n
  • \n
  • (#1448) Fixed project removals not persisting from the task edit modal

    \n
      \n
    • Removing all projects from a task now correctly clears the projects field
    • \n
    • Different link formats (e.g., markdown links vs wikilinks) no longer cause false change detection
    • \n
    • Thanks to @normenmueller for the contribution
    • \n
    \n
  • \n
  • (#1514), (#1517) Fixed task reminders not syncing to Google Calendar

    \n
      \n
    • Task-specific reminders (both relative and absolute) now sync to Google Calendar
    • \n
    • Previously only the global default reminder setting was used, ignoring per-task reminders
    • \n
    • Thanks to @christenbc for the contribution
    • \n
    \n
  • \n
  • (#1525), (#1531) Fixed subtask status dot not refreshing visually when clicked

    \n
      \n
    • Status dot, checkbox, and card styling now update instantly when cycling status
    • \n
    • Thanks to @christenbc for the contribution
    • \n
    \n
  • \n
  • (#1537) Fixed Google Calendar errors during bulk sync

    \n
      \n
    • Added rate limiting to space out API calls, preventing errors when syncing many tasks at once
    • \n
    • Thanks to @Lorite for the contribution
    • \n
    \n
  • \n
  • (#1515), (#1540) Fixed time loss when setting recurrence and recurrence not clearing from Google Calendar

    \n
      \n
    • Setting recurrence on a task with a scheduled time now preserves the time, preventing Google Calendar events from appearing as all-day
    • \n
    • Clearing recurrence from a task now also removes it from the synced Google Calendar event
    • \n
    • Thanks to @christenbc for the contribution
    • \n
    \n
  • \n
  • (#1428), (#1559) Fixed hierarchical tags with slashes (e.g., #project/sub-project) being truncated in link text

    \n
      \n
    • Tags containing slashes, hyphens, and Unicode characters now render correctly
    • \n
    • Thanks to @normenmueller for the contribution and @ysafonov for reporting
    • \n
    \n
  • \n
  • (#1565) Fixed Google Calendar target calendar dropdown appearing empty after app restart

    \n
      \n
    • The dropdown now re-populates once calendars are fetched during startup
    • \n
    • Thanks to @N-HEDGER for reporting
    • \n
    \n
  • \n
  • (#1567) Fixed inline task card widgets disappearing momentarily

    \n
      \n
    • When the task cache is temporarily cleared (e.g., during Smart Connections processing), the previously-rendered widget is now preserved instead of reverting to a plain wiki link
    • \n
    • Thanks to @scztt for reporting
    • \n
    \n
  • \n
  • (#1568) Fixed deleted tasks not being removed from Google Calendar

    \n
      \n
    • When a task file is deleted outside of TaskNotes (e.g., via Obsidian's file manager), the synced Google Calendar event is now cleaned up automatically
    • \n
    • Thanks to @kmaustral for reporting
    • \n
    \n
  • \n
  • Fixed Integrations tab spacing and layout issues

    \n
      \n
    • Improved positioning of buttons and status indicators across Google Calendar, ICS, and Webhooks sections
    • \n
    \n
  • \n
\n","text":"Added# (#1546) Added sticky kanban column headers that remain visible while scrolling Thanks to @normenmueller for the contribution (#1458) Added CSS color classes to context tags for custom styling Each context tag now receives a unique CSS class based on its name (e.g., context-tag--color-0 through context-tag--color-19) Enables styling individual contexts via CSS snippets Thanks to @phortx for the contribution Added mdbase-spec type definition generation New setting in Integrations tab to generate mdbase-spec v0.2.0 type definition files (mdbase.yaml and _types/task.md) at the vault root Type definitions are derived from TaskNotes settings (statuses, priorities, field mappings, user fields) and regenerated automatically when settings change Enables interoperability with other tools that support the mdbase-spec format Fixed# (#1472) Fixed task dependencies not being stored as wikilinks in frontmatter Dependencies now retain their [[wikilink]] format when saved, preventing them from breaking on file rename Thanks to @renekalff for reporting (#1443) Fixed default status/priority not updating when the referenced custom value is deleted Deleting a custom status or priority that was set as the default now resets the default to the first available value Thanks to @l-mb for the contribution (#1448) Fixed project removals not persisting from the task edit modal Removing all projects from a task now correctly clears the projects field Different link formats (e.g., markdown links vs wikilinks) no longer cause false change detection Thanks to @normenmueller for the contribution (#1514), (#1517) Fixed task reminders not syncing to Google Calendar Task-specific reminders (both relative and absolute) now sync to Google Calendar Previously only the global default reminder setting was used, ignoring per-task reminders Thanks to @christenbc for the contribution (#1525), (#1531) Fixed subtask status dot not refreshing visually when clicked Status dot, checkbox, and card styling now update instantly when cycling status Thanks to @christenbc for the contribution (#1537) Fixed Google Calendar errors during bulk sync Added rate limiting to space out API calls, preventing errors when syncing many tasks at once Thanks to @Lorite for the contribution (#1515), (#1540) Fixed time loss when setting recurrence and recurrence not clearing from Google Calendar Setting recurrence on a task with a scheduled time now preserves the time, preventing Google Calendar events from appearing as all-day Clearing recurrence from a task now also removes it from the synced Google Calendar event Thanks to @christenbc for the contribution (#1428), (#1559) Fixed hierarchical tags with slashes (e.g., #project/sub-project) being truncated in link text Tags containing slashes, hyphens, and Unicode characters now render correctly Thanks to @normenmueller for the contribution and @ysafonov for reporting (#1565) Fixed Google Calendar target calendar dropdown appearing empty after app restart The dropdown now re-populates once calendars are fetched during startup Thanks to @N-HEDGER for reporting (#1567) Fixed inline task card widgets disappearing momentarily When the task cache is temporarily cleared (e.g., during Smart Connections processing), the previously-rendered widget is now preserved instead of reverting to a plain wiki link Thanks to @scztt for reporting (#1568) Fixed deleted tasks not being removed from Google Calendar When a task file is deleted outside of TaskNotes (e.g., via Obsidian's file manager), the synced Google Calendar event is now cleaned up automatically Thanks to @kmaustral for reporting Fixed Integrations tab spacing and layout issues Improved positioning of buttons and status indicators across Google Calendar, ICS, and Webhooks sections"},{"route":"/obsidian/releases/4.3.2/","title":"TaskNotes 4.3.2","description":"(#1520) Tag and Context fields in Edit Task modal now show all available suggestions immediately on focus","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.3.2.md","namespace":"obsidian","relativePath":"releases/4.3.2.md","raw":"# TaskNotes 4.3.2\n\n## Added\n\n- (#1520) Tag and Context fields in Edit Task modal now show all available suggestions immediately on focus\n - Previously required typing at least one character before suggestions appeared\n - Already-selected values are excluded from the suggestion list\n - Thanks to @Glint-Eye for the suggestion\n\n- (#1506) Added setting to configure the default color for new timeblocks\n - New color picker in Settings > Features > Timeblocking\n - Previously hardcoded to indigo; now user-configurable\n - Thanks to @phillipadsmith for the suggestion\n\n## Fixed\n\n- Fixed [mdbase-spec](https://mdbase.dev) type definition generation not triggering when settings change\n\n- (#1456) Fixed inline tasks jumping visually when marked as completed\n - Thanks to @3zra47 for reporting\n\n- (#1364) Fixed auto-stop time tracking not triggering when completing recurring task instances\n - Thanks to @slipstyle for reporting\n\n- (#1465) Fixed all-day events synced to Google Calendar receiving wrong notification time\n - All-day events now use Google Calendar's configured all-day notification defaults instead of a minutes-based reminder\n - Thanks to @Jomo94 for reporting\n\n- (#1470) Fixed cursor showing as default instead of pointer on interactive elements\n - Thanks to @TheFrostedDev for reporting\n\n- (#1491) Fixed boolean property values being quoted as strings in Bases filter generation\n - When using a boolean property (e.g. `tasknote: true`) for task identification, the filter now correctly handles the value\n - Thanks to @denisgorod for reporting\n\n- (#1494) Fixed Kanban swimlane resetting to \"None\" on initial load and after navigation\n - Thanks to @tnguyen2018 for reporting\n\n- (#1555) Fixed \"Folder already exists\" error when creating tasks or converting inline tasks\n - Thanks to @jkune5 for reporting\n\n- (#1532) Fixed expanded task modal buttons being cut off when content exceeds viewport height\n - Thanks to @willfanguy for reporting\n\n- (#1542) Fixed declined and cancelled events from ICS calendar subscriptions appearing in calendar view\n - Thanks to @karenchoe428 for reporting\n\n- (#1556) Fixed completion-based recurring tasks not rescheduling when the recurrence interval is large\n - Thanks to @kazerniel for reporting\n\n- (#1492) Fixed hardcoded \"open\" status leaking into filenames, recurring task displays, and parsing fallbacks\n - Users with custom default statuses (e.g. \"inbox\") no longer see \"open\" where their configured default should appear\n - Recurring tasks now show their actual configured status instead of always displaying \"open\" when not completed\n - Thanks to @macdrifter for reporting\n\n- (#1501) Fixed Google/Microsoft Calendar event colors not showing in agenda/list view\n - Per-event and calendar-level colors now display correctly in the list view, matching grid view behavior\n - Added today indicator highlighting to list view day headers\n - Thanks to @Robubble for the suggestion\n","aliases":["/releases/4.3.2/","/releases/4.3.2/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • (#1520) Tag and Context fields in Edit Task modal now show all available suggestions immediately on focus

    \n
      \n
    • Previously required typing at least one character before suggestions appeared
    • \n
    • Already-selected values are excluded from the suggestion list
    • \n
    • Thanks to @Glint-Eye for the suggestion
    • \n
    \n
  • \n
  • (#1506) Added setting to configure the default color for new timeblocks

    \n
      \n
    • New color picker in Settings > Features > Timeblocking
    • \n
    • Previously hardcoded to indigo; now user-configurable
    • \n
    • Thanks to @phillipadsmith for the suggestion
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • Fixed mdbase-spec type definition generation not triggering when settings change

    \n
  • \n
  • (#1456) Fixed inline tasks jumping visually when marked as completed

    \n
      \n
    • Thanks to @3zra47 for reporting
    • \n
    \n
  • \n
  • (#1364) Fixed auto-stop time tracking not triggering when completing recurring task instances

    \n
      \n
    • Thanks to @slipstyle for reporting
    • \n
    \n
  • \n
  • (#1465) Fixed all-day events synced to Google Calendar receiving wrong notification time

    \n
      \n
    • All-day events now use Google Calendar's configured all-day notification defaults instead of a minutes-based reminder
    • \n
    • Thanks to @Jomo94 for reporting
    • \n
    \n
  • \n
  • (#1470) Fixed cursor showing as default instead of pointer on interactive elements

    \n
      \n
    • Thanks to @TheFrostedDev for reporting
    • \n
    \n
  • \n
  • (#1491) Fixed boolean property values being quoted as strings in Bases filter generation

    \n
      \n
    • When using a boolean property (e.g. tasknote: true) for task identification, the filter now correctly handles the value
    • \n
    • Thanks to @denisgorod for reporting
    • \n
    \n
  • \n
  • (#1494) Fixed Kanban swimlane resetting to "None" on initial load and after navigation

    \n
      \n
    • Thanks to @tnguyen2018 for reporting
    • \n
    \n
  • \n
  • (#1555) Fixed "Folder already exists" error when creating tasks or converting inline tasks

    \n
      \n
    • Thanks to @jkune5 for reporting
    • \n
    \n
  • \n
  • (#1532) Fixed expanded task modal buttons being cut off when content exceeds viewport height

    \n
      \n
    • Thanks to @willfanguy for reporting
    • \n
    \n
  • \n
  • (#1542) Fixed declined and cancelled events from ICS calendar subscriptions appearing in calendar view

    \n
      \n
    • Thanks to @karenchoe428 for reporting
    • \n
    \n
  • \n
  • (#1556) Fixed completion-based recurring tasks not rescheduling when the recurrence interval is large

    \n
      \n
    • Thanks to @kazerniel for reporting
    • \n
    \n
  • \n
  • (#1492) Fixed hardcoded "open" status leaking into filenames, recurring task displays, and parsing fallbacks

    \n
      \n
    • Users with custom default statuses (e.g. "inbox") no longer see "open" where their configured default should appear
    • \n
    • Recurring tasks now show their actual configured status instead of always displaying "open" when not completed
    • \n
    • Thanks to @macdrifter for reporting
    • \n
    \n
  • \n
  • (#1501) Fixed Google/Microsoft Calendar event colors not showing in agenda/list view

    \n
      \n
    • Per-event and calendar-level colors now display correctly in the list view, matching grid view behavior
    • \n
    • Added today indicator highlighting to list view day headers
    • \n
    • Thanks to @Robubble for the suggestion
    • \n
    \n
  • \n
\n","text":"Added# (#1520) Tag and Context fields in Edit Task modal now show all available suggestions immediately on focus Previously required typing at least one character before suggestions appeared Already-selected values are excluded from the suggestion list Thanks to @Glint-Eye for the suggestion (#1506) Added setting to configure the default color for new timeblocks New color picker in Settings > Features > Timeblocking Previously hardcoded to indigo; now user-configurable Thanks to @phillipadsmith for the suggestion Fixed# Fixed mdbase-spec type definition generation not triggering when settings change (#1456) Fixed inline tasks jumping visually when marked as completed Thanks to @3zra47 for reporting (#1364) Fixed auto-stop time tracking not triggering when completing recurring task instances Thanks to @slipstyle for reporting (#1465) Fixed all-day events synced to Google Calendar receiving wrong notification time All-day events now use Google Calendar's configured all-day notification defaults instead of a minutes-based reminder Thanks to @Jomo94 for reporting (#1470) Fixed cursor showing as default instead of pointer on interactive elements Thanks to @TheFrostedDev for reporting (#1491) Fixed boolean property values being quoted as strings in Bases filter generation When using a boolean property (e.g. tasknote: true) for task identification, the filter now correctly handles the value Thanks to @denisgorod for reporting (#1494) Fixed Kanban swimlane resetting to \"None\" on initial load and after navigation Thanks to @tnguyen2018 for reporting (#1555) Fixed \"Folder already exists\" error when creating tasks or converting inline tasks Thanks to @jkune5 for reporting (#1532) Fixed expanded task modal buttons being cut off when content exceeds viewport height Thanks to @willfanguy for reporting (#1542) Fixed declined and cancelled events from ICS calendar subscriptions appearing in calendar view Thanks to @karenchoe428 for reporting (#1556) Fixed completion-based recurring tasks not rescheduling when the recurrence interval is large Thanks to @kazerniel for reporting (#1492) Fixed hardcoded \"open\" status leaking into filenames, recurring task displays, and parsing fallbacks Users with custom default statuses (e.g. \"inbox\") no longer see \"open\" where their configured default should appear Recurring tasks now show their actual configured status instead of always displaying \"open\" when not completed Thanks to @macdrifter for reporting (#1501) Fixed Google/Microsoft Calendar event colors not showing in agenda/list view Per-event and calendar-level colors now display correctly in the list view, matching grid view behavior Added today indicator highlighting to list view day headers Thanks to @Robubble for the suggestion"},{"route":"/obsidian/releases/4.3.3/","title":"TaskNotes 4.3.3","description":"Published mdbase-tasknotes (mtn), a standalone CLI for managing tasks in markdown files via mdbase","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.3.3.md","namespace":"obsidian","relativePath":"releases/4.3.3.md","raw":"# TaskNotes 4.3.3\n\n## Changed\n\n- Published [`mdbase-tasknotes`](https://github.com/callumalpass/mdbase-tasknotes) (`mtn`), a standalone CLI for managing tasks in markdown files via mdbase\n - Works on the same vault and `_types/task.md` schema that TaskNotes generates, without requiring the plugin or HTTP API\n - Preferable over [tasknotes-cli](https://github.com/callumalpass/tasknotes-cli) as a lighter-weight alternative and when Obsidian is not running, on remote machines, or in scripts and CI environments\n - Supports natural language task creation, time tracking, project aggregation, statistics, and an interactive REPL\n\n- Extracted shared natural language parsing logic into the standalone npm package [`tasknotes-nlp-core`](https://github.com/callumalpass/tasknotes-nlp-core)\n - The NLP parser and related language configuration are now shared through this package\n - This keeps behavior consistent between the plugin and CLI tools\n\n## Added\n\n- (#1549) Added setting to reset markdown checkboxes when recurring tasks are completed\n - When enabled, all checked checkboxes (`- [x]`) in the task body are reset to unchecked when a recurring task instance is completed and rescheduled\n - Useful for recurring tasks with subtask checklists that need to be repeated each instance\n - Configurable via Settings > Features > Recurring Tasks > \"Reset checkboxes on recurrence\"\n - Thanks to @phortx for the feature request\n\n- (#1548) Added ability to create calendar events on connected external calendars directly from the calendar view\n - When clicking or dragging to select a time slot, a new \"Create calendar event\" option appears in the context menu\n - Opens a modal to enter event title, description, location, and select which calendar to create on\n - Supports both Google Calendar and Microsoft Calendar providers\n - Thanks to @Robubble for the feature request\n\n- (#1597) Added MCP server for AI agent integration\n - Exposes TaskNotes tools at `/mcp` endpoint, gated behind `enableMCP` setting\n - Supports tasks (CRUD, query, toggle status/archive, parse from text), time tracking, pomodoro, calendar events, and task statistics\n - Thanks to @dstotijn for the contribution\n\n## Fixed\n\n- Fixed generated [mdbase](https://mdbase.dev) type definitions for task dependencies using the wrong field type\n - In `_types/task.md`, `blockedBy[].uid` now uses `type: link` (was `type: string`)\n - Better matches how dependency links are serialized in task frontmatter (`[[...]]`)\n\n- Fixed generated mdbase reminder type definitions to better match TaskNotes reminder data\n - In `_types/task.md`, `reminders[].type` now uses enum values `absolute|relative`\n - `reminders[].relatedTo` now uses enum values `due|scheduled`\n - `reminders[].absoluteTime` now uses `type: datetime` (was `type: string`)\n\n- (#1597) Fixed webhook payloads for time tracking start-with-description containing stale data\n - Thanks to @dstotijn for the fix\n\n- (#1581) Fixed Pomodoro starting break instead of work session after app restart\n - After completing a work session and restarting, pressing Start would incorrectly start a break\n - Now properly resets `nextSessionType` when clearing stale sessions or stopping the timer\n - Thanks to @Sirnii for the detailed bug report and root cause analysis\n\n- (#1577) Fixed Edit Note/Task modal hiding action buttons when content exceeds viewport height\n - Added vertical scroll to modal content area while keeping buttons pinned at bottom\n - Thanks to @hossam-elshabory for reporting and @ivannin for helping in discussion\n\n- (#1600) Fixed kanban view grouping not working when more than 20 views exist\n - The `getGroupByPropertyId()` method had a hardcoded loop limit of 20 iterations\n - Views at index 20 or higher would not be found, causing groupBy to return null\n - Thanks to @IHaveNoShame for reporting\n\n- (#1595) Fixed task modal floating buttons blocking content on mobile\n - Added mobile-specific (`body.is-mobile`) CSS to ensure proper flex layout\n - Button container now stays pinned at bottom without overlapping scrollable content\n - Thanks to @Jomo94 for reporting\n\n- (#1590) Fixed HTTP API not allowing `blockedBy` dependencies when creating tasks\n - Added `blockedBy` field support to `TaskService.createTask()`\n - Updated API documentation with `blockedBy`, `recurrence`, and `reminders` fields\n - Thanks to @hGriff0n for reporting\n\n- (#1582) Fixed recurring tasks not appearing at end of visible calendar range for non-UTC timezones\n - Daily/weekly recurring tasks with times after ~1pm would disappear on the last day of the visible range for users in positive UTC offsets (e.g., UTC+11)\n - Fixed date boundary comparisons in both `generateRecurringInstances()` and `generateRecurringTaskInstances()` to compare dates only, not timestamps\n - Thanks to @benefitbug for reporting\n\n- (#1580) Fixed Google Calendar sync failing after OAuth token expires with unhelpful error message\n - When refresh tokens expire or are revoked (e.g., Google Cloud project in Testing mode, user revoked access), the error message was confusing: \"Failed to refresh google token: Request failed, status 400\"\n - Now detects irrecoverable token errors (`invalid_grant`, `invalid_client`) and automatically disconnects the OAuth connection\n - Shows actionable error message: \"Google Calendar connection expired. Please reconnect in Settings > Integrations.\"\n - Prevents repeated failed refresh attempts and error message spam\n - Thanks to @osxisl for reporting and @Naesue for helping in discussion\n\n- (#1584) Fixed DOMTokenList error when task status values contain spaces\n - Clicking the status ring on a task card threw an error when status contained spaces (e.g., \"In Progress\")\n - Status and priority values are now sanitized before being used as CSS class names\n - Thanks to @omber for reporting\n","aliases":["/releases/4.3.3/","/releases/4.3.3/"],"toc":[{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Changed#

\n
    \n
  • Published mdbase-tasknotes (mtn), a standalone CLI for managing tasks in markdown files via mdbase

    \n
      \n
    • Works on the same vault and _types/task.md schema that TaskNotes generates, without requiring the plugin or HTTP API
    • \n
    • Preferable over tasknotes-cli as a lighter-weight alternative and when Obsidian is not running, on remote machines, or in scripts and CI environments
    • \n
    • Supports natural language task creation, time tracking, project aggregation, statistics, and an interactive REPL
    • \n
    \n
  • \n
  • Extracted shared natural language parsing logic into the standalone npm package tasknotes-nlp-core

    \n
      \n
    • The NLP parser and related language configuration are now shared through this package
    • \n
    • This keeps behavior consistent between the plugin and CLI tools
    • \n
    \n
  • \n
\n

Added#

\n
    \n
  • (#1549) Added setting to reset markdown checkboxes when recurring tasks are completed

    \n
      \n
    • When enabled, all checked checkboxes (- [x]) in the task body are reset to unchecked when a recurring task instance is completed and rescheduled
    • \n
    • Useful for recurring tasks with subtask checklists that need to be repeated each instance
    • \n
    • Configurable via Settings > Features > Recurring Tasks > "Reset checkboxes on recurrence"
    • \n
    • Thanks to @phortx for the feature request
    • \n
    \n
  • \n
  • (#1548) Added ability to create calendar events on connected external calendars directly from the calendar view

    \n
      \n
    • When clicking or dragging to select a time slot, a new "Create calendar event" option appears in the context menu
    • \n
    • Opens a modal to enter event title, description, location, and select which calendar to create on
    • \n
    • Supports both Google Calendar and Microsoft Calendar providers
    • \n
    • Thanks to @Robubble for the feature request
    • \n
    \n
  • \n
  • (#1597) Added MCP server for AI agent integration

    \n
      \n
    • Exposes TaskNotes tools at /mcp endpoint, gated behind enableMCP setting
    • \n
    • Supports tasks (CRUD, query, toggle status/archive, parse from text), time tracking, pomodoro, calendar events, and task statistics
    • \n
    • Thanks to @dstotijn for the contribution
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • Fixed generated mdbase type definitions for task dependencies using the wrong field type

    \n
      \n
    • In _types/task.md, blockedBy[].uid now uses type: link (was type: string)
    • \n
    • Better matches how dependency links are serialized in task frontmatter ([[...]])
    • \n
    \n
  • \n
  • Fixed generated mdbase reminder type definitions to better match TaskNotes reminder data

    \n
      \n
    • In _types/task.md, reminders[].type now uses enum values absolute|relative
    • \n
    • reminders[].relatedTo now uses enum values due|scheduled
    • \n
    • reminders[].absoluteTime now uses type: datetime (was type: string)
    • \n
    \n
  • \n
  • (#1597) Fixed webhook payloads for time tracking start-with-description containing stale data

    \n
      \n
    • Thanks to @dstotijn for the fix
    • \n
    \n
  • \n
  • (#1581) Fixed Pomodoro starting break instead of work session after app restart

    \n
      \n
    • After completing a work session and restarting, pressing Start would incorrectly start a break
    • \n
    • Now properly resets nextSessionType when clearing stale sessions or stopping the timer
    • \n
    • Thanks to @Sirnii for the detailed bug report and root cause analysis
    • \n
    \n
  • \n
  • (#1577) Fixed Edit Note/Task modal hiding action buttons when content exceeds viewport height

    \n
      \n
    • Added vertical scroll to modal content area while keeping buttons pinned at bottom
    • \n
    • Thanks to @hossam-elshabory for reporting and @ivannin for helping in discussion
    • \n
    \n
  • \n
  • (#1600) Fixed kanban view grouping not working when more than 20 views exist

    \n
      \n
    • The getGroupByPropertyId() method had a hardcoded loop limit of 20 iterations
    • \n
    • Views at index 20 or higher would not be found, causing groupBy to return null
    • \n
    • Thanks to @IHaveNoShame for reporting
    • \n
    \n
  • \n
  • (#1595) Fixed task modal floating buttons blocking content on mobile

    \n
      \n
    • Added mobile-specific (body.is-mobile) CSS to ensure proper flex layout
    • \n
    • Button container now stays pinned at bottom without overlapping scrollable content
    • \n
    • Thanks to @Jomo94 for reporting
    • \n
    \n
  • \n
  • (#1590) Fixed HTTP API not allowing blockedBy dependencies when creating tasks

    \n
      \n
    • Added blockedBy field support to TaskService.createTask()
    • \n
    • Updated API documentation with blockedBy, recurrence, and reminders fields
    • \n
    • Thanks to @hGriff0n for reporting
    • \n
    \n
  • \n
  • (#1582) Fixed recurring tasks not appearing at end of visible calendar range for non-UTC timezones

    \n
      \n
    • Daily/weekly recurring tasks with times after ~1pm would disappear on the last day of the visible range for users in positive UTC offsets (e.g., UTC+11)
    • \n
    • Fixed date boundary comparisons in both generateRecurringInstances() and generateRecurringTaskInstances() to compare dates only, not timestamps
    • \n
    • Thanks to @benefitbug for reporting
    • \n
    \n
  • \n
  • (#1580) Fixed Google Calendar sync failing after OAuth token expires with unhelpful error message

    \n
      \n
    • When refresh tokens expire or are revoked (e.g., Google Cloud project in Testing mode, user revoked access), the error message was confusing: "Failed to refresh google token: Request failed, status 400"
    • \n
    • Now detects irrecoverable token errors (invalid_grant, invalid_client) and automatically disconnects the OAuth connection
    • \n
    • Shows actionable error message: "Google Calendar connection expired. Please reconnect in Settings > Integrations."
    • \n
    • Prevents repeated failed refresh attempts and error message spam
    • \n
    • Thanks to @osxisl for reporting and @Naesue for helping in discussion
    • \n
    \n
  • \n
  • (#1584) Fixed DOMTokenList error when task status values contain spaces

    \n
      \n
    • Clicking the status ring on a task card threw an error when status contained spaces (e.g., "In Progress")
    • \n
    • Status and priority values are now sanitized before being used as CSS class names
    • \n
    • Thanks to @omber for reporting
    • \n
    \n
  • \n
\n","text":"Changed# Published mdbase-tasknotes (mtn), a standalone CLI for managing tasks in markdown files via mdbase Works on the same vault and _types/task.md schema that TaskNotes generates, without requiring the plugin or HTTP API Preferable over tasknotes-cli as a lighter-weight alternative and when Obsidian is not running, on remote machines, or in scripts and CI environments Supports natural language task creation, time tracking, project aggregation, statistics, and an interactive REPL Extracted shared natural language parsing logic into the standalone npm package tasknotes-nlp-core The NLP parser and related language configuration are now shared through this package This keeps behavior consistent between the plugin and CLI tools Added# (#1549) Added setting to reset markdown checkboxes when recurring tasks are completed When enabled, all checked checkboxes (- [x]) in the task body are reset to unchecked when a recurring task instance is completed and rescheduled Useful for recurring tasks with subtask checklists that need to be repeated each instance Configurable via Settings > Features > Recurring Tasks > \"Reset checkboxes on recurrence\" Thanks to @phortx for the feature request (#1548) Added ability to create calendar events on connected external calendars directly from the calendar view When clicking or dragging to select a time slot, a new \"Create calendar event\" option appears in the context menu Opens a modal to enter event title, description, location, and select which calendar to create on Supports both Google Calendar and Microsoft Calendar providers Thanks to @Robubble for the feature request (#1597) Added MCP server for AI agent integration Exposes TaskNotes tools at /mcp endpoint, gated behind enableMCP setting Supports tasks (CRUD, query, toggle status/archive, parse from text), time tracking, pomodoro, calendar events, and task statistics Thanks to @dstotijn for the contribution Fixed# Fixed generated mdbase type definitions for task dependencies using the wrong field type In _types/task.md, blockedBy[].uid now uses type: link (was type: string) Better matches how dependency links are serialized in task frontmatter ([[...]]) Fixed generated mdbase reminder type definitions to better match TaskNotes reminder data In _types/task.md, reminders[].type now uses enum values absolute|relative reminders[].relatedTo now uses enum values due|scheduled reminders[].absoluteTime now uses type: datetime (was type: string) (#1597) Fixed webhook payloads for time tracking start-with-description containing stale data Thanks to @dstotijn for the fix (#1581) Fixed Pomodoro starting break instead of work session after app restart After completing a work session and restarting, pressing Start would incorrectly start a break Now properly resets nextSessionType when clearing stale sessions or stopping the timer Thanks to @Sirnii for the detailed bug report and root cause analysis (#1577) Fixed Edit Note/Task modal hiding action buttons when content exceeds viewport height Added vertical scroll to modal content area while keeping buttons pinned at bottom Thanks to @hossam-elshabory for reporting and @ivannin for helping in discussion (#1600) Fixed kanban view grouping not working when more than 20 views exist The getGroupByPropertyId() method had a hardcoded loop limit of 20 iterations Views at index 20 or higher would not be found, causing groupBy to return null Thanks to @IHaveNoShame for reporting (#1595) Fixed task modal floating buttons blocking content on mobile Added mobile-specific (body.is-mobile) CSS to ensure proper flex layout Button container now stays pinned at bottom without overlapping scrollable content Thanks to @Jomo94 for reporting (#1590) Fixed HTTP API not allowing blockedBy dependencies when creating tasks Added blockedBy field support to TaskService.createTask() Updated API documentation with blockedBy, recurrence, and reminders fields Thanks to @hGriff0n for reporting (#1582) Fixed recurring tasks not appearing at end of visible calendar range for non-UTC timezones Daily/weekly recurring tasks with times after ~1pm would disappear on the last day of the visible range for users in positive UTC offsets (e.g., UTC+11) Fixed date boundary comparisons in both generateRecurringInstances() and generateRecurringTaskInstances() to compare dates only, not timestamps Thanks to @benefitbug for reporting (#1580) Fixed Google Calendar sync failing after OAuth token expires with unhelpful error message When refresh tokens expire or are revoked (e.g., Google Cloud project in Testing mode, user revoked access), the error message was confusing: \"Failed to refresh google token: Request failed, status 400\" Now detects irrecoverable token errors (invalid_grant, invalid_client) and automatically disconnects the OAuth connection Shows actionable error message: \"Google Calendar connection expired. Please reconnect in Settings > Integrations.\" Prevents repeated failed refresh attempts and error message spam Thanks to @osxisl for reporting and @Naesue for helping in discussion (#1584) Fixed DOMTokenList error when task status values contain spaces Clicking the status ring on a task card threw an error when status contained spaces (e.g., \"In Progress\") Status and priority values are now sanitized before being used as CSS class names Thanks to @omber for reporting"},{"route":"/obsidian/releases/4.4.0/","title":"TaskNotes 4.4.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.4.0.md","namespace":"obsidian","relativePath":"releases/4.4.0.md","raw":"# TaskNotes 4.4.0\n\n## Added\n\n- [Mdbase](https://mdbase.dev) type generation now includes `tn_role` annotations so external tools can identify each field's role even when frontmatter names are customized\n- (#1618) Mdbase type matching now follows your task identification settings (tag or frontmatter property), with fallback to tag matching when needed\n - Thanks to @jimbo108108 for reporting\n- Mdbase type status fields now include `tn_completed_values` so external tools can reliably identify which status values count as completed\n- (#1576) Added an optional `Checklist Progress` task-card property that renders a compact progress bar and `completed/total` count from top-level markdown checkboxes\n - Uses metadata cache list items and excludes nested checklist entries so progress reflects top-level task steps\n - In Bases views, map `tasks` (`file.tasks`) to `Checklist Progress`\n - Existing `.base` files need `file.tasks` added to the view `order` YAML manually\n - Newly generated `.base` templates now include `file.tasks` in view `order` by default\n - Thanks to @phortx for opening #1576 and for the earlier implementation PR, and @piyushaswani55 for feedback in the issue discussion\n\n## Changed\n\n- Mdbase type generation no longer overwrites `mdbase.yaml` if the file already exists, preserving user customisations\n- Webhooks now fire consistently regardless of whether updates come from the UI, HTTP API, or MCP\n- Webhook runtime state now syncs automatically when plugin settings change\n- Shared HTTP response/body parsing utilities are now consolidated in a dedicated `httpUtils` module\n- Release notes now include a reminder on every release page that default generated `.base` template changes never overwrite existing user `.base` files, and that users can regenerate templates from Settings to pick up updates\n\n## Fixed\n\n- (#1608) Fixed task title frontmatter being removed when `storeTitleInFilename` is enabled\n - `title` is now retained in frontmatter while filename derivation from title remains unchanged\n - Thanks to @victoraraujo105 for the PR\n- (#1602) Fixed time tracking statistics showing incorrect or zero values for Today/Week/Month due to UTC-anchored date range boundaries in Stats View\n - Updated range calculations to use local calendar-day boundaries consistently\n- (#1602) Fixed inconsistent `timeEntries` timestamp formats across create/edit/drag/resize flows\n - Time entry timestamps are now written in canonical UTC ISO format (`toISOString()` with `Z`) across all write paths\n- (#1602) Fixed denormalized `timeEntries.duration` drift after edits\n - Time tracking calculations now derive duration from `startTime`/`endTime`\n - Time entry save paths now strip legacy `duration` values instead of persisting them\n - Thanks to @dy66 for opening #1602\n","aliases":["/releases/4.4.0/","/releases/4.4.0/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • Mdbase type generation now includes tn_role annotations so external tools can identify each field's role even when frontmatter names are customized
  • \n
  • (#1618) Mdbase type matching now follows your task identification settings (tag or frontmatter property), with fallback to tag matching when needed
      \n
    • Thanks to @jimbo108108 for reporting
    • \n
    \n
  • \n
  • Mdbase type status fields now include tn_completed_values so external tools can reliably identify which status values count as completed
  • \n
  • (#1576) Added an optional Checklist Progress task-card property that renders a compact progress bar and completed/total count from top-level markdown checkboxes
      \n
    • Uses metadata cache list items and excludes nested checklist entries so progress reflects top-level task steps
    • \n
    • In Bases views, map tasks (file.tasks) to Checklist Progress
    • \n
    • Existing .base files need file.tasks added to the view order YAML manually
    • \n
    • Newly generated .base templates now include file.tasks in view order by default
    • \n
    • Thanks to @phortx for opening #1576 and for the earlier implementation PR, and @piyushaswani55 for feedback in the issue discussion
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Mdbase type generation no longer overwrites mdbase.yaml if the file already exists, preserving user customisations
  • \n
  • Webhooks now fire consistently regardless of whether updates come from the UI, HTTP API, or MCP
  • \n
  • Webhook runtime state now syncs automatically when plugin settings change
  • \n
  • Shared HTTP response/body parsing utilities are now consolidated in a dedicated httpUtils module
  • \n
  • Release notes now include a reminder on every release page that default generated .base template changes never overwrite existing user .base files, and that users can regenerate templates from Settings to pick up updates
  • \n
\n

Fixed#

\n
    \n
  • (#1608) Fixed task title frontmatter being removed when storeTitleInFilename is enabled
      \n
    • title is now retained in frontmatter while filename derivation from title remains unchanged
    • \n
    • Thanks to @victoraraujo105 for the PR
    • \n
    \n
  • \n
  • (#1602) Fixed time tracking statistics showing incorrect or zero values for Today/Week/Month due to UTC-anchored date range boundaries in Stats View
      \n
    • Updated range calculations to use local calendar-day boundaries consistently
    • \n
    \n
  • \n
  • (#1602) Fixed inconsistent timeEntries timestamp formats across create/edit/drag/resize flows
      \n
    • Time entry timestamps are now written in canonical UTC ISO format (toISOString() with Z) across all write paths
    • \n
    \n
  • \n
  • (#1602) Fixed denormalized timeEntries.duration drift after edits
      \n
    • Time tracking calculations now derive duration from startTime/endTime
    • \n
    • Time entry save paths now strip legacy duration values instead of persisting them
    • \n
    • Thanks to @dy66 for opening #1602
    • \n
    \n
  • \n
\n","text":"Added# Mdbase type generation now includes tn_role annotations so external tools can identify each field's role even when frontmatter names are customized (#1618) Mdbase type matching now follows your task identification settings (tag or frontmatter property), with fallback to tag matching when needed Thanks to @jimbo108108 for reporting Mdbase type status fields now include tn_completed_values so external tools can reliably identify which status values count as completed (#1576) Added an optional Checklist Progress task-card property that renders a compact progress bar and completed/total count from top-level markdown checkboxes Uses metadata cache list items and excludes nested checklist entries so progress reflects top-level task steps In Bases views, map tasks (file.tasks) to Checklist Progress Existing .base files need file.tasks added to the view order YAML manually Newly generated .base templates now include file.tasks in view order by default Thanks to @phortx for opening #1576 and for the earlier implementation PR, and @piyushaswani55 for feedback in the issue discussion Changed# Mdbase type generation no longer overwrites mdbase.yaml if the file already exists, preserving user customisations Webhooks now fire consistently regardless of whether updates come from the UI, HTTP API, or MCP Webhook runtime state now syncs automatically when plugin settings change Shared HTTP response/body parsing utilities are now consolidated in a dedicated httpUtils module Release notes now include a reminder on every release page that default generated .base template changes never overwrite existing user .base files, and that users can regenerate templates from Settings to pick up updates Fixed# (#1608) Fixed task title frontmatter being removed when storeTitleInFilename is enabled title is now retained in frontmatter while filename derivation from title remains unchanged Thanks to @victoraraujo105 for the PR (#1602) Fixed time tracking statistics showing incorrect or zero values for Today/Week/Month due to UTC-anchored date range boundaries in Stats View Updated range calculations to use local calendar-day boundaries consistently (#1602) Fixed inconsistent timeEntries timestamp formats across create/edit/drag/resize flows Time entry timestamps are now written in canonical UTC ISO format (toISOString() with Z) across all write paths (#1602) Fixed denormalized timeEntries.duration drift after edits Time tracking calculations now derive duration from startTime/endTime Time entry save paths now strip legacy duration values instead of persisting them Thanks to @dy66 for opening #1602"},{"route":"/obsidian/releases/4.5.0/","title":"TaskNotes 4.5.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.5.0.md","namespace":"obsidian","relativePath":"releases/4.5.0.md","raw":"# TaskNotes 4.5.0\n\n## Fixed\n\n- (#1652) Fixed API, MCP, and NLP task creation so it respects your configured filename format when title storage in filenames is disabled\n - Thanks to @36mimu36 for reporting, and @rafavital and @warm-july for follow-up discussion and reports\n- (#1601, #1709) Fixed reading-mode relationship widgets sometimes rendering multiple times during startup\n - Applied the same protection to task cards so overlapping refreshes are coalesced there too\n - Thanks to @wealthychef1 and @CarlJohnson99 for reporting, and @benmartinek for confirming the behavior\n- (#1713) Fixed ICS export so date-only scheduled tasks are written as all-day events instead of midnight events\n - Thanks to @bepolymathe for the request and interoperability details\n- (#267, #948, #1682, #1717, #1725) Fixed expanded subtasks and dependency cards in Bases Task List and Kanban views so related items can inherit the current view's filters instead of always showing every linked task\n - Added a per-view \"Expanded relationships\" option so you can switch between inherited filters and showing all related tasks\n - Thanks to @mdbraber, @GardarikanetS, @Glint-Eye, @prepare4robots, and @robmcphers0n for the original reports and feature requests, and @marblebyte for follow-up discussion\n- Improved custom view and search-pane activation when reopening deferred tabs\n- (#1720) Fixed Bases Task List cards showing icon tokens such as `clock` instead of readable date-like values, and fixed property labels to use Bases display names instead of raw property IDs\n - Thanks to @Sirnii for reporting\n- (#1633) Fixed interactive task-card labels and ribbon labels so Bases-backed cards use translations and configured display names instead of hardcoded English or raw property IDs\n - Thanks to @Sarryaz for reporting\n- (#1651) Fixed date `is` query filtering so date-only searches also match timed `scheduled` and `due` values during prefiltering\n - Thanks to @36mimu36 for reporting\n- (#1644) Fixed generated default task views so recurring tasks without a `complete_instances` property still appear as incomplete where appropriate\n - Thanks to @bkennedy-improving for reporting, and @SandroK for follow-up discussion on related default-view behavior\n- (#1513, #1686) Fixed a calendar issue where creating or editing events and timeblocks could reset the visible date back to today\n - In-place calendar recreation now preserves the visible date unless you explicitly navigate elsewhere\n - Thanks to @owenoxen for opening #1513, and @Lorite for opening #1686 and contributing the fix\n- Fixed documentation deployment CI failures caused by `docs-builder/src/js/main.js` being excluded by a broad `.gitignore` rule\n- Reduced background calendar-sync overhead when persisting sync tokens\n- Prevented duplicate auto-stop time-tracking listeners from accumulating after settings reloads\n- Fixed a settings-lifecycle issue that could accumulate calendar update callbacks while the Integrations tab is repeatedly opened\n- (#1630) Fixed TaskNote inline task cards ignoring centered \"Readable line length\" layout in the Minimal theme\n - Thanks to @martin-forge for reporting\n- Fixed a broken docs cross-reference from Property Types Reference to Task Properties settings\n- Fixed docs site links so internal Markdown links resolve to app routes instead of broken `.md` paths\n- Fixed docs release-note links by building Markdown pages even when they are not listed directly in the sidebar\n\n## Added\n\n- (#1704) Added an option to widen the current day column in multi-day calendar time-grid views\n - You can control the width multiplier and choose whether it applies to week view, custom multi-day view, or both\n - Thanks to @dictionarymouse for the feature request\n- Added TaskNotes Obsidian CLI commands for task creation, time tracking, and Pomodoro control\n - Includes shared NLP-to-task conversion across the CLI, modal, and API capture flows, plus new user documentation for the built-in CLI commands\n- (#1716) Added roomier subtask and dependency cards inside the task modal while keeping the task options menu available\n - Thanks to @hokfujow for the feature request\n- (#1619, #386, #621) Added drag-to-reorder for Kanban and Task List views\n - Supports grouped Task List moves, manual ordering via the `tasknotes_manual_order` property, and improved drag/drop behavior for swimlanes, filtered views, and interactive task controls\n - To use it, sort the view by the Manual Order field (`tasknotes_manual_order` by default), or regenerate the built-in `.base` templates from **Settings → TaskNotes → General → Create Default Files**\n - Thanks to @ac8318740 for the original contribution in PR #1619, @iholston and @dsebastien for opening #386 and #621, and @mdbraber, @elvarb, @LucidToday, @craziedde, @kmaustral, @SKIERZZ, @sookochoff, and @kanzaki1201 for follow-up discussion and testing across the linked issues and PR\n- Added a standalone [TaskNotes Specification](https://github.com/callumalpass/tasknotes-spec) repo and docs section covering the data model, field mapping, recurrence behavior, validation rules, and conformance tests\n- Added [tasknotes-tui](https://github.com/callumalpass/tasknotes-tui), a terminal UI for working with TaskNotes vaults\n - Includes keyboard-driven views, date navigation, time tracking, recurring task support, and a command palette\n\n## Changed\n\n- Refactored several internal modules to reduce coupling and make maintenance safer\n- Updated generated `_types/task.md` output so `dateCreated` and `dateModified` include generated timestamp values, and `recurrence_anchor` defaults to `scheduled`\n- Cleaned up API, webhook, NLP, privacy, settings, and view documentation for clarity and accuracy\n- Expanded Task List and Kanban documentation for drag-to-reorder, including manual-order sorting, grouped and swimlane scope, and filtered-view limitations\n","aliases":["/releases/4.5.0/","/releases/4.5.0/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"}],"html":"

Fixed#

\n
    \n
  • (#1652) Fixed API, MCP, and NLP task creation so it respects your configured filename format when title storage in filenames is disabled
      \n
    • Thanks to @36mimu36 for reporting, and @rafavital and @warm-july for follow-up discussion and reports
    • \n
    \n
  • \n
  • (#1601, #1709) Fixed reading-mode relationship widgets sometimes rendering multiple times during startup
      \n
    • Applied the same protection to task cards so overlapping refreshes are coalesced there too
    • \n
    • Thanks to @wealthychef1 and @CarlJohnson99 for reporting, and @benmartinek for confirming the behavior
    • \n
    \n
  • \n
  • (#1713) Fixed ICS export so date-only scheduled tasks are written as all-day events instead of midnight events
      \n
    • Thanks to @bepolymathe for the request and interoperability details
    • \n
    \n
  • \n
  • (#267, #948, #1682, #1717, #1725) Fixed expanded subtasks and dependency cards in Bases Task List and Kanban views so related items can inherit the current view's filters instead of always showing every linked task
      \n
    • Added a per-view "Expanded relationships" option so you can switch between inherited filters and showing all related tasks
    • \n
    • Thanks to @mdbraber, @GardarikanetS, @Glint-Eye, @prepare4robots, and @robmcphers0n for the original reports and feature requests, and @marblebyte for follow-up discussion
    • \n
    \n
  • \n
  • Improved custom view and search-pane activation when reopening deferred tabs
  • \n
  • (#1720) Fixed Bases Task List cards showing icon tokens such as clock instead of readable date-like values, and fixed property labels to use Bases display names instead of raw property IDs
      \n
    • Thanks to @Sirnii for reporting
    • \n
    \n
  • \n
  • (#1633) Fixed interactive task-card labels and ribbon labels so Bases-backed cards use translations and configured display names instead of hardcoded English or raw property IDs
      \n
    • Thanks to @Sarryaz for reporting
    • \n
    \n
  • \n
  • (#1651) Fixed date is query filtering so date-only searches also match timed scheduled and due values during prefiltering
      \n
    • Thanks to @36mimu36 for reporting
    • \n
    \n
  • \n
  • (#1644) Fixed generated default task views so recurring tasks without a complete_instances property still appear as incomplete where appropriate
      \n
    • Thanks to @bkennedy-improving for reporting, and @SandroK for follow-up discussion on related default-view behavior
    • \n
    \n
  • \n
  • (#1513, #1686) Fixed a calendar issue where creating or editing events and timeblocks could reset the visible date back to today
      \n
    • In-place calendar recreation now preserves the visible date unless you explicitly navigate elsewhere
    • \n
    • Thanks to @owenoxen for opening #1513, and @Lorite for opening #1686 and contributing the fix
    • \n
    \n
  • \n
  • Fixed documentation deployment CI failures caused by docs-builder/src/js/main.js being excluded by a broad .gitignore rule
  • \n
  • Reduced background calendar-sync overhead when persisting sync tokens
  • \n
  • Prevented duplicate auto-stop time-tracking listeners from accumulating after settings reloads
  • \n
  • Fixed a settings-lifecycle issue that could accumulate calendar update callbacks while the Integrations tab is repeatedly opened
  • \n
  • (#1630) Fixed TaskNote inline task cards ignoring centered "Readable line length" layout in the Minimal theme
      \n
    • Thanks to @martin-forge for reporting
    • \n
    \n
  • \n
  • Fixed a broken docs cross-reference from Property Types Reference to Task Properties settings
  • \n
  • Fixed docs site links so internal Markdown links resolve to app routes instead of broken .md paths
  • \n
  • Fixed docs release-note links by building Markdown pages even when they are not listed directly in the sidebar
  • \n
\n

Added#

\n
    \n
  • (#1704) Added an option to widen the current day column in multi-day calendar time-grid views
      \n
    • You can control the width multiplier and choose whether it applies to week view, custom multi-day view, or both
    • \n
    • Thanks to @dictionarymouse for the feature request
    • \n
    \n
  • \n
  • Added TaskNotes Obsidian CLI commands for task creation, time tracking, and Pomodoro control
      \n
    • Includes shared NLP-to-task conversion across the CLI, modal, and API capture flows, plus new user documentation for the built-in CLI commands
    • \n
    \n
  • \n
  • (#1716) Added roomier subtask and dependency cards inside the task modal while keeping the task options menu available
      \n
    • Thanks to @hokfujow for the feature request
    • \n
    \n
  • \n
  • (#1619, #386, #621) Added drag-to-reorder for Kanban and Task List views
      \n
    • Supports grouped Task List moves, manual ordering via the tasknotes_manual_order property, and improved drag/drop behavior for swimlanes, filtered views, and interactive task controls
    • \n
    • To use it, sort the view by the Manual Order field (tasknotes_manual_order by default), or regenerate the built-in .base templates from Settings → TaskNotes → General → Create Default Files
    • \n
    • Thanks to @ac8318740 for the original contribution in PR #1619, @iholston and @dsebastien for opening #386 and #621, and @mdbraber, @elvarb, @LucidToday, @craziedde, @kmaustral, @SKIERZZ, @sookochoff, and @kanzaki1201 for follow-up discussion and testing across the linked issues and PR
    • \n
    \n
  • \n
  • Added a standalone TaskNotes Specification repo and docs section covering the data model, field mapping, recurrence behavior, validation rules, and conformance tests
  • \n
  • Added tasknotes-tui, a terminal UI for working with TaskNotes vaults
      \n
    • Includes keyboard-driven views, date navigation, time tracking, recurring task support, and a command palette
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Refactored several internal modules to reduce coupling and make maintenance safer
  • \n
  • Updated generated _types/task.md output so dateCreated and dateModified include generated timestamp values, and recurrence_anchor defaults to scheduled
  • \n
  • Cleaned up API, webhook, NLP, privacy, settings, and view documentation for clarity and accuracy
  • \n
  • Expanded Task List and Kanban documentation for drag-to-reorder, including manual-order sorting, grouped and swimlane scope, and filtered-view limitations
  • \n
\n","text":"Fixed# (#1652) Fixed API, MCP, and NLP task creation so it respects your configured filename format when title storage in filenames is disabled Thanks to @36mimu36 for reporting, and @rafavital and @warm-july for follow-up discussion and reports (#1601, #1709) Fixed reading-mode relationship widgets sometimes rendering multiple times during startup Applied the same protection to task cards so overlapping refreshes are coalesced there too Thanks to @wealthychef1 and @CarlJohnson99 for reporting, and @benmartinek for confirming the behavior (#1713) Fixed ICS export so date-only scheduled tasks are written as all-day events instead of midnight events Thanks to @bepolymathe for the request and interoperability details (#267, #948, #1682, #1717, #1725) Fixed expanded subtasks and dependency cards in Bases Task List and Kanban views so related items can inherit the current view's filters instead of always showing every linked task Added a per-view \"Expanded relationships\" option so you can switch between inherited filters and showing all related tasks Thanks to @mdbraber, @GardarikanetS, @Glint-Eye, @prepare4robots, and @robmcphers0n for the original reports and feature requests, and @marblebyte for follow-up discussion Improved custom view and search-pane activation when reopening deferred tabs (#1720) Fixed Bases Task List cards showing icon tokens such as clock instead of readable date-like values, and fixed property labels to use Bases display names instead of raw property IDs Thanks to @Sirnii for reporting (#1633) Fixed interactive task-card labels and ribbon labels so Bases-backed cards use translations and configured display names instead of hardcoded English or raw property IDs Thanks to @Sarryaz for reporting (#1651) Fixed date is query filtering so date-only searches also match timed scheduled and due values during prefiltering Thanks to @36mimu36 for reporting (#1644) Fixed generated default task views so recurring tasks without a complete_instances property still appear as incomplete where appropriate Thanks to @bkennedy-improving for reporting, and @SandroK for follow-up discussion on related default-view behavior (#1513, #1686) Fixed a calendar issue where creating or editing events and timeblocks could reset the visible date back to today In-place calendar recreation now preserves the visible date unless you explicitly navigate elsewhere Thanks to @owenoxen for opening #1513, and @Lorite for opening #1686 and contributing the fix Fixed documentation deployment CI failures caused by docs-builder/src/js/main.js being excluded by a broad .gitignore rule Reduced background calendar-sync overhead when persisting sync tokens Prevented duplicate auto-stop time-tracking listeners from accumulating after settings reloads Fixed a settings-lifecycle issue that could accumulate calendar update callbacks while the Integrations tab is repeatedly opened (#1630) Fixed TaskNote inline task cards ignoring centered \"Readable line length\" layout in the Minimal theme Thanks to @martin-forge for reporting Fixed a broken docs cross-reference from Property Types Reference to Task Properties settings Fixed docs site links so internal Markdown links resolve to app routes instead of broken .md paths Fixed docs release-note links by building Markdown pages even when they are not listed directly in the sidebar Added# (#1704) Added an option to widen the current day column in multi-day calendar time-grid views You can control the width multiplier and choose whether it applies to week view, custom multi-day view, or both Thanks to @dictionarymouse for the feature request Added TaskNotes Obsidian CLI commands for task creation, time tracking, and Pomodoro control Includes shared NLP-to-task conversion across the CLI, modal, and API capture flows, plus new user documentation for the built-in CLI commands (#1716) Added roomier subtask and dependency cards inside the task modal while keeping the task options menu available Thanks to @hokfujow for the feature request (#1619, #386, #621) Added drag-to-reorder for Kanban and Task List views Supports grouped Task List moves, manual ordering via the tasknotes_manual_order property, and improved drag/drop behavior for swimlanes, filtered views, and interactive task controls To use it, sort the view by the Manual Order field (tasknotes_manual_order by default), or regenerate the built-in .base templates from Settings → TaskNotes → General → Create Default Files Thanks to @ac8318740 for the original contribution in PR #1619, @iholston and @dsebastien for opening #386 and #621, and @mdbraber, @elvarb, @LucidToday, @craziedde, @kmaustral, @SKIERZZ, @sookochoff, and @kanzaki1201 for follow-up discussion and testing across the linked issues and PR Added a standalone TaskNotes Specification repo and docs section covering the data model, field mapping, recurrence behavior, validation rules, and conformance tests Added tasknotes-tui, a terminal UI for working with TaskNotes vaults Includes keyboard-driven views, date navigation, time tracking, recurring task support, and a command palette Changed# Refactored several internal modules to reduce coupling and make maintenance safer Updated generated _types/task.md output so dateCreated and dateModified include generated timestamp values, and recurrence_anchor defaults to scheduled Cleaned up API, webhook, NLP, privacy, settings, and view documentation for clarity and accuracy Expanded Task List and Kanban documentation for drag-to-reorder, including manual-order sorting, grouped and swimlane scope, and filtered-view limitations"},{"route":"/obsidian/releases/4.5.1/","title":"TaskNotes 4.5.1","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.5.1.md","namespace":"obsidian","relativePath":"releases/4.5.1.md","raw":"# TaskNotes 4.5.1\n\n## Fixed\n\n- (#1672) Fixed custom date ranges in the MCP time summary tool so `from` and `to` dates work as expected\n - Thanks to @pib for the fix\n- (#1742) Fixed calendar week and day views so the time scale stays aligned on the left instead of drifting inward\n - Thanks to @ysafonov for the report and screenshot\n","aliases":["/releases/4.5.1/","/releases/4.5.1/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Fixed#

\n
    \n
  • (#1672) Fixed custom date ranges in the MCP time summary tool so from and to dates work as expected
      \n
    • Thanks to @pib for the fix
    • \n
    \n
  • \n
  • (#1742) Fixed calendar week and day views so the time scale stays aligned on the left instead of drifting inward
      \n
    • Thanks to @ysafonov for the report and screenshot
    • \n
    \n
  • \n
\n","text":"Fixed# (#1672) Fixed custom date ranges in the MCP time summary tool so from and to dates work as expected Thanks to @pib for the fix (#1742) Fixed calendar week and day views so the time scale stays aligned on the left instead of drifting inward Thanks to @ysafonov for the report and screenshot"},{"route":"/obsidian/releases/4.5.2/","title":"TaskNotes 4.5.2","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.5.2.md","namespace":"obsidian","relativePath":"releases/4.5.2.md","raw":"# TaskNotes 4.5.2\n\n## Added\n\n- (#1342, #1793) Added native tag autocomplete to time entry descriptions by using the embedded markdown editor in the time entry editor modal.\n - Thanks to @fastrick for the request and @renatomen for the PR.\n- (#1756, #1798) Added HTTP API support for configured custom user fields so task responses include them and create/update requests can round-trip their values.\n - Thanks to @Treygec for the request and PR.\n- (#1777) Added a Modal Fields setting to choose whether Tab/Shift+Tab move focus out of the task details editor or use the markdown editor's indentation behavior.\n - Thanks to @P-Sc for the PR.\n\n## Changed\n\n- Updated the Obsidian API dependency to 1.12.3 and switched the Bases integration to the official API type declarations.\n- Bases task cards and property-event cards now render metadata values through Obsidian's native Bases value renderer so links, dates, lists, icons, and formula values display more faithfully.\n\n## Fixed\n\n- (#1778) Fixed MCP initialize requests using newer protocol versions such as `2025-11-25` failing instead of negotiating down to TaskNotes' supported MCP version.\n - Thanks to @SakulaPor for reporting.\n- (#1781) Fixed duplicate metadata properties on Bases task cards when bare and `note.`-prefixed property IDs map to the same TaskNotes field.\n - Thanks to @loukandr for reporting and tracing the issue.\n- (#1787) Removed the \"(click to change)\" helper text from recurrence tooltips on task cards.\n - Thanks to @kazerniel for reporting.\n- (#1828) Fixed subtask creation from a task card dropping the parent task project when natural-language input also adds projects.\n - Thanks to @prepare4robots for reporting.\n- (#1786) Fixed TaskNotes task cards and relationships/subtasks widgets appearing inside embedded task-note heading or block sections.\n - Skips note-level widget injection in detached or embedded Markdown editor contexts used by plugins such as Block Link Plus.\n - Thanks to @3zra47 for reporting.\n- (#1815) Fixed the Priority property settings so the NLP trigger character field is visible and editable even when priority NLP parsing is disabled.\n - Thanks to @spiv for reporting.\n- (#1035) Fixed the task modal title field causing the modal to jump to the bottom when focused on iPhone.\n - Thanks to @3zra47 for reporting and following up.\n- (#1045) Fixed inline linked recurring tasks keeping the previous day's completed state after the calendar day changes.\n - Thanks to @3zra47 for reporting and following up.\n- (#1788) Fixed Task List subgroup headers and cards rendering without clear indentation.\n - Thanks to @renatomen for the PR.\n- (#1810) Updated Japanese Kanban terminology to use the more natural katakana spelling.\n - Thanks to @sigma7863 for the PR.\n- (#1633) Fixed Bases task cards using fallback labels instead of Bases display names for mapped task fields and file properties.\n - Thanks to @Sarryaz for reporting the Bases task card i18n and field-mapping issue.\n- (#884) Fixed untranslated strings and English placeholder examples across non-English interface translations.\n - Thanks to @berzernberg for reporting Russian translation gaps.\n- (#1765, #1769) Fixed auto-archived tasks leaving stale Google Calendar events when cleanup runs before calendar sync is ready or after the task moves into the archive folder.\n - Thanks to @martin-forge for reporting and the PR.\n- (#1764) Fixed Google Calendar sync using stale task metadata after rapid task updates, and fixed late recurring completions/skips recording the completion day instead of the scheduled occurrence date.\n - Thanks to @martin-forge for the PR and to @jpmoo for reporting the recurring completion issues.\n- (#1782) Fixed CI test runs resolving the NLP parser package from a local sibling checkout instead of the published dependency.\n - Thanks to @martin-forge for reporting.\n- Published [`mdbase-tasknotes`](https://github.com/callumalpass/mdbase-tasknotes) 0.1.3 with compatibility fixes for TaskNotes-generated mdbase schemas.\n - Includes clearer create-path diagnostics, natural-language `mtn list --due` filters, timer log datetime filters, home-directory path expansion, project wikilink preservation, and correct `mtn --version` reporting.\n - Thanks to @tparsons9, @anomatomato, @npondel, @plashal, and @waspeer for the reports and PR.\n- (#1667) Fixed NLP scheduled-date parsing so standalone `scheduled` and `start` triggers can set scheduled dates alongside due dates.\n - Thanks to @hokfujow for reporting and @UniqueClone for the NLP core PR.\n- Fixed NLP parser title cleanup for explicit date triggers and Japanese/Chinese priority phrases.\n- (#1658) Fixed Pomodoro stats date bucketing for sessions near local midnight.\n - Pomodoro session stats now compare the recorded session calendar date against UTC-anchored target days without shifting through UTC or the reader's current timezone.\n - Pomodoro daily-note storage now writes sessions to the daily note matching the recorded session date.\n - Thanks to @ewgdg for reporting, @AntonIlinykh and @dkchacha for follow-up discussion, and @ITblacksheep for PR #1758.\n- (#1813) Fixed Pomodoro timer UI stalls caused by refreshing session statistics on every timer tick.\n - Pomodoro stats now refresh on initial render and session completion instead of once per second.\n - Pomodoro daily-note stats now read the relevant date/range instead of routing through all history.\n - Native Pomodoro notifications now respect the notification setting and granted permission before showing.\n - Thanks to @Szu-Szu for reporting and @its-thex for confirming.\n- (#1744) Fixed Bases Task List views so changing the per-view `Expanded relationships` option takes effect on re-render.\n - Restores the expected `show-all` behavior for setups that hide subtasks at the top level with `note.projects.isEmpty()`.\n - Thanks to @minol-dev for reporting, @Glint-Eye for follow-up discussion, and @stanley-910 for PR #1792 exploring the related standalone-subtask workflow.\n- Fixed tag clicks in task cards opening the task edit modal in addition to the tag search panel, and kept rendered tag metadata on a single row inside task cards.\n","aliases":["/releases/4.5.2/","/releases/4.5.2/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • (#1342, #1793) Added native tag autocomplete to time entry descriptions by using the embedded markdown editor in the time entry editor modal.
      \n
    • Thanks to @fastrick for the request and @renatomen for the PR.
    • \n
    \n
  • \n
  • (#1756, #1798) Added HTTP API support for configured custom user fields so task responses include them and create/update requests can round-trip their values.
      \n
    • Thanks to @Treygec for the request and PR.
    • \n
    \n
  • \n
  • (#1777) Added a Modal Fields setting to choose whether Tab/Shift+Tab move focus out of the task details editor or use the markdown editor's indentation behavior.
      \n
    • Thanks to @P-Sc for the PR.
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Updated the Obsidian API dependency to 1.12.3 and switched the Bases integration to the official API type declarations.
  • \n
  • Bases task cards and property-event cards now render metadata values through Obsidian's native Bases value renderer so links, dates, lists, icons, and formula values display more faithfully.
  • \n
\n

Fixed#

\n
    \n
  • (#1778) Fixed MCP initialize requests using newer protocol versions such as 2025-11-25 failing instead of negotiating down to TaskNotes' supported MCP version.
      \n
    • Thanks to @SakulaPor for reporting.
    • \n
    \n
  • \n
  • (#1781) Fixed duplicate metadata properties on Bases task cards when bare and note.-prefixed property IDs map to the same TaskNotes field.
      \n
    • Thanks to @loukandr for reporting and tracing the issue.
    • \n
    \n
  • \n
  • (#1787) Removed the "(click to change)" helper text from recurrence tooltips on task cards.
      \n
    • Thanks to @kazerniel for reporting.
    • \n
    \n
  • \n
  • (#1828) Fixed subtask creation from a task card dropping the parent task project when natural-language input also adds projects.
      \n
    • Thanks to @prepare4robots for reporting.
    • \n
    \n
  • \n
  • (#1786) Fixed TaskNotes task cards and relationships/subtasks widgets appearing inside embedded task-note heading or block sections.
      \n
    • Skips note-level widget injection in detached or embedded Markdown editor contexts used by plugins such as Block Link Plus.
    • \n
    • Thanks to @3zra47 for reporting.
    • \n
    \n
  • \n
  • (#1815) Fixed the Priority property settings so the NLP trigger character field is visible and editable even when priority NLP parsing is disabled.
      \n
    • Thanks to @spiv for reporting.
    • \n
    \n
  • \n
  • (#1035) Fixed the task modal title field causing the modal to jump to the bottom when focused on iPhone.
      \n
    • Thanks to @3zra47 for reporting and following up.
    • \n
    \n
  • \n
  • (#1045) Fixed inline linked recurring tasks keeping the previous day's completed state after the calendar day changes.
      \n
    • Thanks to @3zra47 for reporting and following up.
    • \n
    \n
  • \n
  • (#1788) Fixed Task List subgroup headers and cards rendering without clear indentation.
      \n
    • Thanks to @renatomen for the PR.
    • \n
    \n
  • \n
  • (#1810) Updated Japanese Kanban terminology to use the more natural katakana spelling.
      \n
    • Thanks to @sigma7863 for the PR.
    • \n
    \n
  • \n
  • (#1633) Fixed Bases task cards using fallback labels instead of Bases display names for mapped task fields and file properties.
      \n
    • Thanks to @Sarryaz for reporting the Bases task card i18n and field-mapping issue.
    • \n
    \n
  • \n
  • (#884) Fixed untranslated strings and English placeholder examples across non-English interface translations.
      \n
    • Thanks to @berzernberg for reporting Russian translation gaps.
    • \n
    \n
  • \n
  • (#1765, #1769) Fixed auto-archived tasks leaving stale Google Calendar events when cleanup runs before calendar sync is ready or after the task moves into the archive folder.
      \n
    • Thanks to @martin-forge for reporting and the PR.
    • \n
    \n
  • \n
  • (#1764) Fixed Google Calendar sync using stale task metadata after rapid task updates, and fixed late recurring completions/skips recording the completion day instead of the scheduled occurrence date.
      \n
    • Thanks to @martin-forge for the PR and to @jpmoo for reporting the recurring completion issues.
    • \n
    \n
  • \n
  • (#1782) Fixed CI test runs resolving the NLP parser package from a local sibling checkout instead of the published dependency.
      \n
    • Thanks to @martin-forge for reporting.
    • \n
    \n
  • \n
  • Published mdbase-tasknotes 0.1.3 with compatibility fixes for TaskNotes-generated mdbase schemas.
      \n
    • Includes clearer create-path diagnostics, natural-language mtn list --due filters, timer log datetime filters, home-directory path expansion, project wikilink preservation, and correct mtn --version reporting.
    • \n
    • Thanks to @tparsons9, @anomatomato, @npondel, @plashal, and @waspeer for the reports and PR.
    • \n
    \n
  • \n
  • (#1667) Fixed NLP scheduled-date parsing so standalone scheduled and start triggers can set scheduled dates alongside due dates.
      \n
    • Thanks to @hokfujow for reporting and @UniqueClone for the NLP core PR.
    • \n
    \n
  • \n
  • Fixed NLP parser title cleanup for explicit date triggers and Japanese/Chinese priority phrases.
  • \n
  • (#1658) Fixed Pomodoro stats date bucketing for sessions near local midnight.
      \n
    • Pomodoro session stats now compare the recorded session calendar date against UTC-anchored target days without shifting through UTC or the reader's current timezone.
    • \n
    • Pomodoro daily-note storage now writes sessions to the daily note matching the recorded session date.
    • \n
    • Thanks to @ewgdg for reporting, @AntonIlinykh and @dkchacha for follow-up discussion, and @ITblacksheep for PR #1758.
    • \n
    \n
  • \n
  • (#1813) Fixed Pomodoro timer UI stalls caused by refreshing session statistics on every timer tick.
      \n
    • Pomodoro stats now refresh on initial render and session completion instead of once per second.
    • \n
    • Pomodoro daily-note stats now read the relevant date/range instead of routing through all history.
    • \n
    • Native Pomodoro notifications now respect the notification setting and granted permission before showing.
    • \n
    • Thanks to @Szu-Szu for reporting and @its-thex for confirming.
    • \n
    \n
  • \n
  • (#1744) Fixed Bases Task List views so changing the per-view Expanded relationships option takes effect on re-render.
      \n
    • Restores the expected show-all behavior for setups that hide subtasks at the top level with note.projects.isEmpty().
    • \n
    • Thanks to @minol-dev for reporting, @Glint-Eye for follow-up discussion, and @stanley-910 for PR #1792 exploring the related standalone-subtask workflow.
    • \n
    \n
  • \n
  • Fixed tag clicks in task cards opening the task edit modal in addition to the tag search panel, and kept rendered tag metadata on a single row inside task cards.
  • \n
\n","text":"Added# (#1342, #1793) Added native tag autocomplete to time entry descriptions by using the embedded markdown editor in the time entry editor modal. Thanks to @fastrick for the request and @renatomen for the PR. (#1756, #1798) Added HTTP API support for configured custom user fields so task responses include them and create/update requests can round-trip their values. Thanks to @Treygec for the request and PR. (#1777) Added a Modal Fields setting to choose whether Tab/Shift+Tab move focus out of the task details editor or use the markdown editor's indentation behavior. Thanks to @P-Sc for the PR. Changed# Updated the Obsidian API dependency to 1.12.3 and switched the Bases integration to the official API type declarations. Bases task cards and property-event cards now render metadata values through Obsidian's native Bases value renderer so links, dates, lists, icons, and formula values display more faithfully. Fixed# (#1778) Fixed MCP initialize requests using newer protocol versions such as 2025-11-25 failing instead of negotiating down to TaskNotes' supported MCP version. Thanks to @SakulaPor for reporting. (#1781) Fixed duplicate metadata properties on Bases task cards when bare and note.-prefixed property IDs map to the same TaskNotes field. Thanks to @loukandr for reporting and tracing the issue. (#1787) Removed the \"(click to change)\" helper text from recurrence tooltips on task cards. Thanks to @kazerniel for reporting. (#1828) Fixed subtask creation from a task card dropping the parent task project when natural-language input also adds projects. Thanks to @prepare4robots for reporting. (#1786) Fixed TaskNotes task cards and relationships/subtasks widgets appearing inside embedded task-note heading or block sections. Skips note-level widget injection in detached or embedded Markdown editor contexts used by plugins such as Block Link Plus. Thanks to @3zra47 for reporting. (#1815) Fixed the Priority property settings so the NLP trigger character field is visible and editable even when priority NLP parsing is disabled. Thanks to @spiv for reporting. (#1035) Fixed the task modal title field causing the modal to jump to the bottom when focused on iPhone. Thanks to @3zra47 for reporting and following up. (#1045) Fixed inline linked recurring tasks keeping the previous day's completed state after the calendar day changes. Thanks to @3zra47 for reporting and following up. (#1788) Fixed Task List subgroup headers and cards rendering without clear indentation. Thanks to @renatomen for the PR. (#1810) Updated Japanese Kanban terminology to use the more natural katakana spelling. Thanks to @sigma7863 for the PR. (#1633) Fixed Bases task cards using fallback labels instead of Bases display names for mapped task fields and file properties. Thanks to @Sarryaz for reporting the Bases task card i18n and field-mapping issue. (#884) Fixed untranslated strings and English placeholder examples across non-English interface translations. Thanks to @berzernberg for reporting Russian translation gaps. (#1765, #1769) Fixed auto-archived tasks leaving stale Google Calendar events when cleanup runs before calendar sync is ready or after the task moves into the archive folder. Thanks to @martin-forge for reporting and the PR. (#1764) Fixed Google Calendar sync using stale task metadata after rapid task updates, and fixed late recurring completions/skips recording the completion day instead of the scheduled occurrence date. Thanks to @martin-forge for the PR and to @jpmoo for reporting the recurring completion issues. (#1782) Fixed CI test runs resolving the NLP parser package from a local sibling checkout instead of the published dependency. Thanks to @martin-forge for reporting. Published mdbase-tasknotes 0.1.3 with compatibility fixes for TaskNotes-generated mdbase schemas. Includes clearer create-path diagnostics, natural-language mtn list --due filters, timer log datetime filters, home-directory path expansion, project wikilink preservation, and correct mtn --version reporting. Thanks to @tparsons9, @anomatomato, @npondel, @plashal, and @waspeer for the reports and PR. (#1667) Fixed NLP scheduled-date parsing so standalone scheduled and start triggers can set scheduled dates alongside due dates. Thanks to @hokfujow for reporting and @UniqueClone for the NLP core PR. Fixed NLP parser title cleanup for explicit date triggers and Japanese/Chinese priority phrases. (#1658) Fixed Pomodoro stats date bucketing for sessions near local midnight. Pomodoro session stats now compare the recorded session calendar date against UTC-anchored target days without shifting through UTC or the reader's current timezone. Pomodoro daily-note storage now writes sessions to the daily note matching the recorded session date. Thanks to @ewgdg for reporting, @AntonIlinykh and @dkchacha for follow-up discussion, and @ITblacksheep for PR #1758. (#1813) Fixed Pomodoro timer UI stalls caused by refreshing session statistics on every timer tick. Pomodoro stats now refresh on initial render and session completion instead of once per second. Pomodoro daily-note stats now read the relevant date/range instead of routing through all history. Native Pomodoro notifications now respect the notification setting and granted permission before showing. Thanks to @Szu-Szu for reporting and @its-thex for confirming. (#1744) Fixed Bases Task List views so changing the per-view Expanded relationships option takes effect on re-render. Restores the expected show-all behavior for setups that hide subtasks at the top level with note.projects.isEmpty(). Thanks to @minol-dev for reporting, @Glint-Eye for follow-up discussion, and @stanley-910 for PR #1792 exploring the related standalone-subtask workflow. Fixed tag clicks in task cards opening the task edit modal in addition to the tag search panel, and kept rendered tag metadata on a single row inside task cards."},{"route":"/obsidian/releases/4.5.3/","title":"TaskNotes 4.5.3","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.5.3.md","namespace":"obsidian","relativePath":"releases/4.5.3.md","raw":"# TaskNotes 4.5.3\n\n## Fixed\n\n- (#1834, #1847) Fixed empty Bases formula and custom properties showing `null` or `undefined` on TaskNotes task cards.\n - A big thanks to @Glint-Eye and @3zra47 for reporting.\n- (#1836) Fixed TaskNotes Bases views not refreshing task cards after status, archive, and auto-archive updates.\n - A big thanks to @kmaustral for reporting.\n","aliases":["/releases/4.5.3/","/releases/4.5.3/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Fixed#

\n
    \n
  • (#1834, #1847) Fixed empty Bases formula and custom properties showing null or undefined on TaskNotes task cards.
      \n
    • A big thanks to @Glint-Eye and @3zra47 for reporting.
    • \n
    \n
  • \n
  • (#1836) Fixed TaskNotes Bases views not refreshing task cards after status, archive, and auto-archive updates.
      \n
    • A big thanks to @kmaustral for reporting.
    • \n
    \n
  • \n
\n","text":"Fixed# (#1834, #1847) Fixed empty Bases formula and custom properties showing null or undefined on TaskNotes task cards. A big thanks to @Glint-Eye and @3zra47 for reporting. (#1836) Fixed TaskNotes Bases views not refreshing task cards after status, archive, and auto-archive updates. A big thanks to @kmaustral for reporting."},{"route":"/obsidian/releases/4.6.0/","title":"TaskNotes 4.6.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.6.0.md","namespace":"obsidian","relativePath":"releases/4.6.0.md","raw":"# TaskNotes 4.6.0\n\n## Changed\n\n- TaskNotes now requires Obsidian 1.12.2 or later, matching the Obsidian APIs used by the plugin.\n- Improved internal code quality by resolving lint warnings, moving static inline styles into CSS utilities, and extending sentence-case lint coverage to English localization strings, with no intended behavior changes.\n\n## Fixed\n\n- Fixed TaskNotes failing to load when Obsidian opened without an active Markdown file.\n","aliases":["/releases/4.6.0/","/releases/4.6.0/"],"toc":[{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Changed#

\n
    \n
  • TaskNotes now requires Obsidian 1.12.2 or later, matching the Obsidian APIs used by the plugin.
  • \n
  • Improved internal code quality by resolving lint warnings, moving static inline styles into CSS utilities, and extending sentence-case lint coverage to English localization strings, with no intended behavior changes.
  • \n
\n

Fixed#

\n
    \n
  • Fixed TaskNotes failing to load when Obsidian opened without an active Markdown file.
  • \n
\n","text":"Changed# TaskNotes now requires Obsidian 1.12.2 or later, matching the Obsidian APIs used by the plugin. Improved internal code quality by resolving lint warnings, moving static inline styles into CSS utilities, and extending sentence-case lint coverage to English localization strings, with no intended behavior changes. Fixed# Fixed TaskNotes failing to load when Obsidian opened without an active Markdown file."},{"route":"/obsidian/releases/4.7.0/","title":"TaskNotes 4.7.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.7.0.md","namespace":"obsidian","relativePath":"releases/4.7.0.md","raw":"# TaskNotes 4.7.0\n\n## Changed\n\n- Enabled lint checks that mirror Obsidian community plugin review findings, including dynamic code execution, Promise handling, deprecated APIs, unsafe stringification, directive comments, Node built-in imports, and explicit `any` usage.\n- Clarified privacy documentation for optional integrations that make periodic background network refreshes.\n- Cleaned up internal Obsidian and Bases compatibility adapters used by search and grouped views.\n- (#1839, #1881) Updated default Base urgency scoring so timed tasks earlier in the day sort above later tasks with the same priority and date\n - Thanks to @loukandr for the contribution\n\n## Fixed\n\n- Fixed project autocomplete searches so non-empty `+` queries only return files matching the query in the basename, title, aliases, or explicitly searchable metadata rows.\n- (#1713) Fixed all-tasks ICS export when a task uses a space-separated scheduled datetime such as `2025-08-12 18:00`\n - Thanks to @bepolymathe for requesting this and @m4to-3pe for following up\n- Fixed Pomodoro stats reopening immediately after a plugin reload before the Pomodoro service has finished initializing.\n- (#1872) Fixed unarchiving moved tasks so the destination task folder processes template variables such as `{{project}}` before moving the file\n - Thanks to @OXI-717 for reporting\n- (#1870) Fixed custom user field NLP triggers with file autosuggest so selecting a wikilink suggestion stores the link in the user field instead of leaving it in the task title\n - Thanks to @Sineapple for reporting\n- (#1878) Fixed completed tasks still appearing as active blockers for dependent tasks\n - Thanks to @macbikegeek for reporting\n- (#1880) Fixed the status bar time-tracking label for task titles that contain a dash\n - Thanks to @ubidev for reporting\n- (#1854) Fixed modal task completion so completed tasks receive a completed date consistently\n - Thanks to @misolex for reporting\n- (#1124, #1838, #1881) Fixed default Base views and formulas excluding tasks scheduled or due today at a non-midnight time from day-level comparisons\n - Thanks to @kmaustral for reporting and @loukandr for the fix\n\n## Removed\n\n- Removed JavaScript webhook transform support and examples. JSON webhook transform templates remain supported.\n","aliases":["/releases/4.7.0/","/releases/4.7.0/"],"toc":[{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"removed","text":"Removed"}],"html":"

Changed#

\n
    \n
  • Enabled lint checks that mirror Obsidian community plugin review findings, including dynamic code execution, Promise handling, deprecated APIs, unsafe stringification, directive comments, Node built-in imports, and explicit any usage.
  • \n
  • Clarified privacy documentation for optional integrations that make periodic background network refreshes.
  • \n
  • Cleaned up internal Obsidian and Bases compatibility adapters used by search and grouped views.
  • \n
  • (#1839, #1881) Updated default Base urgency scoring so timed tasks earlier in the day sort above later tasks with the same priority and date
      \n
    • Thanks to @loukandr for the contribution
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • Fixed project autocomplete searches so non-empty + queries only return files matching the query in the basename, title, aliases, or explicitly searchable metadata rows.
  • \n
  • (#1713) Fixed all-tasks ICS export when a task uses a space-separated scheduled datetime such as 2025-08-12 18:00
      \n
    • Thanks to @bepolymathe for requesting this and @m4to-3pe for following up
    • \n
    \n
  • \n
  • Fixed Pomodoro stats reopening immediately after a plugin reload before the Pomodoro service has finished initializing.
  • \n
  • (#1872) Fixed unarchiving moved tasks so the destination task folder processes template variables such as {{project}} before moving the file
      \n
    • Thanks to @OXI-717 for reporting
    • \n
    \n
  • \n
  • (#1870) Fixed custom user field NLP triggers with file autosuggest so selecting a wikilink suggestion stores the link in the user field instead of leaving it in the task title
      \n
    • Thanks to @Sineapple for reporting
    • \n
    \n
  • \n
  • (#1878) Fixed completed tasks still appearing as active blockers for dependent tasks
      \n
    • Thanks to @macbikegeek for reporting
    • \n
    \n
  • \n
  • (#1880) Fixed the status bar time-tracking label for task titles that contain a dash
      \n
    • Thanks to @ubidev for reporting
    • \n
    \n
  • \n
  • (#1854) Fixed modal task completion so completed tasks receive a completed date consistently
      \n
    • Thanks to @misolex for reporting
    • \n
    \n
  • \n
  • (#1124, #1838, #1881) Fixed default Base views and formulas excluding tasks scheduled or due today at a non-midnight time from day-level comparisons
      \n
    • Thanks to @kmaustral for reporting and @loukandr for the fix
    • \n
    \n
  • \n
\n

Removed#

\n
    \n
  • Removed JavaScript webhook transform support and examples. JSON webhook transform templates remain supported.
  • \n
\n","text":"Changed# Enabled lint checks that mirror Obsidian community plugin review findings, including dynamic code execution, Promise handling, deprecated APIs, unsafe stringification, directive comments, Node built-in imports, and explicit any usage. Clarified privacy documentation for optional integrations that make periodic background network refreshes. Cleaned up internal Obsidian and Bases compatibility adapters used by search and grouped views. (#1839, #1881) Updated default Base urgency scoring so timed tasks earlier in the day sort above later tasks with the same priority and date Thanks to @loukandr for the contribution Fixed# Fixed project autocomplete searches so non-empty + queries only return files matching the query in the basename, title, aliases, or explicitly searchable metadata rows. (#1713) Fixed all-tasks ICS export when a task uses a space-separated scheduled datetime such as 2025-08-12 18:00 Thanks to @bepolymathe for requesting this and @m4to-3pe for following up Fixed Pomodoro stats reopening immediately after a plugin reload before the Pomodoro service has finished initializing. (#1872) Fixed unarchiving moved tasks so the destination task folder processes template variables such as {{project}} before moving the file Thanks to @OXI-717 for reporting (#1870) Fixed custom user field NLP triggers with file autosuggest so selecting a wikilink suggestion stores the link in the user field instead of leaving it in the task title Thanks to @Sineapple for reporting (#1878) Fixed completed tasks still appearing as active blockers for dependent tasks Thanks to @macbikegeek for reporting (#1880) Fixed the status bar time-tracking label for task titles that contain a dash Thanks to @ubidev for reporting (#1854) Fixed modal task completion so completed tasks receive a completed date consistently Thanks to @misolex for reporting (#1124, #1838, #1881) Fixed default Base views and formulas excluding tasks scheduled or due today at a non-midnight time from day-level comparisons Thanks to @kmaustral for reporting and @loukandr for the fix Removed# Removed JavaScript webhook transform support and examples. JSON webhook transform templates remain supported."},{"route":"/obsidian/releases/4.7.1/","title":"TaskNotes 4.7.1","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.7.1.md","namespace":"obsidian","relativePath":"releases/4.7.1.md","raw":"# TaskNotes 4.7.1\n\n## Changed\n\n- Release assets are now built with GitHub artifact attestations so users and reviewers can verify the provenance of `main.js`, `manifest.json`, and `styles.css`.\n","aliases":["/releases/4.7.1/","/releases/4.7.1/"],"toc":[{"level":2,"id":"changed","text":"Changed"}],"html":"

Changed#

\n
    \n
  • Release assets are now built with GitHub artifact attestations so users and reviewers can verify the provenance of main.js, manifest.json, and styles.css.
  • \n
\n","text":"Changed# Release assets are now built with GitHub artifact attestations so users and reviewers can verify the provenance of main.js, manifest.json, and styles.css."},{"route":"/obsidian/releases/4.7.2/","title":"TaskNotes 4.7.2","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.7.2.md","namespace":"obsidian","relativePath":"releases/4.7.2.md","raw":"# TaskNotes 4.7.2\n\n## Changed\n\n- Improved local lint checks so package and CSS issues reported by Obsidian's online review can be caught before submission.\n- Cleaned up stylesheet compatibility issues reported by Obsidian's online review without changing the intended TaskNotes appearance.\n- Improved spacing and alignment in task, timeblock, and webhook modals after the stylesheet cleanup.\n- Reworked optional calendar and ICS subscription refresh scheduling to avoid interval-based network polling while preserving the same refresh intervals.\n- Cleaned up additional source patterns reported by Obsidian's online review, including unsafe default object stringification and redundant external type unions.\n- Prevented a console error when plugin listeners are cleaned up after reloads.\n- Added a local lint check to prevent interval-based polling in files that also perform network requests.\n","aliases":["/releases/4.7.2/","/releases/4.7.2/"],"toc":[{"level":2,"id":"changed","text":"Changed"}],"html":"

Changed#

\n
    \n
  • Improved local lint checks so package and CSS issues reported by Obsidian's online review can be caught before submission.
  • \n
  • Cleaned up stylesheet compatibility issues reported by Obsidian's online review without changing the intended TaskNotes appearance.
  • \n
  • Improved spacing and alignment in task, timeblock, and webhook modals after the stylesheet cleanup.
  • \n
  • Reworked optional calendar and ICS subscription refresh scheduling to avoid interval-based network polling while preserving the same refresh intervals.
  • \n
  • Cleaned up additional source patterns reported by Obsidian's online review, including unsafe default object stringification and redundant external type unions.
  • \n
  • Prevented a console error when plugin listeners are cleaned up after reloads.
  • \n
  • Added a local lint check to prevent interval-based polling in files that also perform network requests.
  • \n
\n","text":"Changed# Improved local lint checks so package and CSS issues reported by Obsidian's online review can be caught before submission. Cleaned up stylesheet compatibility issues reported by Obsidian's online review without changing the intended TaskNotes appearance. Improved spacing and alignment in task, timeblock, and webhook modals after the stylesheet cleanup. Reworked optional calendar and ICS subscription refresh scheduling to avoid interval-based network polling while preserving the same refresh intervals. Cleaned up additional source patterns reported by Obsidian's online review, including unsafe default object stringification and redundant external type unions. Prevented a console error when plugin listeners are cleaned up after reloads. Added a local lint check to prevent interval-based polling in files that also perform network requests."},{"route":"/obsidian/releases/4.8.0/","title":"TaskNotes 4.8.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.8.0.md","namespace":"obsidian","relativePath":"releases/4.8.0.md","raw":"# TaskNotes 4.8.0\n\n## Added\n\n- (#353) Added a `Has Subtasks` filter for task queries, so views and API clients can show only project-style tasks or direct tasks. Thanks to @mdbraber for suggesting this.\n- (#380) Added a test-reminder button in notification settings, so reminder setup can be checked without creating a real task reminder. Thanks to @mdbraber for suggesting this.\n- (#711, #168) Added an optional task-creation setting to open the new task note after saving, either in the current tab or a new tab. Thanks to @phortx and @23426356587 for suggesting this, and to @edward-peters and @obsilover for the follow-up.\n- (#1041, #1800) Added copy-drag support for timeblocks: hold Ctrl, Cmd, or Alt/Option while dragging an existing timeblock to duplicate it at the new date and time. Thanks to @0-BSCode and @cweekly for suggesting this.\n- (#1052) Added a public JavaScript API for in-vault scripts at `app.plugins.plugins.tasknotes.api.parseNaturalLanguage(text)`, so Templater, QuickAdd, and MetaBind workflows can use TaskNotes' natural-language parser without running the HTTP API. Thanks to @edakimling for suggesting this.\n- (#1235) Added a task-card toggle for blocked tasks, so you can expand a blocked task to see the tasks it is waiting on. Thanks to @craziedde for suggesting this.\n- (#1254) Added `../` and `./` normalization for folder templates after variables are expanded, so instant task conversion can target sibling folders such as `{{currentNotePath}}/../Tasks`. Thanks to @rdick for suggesting this.\n- (#1267) Added Daily Notes-style date tokens such as `YYYY`, `MM`, `DD`, `MMMM`, and `dddd` to TaskNotes folder templates. Thanks to @paulsen-it for suggesting this.\n- (#1380) Added tag actions to task context menus, including add/remove actions for individual tasks and batch-selected tasks. Thanks to @Chuhtra for suggesting this.\n- (#1377) Added right-click Mini Calendar actions for opening daily notes from day cells and weekly notes from week numbers. Thanks to @hasanyilmaz for suggesting this.\n- (#1151) Added a Mini Calendar max color note count option, so one-note days can use the strongest heatmap color when that better fits the view. Thanks to @arreme for suggesting this.\n- (#1376) Added backslash escapes for NLP trigger tokens, so text like `\\@context`, `\\*done`, or `\\tomorrow` can stay in the task title. Thanks to @JerryLu086 for suggesting this.\n- (#1366) Added CSS variables for compacting nested task-card indentation, with smaller defaults on mobile and documented snippets for tighter task-link lists. Thanks to @rk-kontur for suggesting this.\n- (#1502, #603) Added calendar indicators for external events that have linked notes or tasks, and showed loaded event titles in task-card calendar metadata instead of only the linked event count. Thanks to @Robubble and @mdbraber for suggesting this, and to @ubidev for the follow-up.\n- (#1522) Added a per-status option to skip rarely used statuses when cycling task-card status indicators. Thanks to @Glint-Eye for suggesting this.\n- (#144) Added an \"Open note in new tab\" action to the task context menu. Thanks to @cathywu for suggesting this and @macbikegeek for the follow-up feedback.\n- (#167) Added an optional next-status override for each status, so forward cycling can jump to a configured status instead of always following the status order. Thanks to @DanBrazelton for suggesting this, and to @michelebugio, @Moyf, @anareaty, and @vorrermid for the follow-up feedback.\n- (#1520) Made tag and context fields show available suggestions as soon as the field is focused. Thanks to @Glint-Eye for suggesting this, and to @craziedde for the follow-up.\n- (#1541) Added `{{currentNotePath}}` and `{{currentNoteTitle}}` support to the default tasks folder, so normal task creation can place new tasks beside the active note without creating an inline link. Thanks to @ChristianAnyanwu for suggesting this, and to @abbasou and @ttlaylor for the follow-up feedback.\n- (#648, #1605) Added clickable links in task-card contexts for note links, markdown links, and web URLs while keeping plain contexts as tag-search buttons. Thanks to @trdischat and @Glint-Eye for suggesting this, and to @renatomen for the follow-up feedback.\n- (#1482) Added clickable custom-field links on task cards for wikilinks, markdown links, autolinks, and bare web URLs. Thanks to @ptbosch-figueiredorj for suggesting this, and to @Soleone for the follow-up use case.\n- (#1471) Added Kanban column and swimlane-cell add buttons that open the TaskNotes creation modal with the grouped values already filled in. Thanks to @byheaven for suggesting this and @Davincible for the project-board use case.\n- (#933) Added non-Markdown vault files such as canvases to project suggestions, using extension-qualified link targets so those files can be selected as task projects. Thanks to @Alvin21Bon for suggesting this.\n- (#1475, #725) Added quote/backtick escapes for NLP input, so literal course codes or date words can stay in task titles without being parsed as estimates or dates. Thanks to @RumiaKitinari and @gavingwebb for suggesting this.\n- (#1462) Added natural-language date entry to the task date picker, so existing due and scheduled dates can be changed with phrases such as \"tomorrow at 3pm\" when NLP is enabled. Thanks to @Ruboks-Cube for suggesting this.\n- (#1526) Added a native date field to the task date picker, so scheduled and due dates can be changed with the device date picker while keeping optional times visible. Thanks to @jmartinmcfly for suggesting this and @23426356587 for the follow-up feedback.\n- (#1603) Added Calendar view toggles for hiding completed or skipped recurring task instances while keeping future outstanding instances visible. Thanks to @wandererovertheseaofpiss for suggesting this.\n- (#287, #273, #274) Added linked hover highlighting for Calendar and Agenda events that come from the same task note, so scheduled, due, and recurring entries are easier to connect. Thanks to @girisumit for suggesting this.\n- (#280) Added project-specific CSS hooks to task cards and Calendar events, so project-based visual styling can be handled with user snippets. Thanks to @girisumit for suggesting this.\n- (#1625) Added `Shift` + `Cmd`/`Ctrl` + `Enter` in the Create Task modal to save the current task and reopen the modal for the next one. Thanks to @tcb678 for suggesting this.\n- (#1353) Focused the Create Task modal's natural-language input when the modal opens, with a longer mobile delay so the keyboard can open after layout. Thanks to @GiovanH for suggesting this.\n- (#1664) Added project-based custom filename template variables, including the first project, all projects, and a short `projectId`. Thanks to @bendavis987 for the contribution.\n- (#923) Added `{{projectFilePath}}` and `{{projectFilePaths}}` folder template variables, so task folders can mirror project note locations in the vault. Thanks to @PacoTaco2 for suggesting this.\n- (#1697) Added cached Google Calendar, Microsoft Calendar, and ICS events to Mini Calendar days, with compact colored dots and event details from the existing calendar connection. Thanks to @RPGArchivist for suggesting this.\n- (#1754) Added optional icons for priority values, so task cards can show a configured priority icon instead of only a colored dot. Thanks to @BrucePlumb for suggesting this and @prepare4robots for the follow-up feedback.\n- (#1761) Added TaskNotes edit and task-action submenu entries to Obsidian's native file context menu for recognized task notes. Thanks to @delzero for suggesting this.\n- (#1771) Added mobile drag handles to manually sorted Task List Bases views, so dragging can start from the handle without disabling normal text interaction on the rest of the card. Thanks to @PatrickGolz for suggesting this.\n- (#1776) Allowed calendar timeline end times after midnight, such as `26:00` for a 2 AM next-day end. Thanks to @chrabia for suggesting this.\n- (#1784, #1833) Added a per-view `pinnedColumns` option for TaskNotes Kanban views, so selected empty columns can stay visible as drop targets while other empty columns remain hidden. Thanks to @loukandr for suggesting and prototyping this.\n- (#1794) Added context updates to the task card context menu, so contexts can be added, toggled, or cleared without opening the task edit modal. Thanks to @m13ntrpn for suggesting this.\n- (#315, #1356, #1748, #1809) Added a subtle task-card indicator and CSS hooks for tasks with note body details, including existing task bodies read through Obsidian's metadata cache. Thanks to @volodxyz, @Karut, @yeHHH1g, and @aliceinwaterdeep for suggesting this, and to @minchinweb for the follow-up.\n- (#1808) Added advanced Kanban swimlane ordering through `swimLaneOrder`, so swimlane rows can stay in a stable configured order. Thanks to @rookledookle for suggesting this, and to @benmartinek and @chrabia for the follow-up feedback.\n- (#1805) Added an ICS export option to omit completed tasks from generated calendar files. Thanks to @bepolymathe for suggesting this.\n- (#659) Added Obsidian links to ICS export descriptions, so exported calendar events can open their source task notes. Thanks to @bepolymathe for suggesting this.\n- (#589) Added an Appearance toggle to turn off strikethrough styling on completed task card titles. Thanks to @BrucePlumb for suggesting this.\n- (#561) Added a \"Last day\" option to the custom recurrence month-day picker for month-end repeating tasks. Thanks to @TonyAtlas for suggesting this and @BrucePlumb for the follow-up.\n- (#217) Added weekday selection to daily custom recurrence rules, so interval rules such as every three days can skip weekends from the recurrence modal. Thanks to @kmaustral for suggesting this.\n- (#1818) Added an auto-height mode for TaskNotes Calendar Bases views so embedded agenda/list sections can size to their content instead of forcing an inner scroller. Thanks to @martin-forge for suggesting this.\n- (#1201) Added a Calendar Bases toggle to hide the hourly breakdown in week, custom-days, and day views while keeping the all-day planning row visible. Thanks to @PacoTaco2 for suggesting this.\n- (#1176) Added advanced Kanban WIP limits through `wipLimits`, so column headers can show `(current/limit)` counts and highlight exceeded limits. Thanks to @williamcheuk03 for suggesting this.\n- (#914) Added a generated `Due in` countdown to the default Agenda Base and allowed Calendar Bases list agendas to span up to 365 days. Thanks to @williamcheuk03 for suggesting this.\n- (#900) Added an instant-conversion setting to keep the original Markdown checkbox marker when converting a checkbox into a TaskNote link. Thanks to @dsebastien for suggesting this.\n- (#898) Added a mobile-only calendar integration opt-out, so synced desktop calendar settings no longer have to trigger external calendar loading on Obsidian Mobile. Thanks to @cathywu for suggesting this.\n- (#887) Added built-in scheduled and due date presets to the Quick actions palette for current tasks. Thanks to @willgraham345 for suggesting this and @anrie for the related preset feedback.\n- (#819) Added a command to open Quick actions for the inline task link under the cursor. Thanks to @rlolingo for suggesting this.\n- (#798, #1732, #1835) Added hotkeyable commands to edit the current task, add a project to the current task, and add an existing task as a subtask of the current note. Thanks to @xorander00 and @prepare4robots for requesting this, and to @musta-code and @ubidev for the follow-up suggestions.\n- (#791) Added a UUID v4 task filename format and `{{uuid}}` custom filename template variable. Thanks to @bangbangbanggit for suggesting this.\n- (#932) Added hotkeyable commands to cycle the current task's status and priority. Thanks to @rxunique for suggesting this and @luckb0x for the follow-up feedback.\n- (#1655) Added live elapsed time to the optional active time tracking status bar item. Thanks to @connradolisboa for suggesting this.\n- (#1622) Allowed multiple comma-separated default reminder offsets for timed Google Calendar task exports. Thanks to @solidabstract for suggesting this.\n- (#706, #820, #1040) Added direct Pomodoro duration editing, hour-aware timer formatting, clearer one-minute controls, and an optional active Pomodoro status bar countdown. Thanks to @SublunarSage, @lj1446615403-cloud, @0-BSCode, and @thestrike72 for the suggestions and feedback.\n- (#873) Added an optional built-in sound for task reminder notifications, with volume and preview controls in Settings. Thanks to @berzernberg for suggesting this.\n- Added a generated Pomodoro statistics Base with daily and monthly summary views for Pomodoro history stored in daily notes.\n\n## Changed\n\n- Expanded the bug report template to ask for Obsidian \"Show debug info\" output, affected task frontmatter, relevant Bases file contents, reproduction steps, and related logs or screenshots.\n- Release notes now show the default `.base` file regeneration reminder only on the current version section, keeping older bundled sections focused on their own changes.\n- Updated the release notes GitHub prompt to invite feedback while still asking satisfied users to star the project.\n- (#239) Ordered Kanban status and priority columns by the configured status order and priority weights when no manual column order is saved. Thanks to @ScumbagScalawag for asking about this, and to @nightroman, @lavir, and @elvarb for the follow-up discussion.\n- (#269) Marked Kanban status columns that come from values outside the configured TaskNotes statuses, so manually edited or external status values are visible as non-standard instead of blending into the board. Thanks to @cstelmach for suggesting this and @digitaldoctors for the follow-up.\n- Refined Kanban empty columns, swimlane rows, and column drag handles, and added a per-view compact card layout option for denser boards.\n- Kept Kanban swimlane rows from shrinking to share the viewport so the Max Swimlane Height setting is respected.\n- Added guidance in Pomodoro statistics and Base file settings explaining that Pomodoro Base views require daily notes storage.\n- (#323) Reordered task modal action buttons to match the right-click task menu order. Thanks to @23426356587 for suggesting this.\n- (#1189) Made the Create/Edit Task modal priority picker follow the priority order configured in Settings. Thanks to @n1njaznutz for suggesting this.\n- Made task-card priority dots and configured priority icons slightly larger for better visibility.\n- (#1244) Clarified the Task Properties documentation for custom property keys and status values in Bases filters and sorting. Thanks to @Arachnidai for suggesting this.\n- (#1234) Kept right-aligned subtask chevrons visible on task cards instead of only showing them on hover. Thanks to @n1njaznutz for suggesting this.\n- (#1237) Made today's date more visible in the Mini Calendar view when another day is selected. Thanks to @riekusr for suggesting this.\n- (#1348) Let long task titles wrap inside the Create/Edit Task modal title field while keeping saved titles single-line, and widened the contexts and tags fields in the modal details area. Thanks to @hasanyilmaz for suggesting this.\n- (#1392) Made TaskNotes date fields accept compact `YYYYMMDD` typing and pasted dates. Thanks to @kazerniel for suggesting this.\n- (#1431) Showed the year on task-card due and scheduled dates when the date is outside the current year. Thanks to @kazerniel for suggesting this.\n- (#1429) Opened TaskNotes view commands in a new tab when they load configured Base files, so they do not replace the active note. Thanks to @Ruboks-Cube for suggesting this.\n- (#1426) Added copy actions for TaskNotes Bases views, including current-view filenames, links, and titles from the result count menu, plus selected-task copy actions in the batch menu, while keeping the native Bases copy and CSV export actions available. Thanks to @kmaustral for suggesting this.\n- Improved keyboard access, mobile layout, and theme color consistency across task cards, TaskNotes Kanban, Bases Kanban, calendar controls, stats, settings, and filter popovers.\n- (#1526) Made the Create/Edit Task modal due and scheduled date buttons open a calendar-first picker where clicking a date saves immediately, with time entry still available in the picker. Thanks to @jmartinmcfly for suggesting this and @23426356587 for the follow-up feedback.\n- (#1642) Made completion-based custom recurrence use flexible weekly, monthly, and yearly intervals without forcing a fixed weekday, month day, or month. Thanks to @Volker-brdb for suggesting this.\n- (#1724) Moved recurring task complete/skip instance actions into the date area of the task context menu. Thanks to @prepare4robots for suggesting this.\n- (#1762) Used the configured Google Calendar task export target as the default calendar when creating manual external calendar events. Thanks to @chrabia for suggesting this.\n- (#1774) Made expandable project chevrons visible and easier to tap on mobile. Thanks to @sh0nuff for suggesting this.\n- (#190) Made task-card and inline task-link action controls easier to tap on mobile, including always-visible task options on touch layouts. Thanks to @Poly-0000 for suggesting this.\n- (#518, #1710, #1785) Added an opt-in setting for Create subtask to inherit the parent task's projects, contexts, priority, and non-identifying tags while always keeping the parent-task project link. Thanks to @bepolymathe, @Jalpara, and @poulpoulsen for reporting this, and to @tomsymonds, @AndyEveritt, @wedgen, @lindsaylearns, and @hokfujow for the follow-up feedback.\n- (#1790) Extended the identifying-tag hiding setting to task modal tag suggestions, and kept hidden identifying tag children in place when editing other tags. Thanks to @loukandr for suggesting this.\n- (#1804) Made the inline-created task folder setting visible even when instant conversion is disabled, and clarified that leaving it empty uses the default tasks folder. Thanks to @CaFeZn for suggesting this.\n- (#1822) Matched the Task Edit Modal subtask list order to the existing relationship sort, so active and higher-priority subtasks appear ahead of completed ones. Thanks to @Glint-Eye for suggesting this.\n- (#1233, #1339) Added an Appearance setting to expand project subtasks by default in task cards, while still letting individual cards be collapsed. Thanks to @n1njaznutz and @hasanyilmaz for suggesting this and @kazerniel and @benmartinek for the follow-up.\n- (#763) Made the Relationships widget appear on project notes that match Project Autosuggest tag or property filters, even before any tasks link to the project. Thanks to @ChadHattabaugh for suggesting this.\n- (#732) Remembered the Task & Project Statistics filters between openings, including the selected date range, custom dates, and minimum time filter. Thanks to @RumiaKitinari for suggesting this.\n- (#1335) Added optional default times for new task scheduled and due dates, so default-dated tasks can appear as timed calendar events instead of all-day events. Thanks to @echo-saurav for suggesting this.\n- (#1327) Made TaskNotes Bases search match any word in a multi-word search instead of requiring the whole phrase. Thanks to @craziedde for suggesting this.\n- (#1318) Made aliased inline task links use the alias text inside the task widget, so `[[Task title|short label]]` can display as `short label`. Thanks to @3zra47 for suggesting this and @kazerniel for the follow-up.\n- (#1325) Added `./` and `../` support to Include folders filters for project and file autosuggest, resolved from the active note's folder. Thanks to @EpolPers for suggesting this.\n- (#1313) Added generated `llms.txt` and `llms-full.txt` files to the documentation site, so the primary docs can be shared with LLM tools more easily. Thanks to @JacksonMcDonaldDev for suggesting this.\n- (#1308) Added a Calendar view option to stop date links from creating missing daily notes, while still opening existing daily notes. Thanks to @Arachnidai for suggesting this.\n- (#1300) Allowed priority, status, calendar subscription, and timeblock color settings to use Obsidian theme color names such as `red`, `blue`, and `cyan`. Thanks to @thestrike72 for suggesting this.\n- (#1299) Added a command that creates or opens a task and immediately starts time tracking for it. Thanks to @slipstyle for suggesting this.\n- (#1284) Added an exact-match option for hiding task identification tags, so `#task` can be hidden while nested tags such as `#task/project` remain visible. Thanks to @3zra47 for suggesting this.\n- (#1009) Added a confirmed Delete button to the Edit Task modal, so unwanted task notes can be removed without first opening the note file. Thanks to @jalooc for suggesting this.\n- Improved the internal structure of Calendar, Kanban, Bases, task cards, and task modals to make future changes easier to test and maintain.\n\n## Fixed\n\n- (#697, #1374) Recognized manually authored task notes that use a single scalar tag such as `tags: task`, so they appear in TaskNotes views and menus like notes using YAML list tags. Thanks to @aubreyz and @phortx for reporting this, and to @jleewastaken for the follow-up.\n- Removed the upward hover shift from calendar events while keeping the hover shadow feedback.\n- Made same-column manual-order drops in TaskNotes Kanban settle immediately when the local order patch is safe, including virtual columns through a stable reorder path that avoids layout jumps.\n- Made single-card cross-column drops in TaskNotes Kanban settle through a local state patch when the move is safe, reducing the wait for the full Bases refresh.\n- Fixed Calendar timeblocks created from a selected time range so they appear as soon as Obsidian indexes the daily note update, instead of waiting for a later refresh.\n- Replaced the external calendar event emoji marker with the calendar icon and kept it in the same top-right event corner.\n- Restored Task List group toggles and recurring calendar month controls to compact icon buttons instead of inherited boxed theme buttons.\n- Refined the settings tab navigation styling so tabs read as quieter inline navigation instead of default buttons.\n- (#263) Made the instant inline task conversion button respond to touch/pointer activation, so mobile multi-line selections can be converted into TaskNotes. Thanks to @cathywu for reporting this.\n- (#216) Preserved `@context` markers when converting Tasks-plugin-style checkbox tasks into TaskNotes, while keeping those contexts out of the created task title. Thanks to @ksdavidc for suggesting this, and to @hangryscribe3, @nayatiuh, and @natleahh for the follow-up feedback.\n- (#508) Showed project note names instead of full project paths in grouped Kanban and Task List headings, while keeping the headings linked to the project note. Thanks to @elvarb for reporting this and @dmodify for confirming it in Task List.\n- (#408) Used the task title as the native system notification title for task reminders instead of always showing `TaskNotes Reminder`. Thanks to @DudeThatsErin for reporting this and @phillipadsmith for the follow-up.\n- (#385) Let Mini Calendar month controls shrink and wrap cleanly in narrow sidebars. Thanks to @iholston for reporting this.\n- Fixed Calendar List view task cards so they use the available row width without duplicate list cells, row-hover backgrounds, or linked-hover styling.\n- (#552) Made instant task convert buttons appear for checkbox tasks inside callouts, and kept converted links inside the callout list. Thanks to @Oblique82 for reporting this and @ksdavidc for the follow-up.\n- (#559) Treated notes linked to one loaded recurring calendar event instance as related to the other instances in that series. Thanks to @cathywu for reporting this and @mdbraber for the implementation notes.\n- (#685) Made Calendar list views respect the All-day slot option by hiding all-day events from the list when that option is turned off. Thanks to @RumiaKitinari for reporting this.\n- (#643) Stopped custom filename templates such as `task-{year}{month}{day}{hour}{minute}` from incorrectly showing the \"filename shortened\" notice when creating tasks. Thanks to @minchinweb for reporting this.\n- (#722) Made Skip Break reset a queued Pomodoro break back to the next focus timer without starting a session. Thanks to @Goossiii for reporting this and @YIRU69 for the follow-up.\n- (#782) Made recurrence weekday choices follow the configured first day of week, and made the quick \"Weekdays only\" recurrence use locale weekend data instead of assuming Monday through Friday everywhere. Thanks to @BKSalman for reporting this.\n- (#872) Made note-level task cards appear immediately, and stay visible while editing, when a task note is embedded as a Canvas file node. Thanks to @bangbangbanggit for reporting this and @benmartinek for the follow-up.\n- (#856) Fixed filters for number custom fields so numeric task values match equivalent filter values entered as text. Thanks to @thoughtcipher for reporting this.\n- (#1039) Restored clearer TaskNotes Bases grouping for nested project paths, and made the Calendar refresh control an icon button again. Thanks to @dblinnikov for reporting this.\n- (#1034) Let embedded TaskNotes Calendar views size to their content by default, so month, week, and day embeds no longer reserve full-pane proportions inside notes. Thanks to @same774 for reporting this.\n- (#1023) Kept task modal custom fields scrollable above the iPhone keyboard while creating or editing tasks. Thanks to @3zra47 for reporting this.\n- (#1019) Kept active Pomodoro and time-tracking task references working after the tracked task file is renamed. Thanks to @AndreMonthy for reporting this.\n- (#1037) Let embedded TaskNotes Calendar year views size to their content and kept the year title from wrapping vertically. Thanks to @same774 for reporting this.\n- (#1047) Wrapped long file paths in the Edit Task modal metadata section, so narrow mobile screens no longer get a sideways scrollbar from the File row. Thanks to @3zra47 for reporting this.\n- (#1051) Preserved extra values on a property-based task identification field when saving a task, so list properties such as `class: [task, habit]` no longer get collapsed to only the identifying value. Thanks to @WhoIsSeanGalt for reporting this.\n- (#1060) Reused and revealed an already-open Calendar/Base view when running view commands, so a view kept in the sidebar no longer reopens in a new main tab. Thanks to @kmaustral for reporting this.\n- (#1075) Hid the native WebKit date-input label that could appear as `Label` when editing scheduled dates on macOS. Thanks to @3zra47 for reporting this.\n- (#1076) Allowed timeblocks to end at midnight using `00:00`, and accepted `24:00` as an explicit end-of-day value in timeblock validation. Thanks to @skoove for reporting this and @gregor202 for the follow-up.\n- (#1086) Fixed the Calendar `+ more` control in dark mode so expanded all-day task groups stay readable. Thanks to @same774 for reporting this.\n- (#1100) Applied Advanced Calendar View search and title filters to the tasks used for calendar rendering, so filtering controls affect which tasks appear on the calendar. Thanks to @quiet-coder-io for reporting this.\n- (#1147) Added a delete action for recent Pomodoro statistics sessions, so erroneous Pomodoro history can be removed without editing plugin storage or daily-note frontmatter manually. Thanks to @RumiaKitinari for reporting this and @BrucePlumb for the follow-up.\n- (#1150) Kept recurring tasks' due dates visible in Calendar Bases views, and showed their scheduled date when recurrence instances are hidden. Thanks to @thomatino for reporting this and @BrucePlumb for the follow-up.\n- (#1159) Softened Calendar time-entry styling so recorded time blocks no longer visually outweigh task events. Thanks to @hatespinach for reporting this.\n- (#1191) Aligned the task-card and relationships widgets inside notes with Obsidian's editor margins, including readable-line-width layouts. Thanks to @minchinweb for reporting this.\n- (#1183) Kept the Calendar create menu open after drag-selecting a time range, so the selected duration can be used when creating a task. Thanks to @randomness42 for reporting this.\n- (#1179) Stopped Calendar Bases views from repainting after unrelated note updates when the visible calendar data has not changed. Thanks to @same774 for reporting this.\n- (#1156) Kept property-based task identification through the `tags` property from rewriting task tags as a plain text value, and generated default Bases now use tag membership for that setting. Thanks to @seepage87 for the detailed migration report and @chrsdk for the follow-up.\n- (#1232) Fixed generated Task List Base date filters so recurring tasks scheduled for today appear in the Today view, and today's completed recurring instances stay hidden. Thanks to @mvichosfm for reporting this and @ArthurGideon and @VarunNikam22 for the follow-up.\n- (#1231) Fixed the generated Task List Base Overdue view so tasks with scheduled dates in the past appear alongside tasks with due dates in the past. Thanks to @Lorite for reporting this and @dictionarymouse for the follow-up.\n- (#1228) Matched the task details editor's Markdown heading colors to the active Obsidian theme, including themes that customize heading colors. Thanks to @BrucePlumb for requesting this.\n- (#1227) Refreshed the relationships widget when project references are indexed or updated so project notes can show related tasks automatically again. Thanks to @luckb0x for reporting this.\n- (#1219) Fixed Kanban drags that start on an expanded subtask card so they move that subtask instead of dragging the parent card. Thanks to @craziedde for reporting this.\n- (#990) Treated one-item status lists written by Obsidian Properties as the same status value in TaskNotes Kanban, so they no longer create duplicate columns. Thanks to @mlevison for reporting this.\n- (#983) Let Agenda Calendar views wrap their header controls and task titles inside narrow sidebars, so Today and refresh controls and task icons remain visible without sideways scrolling. Thanks to @3zra47 for reporting this.\n- (#982) Made TaskNotes task-card typography scale from Obsidian's text font size setting, so Bases and Agenda task text follows larger mobile font settings. Thanks to @3zra47 for suggesting this and @chrsdk and @scottaltham-payroc for the follow-up.\n- (#966) Made reminder delete buttons larger and always visible on mobile, so reminders can be removed from the Manage All Reminders modal on iPad. Thanks to @PSG2017 for reporting this.\n- (#964) Made Pomodoro and time-tracking task selection use the current recurring instance status, so a recurring task can still be selected after an earlier instance was completed. Thanks to @lomarcanys for reporting this.\n- (#944) Preserved number and boolean custom field values when moving tasks between grouped Kanban or Task List columns, and when creating a task from a grouped Kanban column. Thanks to @thoughtcipher for reporting this.\n- (#935) Fixed Task List priority sorting so descending order puts higher-weighted priorities first, and due dates are used before scheduled dates when priority values tie. Thanks to @Glint-Eye for reporting this and @kacoroski for the follow-up.\n- (#922) Made the `Blocked` task-card pill expand the blocker tasks, and rendered `blockedBy` dependencies as clickable links when that property is shown on cards. Thanks to @prayidae for reporting this and following up.\n- (#919) Fixed exported ICS task events so they use valid calendar event statuses and can be imported by stricter calendar apps. Thanks to @benoitjadinon for reporting this.\n- (#1213) Fixed embedded Task List Bases in Obsidian pop-out windows so typing below the embed no longer leaves a large blank gap. Thanks to @same774 for reporting this.\n- (#1243) Removed quoted multi-word custom field NLP expressions from created task titles after saving the custom field value. Thanks to @Arachnidai for reporting this.\n- (#1252) Hardened the calendar-first task date picker for iPad taps so date buttons use direct touch manipulation. Thanks to @alxandrharris for reporting this.\n- (#1261) Removed the extra Task List Base scrollbar when an embedded task list note is placed in a sidebar, while keeping normal embedded task lists scrollable in the main note area. Thanks to @cathywu for reporting this.\n- (#1347) Lowered TaskNotes task-card tag CSS specificity so hierarchical tag colors from Obsidian themes and tag-color plugins can apply correctly. Thanks to @3Fish for reporting this.\n- (#1374) Recognized status and priority labels entered through Obsidian Properties or Bases as their configured TaskNotes values. Thanks to @phortx for reporting this.\n- (#1373) Parsed numeric natural-language dates with the configured calendar locale, so `en-GB` treats `11/06/2026` as 11 June instead of November 6, and `YYYY/MM/DD` works consistently. Thanks to @AleMunin for reporting this and @imsuck for the follow-up.\n- (#1370) Prevented recurring task series from being queued for auto-archive when their parent status uses auto-archive, so ongoing recurring tasks are not moved away after completing an occurrence. Thanks to @Jomo94 for reporting this and @martin-forge for the follow-up discussion.\n- (#1367) Made recurring task completion counts use the total expected instances for finite `COUNT` or `UNTIL` recurrences, and stopped showing a made-up percentage for unbounded recurrences. Thanks to @saurinni for reporting this.\n- (#1365) Preserved email and other URI links from converted inline task titles by moving the original links into the new task body, and rendered `message:`/`mailto:` markdown links as external links in TaskNotes surfaces. Thanks to @phillipadsmith for reporting this and @hasanyilmaz for the follow-up.\n- (#1350) Refreshed inline task widgets in Reading mode after task property edits, so changed dates and other visible properties no longer stay stale until the note is reopened. Thanks to @tmsbn for reporting this.\n- (#1329) Pulled the relationships widget up to the end of the note content without removing its normal spacing, and kept that placement updated while editing and on load so it no longer covers the editor. Thanks to @Volker-brdb for reporting this.\n- (#1326) Treated empty task frontmatter values as missing, so empty titles fall back to the filename and blank date, priority, and recurrence fields are ignored. Thanks to @craziedde for suggesting this.\n- (#1316) Stopped stale Workspace state from overriding the configured Calendar view mode, so switching Workspaces no longer forces an old Day/Week/List choice over the view default. Thanks to @kmaustral for reporting this and following up.\n- (#1302) Read task frontmatter directly from the task file when Obsidian has not indexed its metadata yet, so visible tasks can still be opened, updated, and selected instead of reporting \"Task not found\". Thanks to @WorldTeacher for reporting this and @Steven-AA for confirming it.\n- Kept just-written task data available while Obsidian's metadata cache catches up, so immediate reads after task edits no longer briefly return stale values.\n- (#1297) Made the Create or open task footer tappable, so mobile users can create the typed task without needing the Shift+Enter shortcut. Thanks to @slipstyle for reporting this.\n- (#1288) Allowed formula properties to appear in Calendar property-based event start and end date selectors. Thanks to @hasanyilmaz for reporting this.\n- Made TaskNotes Kanban drags show a lightweight held-card preview, so the dragged card remains easy to track while the source column opens the drop slot.\n- (#1423) Refreshed TaskNotes Bases views when subtasks are deleted, so expanded project cards drop removed subtasks and stop showing project controls when the last subtask is gone. Thanks to @normenmueller for reporting this.\n- (#1419) Kept custom user field name, key, and default-value edits in Task Properties settings when closing settings without first blurring the field. Thanks to @s33a for reporting this and @kacoroski for the follow-up.\n- Reduced redundant settings writes by coalescing overlapping saves, so settings changes made in quick succession finish with the latest values without repeating every intermediate save cycle.\n- (#1331, #1411) Made Agenda Calendar Bases respect the Base sort order within each day instead of falling back to alphabetical title order. Thanks to @bane73 and @ky1ejs for reporting this.\n- (#1383) Made task modal markdown editors expose the active editor API expected by plugins such as Templater. Thanks to @tomsymonds for reporting this.\n- Fixed the first-run Create/Edit Task modal so the default fields appear immediately after installing TaskNotes, without needing to open Modal Fields settings or restart Obsidian.\n- (#1895) Restored the natural-language preview in the Create Task modal. Thanks to @ssonhub for reporting this.\n- (#1898) Cleared stale Calendar time-axis column widths when switching views, so Day, Week, and 3-day views keep the time labels anchored on the left. Thanks to @ddevaal for reporting this.\n- (#1439) Fixed generated Bases dependency filters so `blockedBy` entries stored as links, strings, or dependency objects are handled consistently in Not Blocked and Relationships views. Thanks to @prayidae for reporting this and following up.\n- (#1435) Prevented malformed task dependency, status, or priority values from breaking the task context menu. Thanks to @23maverick23 for reporting this.\n- (#1434) Kept older filename-titled tasks readable after turning off \"Store title in filename\" by falling back to the filename when a task has no usable title property. Thanks to @hujuDev for reporting this.\n- (#1433) Made the Due date and Scheduled date weekday picker follow the configured first day of week. Thanks to @sandchipper for reporting this.\n- (#1430) Showed custom user-field property keys in Modal Fields settings instead of internal field IDs. Thanks to @JerryLu086 for reporting this.\n- (#1427) Fixed project autosuggest Required Tags filters so frontmatter tags parsed by Obsidian are handled the same way as direct tag-property filters. Thanks to @ProHaller for reporting this.\n- (#1495) Added an Update default files action for generated Bases views, so task-tag or task-identification setting changes can refresh existing `.base` filters without deleting files manually. Thanks to @Liya430 for reporting this.\n- (#1512) Prevented the split Create/Edit Task modal details pane from collapsing to a one-character-wide column under the Minimal theme. Thanks to @willfanguy for reporting this and sharing detailed CSS notes.\n- (#1524) Fixed task-card font sizes shrinking when a Bases view is opened in an Obsidian pop-out window. Thanks to @Glint-Eye for reporting this.\n- (#1535) Fixed the generated Relationships Base Subtasks filter so single project links do not trigger a Bases `contains` error. Thanks to @DanaKyle for reporting this.\n- (#1102) Refreshed task cards when a task status is edited directly in Obsidian frontmatter, so the card no longer stays on the old status until it is clicked. Thanks to @Wayment9504 for reporting this.\n- (#1105) Added an explicit Close action to the mobile task options menu, so iPhone users do not need to tap near the top system bar to dismiss it. Thanks to @J-R-Troutman for reporting this.\n- (#1550) Prevented mobile Calendar event drags from opening the task context menu before the drag can begin. Thanks to @stil-sudo for suggesting this.\n- (#1563) Removed duplicate entries from Calendar event related notes when the same linked file is also a TaskNote. Thanks to @VarunNikam22 for reporting this.\n- (#1566) Rendered grouped multi-project values as individual links when a Bases group title contains multiple project links. Thanks to @ptsouchlos for suggesting this.\n- (#1569) Allowed local ICS calendar paths inside the vault to be pasted as absolute filesystem paths, and showed a clearer error when the file is outside the vault. Thanks to @Photon89 for reporting this and following up.\n- (#1584) Sanitized task-card status and priority class names, so custom values with spaces no longer create invalid CSS classes. Thanks to @omber for reporting this.\n- (#1587) Stored dependencies added from the task context menu as wikilinks, matching the Edit Task modal. Thanks to @mgrecar for reporting this.\n- (#1590) Clarified HTTP API task creation docs and OpenAPI schema for writable `blockedBy` dependencies, and marked `blocking` as a read-only derived relationship. Thanks to @hGriff0n for reporting this.\n- (#1591) Added a startup guard that avoids saving default settings over an existing settings file if Obsidian temporarily returns no plugin data during an update. Thanks to @GGlider for reporting this.\n- (#1593) Made the New button in TaskNotes Bases views open the TaskNotes create task modal again, so new tasks respect the configured default tasks folder. Thanks to @katlandreth for reporting this.\n- (#1594) Made task cards inside recurring task notes complete the task's current scheduled occurrence instead of today's date when no calendar or view date is supplied. Thanks to @ngraham20 for reporting this.\n- (#1601) Prevented overlapping Live Preview relationship-widget injections from leaving duplicate subtask/relationship sections in a note. Thanks to @wealthychef1 for reporting this and @benmartinek for confirming it.\n- (#1610) Made expanded subtasks in TaskNotes Bases views follow the current view's sorted task order instead of a fixed fallback order. Thanks to @MrZzard for reporting this and @slipstyle for confirming it.\n- (#1609) Restored scrolling in wide split-layout task edit modals when the form content is taller than the modal. Thanks to @3zra47 for reporting this.\n- (#1614) Wrote unchecked boolean custom user-field defaults to new task frontmatter, including tasks created through instant conversion. Thanks to @kobalteule for reporting this.\n- (#1611) Made generated default Bases urgency scores fall back safely when the next-date distance is missing. Thanks to @benoitjadinon for reporting this and suggesting the formula fix.\n- (#1623) Honored \"Store title in filename\" across task creation and edits, so the mapped title property is omitted from frontmatter and stale title fields are removed on save. Thanks to @VenturaNotes for reporting this, and to @Ender367, @slipstyle, and @loukandr for confirming and tracing affected paths.\n- (#1621) Made Kanban swimlane labels stop freezing on mobile and kept their label column compact, leaving more room for task cards while horizontally scrolling. Thanks to @karenchoe428 for reporting this.\n- (#1615) Detected Obsidian custom multi-text properties exposed through `widget: \"multitext\"` as list properties, so Kanban can split those values into multiple columns. Thanks to @konton71 for reporting this.\n- (#1626) Expanded recurring ICS subscription events through the one-year subscription window for high-frequency recurring calendars. Thanks to @pib for reporting this.\n- (#1628) Refreshed Calendar Bases views promptly when switching between filtered Agenda views, so the previous view's task set does not stay visible until the delayed refresh. Thanks to @Lanalangz for reporting this.\n- (#1629) Saved `blockedBy` dependencies selected in the Create Task modal. Thanks to @obsilover for reporting this.\n- (#1634) Aligned custom status icons in inline tasks with the default inline status circle. Thanks to @ttlaylor for reporting this and @basbarten for confirming it.\n- (#1636) Restored the active styling for the Calendar list-view toolbar button. Thanks to @vroablec for reporting this.\n- (#1493, #1638) Kept task time tracking consistent when switching or clearing tasks during an active Pomodoro. Thanks to @ROS-SDN and @katonapng for reporting this, and to @anomatomato for confirming it.\n- (#1639) Respected the aliased-link overlay exclusion in Reading mode even when the alias text matches the task title. Thanks to @MiracleXYZ for reporting this.\n- Fixed actively tracked task cards so the blue time-tracking outline stays visible along the card edges.\n- (#1657) Preserved Bases view defaults when creating tasks from the TaskNotes Kanban/List view New button, so project-scoped views can pass their project assignment into the create task modal. Thanks to @casualQuads122 for reporting this.\n- (#728, #1831) Preserved frontmatter defaults supplied by Obsidian's Bases New action when opening the TaskNotes create task modal from custom Bases views, so filtered views can prefill matching tags, projects, contexts, and custom fields. Thanks to @DillPickle80 and @echo-saurav for suggesting this, and to @prayidae and @renatomen for the detailed follow-up.\n- (#726) Added an instant-conversion option to use the closest heading above the converted line as a project, so checkbox tasks under project headings can inherit that project automatically. Thanks to @ghelton for suggesting this.\n- (#1662) Preserved frontmatter from ICS event note templates when quoted event variables or Templater expressions are used. Thanks to @victorhg for reporting this.\n- (#1663) Fixed Japanese and other Unicode tags on task cards so Kanban tag pills keep the same rounded styling as ASCII tags. Thanks to @kutty-1119 for reporting this.\n- (#1649) Restored daily-note navigation from the Calendar Day view date header. Thanks to @BaccanoMob for reporting this.\n- (#1648, #1665) Fixed the API endpoint list in Integrations settings so it uses the configured bearer token when API authentication is enabled, instead of reporting the running local server as inaccessible. Thanks to @npondel and @warm-july for reporting this.\n- (#1668) Fixed the Create Task magic wand so NLP-triggered custom field values are copied into the custom property inputs before saving. Thanks to @hokfujow for reporting this.\n- (#1669) Stopped the startup settings migration check from rewriting `data.json` just because saved calendar defaults are `false`, `0`, empty, or `null`, reducing unnecessary sync churn. Thanks to @thehyperadvisor for reporting this.\n- (#1674) Improved the timeblock creation error when Daily Notes cannot read its configured folder, so the modal notice points to the Daily Notes core plugin settings instead of only logging the folder lookup failure. Thanks to @Ender367 for reporting this.\n- (#1680) Fixed TaskNotes Calendar Bases options stored under `options`, so Agenda views respect `showPropertyBasedEvents: false` and no longer show duplicate property-based rows for the same task. Thanks to @xiaoyaozhu1991 for reporting this and @KondrotM for confirming it.\n- (#1681) Reduced the cost of inline checkbox convert buttons by only scanning the visible editor range instead of the full document. Thanks to @en-ot for reporting this and @hokfujow for the follow-up.\n- (#1689) Fixed task reminders added or rescheduled through direct frontmatter edits so the notification queue refreshes immediately and relative reminders recalculate from the latest task dates. Thanks to @garzonjav for reporting this.\n- (#1693) Fixed generated default Bases formulas so empty due and scheduled dates are checked with `.isEmpty()` instead of date-field truthiness. Thanks to @benoitjadinon for reporting this.\n- (#1702) Removed the forced bottom gap under TaskNotes custom Bases views, so calendar and other TaskNotes views can fill the available pane height. Thanks to @AudreyLooby for reporting this.\n- (#1719) Fixed task cards in reading mode so Obsidian 1.12.x header changes no longer place the card above the title and properties or drop it after returning to a tab. Thanks to @tholbrook9 for reporting this and tracing the DOM change.\n- (#1722) Saved the source note immediately after converting an inline checkbox task to a TaskNote, so Kanban views do not keep showing the stale inline task alongside the new task file. Thanks to @literallydope for reporting this and sharing screenshots.\n- (#1750) Fixed generated default Bases filters for property-based task identification when the identifying property name contains spaces. Thanks to @Igorgro for reporting this.\n- (#1745) Clarified the inline task documentation so `Create new inline task` is distinguished from current-line conversion. Thanks to @yvos for reporting the mismatch.\n- (#1485) Stopped Google Calendar manual refresh from showing a success notice after token refresh or calendar-list failures. Thanks to @ebanDev for reporting this.\n- (#1474) Made priority-based Kanban swimlanes follow the configured priority order instead of alphabetical task data order. Thanks to @kanzaki1201 for reporting this and @SoTHISIsFitness for the follow-up investigation.\n- (#1470) Restored pointer cursors on TaskNotes interactive elements under Obsidian themes that set `--cursor` to the default cursor. Thanks to @TheFrostedDev for reporting this.\n- (#1463) Documented the supported `FilterQuery` payload for `POST /api/tasks/query`, including context filtering examples and generated API schema details. Thanks to @tcb678 for reporting this and @soloidx for sharing a working query example.\n- (#1464) Made `context` on `GET /api/tasks` follow the same filtering guidance as `project`, so the API now points clients to `POST /api/tasks/query` instead of ignoring the parameter. Thanks to @tcb678 for suggesting this.\n- (#1457) Rendered scheduled-to-due calendar spans with scheduled times as daily timed events instead of moving them to the all-day section. Thanks to @atos2212-blip for reporting this and @rayvermey for confirming it.\n- (#1450) Returned configured user fields in HTTP API task responses under `customProperties`, while keeping the configured frontmatter keys available on each task. Thanks to @Admorei for reporting this and @nschenone for the follow-up.\n- (#1449) Let embedded Agenda views use auto-height sizing by default, so one-day list embeds no longer reserve a large empty calendar block. Thanks to @GlebYavorski for reporting this.\n- (#1446) Kept custom Kanban columns from `columnOrder` available when they are empty, so `hideEmptyColumns: false` can show drop targets for custom grouped values. Thanks to @akhtsang for reporting this.\n- (#1459) Avoided double \"Failed to create task\" prefixes in task creation error notices. Thanks to @Sineapple for reporting this, and to @slipstyle and @Stockemer for the follow-up investigation.\n- (#1469) Fixed Convert current note to task so saving the untouched edit modal writes the task frontmatter instead of reporting no changes. Thanks to @slipstyle for reporting this, and to @jhoogeboom and @ngraham20 for confirming it.\n- (#1466) Prefilled the current note as the project when creating a task from an embedded Subtasks/Relationships Base filtered with `this.file.asLink()`. Thanks to @jhoogeboom for reporting this, and to @cybersader, @fsmontenegro, and @benmartinek for the follow-up discussion.\n- (#1476) Showed linked parent-task project titles instead of timestamp filenames in project stats and grouped task views when the linked task has a frontmatter title. Thanks to @RumiaKitinari for reporting this.\n- (#1487) Let Calendar task event titles wrap instead of clipping long names, and removed the redundant due-date prefix from due task events. Thanks to @Alexander-Bergmann for reporting this.\n- (#1488, #1739) Enabled Kanban touch dragging on touch-capable desktop and convertible devices, not only mobile Obsidian. Thanks to @tmoyland001 and @mgsima for reporting the drag failures, and @SoTHISIsFitness for investigating related task-property cases.\n- (#1738) Fixed Outlook calendar subscriptions whose event timezones reference the base Windows timezone name while the feed defines a suffixed timezone name. Thanks to @Mirrimo for reporting this, @rafavital for confirming it, and @rogerfsh for tracing the ICS timezone mismatch.\n- (#1734) Fixed dependency picker search when task priority values are stored as non-string frontmatter values. Thanks to @MatthewClarkeDev for reporting this and identifying the stack trace.\n- (#1733) Preserved wikilinks in task titles and rendered them as clickable links on task cards. Thanks to @bitscorch for suggesting this.\n- (#1728) Applied the \"Use parent note as project\" default when creating a new task from the command palette or ribbon. Thanks to @greatEmily for reporting this.\n- (#1759) Advanced stale due dates when recurring tasks move to their next scheduled occurrence, so work-window tasks do not remain overdue after completion. Thanks to @MattPryze for reporting this.\n- (#1766) Fixed Calendar Bases date navigation from custom note properties, so embedded calendar views can open on the date stored in the selected property instead of falling back to today. Thanks to @chrabia for reporting this.\n- (#1767) Aligned the start and end time rows in the timeblock creation modal. Thanks to @loiveli for reporting this.\n- (#1783) Replaced the default browser drag ghost for Kanban cards so dragging a card no longer makes the next card look semi-transparent. Thanks to @loukandr for reporting this and tracing the drag image behavior.\n- (#1796) Restored expanded subtasks immediately after renaming a parent task file and updating links. Thanks to @bung69 for reporting this.\n- (#1797) Improved manual ordering so long Kanban columns remain scrollable while dragging, mobile Kanban drops can place a card relative to another card, Kanban/Task List drops resolve the final drop position more reliably, generated manual-order ranks match Bases sorting, and manual-order properties such as `sort_order` render on task cards when enabled. Thanks to @SKIERZZ for reporting this and sharing videos.\n- (#1812) Separated Microsoft OAuth token status from calendar sync status, and surfaced Microsoft calendar fetch errors in the integrations settings card instead of leaving them console-only. Thanks to @henninger80 for the detailed report.\n- (#1814) Restored NLP project autosuggest in the Create or Open Task command, so `+` project suggestions use the same filtered project lookup as the Create Task modal. Thanks to @adammahad for reporting this.\n- (#1820) Kept API-created tasks readable immediately after creation even if Obsidian has not finished indexing the new file metadata yet. Thanks to @vadminas for reporting and tracing the cache desync.\n- (#1823) Prevented zero-duration timed external calendar events from rendering under more than one day in list-style calendar views. Thanks to @martin-forge for reporting and tracing the Google Calendar case.\n- (#1841) Prevented Kanban boards from duplicating columns when wikilinked status values are grouped through Bases. Thanks to @lendamico for reporting and sharing the screen recording.\n- (#1846) Saved NLP-triggered boolean custom fields as real booleans instead of quoted strings, so they match checkbox-created values and Bases filters. Thanks to @DevOps-Toast for reporting and sharing screenshots.\n- (#1849) Prevented repeated clicks on task-card scheduled and due date labels from stacking duplicate date menus when Obsidian native menus are disabled. Thanks to @3zra47 for reporting.\n- (#1850) Added mobile bottom spacing to TaskNotes list views so the final task can scroll above Obsidian's floating mobile controls. Thanks to @AlejandroRigau for reporting and sharing the iPhone screenshot.\n- (#1852) Improved mobile timed calendar event rendering with shorter time labels, tighter spacing, and event-colored task/calendar blocks. Thanks to @redrumthebum for reporting and sharing screenshots.\n- (#1757, #1853, #1775) Respected an existing `mdbase.yaml` `types_folder` when regenerating mdbase task type definitions, so the generated `task.md` can live outside the vault-root `_types` folder. Thanks to @aldrichtr for the original request and implementation exploration, and @hangryscribe3 for the follow-up request.\n- (#1858) Included task body details in single-task HTTP API and MCP reads. Thanks to @vanillaflava for reporting and outlining the expected behavior.\n- (#1859) Clarified the Google Calendar setup guide for OAuth testing-mode `access_denied` errors. Thanks to @PE-Boy for reporting and @tiagoarroz for the workaround.\n- (#1860) Preserved accented characters in tags when converting checkbox tasks to TaskNotes. Thanks to @e-zz for reporting.\n- (#1869) Preserved Calendar Month View scroll position after task updates. Thanks to @sisyowo for reporting and linking the earlier Kanban fix.\n- (#1873) Prevented Calendar Bases from rendering in Obsidian pop-out windows because restoring FullCalendar there can freeze Obsidian. Thanks to @misolex for reporting.\n- (#1497, #1870) Fixed NLP file suggestions for custom fields so selected wikilinks are captured as custom field values, including list-type fields. Thanks to @Naesue and @Sineapple for reporting this, and to @bradleyed and @Xananax for the follow-up details.\n- (#1888) Allowed project autosuggest required property filters to match any comma-separated value, such as `project, area`. Thanks to @BrianHicks for suggesting.\n- (#1886) Added a command to postpone active overdue scheduled tasks to today. Thanks to @chrabia for the suggestion.\n- (#1889) Fixed Kanban swimlanes for list-valued properties so tags and contexts use individual list items instead of comma-joined values. Thanks to @pkropotin for reporting.\n- (#1890) Fixed scheduled-date Kanban columns dropping tasks when date-only and timed tasks on the same day are sorted by a scheduled-time formula. Thanks to @chrabia for reporting and investigating.\n- (#773) Added ICS export filters for archived tasks, completed tasks, due dates, and scheduled dates. Thanks to @ras0q for suggesting this and @slipstyle for the scheduled-date follow-up.\n- (#765) Reduced side-pane gutters around embedded TaskNotes Bases views, so embedded task lists use about the same horizontal space as directly opened Bases views. Thanks to @TonyAtlas for suggesting this.\n- (#1892) Fixed nested Markdown list indentation in the Task Edit Modal details editor. Thanks to @Glint-Eye for reporting.\n- (#1891) Fixed TaskNotes modal markdown editors collapsing to one-character-wide lines when Pretty Properties is installed. Thanks to @bkennedy-improving for reporting.\n- (#1499) Respected excluded folders when opening tasks directly from view results and when building dependency/project indexes, so template-folder tasks no longer appear through TaskNotes views. Thanks to @Liya430 for reporting.\n- (#136, #1500) Made the Pomodoro countdown derive remaining time from the session clock instead of from counted interval ticks, so delayed, backgrounded, or screen-off ticks catch up cleanly without over-recording a completed session. Thanks to @Poly-0000 for reporting and documenting the original background timer issue, @Totobal5 for the earlier worker-based fix, and @CoffeaUrbana for the Android screen-off report.\n- Restored padding in task modal Markdown editors.\n- Made the markdown editor areas in task modals easier to click and focus.\n- Strengthened local CSS linting to catch unscoped selectors, unknown CSS, and fixed-position overlays before review.\n- Reduced false-positive plugin review warnings by making background auto-export and auto-archive schedulers non-overlapping and tightening type/string conversion paths.\n- (#1882) Made Google Calendar task descriptions use mobile-friendly plain text for Obsidian links and display labels for wiki-style project/context links. Thanks to @martin-forge for the contribution.\n- (#1883) Improved Google Calendar task sync recovery so failed deletions, offline sync requests, reconnects, and quick create/update races are retried more reliably. Thanks to @martin-forge for the contribution.\n","aliases":["/releases/4.8.0/","/releases/4.8.0/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"changed","text":"Changed"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • (#353) Added a Has Subtasks filter for task queries, so views and API clients can show only project-style tasks or direct tasks. Thanks to @mdbraber for suggesting this.
  • \n
  • (#380) Added a test-reminder button in notification settings, so reminder setup can be checked without creating a real task reminder. Thanks to @mdbraber for suggesting this.
  • \n
  • (#711, #168) Added an optional task-creation setting to open the new task note after saving, either in the current tab or a new tab. Thanks to @phortx and @23426356587 for suggesting this, and to @edward-peters and @obsilover for the follow-up.
  • \n
  • (#1041, #1800) Added copy-drag support for timeblocks: hold Ctrl, Cmd, or Alt/Option while dragging an existing timeblock to duplicate it at the new date and time. Thanks to @0-BSCode and @cweekly for suggesting this.
  • \n
  • (#1052) Added a public JavaScript API for in-vault scripts at app.plugins.plugins.tasknotes.api.parseNaturalLanguage(text), so Templater, QuickAdd, and MetaBind workflows can use TaskNotes' natural-language parser without running the HTTP API. Thanks to @edakimling for suggesting this.
  • \n
  • (#1235) Added a task-card toggle for blocked tasks, so you can expand a blocked task to see the tasks it is waiting on. Thanks to @craziedde for suggesting this.
  • \n
  • (#1254) Added ../ and ./ normalization for folder templates after variables are expanded, so instant task conversion can target sibling folders such as {{currentNotePath}}/../Tasks. Thanks to @rdick for suggesting this.
  • \n
  • (#1267) Added Daily Notes-style date tokens such as YYYY, MM, DD, MMMM, and dddd to TaskNotes folder templates. Thanks to @paulsen-it for suggesting this.
  • \n
  • (#1380) Added tag actions to task context menus, including add/remove actions for individual tasks and batch-selected tasks. Thanks to @Chuhtra for suggesting this.
  • \n
  • (#1377) Added right-click Mini Calendar actions for opening daily notes from day cells and weekly notes from week numbers. Thanks to @hasanyilmaz for suggesting this.
  • \n
  • (#1151) Added a Mini Calendar max color note count option, so one-note days can use the strongest heatmap color when that better fits the view. Thanks to @arreme for suggesting this.
  • \n
  • (#1376) Added backslash escapes for NLP trigger tokens, so text like \\@context, \\*done, or \\tomorrow can stay in the task title. Thanks to @JerryLu086 for suggesting this.
  • \n
  • (#1366) Added CSS variables for compacting nested task-card indentation, with smaller defaults on mobile and documented snippets for tighter task-link lists. Thanks to @rk-kontur for suggesting this.
  • \n
  • (#1502, #603) Added calendar indicators for external events that have linked notes or tasks, and showed loaded event titles in task-card calendar metadata instead of only the linked event count. Thanks to @Robubble and @mdbraber for suggesting this, and to @ubidev for the follow-up.
  • \n
  • (#1522) Added a per-status option to skip rarely used statuses when cycling task-card status indicators. Thanks to @Glint-Eye for suggesting this.
  • \n
  • (#144) Added an "Open note in new tab" action to the task context menu. Thanks to @cathywu for suggesting this and @macbikegeek for the follow-up feedback.
  • \n
  • (#167) Added an optional next-status override for each status, so forward cycling can jump to a configured status instead of always following the status order. Thanks to @DanBrazelton for suggesting this, and to @michelebugio, @Moyf, @anareaty, and @vorrermid for the follow-up feedback.
  • \n
  • (#1520) Made tag and context fields show available suggestions as soon as the field is focused. Thanks to @Glint-Eye for suggesting this, and to @craziedde for the follow-up.
  • \n
  • (#1541) Added {{currentNotePath}} and {{currentNoteTitle}} support to the default tasks folder, so normal task creation can place new tasks beside the active note without creating an inline link. Thanks to @ChristianAnyanwu for suggesting this, and to @abbasou and @ttlaylor for the follow-up feedback.
  • \n
  • (#648, #1605) Added clickable links in task-card contexts for note links, markdown links, and web URLs while keeping plain contexts as tag-search buttons. Thanks to @trdischat and @Glint-Eye for suggesting this, and to @renatomen for the follow-up feedback.
  • \n
  • (#1482) Added clickable custom-field links on task cards for wikilinks, markdown links, autolinks, and bare web URLs. Thanks to @ptbosch-figueiredorj for suggesting this, and to @Soleone for the follow-up use case.
  • \n
  • (#1471) Added Kanban column and swimlane-cell add buttons that open the TaskNotes creation modal with the grouped values already filled in. Thanks to @byheaven for suggesting this and @Davincible for the project-board use case.
  • \n
  • (#933) Added non-Markdown vault files such as canvases to project suggestions, using extension-qualified link targets so those files can be selected as task projects. Thanks to @Alvin21Bon for suggesting this.
  • \n
  • (#1475, #725) Added quote/backtick escapes for NLP input, so literal course codes or date words can stay in task titles without being parsed as estimates or dates. Thanks to @RumiaKitinari and @gavingwebb for suggesting this.
  • \n
  • (#1462) Added natural-language date entry to the task date picker, so existing due and scheduled dates can be changed with phrases such as "tomorrow at 3pm" when NLP is enabled. Thanks to @Ruboks-Cube for suggesting this.
  • \n
  • (#1526) Added a native date field to the task date picker, so scheduled and due dates can be changed with the device date picker while keeping optional times visible. Thanks to @jmartinmcfly for suggesting this and @23426356587 for the follow-up feedback.
  • \n
  • (#1603) Added Calendar view toggles for hiding completed or skipped recurring task instances while keeping future outstanding instances visible. Thanks to @wandererovertheseaofpiss for suggesting this.
  • \n
  • (#287, #273, #274) Added linked hover highlighting for Calendar and Agenda events that come from the same task note, so scheduled, due, and recurring entries are easier to connect. Thanks to @girisumit for suggesting this.
  • \n
  • (#280) Added project-specific CSS hooks to task cards and Calendar events, so project-based visual styling can be handled with user snippets. Thanks to @girisumit for suggesting this.
  • \n
  • (#1625) Added Shift + Cmd/Ctrl + Enter in the Create Task modal to save the current task and reopen the modal for the next one. Thanks to @tcb678 for suggesting this.
  • \n
  • (#1353) Focused the Create Task modal's natural-language input when the modal opens, with a longer mobile delay so the keyboard can open after layout. Thanks to @GiovanH for suggesting this.
  • \n
  • (#1664) Added project-based custom filename template variables, including the first project, all projects, and a short projectId. Thanks to @bendavis987 for the contribution.
  • \n
  • (#923) Added {{projectFilePath}} and {{projectFilePaths}} folder template variables, so task folders can mirror project note locations in the vault. Thanks to @PacoTaco2 for suggesting this.
  • \n
  • (#1697) Added cached Google Calendar, Microsoft Calendar, and ICS events to Mini Calendar days, with compact colored dots and event details from the existing calendar connection. Thanks to @RPGArchivist for suggesting this.
  • \n
  • (#1754) Added optional icons for priority values, so task cards can show a configured priority icon instead of only a colored dot. Thanks to @BrucePlumb for suggesting this and @prepare4robots for the follow-up feedback.
  • \n
  • (#1761) Added TaskNotes edit and task-action submenu entries to Obsidian's native file context menu for recognized task notes. Thanks to @delzero for suggesting this.
  • \n
  • (#1771) Added mobile drag handles to manually sorted Task List Bases views, so dragging can start from the handle without disabling normal text interaction on the rest of the card. Thanks to @PatrickGolz for suggesting this.
  • \n
  • (#1776) Allowed calendar timeline end times after midnight, such as 26:00 for a 2 AM next-day end. Thanks to @chrabia for suggesting this.
  • \n
  • (#1784, #1833) Added a per-view pinnedColumns option for TaskNotes Kanban views, so selected empty columns can stay visible as drop targets while other empty columns remain hidden. Thanks to @loukandr for suggesting and prototyping this.
  • \n
  • (#1794) Added context updates to the task card context menu, so contexts can be added, toggled, or cleared without opening the task edit modal. Thanks to @m13ntrpn for suggesting this.
  • \n
  • (#315, #1356, #1748, #1809) Added a subtle task-card indicator and CSS hooks for tasks with note body details, including existing task bodies read through Obsidian's metadata cache. Thanks to @volodxyz, @Karut, @yeHHH1g, and @aliceinwaterdeep for suggesting this, and to @minchinweb for the follow-up.
  • \n
  • (#1808) Added advanced Kanban swimlane ordering through swimLaneOrder, so swimlane rows can stay in a stable configured order. Thanks to @rookledookle for suggesting this, and to @benmartinek and @chrabia for the follow-up feedback.
  • \n
  • (#1805) Added an ICS export option to omit completed tasks from generated calendar files. Thanks to @bepolymathe for suggesting this.
  • \n
  • (#659) Added Obsidian links to ICS export descriptions, so exported calendar events can open their source task notes. Thanks to @bepolymathe for suggesting this.
  • \n
  • (#589) Added an Appearance toggle to turn off strikethrough styling on completed task card titles. Thanks to @BrucePlumb for suggesting this.
  • \n
  • (#561) Added a "Last day" option to the custom recurrence month-day picker for month-end repeating tasks. Thanks to @TonyAtlas for suggesting this and @BrucePlumb for the follow-up.
  • \n
  • (#217) Added weekday selection to daily custom recurrence rules, so interval rules such as every three days can skip weekends from the recurrence modal. Thanks to @kmaustral for suggesting this.
  • \n
  • (#1818) Added an auto-height mode for TaskNotes Calendar Bases views so embedded agenda/list sections can size to their content instead of forcing an inner scroller. Thanks to @martin-forge for suggesting this.
  • \n
  • (#1201) Added a Calendar Bases toggle to hide the hourly breakdown in week, custom-days, and day views while keeping the all-day planning row visible. Thanks to @PacoTaco2 for suggesting this.
  • \n
  • (#1176) Added advanced Kanban WIP limits through wipLimits, so column headers can show (current/limit) counts and highlight exceeded limits. Thanks to @williamcheuk03 for suggesting this.
  • \n
  • (#914) Added a generated Due in countdown to the default Agenda Base and allowed Calendar Bases list agendas to span up to 365 days. Thanks to @williamcheuk03 for suggesting this.
  • \n
  • (#900) Added an instant-conversion setting to keep the original Markdown checkbox marker when converting a checkbox into a TaskNote link. Thanks to @dsebastien for suggesting this.
  • \n
  • (#898) Added a mobile-only calendar integration opt-out, so synced desktop calendar settings no longer have to trigger external calendar loading on Obsidian Mobile. Thanks to @cathywu for suggesting this.
  • \n
  • (#887) Added built-in scheduled and due date presets to the Quick actions palette for current tasks. Thanks to @willgraham345 for suggesting this and @anrie for the related preset feedback.
  • \n
  • (#819) Added a command to open Quick actions for the inline task link under the cursor. Thanks to @rlolingo for suggesting this.
  • \n
  • (#798, #1732, #1835) Added hotkeyable commands to edit the current task, add a project to the current task, and add an existing task as a subtask of the current note. Thanks to @xorander00 and @prepare4robots for requesting this, and to @musta-code and @ubidev for the follow-up suggestions.
  • \n
  • (#791) Added a UUID v4 task filename format and {{uuid}} custom filename template variable. Thanks to @bangbangbanggit for suggesting this.
  • \n
  • (#932) Added hotkeyable commands to cycle the current task's status and priority. Thanks to @rxunique for suggesting this and @luckb0x for the follow-up feedback.
  • \n
  • (#1655) Added live elapsed time to the optional active time tracking status bar item. Thanks to @connradolisboa for suggesting this.
  • \n
  • (#1622) Allowed multiple comma-separated default reminder offsets for timed Google Calendar task exports. Thanks to @solidabstract for suggesting this.
  • \n
  • (#706, #820, #1040) Added direct Pomodoro duration editing, hour-aware timer formatting, clearer one-minute controls, and an optional active Pomodoro status bar countdown. Thanks to @SublunarSage, @lj1446615403-cloud, @0-BSCode, and @thestrike72 for the suggestions and feedback.
  • \n
  • (#873) Added an optional built-in sound for task reminder notifications, with volume and preview controls in Settings. Thanks to @berzernberg for suggesting this.
  • \n
  • Added a generated Pomodoro statistics Base with daily and monthly summary views for Pomodoro history stored in daily notes.
  • \n
\n

Changed#

\n
    \n
  • Expanded the bug report template to ask for Obsidian "Show debug info" output, affected task frontmatter, relevant Bases file contents, reproduction steps, and related logs or screenshots.
  • \n
  • Release notes now show the default .base file regeneration reminder only on the current version section, keeping older bundled sections focused on their own changes.
  • \n
  • Updated the release notes GitHub prompt to invite feedback while still asking satisfied users to star the project.
  • \n
  • (#239) Ordered Kanban status and priority columns by the configured status order and priority weights when no manual column order is saved. Thanks to @ScumbagScalawag for asking about this, and to @nightroman, @lavir, and @elvarb for the follow-up discussion.
  • \n
  • (#269) Marked Kanban status columns that come from values outside the configured TaskNotes statuses, so manually edited or external status values are visible as non-standard instead of blending into the board. Thanks to @cstelmach for suggesting this and @digitaldoctors for the follow-up.
  • \n
  • Refined Kanban empty columns, swimlane rows, and column drag handles, and added a per-view compact card layout option for denser boards.
  • \n
  • Kept Kanban swimlane rows from shrinking to share the viewport so the Max Swimlane Height setting is respected.
  • \n
  • Added guidance in Pomodoro statistics and Base file settings explaining that Pomodoro Base views require daily notes storage.
  • \n
  • (#323) Reordered task modal action buttons to match the right-click task menu order. Thanks to @23426356587 for suggesting this.
  • \n
  • (#1189) Made the Create/Edit Task modal priority picker follow the priority order configured in Settings. Thanks to @n1njaznutz for suggesting this.
  • \n
  • Made task-card priority dots and configured priority icons slightly larger for better visibility.
  • \n
  • (#1244) Clarified the Task Properties documentation for custom property keys and status values in Bases filters and sorting. Thanks to @Arachnidai for suggesting this.
  • \n
  • (#1234) Kept right-aligned subtask chevrons visible on task cards instead of only showing them on hover. Thanks to @n1njaznutz for suggesting this.
  • \n
  • (#1237) Made today's date more visible in the Mini Calendar view when another day is selected. Thanks to @riekusr for suggesting this.
  • \n
  • (#1348) Let long task titles wrap inside the Create/Edit Task modal title field while keeping saved titles single-line, and widened the contexts and tags fields in the modal details area. Thanks to @hasanyilmaz for suggesting this.
  • \n
  • (#1392) Made TaskNotes date fields accept compact YYYYMMDD typing and pasted dates. Thanks to @kazerniel for suggesting this.
  • \n
  • (#1431) Showed the year on task-card due and scheduled dates when the date is outside the current year. Thanks to @kazerniel for suggesting this.
  • \n
  • (#1429) Opened TaskNotes view commands in a new tab when they load configured Base files, so they do not replace the active note. Thanks to @Ruboks-Cube for suggesting this.
  • \n
  • (#1426) Added copy actions for TaskNotes Bases views, including current-view filenames, links, and titles from the result count menu, plus selected-task copy actions in the batch menu, while keeping the native Bases copy and CSV export actions available. Thanks to @kmaustral for suggesting this.
  • \n
  • Improved keyboard access, mobile layout, and theme color consistency across task cards, TaskNotes Kanban, Bases Kanban, calendar controls, stats, settings, and filter popovers.
  • \n
  • (#1526) Made the Create/Edit Task modal due and scheduled date buttons open a calendar-first picker where clicking a date saves immediately, with time entry still available in the picker. Thanks to @jmartinmcfly for suggesting this and @23426356587 for the follow-up feedback.
  • \n
  • (#1642) Made completion-based custom recurrence use flexible weekly, monthly, and yearly intervals without forcing a fixed weekday, month day, or month. Thanks to @Volker-brdb for suggesting this.
  • \n
  • (#1724) Moved recurring task complete/skip instance actions into the date area of the task context menu. Thanks to @prepare4robots for suggesting this.
  • \n
  • (#1762) Used the configured Google Calendar task export target as the default calendar when creating manual external calendar events. Thanks to @chrabia for suggesting this.
  • \n
  • (#1774) Made expandable project chevrons visible and easier to tap on mobile. Thanks to @sh0nuff for suggesting this.
  • \n
  • (#190) Made task-card and inline task-link action controls easier to tap on mobile, including always-visible task options on touch layouts. Thanks to @Poly-0000 for suggesting this.
  • \n
  • (#518, #1710, #1785) Added an opt-in setting for Create subtask to inherit the parent task's projects, contexts, priority, and non-identifying tags while always keeping the parent-task project link. Thanks to @bepolymathe, @Jalpara, and @poulpoulsen for reporting this, and to @tomsymonds, @AndyEveritt, @wedgen, @lindsaylearns, and @hokfujow for the follow-up feedback.
  • \n
  • (#1790) Extended the identifying-tag hiding setting to task modal tag suggestions, and kept hidden identifying tag children in place when editing other tags. Thanks to @loukandr for suggesting this.
  • \n
  • (#1804) Made the inline-created task folder setting visible even when instant conversion is disabled, and clarified that leaving it empty uses the default tasks folder. Thanks to @CaFeZn for suggesting this.
  • \n
  • (#1822) Matched the Task Edit Modal subtask list order to the existing relationship sort, so active and higher-priority subtasks appear ahead of completed ones. Thanks to @Glint-Eye for suggesting this.
  • \n
  • (#1233, #1339) Added an Appearance setting to expand project subtasks by default in task cards, while still letting individual cards be collapsed. Thanks to @n1njaznutz and @hasanyilmaz for suggesting this and @kazerniel and @benmartinek for the follow-up.
  • \n
  • (#763) Made the Relationships widget appear on project notes that match Project Autosuggest tag or property filters, even before any tasks link to the project. Thanks to @ChadHattabaugh for suggesting this.
  • \n
  • (#732) Remembered the Task & Project Statistics filters between openings, including the selected date range, custom dates, and minimum time filter. Thanks to @RumiaKitinari for suggesting this.
  • \n
  • (#1335) Added optional default times for new task scheduled and due dates, so default-dated tasks can appear as timed calendar events instead of all-day events. Thanks to @echo-saurav for suggesting this.
  • \n
  • (#1327) Made TaskNotes Bases search match any word in a multi-word search instead of requiring the whole phrase. Thanks to @craziedde for suggesting this.
  • \n
  • (#1318) Made aliased inline task links use the alias text inside the task widget, so [[Task title|short label]] can display as short label. Thanks to @3zra47 for suggesting this and @kazerniel for the follow-up.
  • \n
  • (#1325) Added ./ and ../ support to Include folders filters for project and file autosuggest, resolved from the active note's folder. Thanks to @EpolPers for suggesting this.
  • \n
  • (#1313) Added generated llms.txt and llms-full.txt files to the documentation site, so the primary docs can be shared with LLM tools more easily. Thanks to @JacksonMcDonaldDev for suggesting this.
  • \n
  • (#1308) Added a Calendar view option to stop date links from creating missing daily notes, while still opening existing daily notes. Thanks to @Arachnidai for suggesting this.
  • \n
  • (#1300) Allowed priority, status, calendar subscription, and timeblock color settings to use Obsidian theme color names such as red, blue, and cyan. Thanks to @thestrike72 for suggesting this.
  • \n
  • (#1299) Added a command that creates or opens a task and immediately starts time tracking for it. Thanks to @slipstyle for suggesting this.
  • \n
  • (#1284) Added an exact-match option for hiding task identification tags, so #task can be hidden while nested tags such as #task/project remain visible. Thanks to @3zra47 for suggesting this.
  • \n
  • (#1009) Added a confirmed Delete button to the Edit Task modal, so unwanted task notes can be removed without first opening the note file. Thanks to @jalooc for suggesting this.
  • \n
  • Improved the internal structure of Calendar, Kanban, Bases, task cards, and task modals to make future changes easier to test and maintain.
  • \n
\n

Fixed#

\n
    \n
  • (#697, #1374) Recognized manually authored task notes that use a single scalar tag such as tags: task, so they appear in TaskNotes views and menus like notes using YAML list tags. Thanks to @aubreyz and @phortx for reporting this, and to @jleewastaken for the follow-up.
  • \n
  • Removed the upward hover shift from calendar events while keeping the hover shadow feedback.
  • \n
  • Made same-column manual-order drops in TaskNotes Kanban settle immediately when the local order patch is safe, including virtual columns through a stable reorder path that avoids layout jumps.
  • \n
  • Made single-card cross-column drops in TaskNotes Kanban settle through a local state patch when the move is safe, reducing the wait for the full Bases refresh.
  • \n
  • Fixed Calendar timeblocks created from a selected time range so they appear as soon as Obsidian indexes the daily note update, instead of waiting for a later refresh.
  • \n
  • Replaced the external calendar event emoji marker with the calendar icon and kept it in the same top-right event corner.
  • \n
  • Restored Task List group toggles and recurring calendar month controls to compact icon buttons instead of inherited boxed theme buttons.
  • \n
  • Refined the settings tab navigation styling so tabs read as quieter inline navigation instead of default buttons.
  • \n
  • (#263) Made the instant inline task conversion button respond to touch/pointer activation, so mobile multi-line selections can be converted into TaskNotes. Thanks to @cathywu for reporting this.
  • \n
  • (#216) Preserved @context markers when converting Tasks-plugin-style checkbox tasks into TaskNotes, while keeping those contexts out of the created task title. Thanks to @ksdavidc for suggesting this, and to @hangryscribe3, @nayatiuh, and @natleahh for the follow-up feedback.
  • \n
  • (#508) Showed project note names instead of full project paths in grouped Kanban and Task List headings, while keeping the headings linked to the project note. Thanks to @elvarb for reporting this and @dmodify for confirming it in Task List.
  • \n
  • (#408) Used the task title as the native system notification title for task reminders instead of always showing TaskNotes Reminder. Thanks to @DudeThatsErin for reporting this and @phillipadsmith for the follow-up.
  • \n
  • (#385) Let Mini Calendar month controls shrink and wrap cleanly in narrow sidebars. Thanks to @iholston for reporting this.
  • \n
  • Fixed Calendar List view task cards so they use the available row width without duplicate list cells, row-hover backgrounds, or linked-hover styling.
  • \n
  • (#552) Made instant task convert buttons appear for checkbox tasks inside callouts, and kept converted links inside the callout list. Thanks to @Oblique82 for reporting this and @ksdavidc for the follow-up.
  • \n
  • (#559) Treated notes linked to one loaded recurring calendar event instance as related to the other instances in that series. Thanks to @cathywu for reporting this and @mdbraber for the implementation notes.
  • \n
  • (#685) Made Calendar list views respect the All-day slot option by hiding all-day events from the list when that option is turned off. Thanks to @RumiaKitinari for reporting this.
  • \n
  • (#643) Stopped custom filename templates such as task-{year}{month}{day}{hour}{minute} from incorrectly showing the "filename shortened" notice when creating tasks. Thanks to @minchinweb for reporting this.
  • \n
  • (#722) Made Skip Break reset a queued Pomodoro break back to the next focus timer without starting a session. Thanks to @Goossiii for reporting this and @YIRU69 for the follow-up.
  • \n
  • (#782) Made recurrence weekday choices follow the configured first day of week, and made the quick "Weekdays only" recurrence use locale weekend data instead of assuming Monday through Friday everywhere. Thanks to @BKSalman for reporting this.
  • \n
  • (#872) Made note-level task cards appear immediately, and stay visible while editing, when a task note is embedded as a Canvas file node. Thanks to @bangbangbanggit for reporting this and @benmartinek for the follow-up.
  • \n
  • (#856) Fixed filters for number custom fields so numeric task values match equivalent filter values entered as text. Thanks to @thoughtcipher for reporting this.
  • \n
  • (#1039) Restored clearer TaskNotes Bases grouping for nested project paths, and made the Calendar refresh control an icon button again. Thanks to @dblinnikov for reporting this.
  • \n
  • (#1034) Let embedded TaskNotes Calendar views size to their content by default, so month, week, and day embeds no longer reserve full-pane proportions inside notes. Thanks to @same774 for reporting this.
  • \n
  • (#1023) Kept task modal custom fields scrollable above the iPhone keyboard while creating or editing tasks. Thanks to @3zra47 for reporting this.
  • \n
  • (#1019) Kept active Pomodoro and time-tracking task references working after the tracked task file is renamed. Thanks to @AndreMonthy for reporting this.
  • \n
  • (#1037) Let embedded TaskNotes Calendar year views size to their content and kept the year title from wrapping vertically. Thanks to @same774 for reporting this.
  • \n
  • (#1047) Wrapped long file paths in the Edit Task modal metadata section, so narrow mobile screens no longer get a sideways scrollbar from the File row. Thanks to @3zra47 for reporting this.
  • \n
  • (#1051) Preserved extra values on a property-based task identification field when saving a task, so list properties such as class: [task, habit] no longer get collapsed to only the identifying value. Thanks to @WhoIsSeanGalt for reporting this.
  • \n
  • (#1060) Reused and revealed an already-open Calendar/Base view when running view commands, so a view kept in the sidebar no longer reopens in a new main tab. Thanks to @kmaustral for reporting this.
  • \n
  • (#1075) Hid the native WebKit date-input label that could appear as Label when editing scheduled dates on macOS. Thanks to @3zra47 for reporting this.
  • \n
  • (#1076) Allowed timeblocks to end at midnight using 00:00, and accepted 24:00 as an explicit end-of-day value in timeblock validation. Thanks to @skoove for reporting this and @gregor202 for the follow-up.
  • \n
  • (#1086) Fixed the Calendar + more control in dark mode so expanded all-day task groups stay readable. Thanks to @same774 for reporting this.
  • \n
  • (#1100) Applied Advanced Calendar View search and title filters to the tasks used for calendar rendering, so filtering controls affect which tasks appear on the calendar. Thanks to @quiet-coder-io for reporting this.
  • \n
  • (#1147) Added a delete action for recent Pomodoro statistics sessions, so erroneous Pomodoro history can be removed without editing plugin storage or daily-note frontmatter manually. Thanks to @RumiaKitinari for reporting this and @BrucePlumb for the follow-up.
  • \n
  • (#1150) Kept recurring tasks' due dates visible in Calendar Bases views, and showed their scheduled date when recurrence instances are hidden. Thanks to @thomatino for reporting this and @BrucePlumb for the follow-up.
  • \n
  • (#1159) Softened Calendar time-entry styling so recorded time blocks no longer visually outweigh task events. Thanks to @hatespinach for reporting this.
  • \n
  • (#1191) Aligned the task-card and relationships widgets inside notes with Obsidian's editor margins, including readable-line-width layouts. Thanks to @minchinweb for reporting this.
  • \n
  • (#1183) Kept the Calendar create menu open after drag-selecting a time range, so the selected duration can be used when creating a task. Thanks to @randomness42 for reporting this.
  • \n
  • (#1179) Stopped Calendar Bases views from repainting after unrelated note updates when the visible calendar data has not changed. Thanks to @same774 for reporting this.
  • \n
  • (#1156) Kept property-based task identification through the tags property from rewriting task tags as a plain text value, and generated default Bases now use tag membership for that setting. Thanks to @seepage87 for the detailed migration report and @chrsdk for the follow-up.
  • \n
  • (#1232) Fixed generated Task List Base date filters so recurring tasks scheduled for today appear in the Today view, and today's completed recurring instances stay hidden. Thanks to @mvichosfm for reporting this and @ArthurGideon and @VarunNikam22 for the follow-up.
  • \n
  • (#1231) Fixed the generated Task List Base Overdue view so tasks with scheduled dates in the past appear alongside tasks with due dates in the past. Thanks to @Lorite for reporting this and @dictionarymouse for the follow-up.
  • \n
  • (#1228) Matched the task details editor's Markdown heading colors to the active Obsidian theme, including themes that customize heading colors. Thanks to @BrucePlumb for requesting this.
  • \n
  • (#1227) Refreshed the relationships widget when project references are indexed or updated so project notes can show related tasks automatically again. Thanks to @luckb0x for reporting this.
  • \n
  • (#1219) Fixed Kanban drags that start on an expanded subtask card so they move that subtask instead of dragging the parent card. Thanks to @craziedde for reporting this.
  • \n
  • (#990) Treated one-item status lists written by Obsidian Properties as the same status value in TaskNotes Kanban, so they no longer create duplicate columns. Thanks to @mlevison for reporting this.
  • \n
  • (#983) Let Agenda Calendar views wrap their header controls and task titles inside narrow sidebars, so Today and refresh controls and task icons remain visible without sideways scrolling. Thanks to @3zra47 for reporting this.
  • \n
  • (#982) Made TaskNotes task-card typography scale from Obsidian's text font size setting, so Bases and Agenda task text follows larger mobile font settings. Thanks to @3zra47 for suggesting this and @chrsdk and @scottaltham-payroc for the follow-up.
  • \n
  • (#966) Made reminder delete buttons larger and always visible on mobile, so reminders can be removed from the Manage All Reminders modal on iPad. Thanks to @PSG2017 for reporting this.
  • \n
  • (#964) Made Pomodoro and time-tracking task selection use the current recurring instance status, so a recurring task can still be selected after an earlier instance was completed. Thanks to @lomarcanys for reporting this.
  • \n
  • (#944) Preserved number and boolean custom field values when moving tasks between grouped Kanban or Task List columns, and when creating a task from a grouped Kanban column. Thanks to @thoughtcipher for reporting this.
  • \n
  • (#935) Fixed Task List priority sorting so descending order puts higher-weighted priorities first, and due dates are used before scheduled dates when priority values tie. Thanks to @Glint-Eye for reporting this and @kacoroski for the follow-up.
  • \n
  • (#922) Made the Blocked task-card pill expand the blocker tasks, and rendered blockedBy dependencies as clickable links when that property is shown on cards. Thanks to @prayidae for reporting this and following up.
  • \n
  • (#919) Fixed exported ICS task events so they use valid calendar event statuses and can be imported by stricter calendar apps. Thanks to @benoitjadinon for reporting this.
  • \n
  • (#1213) Fixed embedded Task List Bases in Obsidian pop-out windows so typing below the embed no longer leaves a large blank gap. Thanks to @same774 for reporting this.
  • \n
  • (#1243) Removed quoted multi-word custom field NLP expressions from created task titles after saving the custom field value. Thanks to @Arachnidai for reporting this.
  • \n
  • (#1252) Hardened the calendar-first task date picker for iPad taps so date buttons use direct touch manipulation. Thanks to @alxandrharris for reporting this.
  • \n
  • (#1261) Removed the extra Task List Base scrollbar when an embedded task list note is placed in a sidebar, while keeping normal embedded task lists scrollable in the main note area. Thanks to @cathywu for reporting this.
  • \n
  • (#1347) Lowered TaskNotes task-card tag CSS specificity so hierarchical tag colors from Obsidian themes and tag-color plugins can apply correctly. Thanks to @3Fish for reporting this.
  • \n
  • (#1374) Recognized status and priority labels entered through Obsidian Properties or Bases as their configured TaskNotes values. Thanks to @phortx for reporting this.
  • \n
  • (#1373) Parsed numeric natural-language dates with the configured calendar locale, so en-GB treats 11/06/2026 as 11 June instead of November 6, and YYYY/MM/DD works consistently. Thanks to @AleMunin for reporting this and @imsuck for the follow-up.
  • \n
  • (#1370) Prevented recurring task series from being queued for auto-archive when their parent status uses auto-archive, so ongoing recurring tasks are not moved away after completing an occurrence. Thanks to @Jomo94 for reporting this and @martin-forge for the follow-up discussion.
  • \n
  • (#1367) Made recurring task completion counts use the total expected instances for finite COUNT or UNTIL recurrences, and stopped showing a made-up percentage for unbounded recurrences. Thanks to @saurinni for reporting this.
  • \n
  • (#1365) Preserved email and other URI links from converted inline task titles by moving the original links into the new task body, and rendered message:/mailto: markdown links as external links in TaskNotes surfaces. Thanks to @phillipadsmith for reporting this and @hasanyilmaz for the follow-up.
  • \n
  • (#1350) Refreshed inline task widgets in Reading mode after task property edits, so changed dates and other visible properties no longer stay stale until the note is reopened. Thanks to @tmsbn for reporting this.
  • \n
  • (#1329) Pulled the relationships widget up to the end of the note content without removing its normal spacing, and kept that placement updated while editing and on load so it no longer covers the editor. Thanks to @Volker-brdb for reporting this.
  • \n
  • (#1326) Treated empty task frontmatter values as missing, so empty titles fall back to the filename and blank date, priority, and recurrence fields are ignored. Thanks to @craziedde for suggesting this.
  • \n
  • (#1316) Stopped stale Workspace state from overriding the configured Calendar view mode, so switching Workspaces no longer forces an old Day/Week/List choice over the view default. Thanks to @kmaustral for reporting this and following up.
  • \n
  • (#1302) Read task frontmatter directly from the task file when Obsidian has not indexed its metadata yet, so visible tasks can still be opened, updated, and selected instead of reporting "Task not found". Thanks to @WorldTeacher for reporting this and @Steven-AA for confirming it.
  • \n
  • Kept just-written task data available while Obsidian's metadata cache catches up, so immediate reads after task edits no longer briefly return stale values.
  • \n
  • (#1297) Made the Create or open task footer tappable, so mobile users can create the typed task without needing the Shift+Enter shortcut. Thanks to @slipstyle for reporting this.
  • \n
  • (#1288) Allowed formula properties to appear in Calendar property-based event start and end date selectors. Thanks to @hasanyilmaz for reporting this.
  • \n
  • Made TaskNotes Kanban drags show a lightweight held-card preview, so the dragged card remains easy to track while the source column opens the drop slot.
  • \n
  • (#1423) Refreshed TaskNotes Bases views when subtasks are deleted, so expanded project cards drop removed subtasks and stop showing project controls when the last subtask is gone. Thanks to @normenmueller for reporting this.
  • \n
  • (#1419) Kept custom user field name, key, and default-value edits in Task Properties settings when closing settings without first blurring the field. Thanks to @s33a for reporting this and @kacoroski for the follow-up.
  • \n
  • Reduced redundant settings writes by coalescing overlapping saves, so settings changes made in quick succession finish with the latest values without repeating every intermediate save cycle.
  • \n
  • (#1331, #1411) Made Agenda Calendar Bases respect the Base sort order within each day instead of falling back to alphabetical title order. Thanks to @bane73 and @ky1ejs for reporting this.
  • \n
  • (#1383) Made task modal markdown editors expose the active editor API expected by plugins such as Templater. Thanks to @tomsymonds for reporting this.
  • \n
  • Fixed the first-run Create/Edit Task modal so the default fields appear immediately after installing TaskNotes, without needing to open Modal Fields settings or restart Obsidian.
  • \n
  • (#1895) Restored the natural-language preview in the Create Task modal. Thanks to @ssonhub for reporting this.
  • \n
  • (#1898) Cleared stale Calendar time-axis column widths when switching views, so Day, Week, and 3-day views keep the time labels anchored on the left. Thanks to @ddevaal for reporting this.
  • \n
  • (#1439) Fixed generated Bases dependency filters so blockedBy entries stored as links, strings, or dependency objects are handled consistently in Not Blocked and Relationships views. Thanks to @prayidae for reporting this and following up.
  • \n
  • (#1435) Prevented malformed task dependency, status, or priority values from breaking the task context menu. Thanks to @23maverick23 for reporting this.
  • \n
  • (#1434) Kept older filename-titled tasks readable after turning off "Store title in filename" by falling back to the filename when a task has no usable title property. Thanks to @hujuDev for reporting this.
  • \n
  • (#1433) Made the Due date and Scheduled date weekday picker follow the configured first day of week. Thanks to @sandchipper for reporting this.
  • \n
  • (#1430) Showed custom user-field property keys in Modal Fields settings instead of internal field IDs. Thanks to @JerryLu086 for reporting this.
  • \n
  • (#1427) Fixed project autosuggest Required Tags filters so frontmatter tags parsed by Obsidian are handled the same way as direct tag-property filters. Thanks to @ProHaller for reporting this.
  • \n
  • (#1495) Added an Update default files action for generated Bases views, so task-tag or task-identification setting changes can refresh existing .base filters without deleting files manually. Thanks to @Liya430 for reporting this.
  • \n
  • (#1512) Prevented the split Create/Edit Task modal details pane from collapsing to a one-character-wide column under the Minimal theme. Thanks to @willfanguy for reporting this and sharing detailed CSS notes.
  • \n
  • (#1524) Fixed task-card font sizes shrinking when a Bases view is opened in an Obsidian pop-out window. Thanks to @Glint-Eye for reporting this.
  • \n
  • (#1535) Fixed the generated Relationships Base Subtasks filter so single project links do not trigger a Bases contains error. Thanks to @DanaKyle for reporting this.
  • \n
  • (#1102) Refreshed task cards when a task status is edited directly in Obsidian frontmatter, so the card no longer stays on the old status until it is clicked. Thanks to @Wayment9504 for reporting this.
  • \n
  • (#1105) Added an explicit Close action to the mobile task options menu, so iPhone users do not need to tap near the top system bar to dismiss it. Thanks to @J-R-Troutman for reporting this.
  • \n
  • (#1550) Prevented mobile Calendar event drags from opening the task context menu before the drag can begin. Thanks to @stil-sudo for suggesting this.
  • \n
  • (#1563) Removed duplicate entries from Calendar event related notes when the same linked file is also a TaskNote. Thanks to @VarunNikam22 for reporting this.
  • \n
  • (#1566) Rendered grouped multi-project values as individual links when a Bases group title contains multiple project links. Thanks to @ptsouchlos for suggesting this.
  • \n
  • (#1569) Allowed local ICS calendar paths inside the vault to be pasted as absolute filesystem paths, and showed a clearer error when the file is outside the vault. Thanks to @Photon89 for reporting this and following up.
  • \n
  • (#1584) Sanitized task-card status and priority class names, so custom values with spaces no longer create invalid CSS classes. Thanks to @omber for reporting this.
  • \n
  • (#1587) Stored dependencies added from the task context menu as wikilinks, matching the Edit Task modal. Thanks to @mgrecar for reporting this.
  • \n
  • (#1590) Clarified HTTP API task creation docs and OpenAPI schema for writable blockedBy dependencies, and marked blocking as a read-only derived relationship. Thanks to @hGriff0n for reporting this.
  • \n
  • (#1591) Added a startup guard that avoids saving default settings over an existing settings file if Obsidian temporarily returns no plugin data during an update. Thanks to @GGlider for reporting this.
  • \n
  • (#1593) Made the New button in TaskNotes Bases views open the TaskNotes create task modal again, so new tasks respect the configured default tasks folder. Thanks to @katlandreth for reporting this.
  • \n
  • (#1594) Made task cards inside recurring task notes complete the task's current scheduled occurrence instead of today's date when no calendar or view date is supplied. Thanks to @ngraham20 for reporting this.
  • \n
  • (#1601) Prevented overlapping Live Preview relationship-widget injections from leaving duplicate subtask/relationship sections in a note. Thanks to @wealthychef1 for reporting this and @benmartinek for confirming it.
  • \n
  • (#1610) Made expanded subtasks in TaskNotes Bases views follow the current view's sorted task order instead of a fixed fallback order. Thanks to @MrZzard for reporting this and @slipstyle for confirming it.
  • \n
  • (#1609) Restored scrolling in wide split-layout task edit modals when the form content is taller than the modal. Thanks to @3zra47 for reporting this.
  • \n
  • (#1614) Wrote unchecked boolean custom user-field defaults to new task frontmatter, including tasks created through instant conversion. Thanks to @kobalteule for reporting this.
  • \n
  • (#1611) Made generated default Bases urgency scores fall back safely when the next-date distance is missing. Thanks to @benoitjadinon for reporting this and suggesting the formula fix.
  • \n
  • (#1623) Honored "Store title in filename" across task creation and edits, so the mapped title property is omitted from frontmatter and stale title fields are removed on save. Thanks to @VenturaNotes for reporting this, and to @Ender367, @slipstyle, and @loukandr for confirming and tracing affected paths.
  • \n
  • (#1621) Made Kanban swimlane labels stop freezing on mobile and kept their label column compact, leaving more room for task cards while horizontally scrolling. Thanks to @karenchoe428 for reporting this.
  • \n
  • (#1615) Detected Obsidian custom multi-text properties exposed through widget: "multitext" as list properties, so Kanban can split those values into multiple columns. Thanks to @konton71 for reporting this.
  • \n
  • (#1626) Expanded recurring ICS subscription events through the one-year subscription window for high-frequency recurring calendars. Thanks to @pib for reporting this.
  • \n
  • (#1628) Refreshed Calendar Bases views promptly when switching between filtered Agenda views, so the previous view's task set does not stay visible until the delayed refresh. Thanks to @Lanalangz for reporting this.
  • \n
  • (#1629) Saved blockedBy dependencies selected in the Create Task modal. Thanks to @obsilover for reporting this.
  • \n
  • (#1634) Aligned custom status icons in inline tasks with the default inline status circle. Thanks to @ttlaylor for reporting this and @basbarten for confirming it.
  • \n
  • (#1636) Restored the active styling for the Calendar list-view toolbar button. Thanks to @vroablec for reporting this.
  • \n
  • (#1493, #1638) Kept task time tracking consistent when switching or clearing tasks during an active Pomodoro. Thanks to @ROS-SDN and @katonapng for reporting this, and to @anomatomato for confirming it.
  • \n
  • (#1639) Respected the aliased-link overlay exclusion in Reading mode even when the alias text matches the task title. Thanks to @MiracleXYZ for reporting this.
  • \n
  • Fixed actively tracked task cards so the blue time-tracking outline stays visible along the card edges.
  • \n
  • (#1657) Preserved Bases view defaults when creating tasks from the TaskNotes Kanban/List view New button, so project-scoped views can pass their project assignment into the create task modal. Thanks to @casualQuads122 for reporting this.
  • \n
  • (#728, #1831) Preserved frontmatter defaults supplied by Obsidian's Bases New action when opening the TaskNotes create task modal from custom Bases views, so filtered views can prefill matching tags, projects, contexts, and custom fields. Thanks to @DillPickle80 and @echo-saurav for suggesting this, and to @prayidae and @renatomen for the detailed follow-up.
  • \n
  • (#726) Added an instant-conversion option to use the closest heading above the converted line as a project, so checkbox tasks under project headings can inherit that project automatically. Thanks to @ghelton for suggesting this.
  • \n
  • (#1662) Preserved frontmatter from ICS event note templates when quoted event variables or Templater expressions are used. Thanks to @victorhg for reporting this.
  • \n
  • (#1663) Fixed Japanese and other Unicode tags on task cards so Kanban tag pills keep the same rounded styling as ASCII tags. Thanks to @kutty-1119 for reporting this.
  • \n
  • (#1649) Restored daily-note navigation from the Calendar Day view date header. Thanks to @BaccanoMob for reporting this.
  • \n
  • (#1648, #1665) Fixed the API endpoint list in Integrations settings so it uses the configured bearer token when API authentication is enabled, instead of reporting the running local server as inaccessible. Thanks to @npondel and @warm-july for reporting this.
  • \n
  • (#1668) Fixed the Create Task magic wand so NLP-triggered custom field values are copied into the custom property inputs before saving. Thanks to @hokfujow for reporting this.
  • \n
  • (#1669) Stopped the startup settings migration check from rewriting data.json just because saved calendar defaults are false, 0, empty, or null, reducing unnecessary sync churn. Thanks to @thehyperadvisor for reporting this.
  • \n
  • (#1674) Improved the timeblock creation error when Daily Notes cannot read its configured folder, so the modal notice points to the Daily Notes core plugin settings instead of only logging the folder lookup failure. Thanks to @Ender367 for reporting this.
  • \n
  • (#1680) Fixed TaskNotes Calendar Bases options stored under options, so Agenda views respect showPropertyBasedEvents: false and no longer show duplicate property-based rows for the same task. Thanks to @xiaoyaozhu1991 for reporting this and @KondrotM for confirming it.
  • \n
  • (#1681) Reduced the cost of inline checkbox convert buttons by only scanning the visible editor range instead of the full document. Thanks to @en-ot for reporting this and @hokfujow for the follow-up.
  • \n
  • (#1689) Fixed task reminders added or rescheduled through direct frontmatter edits so the notification queue refreshes immediately and relative reminders recalculate from the latest task dates. Thanks to @garzonjav for reporting this.
  • \n
  • (#1693) Fixed generated default Bases formulas so empty due and scheduled dates are checked with .isEmpty() instead of date-field truthiness. Thanks to @benoitjadinon for reporting this.
  • \n
  • (#1702) Removed the forced bottom gap under TaskNotes custom Bases views, so calendar and other TaskNotes views can fill the available pane height. Thanks to @AudreyLooby for reporting this.
  • \n
  • (#1719) Fixed task cards in reading mode so Obsidian 1.12.x header changes no longer place the card above the title and properties or drop it after returning to a tab. Thanks to @tholbrook9 for reporting this and tracing the DOM change.
  • \n
  • (#1722) Saved the source note immediately after converting an inline checkbox task to a TaskNote, so Kanban views do not keep showing the stale inline task alongside the new task file. Thanks to @literallydope for reporting this and sharing screenshots.
  • \n
  • (#1750) Fixed generated default Bases filters for property-based task identification when the identifying property name contains spaces. Thanks to @Igorgro for reporting this.
  • \n
  • (#1745) Clarified the inline task documentation so Create new inline task is distinguished from current-line conversion. Thanks to @yvos for reporting the mismatch.
  • \n
  • (#1485) Stopped Google Calendar manual refresh from showing a success notice after token refresh or calendar-list failures. Thanks to @ebanDev for reporting this.
  • \n
  • (#1474) Made priority-based Kanban swimlanes follow the configured priority order instead of alphabetical task data order. Thanks to @kanzaki1201 for reporting this and @SoTHISIsFitness for the follow-up investigation.
  • \n
  • (#1470) Restored pointer cursors on TaskNotes interactive elements under Obsidian themes that set --cursor to the default cursor. Thanks to @TheFrostedDev for reporting this.
  • \n
  • (#1463) Documented the supported FilterQuery payload for POST /api/tasks/query, including context filtering examples and generated API schema details. Thanks to @tcb678 for reporting this and @soloidx for sharing a working query example.
  • \n
  • (#1464) Made context on GET /api/tasks follow the same filtering guidance as project, so the API now points clients to POST /api/tasks/query instead of ignoring the parameter. Thanks to @tcb678 for suggesting this.
  • \n
  • (#1457) Rendered scheduled-to-due calendar spans with scheduled times as daily timed events instead of moving them to the all-day section. Thanks to @atos2212-blip for reporting this and @rayvermey for confirming it.
  • \n
  • (#1450) Returned configured user fields in HTTP API task responses under customProperties, while keeping the configured frontmatter keys available on each task. Thanks to @Admorei for reporting this and @nschenone for the follow-up.
  • \n
  • (#1449) Let embedded Agenda views use auto-height sizing by default, so one-day list embeds no longer reserve a large empty calendar block. Thanks to @GlebYavorski for reporting this.
  • \n
  • (#1446) Kept custom Kanban columns from columnOrder available when they are empty, so hideEmptyColumns: false can show drop targets for custom grouped values. Thanks to @akhtsang for reporting this.
  • \n
  • (#1459) Avoided double "Failed to create task" prefixes in task creation error notices. Thanks to @Sineapple for reporting this, and to @slipstyle and @Stockemer for the follow-up investigation.
  • \n
  • (#1469) Fixed Convert current note to task so saving the untouched edit modal writes the task frontmatter instead of reporting no changes. Thanks to @slipstyle for reporting this, and to @jhoogeboom and @ngraham20 for confirming it.
  • \n
  • (#1466) Prefilled the current note as the project when creating a task from an embedded Subtasks/Relationships Base filtered with this.file.asLink(). Thanks to @jhoogeboom for reporting this, and to @cybersader, @fsmontenegro, and @benmartinek for the follow-up discussion.
  • \n
  • (#1476) Showed linked parent-task project titles instead of timestamp filenames in project stats and grouped task views when the linked task has a frontmatter title. Thanks to @RumiaKitinari for reporting this.
  • \n
  • (#1487) Let Calendar task event titles wrap instead of clipping long names, and removed the redundant due-date prefix from due task events. Thanks to @Alexander-Bergmann for reporting this.
  • \n
  • (#1488, #1739) Enabled Kanban touch dragging on touch-capable desktop and convertible devices, not only mobile Obsidian. Thanks to @tmoyland001 and @mgsima for reporting the drag failures, and @SoTHISIsFitness for investigating related task-property cases.
  • \n
  • (#1738) Fixed Outlook calendar subscriptions whose event timezones reference the base Windows timezone name while the feed defines a suffixed timezone name. Thanks to @Mirrimo for reporting this, @rafavital for confirming it, and @rogerfsh for tracing the ICS timezone mismatch.
  • \n
  • (#1734) Fixed dependency picker search when task priority values are stored as non-string frontmatter values. Thanks to @MatthewClarkeDev for reporting this and identifying the stack trace.
  • \n
  • (#1733) Preserved wikilinks in task titles and rendered them as clickable links on task cards. Thanks to @bitscorch for suggesting this.
  • \n
  • (#1728) Applied the "Use parent note as project" default when creating a new task from the command palette or ribbon. Thanks to @greatEmily for reporting this.
  • \n
  • (#1759) Advanced stale due dates when recurring tasks move to their next scheduled occurrence, so work-window tasks do not remain overdue after completion. Thanks to @MattPryze for reporting this.
  • \n
  • (#1766) Fixed Calendar Bases date navigation from custom note properties, so embedded calendar views can open on the date stored in the selected property instead of falling back to today. Thanks to @chrabia for reporting this.
  • \n
  • (#1767) Aligned the start and end time rows in the timeblock creation modal. Thanks to @loiveli for reporting this.
  • \n
  • (#1783) Replaced the default browser drag ghost for Kanban cards so dragging a card no longer makes the next card look semi-transparent. Thanks to @loukandr for reporting this and tracing the drag image behavior.
  • \n
  • (#1796) Restored expanded subtasks immediately after renaming a parent task file and updating links. Thanks to @bung69 for reporting this.
  • \n
  • (#1797) Improved manual ordering so long Kanban columns remain scrollable while dragging, mobile Kanban drops can place a card relative to another card, Kanban/Task List drops resolve the final drop position more reliably, generated manual-order ranks match Bases sorting, and manual-order properties such as sort_order render on task cards when enabled. Thanks to @SKIERZZ for reporting this and sharing videos.
  • \n
  • (#1812) Separated Microsoft OAuth token status from calendar sync status, and surfaced Microsoft calendar fetch errors in the integrations settings card instead of leaving them console-only. Thanks to @henninger80 for the detailed report.
  • \n
  • (#1814) Restored NLP project autosuggest in the Create or Open Task command, so + project suggestions use the same filtered project lookup as the Create Task modal. Thanks to @adammahad for reporting this.
  • \n
  • (#1820) Kept API-created tasks readable immediately after creation even if Obsidian has not finished indexing the new file metadata yet. Thanks to @vadminas for reporting and tracing the cache desync.
  • \n
  • (#1823) Prevented zero-duration timed external calendar events from rendering under more than one day in list-style calendar views. Thanks to @martin-forge for reporting and tracing the Google Calendar case.
  • \n
  • (#1841) Prevented Kanban boards from duplicating columns when wikilinked status values are grouped through Bases. Thanks to @lendamico for reporting and sharing the screen recording.
  • \n
  • (#1846) Saved NLP-triggered boolean custom fields as real booleans instead of quoted strings, so they match checkbox-created values and Bases filters. Thanks to @DevOps-Toast for reporting and sharing screenshots.
  • \n
  • (#1849) Prevented repeated clicks on task-card scheduled and due date labels from stacking duplicate date menus when Obsidian native menus are disabled. Thanks to @3zra47 for reporting.
  • \n
  • (#1850) Added mobile bottom spacing to TaskNotes list views so the final task can scroll above Obsidian's floating mobile controls. Thanks to @AlejandroRigau for reporting and sharing the iPhone screenshot.
  • \n
  • (#1852) Improved mobile timed calendar event rendering with shorter time labels, tighter spacing, and event-colored task/calendar blocks. Thanks to @redrumthebum for reporting and sharing screenshots.
  • \n
  • (#1757, #1853, #1775) Respected an existing mdbase.yaml types_folder when regenerating mdbase task type definitions, so the generated task.md can live outside the vault-root _types folder. Thanks to @aldrichtr for the original request and implementation exploration, and @hangryscribe3 for the follow-up request.
  • \n
  • (#1858) Included task body details in single-task HTTP API and MCP reads. Thanks to @vanillaflava for reporting and outlining the expected behavior.
  • \n
  • (#1859) Clarified the Google Calendar setup guide for OAuth testing-mode access_denied errors. Thanks to @PE-Boy for reporting and @tiagoarroz for the workaround.
  • \n
  • (#1860) Preserved accented characters in tags when converting checkbox tasks to TaskNotes. Thanks to @e-zz for reporting.
  • \n
  • (#1869) Preserved Calendar Month View scroll position after task updates. Thanks to @sisyowo for reporting and linking the earlier Kanban fix.
  • \n
  • (#1873) Prevented Calendar Bases from rendering in Obsidian pop-out windows because restoring FullCalendar there can freeze Obsidian. Thanks to @misolex for reporting.
  • \n
  • (#1497, #1870) Fixed NLP file suggestions for custom fields so selected wikilinks are captured as custom field values, including list-type fields. Thanks to @Naesue and @Sineapple for reporting this, and to @bradleyed and @Xananax for the follow-up details.
  • \n
  • (#1888) Allowed project autosuggest required property filters to match any comma-separated value, such as project, area. Thanks to @BrianHicks for suggesting.
  • \n
  • (#1886) Added a command to postpone active overdue scheduled tasks to today. Thanks to @chrabia for the suggestion.
  • \n
  • (#1889) Fixed Kanban swimlanes for list-valued properties so tags and contexts use individual list items instead of comma-joined values. Thanks to @pkropotin for reporting.
  • \n
  • (#1890) Fixed scheduled-date Kanban columns dropping tasks when date-only and timed tasks on the same day are sorted by a scheduled-time formula. Thanks to @chrabia for reporting and investigating.
  • \n
  • (#773) Added ICS export filters for archived tasks, completed tasks, due dates, and scheduled dates. Thanks to @ras0q for suggesting this and @slipstyle for the scheduled-date follow-up.
  • \n
  • (#765) Reduced side-pane gutters around embedded TaskNotes Bases views, so embedded task lists use about the same horizontal space as directly opened Bases views. Thanks to @TonyAtlas for suggesting this.
  • \n
  • (#1892) Fixed nested Markdown list indentation in the Task Edit Modal details editor. Thanks to @Glint-Eye for reporting.
  • \n
  • (#1891) Fixed TaskNotes modal markdown editors collapsing to one-character-wide lines when Pretty Properties is installed. Thanks to @bkennedy-improving for reporting.
  • \n
  • (#1499) Respected excluded folders when opening tasks directly from view results and when building dependency/project indexes, so template-folder tasks no longer appear through TaskNotes views. Thanks to @Liya430 for reporting.
  • \n
  • (#136, #1500) Made the Pomodoro countdown derive remaining time from the session clock instead of from counted interval ticks, so delayed, backgrounded, or screen-off ticks catch up cleanly without over-recording a completed session. Thanks to @Poly-0000 for reporting and documenting the original background timer issue, @Totobal5 for the earlier worker-based fix, and @CoffeaUrbana for the Android screen-off report.
  • \n
  • Restored padding in task modal Markdown editors.
  • \n
  • Made the markdown editor areas in task modals easier to click and focus.
  • \n
  • Strengthened local CSS linting to catch unscoped selectors, unknown CSS, and fixed-position overlays before review.
  • \n
  • Reduced false-positive plugin review warnings by making background auto-export and auto-archive schedulers non-overlapping and tightening type/string conversion paths.
  • \n
  • (#1882) Made Google Calendar task descriptions use mobile-friendly plain text for Obsidian links and display labels for wiki-style project/context links. Thanks to @martin-forge for the contribution.
  • \n
  • (#1883) Improved Google Calendar task sync recovery so failed deletions, offline sync requests, reconnects, and quick create/update races are retried more reliably. Thanks to @martin-forge for the contribution.
  • \n
\n","text":"Added# (#353) Added a Has Subtasks filter for task queries, so views and API clients can show only project-style tasks or direct tasks. Thanks to @mdbraber for suggesting this. (#380) Added a test-reminder button in notification settings, so reminder setup can be checked without creating a real task reminder. Thanks to @mdbraber for suggesting this. (#711, #168) Added an optional task-creation setting to open the new task note after saving, either in the current tab or a new tab. Thanks to @phortx and @23426356587 for suggesting this, and to @edward-peters and @obsilover for the follow-up. (#1041, #1800) Added copy-drag support for timeblocks: hold Ctrl, Cmd, or Alt/Option while dragging an existing timeblock to duplicate it at the new date and time. Thanks to @0-BSCode and @cweekly for suggesting this. (#1052) Added a public JavaScript API for in-vault scripts at app.plugins.plugins.tasknotes.api.parseNaturalLanguage(text), so Templater, QuickAdd, and MetaBind workflows can use TaskNotes' natural-language parser without running the HTTP API. Thanks to @edakimling for suggesting this. (#1235) Added a task-card toggle for blocked tasks, so you can expand a blocked task to see the tasks it is waiting on. Thanks to @craziedde for suggesting this. (#1254) Added ../ and ./ normalization for folder templates after variables are expanded, so instant task conversion can target sibling folders such as {{currentNotePath}}/../Tasks. Thanks to @rdick for suggesting this. (#1267) Added Daily Notes-style date tokens such as YYYY, MM, DD, MMMM, and dddd to TaskNotes folder templates. Thanks to @paulsen-it for suggesting this. (#1380) Added tag actions to task context menus, including add/remove actions for individual tasks and batch-selected tasks. Thanks to @Chuhtra for suggesting this. (#1377) Added right-click Mini Calendar actions for opening daily notes from day cells and weekly notes from week numbers. Thanks to @hasanyilmaz for suggesting this. (#1151) Added a Mini Calendar max color note count option, so one-note days can use the strongest heatmap color when that better fits the view. Thanks to @arreme for suggesting this. (#1376) Added backslash escapes for NLP trigger tokens, so text like \\@context, \\*done, or \\tomorrow can stay in the task title. Thanks to @JerryLu086 for suggesting this. (#1366) Added CSS variables for compacting nested task-card indentation, with smaller defaults on mobile and documented snippets for tighter task-link lists. Thanks to @rk-kontur for suggesting this. (#1502, #603) Added calendar indicators for external events that have linked notes or tasks, and showed loaded event titles in task-card calendar metadata instead of only the linked event count. Thanks to @Robubble and @mdbraber for suggesting this, and to @ubidev for the follow-up. (#1522) Added a per-status option to skip rarely used statuses when cycling task-card status indicators. Thanks to @Glint-Eye for suggesting this. (#144) Added an \"Open note in new tab\" action to the task context menu. Thanks to @cathywu for suggesting this and @macbikegeek for the follow-up feedback. (#167) Added an optional next-status override for each status, so forward cycling can jump to a configured status instead of always following the status order. Thanks to @DanBrazelton for suggesting this, and to @michelebugio, @Moyf, @anareaty, and @vorrermid for the follow-up feedback. (#1520) Made tag and context fields show available suggestions as soon as the field is focused. Thanks to @Glint-Eye for suggesting this, and to @craziedde for the follow-up. (#1541) Added {{currentNotePath}} and {{currentNoteTitle}} support to the default tasks folder, so normal task creation can place new tasks beside the active note without creating an inline link. Thanks to @ChristianAnyanwu for suggesting this, and to @abbasou and @ttlaylor for the follow-up feedback. (#648, #1605) Added clickable links in task-card contexts for note links, markdown links, and web URLs while keeping plain contexts as tag-search buttons. Thanks to @trdischat and @Glint-Eye for suggesting this, and to @renatomen for the follow-up feedback. (#1482) Added clickable custom-field links on task cards for wikilinks, markdown links, autolinks, and bare web URLs. Thanks to @ptbosch-figueiredorj for suggesting this, and to @Soleone for the follow-up use case. (#1471) Added Kanban column and swimlane-cell add buttons that open the TaskNotes creation modal with the grouped values already filled in. Thanks to @byheaven for suggesting this and @Davincible for the project-board use case. (#933) Added non-Markdown vault files such as canvases to project suggestions, using extension-qualified link targets so those files can be selected as task projects. Thanks to @Alvin21Bon for suggesting this. (#1475, #725) Added quote/backtick escapes for NLP input, so literal course codes or date words can stay in task titles without being parsed as estimates or dates. Thanks to @RumiaKitinari and @gavingwebb for suggesting this. (#1462) Added natural-language date entry to the task date picker, so existing due and scheduled dates can be changed with phrases such as \"tomorrow at 3pm\" when NLP is enabled. Thanks to @Ruboks-Cube for suggesting this. (#1526) Added a native date field to the task date picker, so scheduled and due dates can be changed with the device date picker while keeping optional times visible. Thanks to @jmartinmcfly for suggesting this and @23426356587 for the follow-up feedback. (#1603) Added Calendar view toggles for hiding completed or skipped recurring task instances while keeping future outstanding instances visible. Thanks to @wandererovertheseaofpiss for suggesting this. (#287, #273, #274) Added linked hover highlighting for Calendar and Agenda events that come from the same task note, so scheduled, due, and recurring entries are easier to connect. Thanks to @girisumit for suggesting this. (#280) Added project-specific CSS hooks to task cards and Calendar events, so project-based visual styling can be handled with user snippets. Thanks to @girisumit for suggesting this. (#1625) Added Shift + Cmd/Ctrl + Enter in the Create Task modal to save the current task and reopen the modal for the next one. Thanks to @tcb678 for suggesting this. (#1353) Focused the Create Task modal's natural-language input when the modal opens, with a longer mobile delay so the keyboard can open after layout. Thanks to @GiovanH for suggesting this. (#1664) Added project-based custom filename template variables, including the first project, all projects, and a short projectId. Thanks to @bendavis987 for the contribution. (#923) Added {{projectFilePath}} and {{projectFilePaths}} folder template variables, so task folders can mirror project note locations in the vault. Thanks to @PacoTaco2 for suggesting this. (#1697) Added cached Google Calendar, Microsoft Calendar, and ICS events to Mini Calendar days, with compact colored dots and event details from the existing calendar connection. Thanks to @RPGArchivist for suggesting this. (#1754) Added optional icons for priority values, so task cards can show a configured priority icon instead of only a colored dot. Thanks to @BrucePlumb for suggesting this and @prepare4robots for the follow-up feedback. (#1761) Added TaskNotes edit and task-action submenu entries to Obsidian's native file context menu for recognized task notes. Thanks to @delzero for suggesting this. (#1771) Added mobile drag handles to manually sorted Task List Bases views, so dragging can start from the handle without disabling normal text interaction on the rest of the card. Thanks to @PatrickGolz for suggesting this. (#1776) Allowed calendar timeline end times after midnight, such as 26:00 for a 2 AM next-day end. Thanks to @chrabia for suggesting this. (#1784, #1833) Added a per-view pinnedColumns option for TaskNotes Kanban views, so selected empty columns can stay visible as drop targets while other empty columns remain hidden. Thanks to @loukandr for suggesting and prototyping this. (#1794) Added context updates to the task card context menu, so contexts can be added, toggled, or cleared without opening the task edit modal. Thanks to @m13ntrpn for suggesting this. (#315, #1356, #1748, #1809) Added a subtle task-card indicator and CSS hooks for tasks with note body details, including existing task bodies read through Obsidian's metadata cache. Thanks to @volodxyz, @Karut, @yeHHH1g, and @aliceinwaterdeep for suggesting this, and to @minchinweb for the follow-up. (#1808) Added advanced Kanban swimlane ordering through swimLaneOrder, so swimlane rows can stay in a stable configured order. Thanks to @rookledookle for suggesting this, and to @benmartinek and @chrabia for the follow-up feedback. (#1805) Added an ICS export option to omit completed tasks from generated calendar files. Thanks to @bepolymathe for suggesting this. (#659) Added Obsidian links to ICS export descriptions, so exported calendar events can open their source task notes. Thanks to @bepolymathe for suggesting this. (#589) Added an Appearance toggle to turn off strikethrough styling on completed task card titles. Thanks to @BrucePlumb for suggesting this. (#561) Added a \"Last day\" option to the custom recurrence month-day picker for month-end repeating tasks. Thanks to @TonyAtlas for suggesting this and @BrucePlumb for the follow-up. (#217) Added weekday selection to daily custom recurrence rules, so interval rules such as every three days can skip weekends from the recurrence modal. Thanks to @kmaustral for suggesting this. (#1818) Added an auto-height mode for TaskNotes Calendar Bases views so embedded agenda/list sections can size to their content instead of forcing an inner scroller. Thanks to @martin-forge for suggesting this. (#1201) Added a Calendar Bases toggle to hide the hourly breakdown in week, custom-days, and day views while keeping the all-day planning row visible. Thanks to @PacoTaco2 for suggesting this. (#1176) Added advanced Kanban WIP limits through wipLimits, so column headers can show (current/limit) counts and highlight exceeded limits. Thanks to @williamcheuk03 for suggesting this. (#914) Added a generated Due in countdown to the default Agenda Base and allowed Calendar Bases list agendas to span up to 365 days. Thanks to @williamcheuk03 for suggesting this. (#900) Added an instant-conversion setting to keep the original Markdown checkbox marker when converting a checkbox into a TaskNote link. Thanks to @dsebastien for suggesting this. (#898) Added a mobile-only calendar integration opt-out, so synced desktop calendar settings no longer have to trigger external calendar loading on Obsidian Mobile. Thanks to @cathywu for suggesting this. (#887) Added built-in scheduled and due date presets to the Quick actions palette for current tasks. Thanks to @willgraham345 for suggesting this and @anrie for the related preset feedback. (#819) Added a command to open Quick actions for the inline task link under the cursor. Thanks to @rlolingo for suggesting this. (#798, #1732, #1835) Added hotkeyable commands to edit the current task, add a project to the current task, and add an existing task as a subtask of the current note. Thanks to @xorander00 and @prepare4robots for requesting this, and to @musta-code and @ubidev for the follow-up suggestions. (#791) Added a UUID v4 task filename format and {{uuid}} custom filename template variable. Thanks to @bangbangbanggit for suggesting this. (#932) Added hotkeyable commands to cycle the current task's status and priority. Thanks to @rxunique for suggesting this and @luckb0x for the follow-up feedback. (#1655) Added live elapsed time to the optional active time tracking status bar item. Thanks to @connradolisboa for suggesting this. (#1622) Allowed multiple comma-separated default reminder offsets for timed Google Calendar task exports. Thanks to @solidabstract for suggesting this. (#706, #820, #1040) Added direct Pomodoro duration editing, hour-aware timer formatting, clearer one-minute controls, and an optional active Pomodoro status bar countdown. Thanks to @SublunarSage, @lj1446615403-cloud, @0-BSCode, and @thestrike72 for the suggestions and feedback. (#873) Added an optional built-in sound for task reminder notifications, with volume and preview controls in Settings. Thanks to @berzernberg for suggesting this. Added a generated Pomodoro statistics Base with daily and monthly summary views for Pomodoro history stored in daily notes. Changed# Expanded the bug report template to ask for Obsidian \"Show debug info\" output, affected task frontmatter, relevant Bases file contents, reproduction steps, and related logs or screenshots. Release notes now show the default .base file regeneration reminder only on the current version section, keeping older bundled sections focused on their own changes. Updated the release notes GitHub prompt to invite feedback while still asking satisfied users to star the project. (#239) Ordered Kanban status and priority columns by the configured status order and priority weights when no manual column order is saved. Thanks to @ScumbagScalawag for asking about this, and to @nightroman, @lavir, and @elvarb for the follow-up discussion. (#269) Marked Kanban status columns that come from values outside the configured TaskNotes statuses, so manually edited or external status values are visible as non-standard instead of blending into the board. Thanks to @cstelmach for suggesting this and @digitaldoctors for the follow-up. Refined Kanban empty columns, swimlane rows, and column drag handles, and added a per-view compact card layout option for denser boards. Kept Kanban swimlane rows from shrinking to share the viewport so the Max Swimlane Height setting is respected. Added guidance in Pomodoro statistics and Base file settings explaining that Pomodoro Base views require daily notes storage. (#323) Reordered task modal action buttons to match the right-click task menu order. Thanks to @23426356587 for suggesting this. (#1189) Made the Create/Edit Task modal priority picker follow the priority order configured in Settings. Thanks to @n1njaznutz for suggesting this. Made task-card priority dots and configured priority icons slightly larger for better visibility. (#1244) Clarified the Task Properties documentation for custom property keys and status values in Bases filters and sorting. Thanks to @Arachnidai for suggesting this. (#1234) Kept right-aligned subtask chevrons visible on task cards instead of only showing them on hover. Thanks to @n1njaznutz for suggesting this. (#1237) Made today's date more visible in the Mini Calendar view when another day is selected. Thanks to @riekusr for suggesting this. (#1348) Let long task titles wrap inside the Create/Edit Task modal title field while keeping saved titles single-line, and widened the contexts and tags fields in the modal details area. Thanks to @hasanyilmaz for suggesting this. (#1392) Made TaskNotes date fields accept compact YYYYMMDD typing and pasted dates. Thanks to @kazerniel for suggesting this. (#1431) Showed the year on task-card due and scheduled dates when the date is outside the current year. Thanks to @kazerniel for suggesting this. (#1429) Opened TaskNotes view commands in a new tab when they load configured Base files, so they do not replace the active note. Thanks to @Ruboks-Cube for suggesting this. (#1426) Added copy actions for TaskNotes Bases views, including current-view filenames, links, and titles from the result count menu, plus selected-task copy actions in the batch menu, while keeping the native Bases copy and CSV export actions available. Thanks to @kmaustral for suggesting this. Improved keyboard access, mobile layout, and theme color consistency across task cards, TaskNotes Kanban, Bases Kanban, calendar controls, stats, settings, and filter popovers. (#1526) Made the Create/Edit Task modal due and scheduled date buttons open a calendar-first "},{"route":"/obsidian/releases/4.8.1/","title":"TaskNotes 4.8.1","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.8.1.md","namespace":"obsidian","relativePath":"releases/4.8.1.md","raw":"# TaskNotes 4.8.1\n\n## Fixed\n\n- (#1903) Improved the Edit Task modal on iPhone-sized screens so opening a task no longer automatically focuses the title field, and the mobile layout gives the title, fields, and action buttons more usable space.\n - Thanks to @3zra47 for reporting the issue and sharing the screen recording.\n- (#1909) Fixed compact Kanban task cards showing oversized status and priority indicators on touch devices.\n - Thanks to @pxxush for reporting the issue.\n- (#1908) Restored newly generated Calendar Bases to show the full day by default and inherit the calendar start/end settings instead of hard-coding 06:00-22:00.\n - Thanks to @AndreMonthy for the report.\n- (#1907) Fixed calendar time labels drifting away from the left axis in narrow sidebar calendar views.\n - Thanks to @kmaustral for reporting the issue.\n- (#1906) Fixed NLP priority shortcuts leaving partial text in task titles when custom priority values include words like `high` or `low`.\n - Thanks to @RumiaKitinari for reporting the issue.\n- (#1904, #1905) Fixed long tags in task cards wrapping instead of forcing horizontal scrolling in TaskNotes Bases views and note cards.\n - Long tag pills can now wrap across lines and break within very long tag names on narrow screens.\n - Thanks to @3zra47 for reporting the issue and to @zhouzhou626 for the contribution.\n- (#1901) Fixed the task context menu creating an `undefined` property when adding or removing tags.\n - Hardened task property updates so invalid frontmatter property names are rejected instead of written.\n - Thanks to @mgrecar for reporting the issue.\n- (#1902) Fixed Markdown-style project links in task frontmatter not appearing as subtasks on project pages.\n - Thanks to @minchinweb for reporting the issue.\n\n## Changed\n\n- Improved the internal structure around service notifications, vault writes, and shared utilities to make future fixes easier to test and maintain.\n","aliases":["/releases/4.8.1/","/releases/4.8.1/"],"toc":[{"level":2,"id":"fixed","text":"Fixed"},{"level":2,"id":"changed","text":"Changed"}],"html":"

Fixed#

\n
    \n
  • (#1903) Improved the Edit Task modal on iPhone-sized screens so opening a task no longer automatically focuses the title field, and the mobile layout gives the title, fields, and action buttons more usable space.
      \n
    • Thanks to @3zra47 for reporting the issue and sharing the screen recording.
    • \n
    \n
  • \n
  • (#1909) Fixed compact Kanban task cards showing oversized status and priority indicators on touch devices.
      \n
    • Thanks to @pxxush for reporting the issue.
    • \n
    \n
  • \n
  • (#1908) Restored newly generated Calendar Bases to show the full day by default and inherit the calendar start/end settings instead of hard-coding 06:00-22:00.
      \n
    • Thanks to @AndreMonthy for the report.
    • \n
    \n
  • \n
  • (#1907) Fixed calendar time labels drifting away from the left axis in narrow sidebar calendar views.
      \n
    • Thanks to @kmaustral for reporting the issue.
    • \n
    \n
  • \n
  • (#1906) Fixed NLP priority shortcuts leaving partial text in task titles when custom priority values include words like high or low.
      \n
    • Thanks to @RumiaKitinari for reporting the issue.
    • \n
    \n
  • \n
  • (#1904, #1905) Fixed long tags in task cards wrapping instead of forcing horizontal scrolling in TaskNotes Bases views and note cards.
      \n
    • Long tag pills can now wrap across lines and break within very long tag names on narrow screens.
    • \n
    • Thanks to @3zra47 for reporting the issue and to @zhouzhou626 for the contribution.
    • \n
    \n
  • \n
  • (#1901) Fixed the task context menu creating an undefined property when adding or removing tags.
      \n
    • Hardened task property updates so invalid frontmatter property names are rejected instead of written.
    • \n
    • Thanks to @mgrecar for reporting the issue.
    • \n
    \n
  • \n
  • (#1902) Fixed Markdown-style project links in task frontmatter not appearing as subtasks on project pages.
      \n
    • Thanks to @minchinweb for reporting the issue.
    • \n
    \n
  • \n
\n

Changed#

\n
    \n
  • Improved the internal structure around service notifications, vault writes, and shared utilities to make future fixes easier to test and maintain.
  • \n
\n","text":"Fixed# (#1903) Improved the Edit Task modal on iPhone-sized screens so opening a task no longer automatically focuses the title field, and the mobile layout gives the title, fields, and action buttons more usable space. Thanks to @3zra47 for reporting the issue and sharing the screen recording. (#1909) Fixed compact Kanban task cards showing oversized status and priority indicators on touch devices. Thanks to @pxxush for reporting the issue. (#1908) Restored newly generated Calendar Bases to show the full day by default and inherit the calendar start/end settings instead of hard-coding 06:00-22:00. Thanks to @AndreMonthy for the report. (#1907) Fixed calendar time labels drifting away from the left axis in narrow sidebar calendar views. Thanks to @kmaustral for reporting the issue. (#1906) Fixed NLP priority shortcuts leaving partial text in task titles when custom priority values include words like high or low. Thanks to @RumiaKitinari for reporting the issue. (#1904, #1905) Fixed long tags in task cards wrapping instead of forcing horizontal scrolling in TaskNotes Bases views and note cards. Long tag pills can now wrap across lines and break within very long tag names on narrow screens. Thanks to @3zra47 for reporting the issue and to @zhouzhou626 for the contribution. (#1901) Fixed the task context menu creating an undefined property when adding or removing tags. Hardened task property updates so invalid frontmatter property names are rejected instead of written. Thanks to @mgrecar for reporting the issue. (#1902) Fixed Markdown-style project links in task frontmatter not appearing as subtasks on project pages. Thanks to @minchinweb for reporting the issue. Changed# Improved the internal structure around service notifications, vault writes, and shared utilities to make future fixes easier to test and maintain."},{"route":"/obsidian/releases/4.9.0/","title":"TaskNotes 4.9.0","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.9.0.md","namespace":"obsidian","relativePath":"releases/4.9.0.md","raw":"# TaskNotes 4.9.0\n\n## Security\n\n- (#1923) Restricted the HTTP API server to loopback and limited browser CORS access to loopback origins.\n - Thanks to @martin-forge for reporting.\n\n## Added\n\n- (#1932) Added middle-click support for opening task cards in a new tab.\n - Thanks to @imsuck for the request.\n\n## Fixed\n\n- (#1934) Fixed custom priority colors being overridden by default task-card priority styles in views.\n - Thanks to @KittehBit for reporting.\n- (#1933) Added the note path to fallback frontmatter parse warnings so malformed task YAML is easier to find.\n - Thanks to @rayvermey for reporting.\n- (#1931) Made the Pomodoro task chooser open from cached task data and ignore repeated clicks while it is already opening.\n - Thanks to @sumiyalairu03 for reporting.\n- (#1930) Fixed starting the Pomodoro timer from its hotkey without starting time tracking for the selected Pomodoro task.\n - Thanks to @sumiyalairu03 for reporting.\n- (#1929) Fixed the bottom Relationships widget overlapping embedded content such as Bases/Kanban views in task notes.\n - Thanks to @rchaklashiya for reporting and following up with the embed case.\n- (#1922) Restored the native color picker alongside manual color text entry in Create/Edit Timeblock fields.\n - Thanks to @AndreMonthy for reporting.\n- (#1921) Fixed direct frontmatter edits to lifecycle-relevant task fields not triggering Google Calendar sync or auto-archive side effects.\n - Thanks to @martin-forge for reporting and verifying the direct-edit reproduction.\n- (#1919) Fixed the Pomodoro view rapidly resizing at certain sidebar sizes.\n - Thanks to @RumiaKitinari for reporting.\n- (#1898, #1907) Fixed Calendar time labels shifting into the middle of Day and sidebar calendar grids after switching views.\n - Thanks to @ddevaal for reporting and confirming the regression, and to @kmaustral for confirming the sidebar case in 4.8.1.\n- (#1936) Added a Calendar Base drag/drop resolution option so events can snap to smaller increments than the visible time slot grid.\n - Thanks to @benmartinek for suggesting this.\n- Improved mobile task cards, inline widgets, modals, and settings layouts so dense controls and long labels fit more comfortably on small screens.\n- (#1916) Fixed Markdown task links using Obsidian's generated filename label instead of the TaskNote title in the task link overlay.\n - Thanks to @minchinweb for reporting.\n- (#1911) Fixed recurrence choices starting from today instead of the selected calendar date when creating a task from Calendar view.\n - Thanks to @mikhailmarka for reporting.\n- (#1912) Fixed \"Create subtask\" pre-filling the parent task's full folder path in the Projects field instead of using the normal Obsidian link text.\n - Thanks to @pkuehne for reporting and @benmartinek for confirming.\n","aliases":["/releases/4.9.0/","/releases/4.9.0/"],"toc":[{"level":2,"id":"security","text":"Security"},{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Security#

\n
    \n
  • (#1923) Restricted the HTTP API server to loopback and limited browser CORS access to loopback origins.
      \n
    • Thanks to @martin-forge for reporting.
    • \n
    \n
  • \n
\n

Added#

\n
    \n
  • (#1932) Added middle-click support for opening task cards in a new tab.
      \n
    • Thanks to @imsuck for the request.
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#1934) Fixed custom priority colors being overridden by default task-card priority styles in views.
      \n
    • Thanks to @KittehBit for reporting.
    • \n
    \n
  • \n
  • (#1933) Added the note path to fallback frontmatter parse warnings so malformed task YAML is easier to find.
      \n
    • Thanks to @rayvermey for reporting.
    • \n
    \n
  • \n
  • (#1931) Made the Pomodoro task chooser open from cached task data and ignore repeated clicks while it is already opening.
      \n
    • Thanks to @sumiyalairu03 for reporting.
    • \n
    \n
  • \n
  • (#1930) Fixed starting the Pomodoro timer from its hotkey without starting time tracking for the selected Pomodoro task.
      \n
    • Thanks to @sumiyalairu03 for reporting.
    • \n
    \n
  • \n
  • (#1929) Fixed the bottom Relationships widget overlapping embedded content such as Bases/Kanban views in task notes.
      \n
    • Thanks to @rchaklashiya for reporting and following up with the embed case.
    • \n
    \n
  • \n
  • (#1922) Restored the native color picker alongside manual color text entry in Create/Edit Timeblock fields.
      \n
    • Thanks to @AndreMonthy for reporting.
    • \n
    \n
  • \n
  • (#1921) Fixed direct frontmatter edits to lifecycle-relevant task fields not triggering Google Calendar sync or auto-archive side effects.
      \n
    • Thanks to @martin-forge for reporting and verifying the direct-edit reproduction.
    • \n
    \n
  • \n
  • (#1919) Fixed the Pomodoro view rapidly resizing at certain sidebar sizes.
      \n
    • Thanks to @RumiaKitinari for reporting.
    • \n
    \n
  • \n
  • (#1898, #1907) Fixed Calendar time labels shifting into the middle of Day and sidebar calendar grids after switching views.
      \n
    • Thanks to @ddevaal for reporting and confirming the regression, and to @kmaustral for confirming the sidebar case in 4.8.1.
    • \n
    \n
  • \n
  • (#1936) Added a Calendar Base drag/drop resolution option so events can snap to smaller increments than the visible time slot grid.
      \n
    • Thanks to @benmartinek for suggesting this.
    • \n
    \n
  • \n
  • Improved mobile task cards, inline widgets, modals, and settings layouts so dense controls and long labels fit more comfortably on small screens.
  • \n
  • (#1916) Fixed Markdown task links using Obsidian's generated filename label instead of the TaskNote title in the task link overlay.
      \n
    • Thanks to @minchinweb for reporting.
    • \n
    \n
  • \n
  • (#1911) Fixed recurrence choices starting from today instead of the selected calendar date when creating a task from Calendar view.
      \n
    • Thanks to @mikhailmarka for reporting.
    • \n
    \n
  • \n
  • (#1912) Fixed "Create subtask" pre-filling the parent task's full folder path in the Projects field instead of using the normal Obsidian link text.
      \n
    • Thanks to @pkuehne for reporting and @benmartinek for confirming.
    • \n
    \n
  • \n
\n","text":"Security# (#1923) Restricted the HTTP API server to loopback and limited browser CORS access to loopback origins. Thanks to @martin-forge for reporting. Added# (#1932) Added middle-click support for opening task cards in a new tab. Thanks to @imsuck for the request. Fixed# (#1934) Fixed custom priority colors being overridden by default task-card priority styles in views. Thanks to @KittehBit for reporting. (#1933) Added the note path to fallback frontmatter parse warnings so malformed task YAML is easier to find. Thanks to @rayvermey for reporting. (#1931) Made the Pomodoro task chooser open from cached task data and ignore repeated clicks while it is already opening. Thanks to @sumiyalairu03 for reporting. (#1930) Fixed starting the Pomodoro timer from its hotkey without starting time tracking for the selected Pomodoro task. Thanks to @sumiyalairu03 for reporting. (#1929) Fixed the bottom Relationships widget overlapping embedded content such as Bases/Kanban views in task notes. Thanks to @rchaklashiya for reporting and following up with the embed case. (#1922) Restored the native color picker alongside manual color text entry in Create/Edit Timeblock fields. Thanks to @AndreMonthy for reporting. (#1921) Fixed direct frontmatter edits to lifecycle-relevant task fields not triggering Google Calendar sync or auto-archive side effects. Thanks to @martin-forge for reporting and verifying the direct-edit reproduction. (#1919) Fixed the Pomodoro view rapidly resizing at certain sidebar sizes. Thanks to @RumiaKitinari for reporting. (#1898, #1907) Fixed Calendar time labels shifting into the middle of Day and sidebar calendar grids after switching views. Thanks to @ddevaal for reporting and confirming the regression, and to @kmaustral for confirming the sidebar case in 4.8.1. (#1936) Added a Calendar Base drag/drop resolution option so events can snap to smaller increments than the visible time slot grid. Thanks to @benmartinek for suggesting this. Improved mobile task cards, inline widgets, modals, and settings layouts so dense controls and long labels fit more comfortably on small screens. (#1916) Fixed Markdown task links using Obsidian's generated filename label instead of the TaskNote title in the task link overlay. Thanks to @minchinweb for reporting. (#1911) Fixed recurrence choices starting from today instead of the selected calendar date when creating a task from Calendar view. Thanks to @mikhailmarka for reporting. (#1912) Fixed \"Create subtask\" pre-filling the parent task's full folder path in the Projects field instead of using the normal Obsidian link text. Thanks to @pkuehne for reporting and @benmartinek for confirming."},{"route":"/obsidian/releases/4.9.1/","title":"TaskNotes 4.9.1","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.9.1.md","namespace":"obsidian","relativePath":"releases/4.9.1.md","raw":"# TaskNotes 4.9.1\n\n## Added\n\n- (#1885) Added Shift+arrow keyboard range selection while bulk task selection mode is active.\n - Thanks to @chrabia for suggesting bulk selection improvements and @sumiyalairu03 for the keyboard selection idea.\n\n## Fixed\n\n- (#781, #1085) Fixed Outlook-published ICS calendar events appearing at the wrong time when their feed used Windows timezone names without matching timezone definitions.\n - Thanks to @chrlaney for reporting and @mjkrasny for confirming the Outlook timezone case.\n- (#1696) Fixed Google Calendar export for scheduled recurring tasks when a single occurrence is moved to a different date.\n - Keeps the recurring master event on its original rule, excludes the original occurrence date, and syncs the moved occurrence as a detached event.\n - Thanks to @martin-forge for reporting and contributing the fix.\n- (#1912) Fixed \"Create subtask\" inserting the full path of the parent task in the Projects field instead of using the normal Obsidian link text.\n - Thanks to @pkuehne for reporting and @benmartinek for confirming.\n- (#1921) Fixed Google Calendar and auto-archive updates not running after direct task file edits.\n - TaskNotes now picks up status, completion, and date changes made directly in a task file without triggering a large one-time Google Calendar rewrite at startup.\n - Recovery also removes stale Google Calendar links when task files were deleted or replaced outside TaskNotes.\n - Thanks to @martin-forge for reporting and contributing the fix.\n- (#1938) Fixed partial HTTP API task updates rewriting native tags with `#` prefixes or duplicate task tags.\n - Thanks to @joseluisgonzalezdelgado-ctrl for reporting.\n- (#1939) Fixed the task Details field rendering as a small nested textarea when the embedded editor falls back.\n - Thanks to @g-arthurvanderbilt for reporting and @cookbr for confirming the desktop impact.\n- Fixed tag and modal preview edge cases found during validation: double-hash tags no longer match the task tag, empty tag lists stay empty when read back, and natural-language previews remain visible when enabled.\n- (#1941) Fixed mobile Kanban boards scrolling the whole board vertically instead of keeping each list independently scrollable.\n - Thanks to @pxxush for reporting.\n- (#1943) Fixed MCP task-query tool instructions so filter operators match the operators TaskNotes actually accepts.\n - Thanks to @jordankbartos for reporting and proposing a fix in #1944.\n- (#1945) Fixed Google Calendar export so overlapping sync services do not create duplicate events for the same task while the saved event ID is still catching up.\n - Thanks to @martin-forge for reporting and contributing the fix.\n- (#1946) Fixed the bottom task in virtualized Task List Bases being partially hidden behind Obsidian's mobile bottom bar.\n - Thanks to @3zra47 for reporting.\n- (#1947) Fixed mobile Task List cards with left-positioned subtask chevrons so the chevron remains visible and project/detail badges stay on the main row.\n - Thanks to @Jomo94 for reporting.\n- (#1948) Fixed Agenda Calendar Bases so completed recurring instances can appear on their recorded completion dates, even when recurring task projections are hidden or the completion date is outside the recurrence pattern.\n - Thanks to @Jomo94 for reporting.\n","aliases":["/releases/4.9.1/","/releases/4.9.1/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • (#1885) Added Shift+arrow keyboard range selection while bulk task selection mode is active.
      \n
    • Thanks to @chrabia for suggesting bulk selection improvements and @sumiyalairu03 for the keyboard selection idea.
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • (#781, #1085) Fixed Outlook-published ICS calendar events appearing at the wrong time when their feed used Windows timezone names without matching timezone definitions.
      \n
    • Thanks to @chrlaney for reporting and @mjkrasny for confirming the Outlook timezone case.
    • \n
    \n
  • \n
  • (#1696) Fixed Google Calendar export for scheduled recurring tasks when a single occurrence is moved to a different date.
      \n
    • Keeps the recurring master event on its original rule, excludes the original occurrence date, and syncs the moved occurrence as a detached event.
    • \n
    • Thanks to @martin-forge for reporting and contributing the fix.
    • \n
    \n
  • \n
  • (#1912) Fixed "Create subtask" inserting the full path of the parent task in the Projects field instead of using the normal Obsidian link text.
      \n
    • Thanks to @pkuehne for reporting and @benmartinek for confirming.
    • \n
    \n
  • \n
  • (#1921) Fixed Google Calendar and auto-archive updates not running after direct task file edits.
      \n
    • TaskNotes now picks up status, completion, and date changes made directly in a task file without triggering a large one-time Google Calendar rewrite at startup.
    • \n
    • Recovery also removes stale Google Calendar links when task files were deleted or replaced outside TaskNotes.
    • \n
    • Thanks to @martin-forge for reporting and contributing the fix.
    • \n
    \n
  • \n
  • (#1938) Fixed partial HTTP API task updates rewriting native tags with # prefixes or duplicate task tags.
      \n
    • Thanks to @joseluisgonzalezdelgado-ctrl for reporting.
    • \n
    \n
  • \n
  • (#1939) Fixed the task Details field rendering as a small nested textarea when the embedded editor falls back.
      \n
    • Thanks to @g-arthurvanderbilt for reporting and @cookbr for confirming the desktop impact.
    • \n
    \n
  • \n
  • Fixed tag and modal preview edge cases found during validation: double-hash tags no longer match the task tag, empty tag lists stay empty when read back, and natural-language previews remain visible when enabled.
  • \n
  • (#1941) Fixed mobile Kanban boards scrolling the whole board vertically instead of keeping each list independently scrollable.
      \n
    • Thanks to @pxxush for reporting.
    • \n
    \n
  • \n
  • (#1943) Fixed MCP task-query tool instructions so filter operators match the operators TaskNotes actually accepts.
      \n
    • Thanks to @jordankbartos for reporting and proposing a fix in #1944.
    • \n
    \n
  • \n
  • (#1945) Fixed Google Calendar export so overlapping sync services do not create duplicate events for the same task while the saved event ID is still catching up.
      \n
    • Thanks to @martin-forge for reporting and contributing the fix.
    • \n
    \n
  • \n
  • (#1946) Fixed the bottom task in virtualized Task List Bases being partially hidden behind Obsidian's mobile bottom bar.
      \n
    • Thanks to @3zra47 for reporting.
    • \n
    \n
  • \n
  • (#1947) Fixed mobile Task List cards with left-positioned subtask chevrons so the chevron remains visible and project/detail badges stay on the main row.
      \n
    • Thanks to @Jomo94 for reporting.
    • \n
    \n
  • \n
  • (#1948) Fixed Agenda Calendar Bases so completed recurring instances can appear on their recorded completion dates, even when recurring task projections are hidden or the completion date is outside the recurrence pattern.
      \n
    • Thanks to @Jomo94 for reporting.
    • \n
    \n
  • \n
\n","text":"Added# (#1885) Added Shift+arrow keyboard range selection while bulk task selection mode is active. Thanks to @chrabia for suggesting bulk selection improvements and @sumiyalairu03 for the keyboard selection idea. Fixed# (#781, #1085) Fixed Outlook-published ICS calendar events appearing at the wrong time when their feed used Windows timezone names without matching timezone definitions. Thanks to @chrlaney for reporting and @mjkrasny for confirming the Outlook timezone case. (#1696) Fixed Google Calendar export for scheduled recurring tasks when a single occurrence is moved to a different date. Keeps the recurring master event on its original rule, excludes the original occurrence date, and syncs the moved occurrence as a detached event. Thanks to @martin-forge for reporting and contributing the fix. (#1912) Fixed \"Create subtask\" inserting the full path of the parent task in the Projects field instead of using the normal Obsidian link text. Thanks to @pkuehne for reporting and @benmartinek for confirming. (#1921) Fixed Google Calendar and auto-archive updates not running after direct task file edits. TaskNotes now picks up status, completion, and date changes made directly in a task file without triggering a large one-time Google Calendar rewrite at startup. Recovery also removes stale Google Calendar links when task files were deleted or replaced outside TaskNotes. Thanks to @martin-forge for reporting and contributing the fix. (#1938) Fixed partial HTTP API task updates rewriting native tags with # prefixes or duplicate task tags. Thanks to @joseluisgonzalezdelgado-ctrl for reporting. (#1939) Fixed the task Details field rendering as a small nested textarea when the embedded editor falls back. Thanks to @g-arthurvanderbilt for reporting and @cookbr for confirming the desktop impact. Fixed tag and modal preview edge cases found during validation: double-hash tags no longer match the task tag, empty tag lists stay empty when read back, and natural-language previews remain visible when enabled. (#1941) Fixed mobile Kanban boards scrolling the whole board vertically instead of keeping each list independently scrollable. Thanks to @pxxush for reporting. (#1943) Fixed MCP task-query tool instructions so filter operators match the operators TaskNotes actually accepts. Thanks to @jordankbartos for reporting and proposing a fix in #1944. (#1945) Fixed Google Calendar export so overlapping sync services do not create duplicate events for the same task while the saved event ID is still catching up. Thanks to @martin-forge for reporting and contributing the fix. (#1946) Fixed the bottom task in virtualized Task List Bases being partially hidden behind Obsidian's mobile bottom bar. Thanks to @3zra47 for reporting. (#1947) Fixed mobile Task List cards with left-positioned subtask chevrons so the chevron remains visible and project/detail badges stay on the main row. Thanks to @Jomo94 for reporting. (#1948) Fixed Agenda Calendar Bases so completed recurring instances can appear on their recorded completion dates, even when recurring task projections are hidden or the completion date is outside the recurrence pattern. Thanks to @Jomo94 for reporting."},{"route":"/obsidian/releases/4.9.2/","title":"TaskNotes 4.9.2","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/4.9.2.md","namespace":"obsidian","relativePath":"releases/4.9.2.md","raw":"# TaskNotes 4.9.2\n\n## Added\n\n- (#1791) Added collapse and expand controls for grouped Bases Task List views, including a default collapsed state option.\n - Thanks to @renatomen for the contribution.\n\n## Fixed\n\n- Fixed Pomodoro storage migration so existing plugin-data history is written to daily notes before switching storage, and clarified that daily notes can come from either the core Daily Notes plugin or Periodic Notes.\n- (#1964) Fixed Microsoft Calendar OAuth so connecting no longer forces a fresh consent prompt every time, and clarified the Microsoft desktop app setup steps.\n - Thanks to @thechonta for reporting.\n- (#1966) Fixed custom priority icons so they render as icons instead of filled squares on task cards.\n - Thanks to @sruiz-savia for reporting.\n- (#1963) Fixed Google Calendar sync so duplicate event ID fields are repaired when saving task calendar metadata.\n - Thanks to @christenbc for reporting.\n- (#1961) Fixed the default custom filename template so it uses the recommended double-brace syntax and no longer warns on first use.\n - Thanks to @chmac for reporting.\n- (#1962) Fixed task tag normalization so tags entered with spaces are saved with hyphens for Obsidian tag compatibility.\n - Thanks to @christenbc for reporting.\n- (#1959) Fixed the MCP `tasknotes_list_tasks` tool so circular internal task data and live Obsidian object references no longer break task-list responses.\n - Thanks to @kmaustral for reporting.\n- (#1957) Fixed the Pomodoro timer layout in vertically split panes so the timer header and progress circle remain reachable when the pane is short.\n - Thanks to @sumiyalairu03 for reporting.\n- (#1956) Fixed Google Calendar sync so completing a recurring task updates the linked event title with the completion checkmark.\n - Thanks to @jacksoluke for reporting.\n- (#1953) Fixed inline task conversion so source-line wikilinks no longer create nested wikilinks in the replacement link text.\n - Thanks to @bgk0018 for reporting.\n- (#1952) Fixed Pomodoro task picker search results so matching task titles are ranked and sorted ahead of due-date ordering.\n - Thanks to @KFrancoD for reporting.\n- (#1392, #1949) Fixed due and scheduled date picker fields so typed or pasted date edits stay open until you choose Select, including compact `YYYYMMDD` entry when a date is already set.\n - Thanks to @kazerniel for reporting and following up.\n- (#982, #1947) Restored larger mobile task-card typography and let secondary card icons wrap below the task details when they no longer fit comfortably on mobile.\n - Thanks to @3zra47 for reporting the font-size regression, @chrsdk and @scottaltham-payroc for confirming the mobile font-size issue, and @Jomo94 for reporting the mobile card layout problem.\n","aliases":["/releases/4.9.2/","/releases/4.9.2/"],"toc":[{"level":2,"id":"added","text":"Added"},{"level":2,"id":"fixed","text":"Fixed"}],"html":"

Added#

\n
    \n
  • (#1791) Added collapse and expand controls for grouped Bases Task List views, including a default collapsed state option.
      \n
    • Thanks to @renatomen for the contribution.
    • \n
    \n
  • \n
\n

Fixed#

\n
    \n
  • Fixed Pomodoro storage migration so existing plugin-data history is written to daily notes before switching storage, and clarified that daily notes can come from either the core Daily Notes plugin or Periodic Notes.
  • \n
  • (#1964) Fixed Microsoft Calendar OAuth so connecting no longer forces a fresh consent prompt every time, and clarified the Microsoft desktop app setup steps.
      \n
    • Thanks to @thechonta for reporting.
    • \n
    \n
  • \n
  • (#1966) Fixed custom priority icons so they render as icons instead of filled squares on task cards.
      \n
    • Thanks to @sruiz-savia for reporting.
    • \n
    \n
  • \n
  • (#1963) Fixed Google Calendar sync so duplicate event ID fields are repaired when saving task calendar metadata.
      \n
    • Thanks to @christenbc for reporting.
    • \n
    \n
  • \n
  • (#1961) Fixed the default custom filename template so it uses the recommended double-brace syntax and no longer warns on first use.
      \n
    • Thanks to @chmac for reporting.
    • \n
    \n
  • \n
  • (#1962) Fixed task tag normalization so tags entered with spaces are saved with hyphens for Obsidian tag compatibility.
      \n
    • Thanks to @christenbc for reporting.
    • \n
    \n
  • \n
  • (#1959) Fixed the MCP tasknotes_list_tasks tool so circular internal task data and live Obsidian object references no longer break task-list responses.
      \n
    • Thanks to @kmaustral for reporting.
    • \n
    \n
  • \n
  • (#1957) Fixed the Pomodoro timer layout in vertically split panes so the timer header and progress circle remain reachable when the pane is short.
      \n
    • Thanks to @sumiyalairu03 for reporting.
    • \n
    \n
  • \n
  • (#1956) Fixed Google Calendar sync so completing a recurring task updates the linked event title with the completion checkmark.
      \n
    • Thanks to @jacksoluke for reporting.
    • \n
    \n
  • \n
  • (#1953) Fixed inline task conversion so source-line wikilinks no longer create nested wikilinks in the replacement link text.
      \n
    • Thanks to @bgk0018 for reporting.
    • \n
    \n
  • \n
  • (#1952) Fixed Pomodoro task picker search results so matching task titles are ranked and sorted ahead of due-date ordering.
      \n
    • Thanks to @KFrancoD for reporting.
    • \n
    \n
  • \n
  • (#1392, #1949) Fixed due and scheduled date picker fields so typed or pasted date edits stay open until you choose Select, including compact YYYYMMDD entry when a date is already set.
      \n
    • Thanks to @kazerniel for reporting and following up.
    • \n
    \n
  • \n
  • (#982, #1947) Restored larger mobile task-card typography and let secondary card icons wrap below the task details when they no longer fit comfortably on mobile.
      \n
    • Thanks to @3zra47 for reporting the font-size regression, @chrsdk and @scottaltham-payroc for confirming the mobile font-size issue, and @Jomo94 for reporting the mobile card layout problem.
    • \n
    \n
  • \n
\n","text":"Added# (#1791) Added collapse and expand controls for grouped Bases Task List views, including a default collapsed state option. Thanks to @renatomen for the contribution. Fixed# Fixed Pomodoro storage migration so existing plugin-data history is written to daily notes before switching storage, and clarified that daily notes can come from either the core Daily Notes plugin or Periodic Notes. (#1964) Fixed Microsoft Calendar OAuth so connecting no longer forces a fresh consent prompt every time, and clarified the Microsoft desktop app setup steps. Thanks to @thechonta for reporting. (#1966) Fixed custom priority icons so they render as icons instead of filled squares on task cards. Thanks to @sruiz-savia for reporting. (#1963) Fixed Google Calendar sync so duplicate event ID fields are repaired when saving task calendar metadata. Thanks to @christenbc for reporting. (#1961) Fixed the default custom filename template so it uses the recommended double-brace syntax and no longer warns on first use. Thanks to @chmac for reporting. (#1962) Fixed task tag normalization so tags entered with spaces are saved with hyphens for Obsidian tag compatibility. Thanks to @christenbc for reporting. (#1959) Fixed the MCP tasknotes_list_tasks tool so circular internal task data and live Obsidian object references no longer break task-list responses. Thanks to @kmaustral for reporting. (#1957) Fixed the Pomodoro timer layout in vertically split panes so the timer header and progress circle remain reachable when the pane is short. Thanks to @sumiyalairu03 for reporting. (#1956) Fixed Google Calendar sync so completing a recurring task updates the linked event title with the completion checkmark. Thanks to @jacksoluke for reporting. (#1953) Fixed inline task conversion so source-line wikilinks no longer create nested wikilinks in the replacement link text. Thanks to @bgk0018 for reporting. (#1952) Fixed Pomodoro task picker search results so matching task titles are ranked and sorted ahead of due-date ordering. Thanks to @KFrancoD for reporting. (#1392, #1949) Fixed due and scheduled date picker fields so typed or pasted date edits stay open until you choose Select, including compact YYYYMMDD entry when a date is already set. Thanks to @kazerniel for reporting and following up. (#982, #1947) Restored larger mobile task-card typography and let secondary card icons wrap below the task details when they no longer fit comfortably on mobile. Thanks to @3zra47 for reporting the font-size regression, @chrsdk and @scottaltham-payroc for confirming the mobile font-size issue, and @Jomo94 for reporting the mobile card layout problem."},{"route":"/obsidian/releases/unreleased/","title":"TaskNotes - Unreleased","description":"TaskNotes documentation.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes:docs/releases/unreleased.md","namespace":"obsidian","relativePath":"releases/unreleased.md","raw":"# TaskNotes - Unreleased\n\n\n","aliases":["/releases/unreleased/","/releases/unreleased/"],"toc":[],"html":"\n","text":""},{"route":"/obsidian/settings/","title":"Settings","description":"TaskNotes settings are organized into tabs. Each tab controls a different part of plugin behavior.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/settings.md","namespace":"obsidian","relativePath":"settings.md","raw":"# Settings\n\nTaskNotes settings are organized into tabs. Each tab controls a different part of plugin behavior.\n\n\n## General\n\nThe General tab controls task identification, storage locations, and task-card click behavior. Use this tab when your vault already has conventions such as custom tags, property-based identification, or specific folder structures.\n\nFor more information, see the [General Settings](settings/general.md) documentation.\n\n## Task Properties\n\nTask Properties defines the schema TaskNotes writes to frontmatter, including status, priority, dates, reminders, projects, and user fields. Each property card lets you remap key names and behavior so TaskNotes can match existing metadata rather than forcing a migration.\n\nFor more detailed information, see the [Task Properties Settings](settings/task-properties.md) documentation.\n\n## Modal Fields\n\nModal Fields controls the task create/edit experience by deciding which fields are visible and in what order. If your workflow depends on a handful of fields, you can surface only those and reduce form noise.\n\nFor more information, see the [Modal Fields Settings](settings/modal-fields.md) documentation.\n\n## Appearance & UI\n\nAppearance & UI handles task card density, calendar defaults, time formatting, and visual toggles for supporting widgets. Use this tab to tune how much information is visible at a glance.\n\nFor more detailed information, see the [Appearance & UI Settings](settings/appearance.md) documentation.\n\n## Features\n\nFeatures groups behavior toggles for inline tasks, natural language input, Pomodoro, reminders, and performance-related options. It is where you enable advanced workflow capabilities and then refine defaults.\n\nFor more information, see the [Features Settings](settings/features.md) documentation.\n\n## Integrations\n\nIntegrations covers external connectivity: Bases view wiring, Google/Microsoft OAuth calendar sync, ICS subscriptions, automatic ICS export, HTTP API settings, and webhook endpoints.\n\nFor more detailed information, see the [Integrations Settings](settings/integrations.md) documentation.\n","aliases":["/settings/"],"toc":[{"level":2,"id":"general","text":"General"},{"level":2,"id":"task-properties","text":"Task Properties"},{"level":2,"id":"modal-fields","text":"Modal Fields"},{"level":2,"id":"appearance-ui","text":"Appearance & UI"},{"level":2,"id":"features","text":"Features"},{"level":2,"id":"integrations","text":"Integrations"}],"html":"

TaskNotes settings are organized into tabs. Each tab controls a different part of plugin behavior.

\n

General#

\n

The General tab controls task identification, storage locations, and task-card click behavior. Use this tab when your vault already has conventions such as custom tags, property-based identification, or specific folder structures.

\n

For more information, see the General Settings documentation.

\n

Task Properties#

\n

Task Properties defines the schema TaskNotes writes to frontmatter, including status, priority, dates, reminders, projects, and user fields. Each property card lets you remap key names and behavior so TaskNotes can match existing metadata rather than forcing a migration.

\n

For more detailed information, see the Task Properties Settings documentation.

\n

Modal Fields#

\n

Modal Fields controls the task create/edit experience by deciding which fields are visible and in what order. If your workflow depends on a handful of fields, you can surface only those and reduce form noise.

\n

For more information, see the Modal Fields Settings documentation.

\n

Appearance & UI#

\n

Appearance & UI handles task card density, calendar defaults, time formatting, and visual toggles for supporting widgets. Use this tab to tune how much information is visible at a glance.

\n

For more detailed information, see the Appearance & UI Settings documentation.

\n

Features#

\n

Features groups behavior toggles for inline tasks, natural language input, Pomodoro, reminders, and performance-related options. It is where you enable advanced workflow capabilities and then refine defaults.

\n

For more information, see the Features Settings documentation.

\n

Integrations#

\n

Integrations covers external connectivity: Bases view wiring, Google/Microsoft OAuth calendar sync, ICS subscriptions, automatic ICS export, HTTP API settings, and webhook endpoints.

\n

For more detailed information, see the Integrations Settings documentation.

\n","text":"TaskNotes settings are organized into tabs. Each tab controls a different part of plugin behavior. General# The General tab controls task identification, storage locations, and task-card click behavior. Use this tab when your vault already has conventions such as custom tags, property-based identification, or specific folder structures. For more information, see the General Settings documentation. Task Properties# Task Properties defines the schema TaskNotes writes to frontmatter, including status, priority, dates, reminders, projects, and user fields. Each property card lets you remap key names and behavior so TaskNotes can match existing metadata rather than forcing a migration. For more detailed information, see the Task Properties Settings documentation. Modal Fields# Modal Fields controls the task create/edit experience by deciding which fields are visible and in what order. If your workflow depends on a handful of fields, you can surface only those and reduce form noise. For more information, see the Modal Fields Settings documentation. Appearance & UI# Appearance & UI handles task card density, calendar defaults, time formatting, and visual toggles for supporting widgets. Use this tab to tune how much information is visible at a glance. For more detailed information, see the Appearance & UI Settings documentation. Features# Features groups behavior toggles for inline tasks, natural language input, Pomodoro, reminders, and performance-related options. It is where you enable advanced workflow capabilities and then refine defaults. For more information, see the Features Settings documentation. Integrations# Integrations covers external connectivity: Bases view wiring, Google/Microsoft OAuth calendar sync, ICS subscriptions, automatic ICS export, HTTP API settings, and webhook endpoints. For more detailed information, see the Integrations Settings documentation."},{"route":"/obsidian/settings/appearance/","title":"Appearance & UI Settings","description":"These settings control the visual appearance of the plugin, including the calendar, task cards, and other UI elements.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/settings/appearance.md","namespace":"obsidian","relativePath":"settings/appearance.md","raw":"# Appearance & UI Settings\n\nThese settings control the visual appearance of the plugin, including the calendar, task cards, and other UI elements.\n\n\n![Appearance Settings](../assets/settings-appearance.png)\n\n## Task Cards\n\nUse **Default visible properties** to decide what metadata appears on task cards without opening each task. This is the primary control for card density.\n\nChecklist progress is available as a visible property in task cards. In Bases view `order` arrays, the corresponding source property is `file.tasks` (shown as `tasks` in Bases property pickers once present in the view `order` list).\n\nNested task cards use CSS variables for their indentation. Add a CSS snippet if\nyou want a denser hierarchy than the default:\n\n```css\n.tasknotes-plugin {\n --tn-nested-task-indent: 12px;\n --tn-nested-task-padding: 8px;\n}\n\nbody.is-mobile .tasknotes-plugin {\n --tn-nested-task-indent: 8px;\n --tn-nested-task-padding: 6px;\n}\n```\n\nIf task links inside normal markdown lists feel visually doubled with both a\nlist marker and the task status indicator, a CSS snippet can hide those markers\nfor task-link lines:\n\n```css\n.markdown-reading-view li:has(.task-inline-preview--reading-mode)::marker {\n content: \"\";\n}\n\n.markdown-source-view.mod-cm6 .cm-line:has(.tasknotes-inline-widget) .cm-formatting-list {\n display: none;\n}\n```\n\n## Display Formatting\n\nUse **Time format** to switch between 12-hour and 24-hour display across all TaskNotes surfaces.\n\n## Calendar View\n\nCalendar view settings determine the default landing mode, day/week framing, and timeline affordances. You can choose the default view, custom day span, first day of week, weekend visibility, week numbers, and whether today/current-time markers are shown. **Selection mirror** controls whether drag selections show a visual preview before committing.\n\nUse **Calendar locale** for region-specific formatting and calendar systems (for example `en`, `de`, or `fa`). Leave it empty to use automatic detection.\n\n## Default Event Visibility\n\nThis section controls which event layers are enabled when a calendar view opens. You can independently toggle scheduled tasks, due dates, due dates for already-scheduled tasks, time entries, recurring tasks, and ICS events.\n\n## Time Settings\n\nTime settings define the structure of timeline views: slot duration, earliest visible time, latest visible time, and initial scroll position. Use these together to match your workday shape.\n\n## UI Elements\n\nUI element toggles control auxiliary surfaces such as the tracked-task status bar entry, the project subtasks widget and its placement, expandable subtasks in cards, chevron position, and the alignment of the views/filters button.\n\n## Related Settings\n\nSome appearance-related settings are configured elsewhere:\n\n- **Task filename format**: Configured in [Task Properties](task-properties.md) → Title card\n- **Project autosuggest display**: Configured in [Task Properties](task-properties.md) → Projects card\n","aliases":["/settings/appearance/"],"toc":[{"level":2,"id":"task-cards","text":"Task Cards"},{"level":2,"id":"display-formatting","text":"Display Formatting"},{"level":2,"id":"calendar-view","text":"Calendar View"},{"level":2,"id":"default-event-visibility","text":"Default Event Visibility"},{"level":2,"id":"time-settings","text":"Time Settings"},{"level":2,"id":"ui-elements","text":"UI Elements"},{"level":2,"id":"related-settings","text":"Related Settings"}],"html":"

These settings control the visual appearance of the plugin, including the calendar, task cards, and other UI elements.

\n

\"Appearance

\n

Task Cards#

\n

Use Default visible properties to decide what metadata appears on task cards without opening each task. This is the primary control for card density.

\n

Checklist progress is available as a visible property in task cards. In Bases view order arrays, the corresponding source property is file.tasks (shown as tasks in Bases property pickers once present in the view order list).

\n

Nested task cards use CSS variables for their indentation. Add a CSS snippet if\nyou want a denser hierarchy than the default:

\n
.tasknotes-plugin {\n  --tn-nested-task-indent: 12px;\n  --tn-nested-task-padding: 8px;\n}\n\nbody.is-mobile .tasknotes-plugin {\n  --tn-nested-task-indent: 8px;\n  --tn-nested-task-padding: 6px;\n}\n

If task links inside normal markdown lists feel visually doubled with both a\nlist marker and the task status indicator, a CSS snippet can hide those markers\nfor task-link lines:

\n
.markdown-reading-view li:has(.task-inline-preview--reading-mode)::marker {\n  content: "";\n}\n\n.markdown-source-view.mod-cm6 .cm-line:has(.tasknotes-inline-widget) .cm-formatting-list {\n  display: none;\n}\n

Display Formatting#

\n

Use Time format to switch between 12-hour and 24-hour display across all TaskNotes surfaces.

\n

Calendar View#

\n

Calendar view settings determine the default landing mode, day/week framing, and timeline affordances. You can choose the default view, custom day span, first day of week, weekend visibility, week numbers, and whether today/current-time markers are shown. Selection mirror controls whether drag selections show a visual preview before committing.

\n

Use Calendar locale for region-specific formatting and calendar systems (for example en, de, or fa). Leave it empty to use automatic detection.

\n

Default Event Visibility#

\n

This section controls which event layers are enabled when a calendar view opens. You can independently toggle scheduled tasks, due dates, due dates for already-scheduled tasks, time entries, recurring tasks, and ICS events.

\n

Time Settings#

\n

Time settings define the structure of timeline views: slot duration, earliest visible time, latest visible time, and initial scroll position. Use these together to match your workday shape.

\n

UI Elements#

\n

UI element toggles control auxiliary surfaces such as the tracked-task status bar entry, the project subtasks widget and its placement, expandable subtasks in cards, chevron position, and the alignment of the views/filters button.

\n

Related Settings#

\n

Some appearance-related settings are configured elsewhere:

\n\n","text":"These settings control the visual appearance of the plugin, including the calendar, task cards, and other UI elements. Task Cards# Use Default visible properties to decide what metadata appears on task cards without opening each task. This is the primary control for card density. Checklist progress is available as a visible property in task cards. In Bases view order arrays, the corresponding source property is file.tasks (shown as tasks in Bases property pickers once present in the view order list). Nested task cards use CSS variables for their indentation. Add a CSS snippet if you want a denser hierarchy than the default: .tasknotes-plugin { --tn-nested-task-indent: 12px; --tn-nested-task-padding: 8px; } body.is-mobile .tasknotes-plugin { --tn-nested-task-indent: 8px; --tn-nested-task-padding: 6px; } If task links inside normal markdown lists feel visually doubled with both a list marker and the task status indicator, a CSS snippet can hide those markers for task-link lines: .markdown-reading-view li:has(.task-inline-preview--reading-mode)::marker { content: \"\"; } .markdown-source-view.mod-cm6 .cm-line:has(.tasknotes-inline-widget) .cm-formatting-list { display: none; } Display Formatting# Use Time format to switch between 12-hour and 24-hour display across all TaskNotes surfaces. Calendar View# Calendar view settings determine the default landing mode, day/week framing, and timeline affordances. You can choose the default view, custom day span, first day of week, weekend visibility, week numbers, and whether today/current-time markers are shown. Selection mirror controls whether drag selections show a visual preview before committing. Use Calendar locale for region-specific formatting and calendar systems (for example en, de, or fa). Leave it empty to use automatic detection. Default Event Visibility# This section controls which event layers are enabled when a calendar view opens. You can independently toggle scheduled tasks, due dates, due dates for already-scheduled tasks, time entries, recurring tasks, and ICS events. Time Settings# Time settings define the structure of timeline views: slot duration, earliest visible time, latest visible time, and initial scroll position. Use these together to match your workday shape. UI Elements# UI element toggles control auxiliary surfaces such as the tracked-task status bar entry, the project subtasks widget and its placement, expandable subtasks in cards, chevron position, and the alignment of the views/filters button. Related Settings# Some appearance-related settings are configured elsewhere: Task filename format: Configured in Task Properties → Title card Project autosuggest display: Configured in Task Properties → Projects card"},{"route":"/obsidian/settings/features/","title":"Features Settings","description":"These settings allow you to enable, disable, and configure the various features of the plugin, such as inline tasks, natural language processing, the Pomodoro timer, and notific...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/settings/features.md","namespace":"obsidian","relativePath":"settings/features.md","raw":"# Features Settings\n\nThese settings allow you to enable, disable, and configure the various features of the plugin, such as inline tasks, natural language processing, the Pomodoro timer, and notifications.\n\n\n![Features Settings](../assets/settings-features.png)\n\n## Inline Tasks\n\nInline task settings control how aggressively TaskNotes turns plain note content into structured task interactions. **Task link overlay** enables the Live Preview card behavior for task links, while **Instant task convert** surfaces conversion buttons next to list items and checkboxes. **Keep checkbox when converting** leaves the original Markdown checkbox marker in the source note when a checkbox becomes a TaskNote link. For conversion output, **Inline task convert folder** sets destination behavior and supports `{{currentNotePath}}`, and **Use task defaults on instant convert** applies your default task values at conversion time.\n\nThe separate **Convert current note to task** command keeps the current note body as the task details. If the note has no `scheduled` frontmatter, the command uses the Scheduled Date default from **Task Properties**; it does not apply body templates.\n\n## Body Template\n\nBody template settings let you scaffold newly created tasks with consistent note content. When enabled, TaskNotes reads the configured template file and expands variables like `{{title}}`, `{{date}}`, `{{time}}`, `{{priority}}`, `{{status}}`, `{{contexts}}`, `{{tags}}`, and `{{projects}}`.\n\nMaterialized occurrence notes can use a separate template. Set **Occurrence note template file** to provide a global fallback for occurrence notes; a recurring task's `occurrence_template` frontmatter field takes priority when it is set. If neither occurrence-specific template is configured, occurrence notes continue through the normal body template behavior.\n\n## Natural Language Processing\n\nNLP settings define how text input is interpreted during task capture. **Enable natural language task input** activates date and metadata parsing, **Default to scheduled** changes ambiguous date handling, **NLP language** selects parsing patterns, and **Status suggestion trigger** controls optional status autocomplete activation.\n\nWrap text in double quotes, single quotes, or backticks to keep it as literal title text during NLP parsing. For example, `BIO \"123H\" - HW1` keeps `123H` in the title instead of treating it as a 123-hour estimate, while `Review \"Today\" notes` keeps `Today` as text instead of parsing it as a date.\n\n## Pomodoro Timer\n\nPomodoro settings control interval lengths, long-break cadence, optional auto-start behavior, and end-of-session notifications/sound. **Pomodoro data storage** chooses whether history is kept in plugin data or daily notes.\n\n## Notifications\n\nUse this section to enable reminders globally, choose whether notices are shown in-app or through system notifications, and optionally play a built-in reminder sound with its own volume control.\n\n## Performance & Behavior\n\nPerformance and behavior toggles let you refine overhead and interaction feel: exclude completed tasks from overdue calculations, disable indexing for very large vaults, and tune suggestion debounce timing.\n\n## Time Tracking\n\nTime tracking options handle completion behavior. You can automatically stop running timers when a task is completed and optionally show a confirmation notification.\n\n## Recurring Tasks\n\nUse **Maintain due date offset in recurring tasks** to keep due/scheduled spacing consistent when recurring tasks roll forward.\n\nOccurrence note behavior is configured per recurring task from the task context menu: open **Recurrence → Occurrence notes** to choose manual creation or automatic creation of the next materialized occurrence after completion. See [Recurring Tasks](../features/recurring-tasks.md#materialized-occurrence-notes) for the workflow and storage model.\n\n## Timeblocking\n\nTimeblocking enables lightweight daily-note scheduling blocks and controls whether those blocks are visible by default in calendar views.\n\n### Usage\n\nIn the calendar view, click and drag on a time slot to select a time range. A context menu will appear—select \"Create timeblock\" to create a timeblock (this option only appears if timeblocking is enabled in settings). Drag existing timeblocks to move them. Resize edges to adjust duration.\n","aliases":["/settings/features/"],"toc":[{"level":2,"id":"inline-tasks","text":"Inline Tasks"},{"level":2,"id":"body-template","text":"Body Template"},{"level":2,"id":"natural-language-processing","text":"Natural Language Processing"},{"level":2,"id":"pomodoro-timer","text":"Pomodoro Timer"},{"level":2,"id":"notifications","text":"Notifications"},{"level":2,"id":"performance-behavior","text":"Performance & Behavior"},{"level":2,"id":"time-tracking","text":"Time Tracking"},{"level":2,"id":"recurring-tasks","text":"Recurring Tasks"},{"level":2,"id":"timeblocking","text":"Timeblocking"},{"level":3,"id":"usage","text":"Usage"}],"html":"

These settings allow you to enable, disable, and configure the various features of the plugin, such as inline tasks, natural language processing, the Pomodoro timer, and notifications.

\n

\"Features

\n

Inline Tasks#

\n

Inline task settings control how aggressively TaskNotes turns plain note content into structured task interactions. Task link overlay enables the Live Preview card behavior for task links, while Instant task convert surfaces conversion buttons next to list items and checkboxes. Keep checkbox when converting leaves the original Markdown checkbox marker in the source note when a checkbox becomes a TaskNote link. For conversion output, Inline task convert folder sets destination behavior and supports {{currentNotePath}}, and Use task defaults on instant convert applies your default task values at conversion time.

\n

The separate Convert current note to task command keeps the current note body as the task details. If the note has no scheduled frontmatter, the command uses the Scheduled Date default from Task Properties; it does not apply body templates.

\n

Body Template#

\n

Body template settings let you scaffold newly created tasks with consistent note content. When enabled, TaskNotes reads the configured template file and expands variables like {{title}}, {{date}}, {{time}}, {{priority}}, {{status}}, {{contexts}}, {{tags}}, and {{projects}}.

\n

Materialized occurrence notes can use a separate template. Set Occurrence note template file to provide a global fallback for occurrence notes; a recurring task's occurrence_template frontmatter field takes priority when it is set. If neither occurrence-specific template is configured, occurrence notes continue through the normal body template behavior.

\n

Natural Language Processing#

\n

NLP settings define how text input is interpreted during task capture. Enable natural language task input activates date and metadata parsing, Default to scheduled changes ambiguous date handling, NLP language selects parsing patterns, and Status suggestion trigger controls optional status autocomplete activation.

\n

Wrap text in double quotes, single quotes, or backticks to keep it as literal title text during NLP parsing. For example, BIO "123H" - HW1 keeps 123H in the title instead of treating it as a 123-hour estimate, while Review "Today" notes keeps Today as text instead of parsing it as a date.

\n

Pomodoro Timer#

\n

Pomodoro settings control interval lengths, long-break cadence, optional auto-start behavior, and end-of-session notifications/sound. Pomodoro data storage chooses whether history is kept in plugin data or daily notes.

\n

Notifications#

\n

Use this section to enable reminders globally, choose whether notices are shown in-app or through system notifications, and optionally play a built-in reminder sound with its own volume control.

\n

Performance & Behavior#

\n

Performance and behavior toggles let you refine overhead and interaction feel: exclude completed tasks from overdue calculations, disable indexing for very large vaults, and tune suggestion debounce timing.

\n

Time Tracking#

\n

Time tracking options handle completion behavior. You can automatically stop running timers when a task is completed and optionally show a confirmation notification.

\n

Recurring Tasks#

\n

Use Maintain due date offset in recurring tasks to keep due/scheduled spacing consistent when recurring tasks roll forward.

\n

Occurrence note behavior is configured per recurring task from the task context menu: open Recurrence → Occurrence notes to choose manual creation or automatic creation of the next materialized occurrence after completion. See Recurring Tasks for the workflow and storage model.

\n

Timeblocking#

\n

Timeblocking enables lightweight daily-note scheduling blocks and controls whether those blocks are visible by default in calendar views.

\n

Usage#

\n

In the calendar view, click and drag on a time slot to select a time range. A context menu will appear—select "Create timeblock" to create a timeblock (this option only appears if timeblocking is enabled in settings). Drag existing timeblocks to move them. Resize edges to adjust duration.

\n","text":"These settings allow you to enable, disable, and configure the various features of the plugin, such as inline tasks, natural language processing, the Pomodoro timer, and notifications. Inline Tasks# Inline task settings control how aggressively TaskNotes turns plain note content into structured task interactions. Task link overlay enables the Live Preview card behavior for task links, while Instant task convert surfaces conversion buttons next to list items and checkboxes. Keep checkbox when converting leaves the original Markdown checkbox marker in the source note when a checkbox becomes a TaskNote link. For conversion output, Inline task convert folder sets destination behavior and supports {{currentNotePath}}, and Use task defaults on instant convert applies your default task values at conversion time. The separate Convert current note to task command keeps the current note body as the task details. If the note has no scheduled frontmatter, the command uses the Scheduled Date default from Task Properties; it does not apply body templates. Body Template# Body template settings let you scaffold newly created tasks with consistent note content. When enabled, TaskNotes reads the configured template file and expands variables like {{title}}, {{date}}, {{time}}, {{priority}}, {{status}}, {{contexts}}, {{tags}}, and {{projects}}. Materialized occurrence notes can use a separate template. Set Occurrence note template file to provide a global fallback for occurrence notes; a recurring task's occurrence_template frontmatter field takes priority when it is set. If neither occurrence-specific template is configured, occurrence notes continue through the normal body template behavior. Natural Language Processing# NLP settings define how text input is interpreted during task capture. Enable natural language task input activates date and metadata parsing, Default to scheduled changes ambiguous date handling, NLP language selects parsing patterns, and Status suggestion trigger controls optional status autocomplete activation. Wrap text in double quotes, single quotes, or backticks to keep it as literal title text during NLP parsing. For example, BIO \"123H\" - HW1 keeps 123H in the title instead of treating it as a 123-hour estimate, while Review \"Today\" notes keeps Today as text instead of parsing it as a date. Pomodoro Timer# Pomodoro settings control interval lengths, long-break cadence, optional auto-start behavior, and end-of-session notifications/sound. Pomodoro data storage chooses whether history is kept in plugin data or daily notes. Notifications# Use this section to enable reminders globally, choose whether notices are shown in-app or through system notifications, and optionally play a built-in reminder sound with its own volume control. Performance & Behavior# Performance and behavior toggles let you refine overhead and interaction feel: exclude completed tasks from overdue calculations, disable indexing for very large vaults, and tune suggestion debounce timing. Time Tracking# Time tracking options handle completion behavior. You can automatically stop running timers when a task is completed and optionally show a confirmation notification. Recurring Tasks# Use Maintain due date offset in recurring tasks to keep due/scheduled spacing consistent when recurring tasks roll forward. Occurrence note behavior is configured per recurring task from the task context menu: open Recurrence → Occurrence notes to choose manual creation or automatic creation of the next materialized occurrence after completion. See Recurring Tasks for the workflow and storage model. Timeblocking# Timeblocking enables lightweight daily-note scheduling blocks and controls whether those blocks are visible by default in calendar views. Usage# In the calendar view, click and drag on a time slot to select a time range. A context menu will appear—select \"Create timeblock\" to create a timeblock (this option only appears if timeblocking is enabled in settings). Drag existing timeblocks to move them. Resize edges to adjust duration."},{"route":"/obsidian/settings/general/","title":"General Settings","description":"These settings control the foundational aspects of the plugin, such as task identification, file storage, and click behavior.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/settings/general.md","namespace":"obsidian","relativePath":"settings/general.md","raw":"# General Settings\n\nThese settings control the foundational aspects of the plugin, such as task identification, file storage, and click behavior.\n\n\n![General Settings](../assets/settings-general.png)\n\n## Task Storage\n\nTask storage settings define where new and inline-created task files are created and how archived tasks are relocated. **Default tasks folder** sets the base location and supports folder template variables, including `{{currentNotePath}}` and `{{currentNoteTitle}}` for creating command-palette or ribbon tasks beside the active note. It also supports date variables such as `{{year}}` and Daily Notes-style date tokens such as `YYYY/MM/DD`. **Folder for inline-created tasks** controls the Create Inline Task command and instant conversion output. Leave it empty to use the default tasks folder, set a fixed folder path to centralize inline tasks, or use `{{currentNotePath}}` and `{{currentNoteTitle}}` placeholders for contextual routing. Relative path segments such as `../` are normalized after variables are expanded. If archive moves are enabled, completed archived tasks are moved automatically to your configured archive folder.\n\n## Task Identification\n\nTaskNotes can identify task notes using either a tag or a frontmatter property.\n\nUse **Identify tasks by** to select a strategy.\n\n- **Tag mode** uses a configured task tag (for example `task`) and can optionally hide that identifying tag in card displays.\n- **Property mode** matches a property/value pair (for example `isTask: true` or `category: task`) and is useful when you avoid tag-based identification.\n\nIf you change the task tag after creating default Base views, existing `.base` filters will still point at the old tag until you update the default Base files or edit those filters.\n\n### Hide Identification Tags\n\nWhen using tag-based identification, you may want to keep your task identification tags in the frontmatter for organizational purposes, but hide them from the visual display in task cards to reduce clutter.\n\nThe **Hide identification tags in task cards** setting allows you to do this. When enabled:\n\n- Tags that exactly match your task identification tag (e.g., `#task`) will be hidden\n- Hierarchical child tags (e.g., `#task/project`, `#task/work/urgent`) will also be hidden\n- Other tags that don't match the identification pattern will still be displayed\n- The setting only affects the visual display—tags remain in the frontmatter\n\n![Hide identification tags demo](../assets/demo-hide-identification-tags.gif)\n\n**Example:**\n\nIf your task identification tag is `task` and a task has the tags `#task`, `#task/project`, `#important`, and `#review`:\n\n- With the setting **disabled** (default): All tags are shown: `#task`, `#task/project`, `#important`, `#review`\n- With the setting **enabled**: Only non-identifying tags are shown: `#important`, `#review`\n\n## Folder Management\n\nUse **Excluded folders** to omit paths from Notes tab indexing and keep large archive areas out of regular task browsing.\n\n## Views & Base Files\n\nTaskNotes uses Obsidian Bases files (`.base`) to power its task views. By default, missing view files are created automatically on startup.\n\nUse **Create files** to generate missing default files in `TaskNotes/Views/` without overwriting existing files. Use **Update files** to overwrite the configured default files with templates generated from your current TaskNotes settings.\n\n## Frontmatter\n\nThis section only appears when you have markdown links enabled globally in Obsidian settings.\n\n**Use markdown links in frontmatter** switches project/dependency serialization from wikilinks (`[[path]]`) to markdown links (`[text](path)`). This requires the `obsidian-frontmatter-markdown-links` plugin.\n\n## Task Interaction\n\nTask interaction settings define default click behavior on task cards. You can independently choose single-click and double-click actions (edit task, open note, or no action for double click).\n\n## Release Notes\n\n**View release notes** opens the release notes view for the current version. Notes also open automatically after updates and remain available from the command palette.\n","aliases":["/settings/general/"],"toc":[{"level":2,"id":"task-storage","text":"Task Storage"},{"level":2,"id":"task-identification","text":"Task Identification"},{"level":3,"id":"hide-identification-tags","text":"Hide Identification Tags"},{"level":2,"id":"folder-management","text":"Folder Management"},{"level":2,"id":"views-base-files","text":"Views & Base Files"},{"level":2,"id":"frontmatter","text":"Frontmatter"},{"level":2,"id":"task-interaction","text":"Task Interaction"},{"level":2,"id":"release-notes","text":"Release Notes"}],"html":"

These settings control the foundational aspects of the plugin, such as task identification, file storage, and click behavior.

\n

\"General

\n

Task Storage#

\n

Task storage settings define where new and inline-created task files are created and how archived tasks are relocated. Default tasks folder sets the base location and supports folder template variables, including {{currentNotePath}} and {{currentNoteTitle}} for creating command-palette or ribbon tasks beside the active note. It also supports date variables such as {{year}} and Daily Notes-style date tokens such as YYYY/MM/DD. Folder for inline-created tasks controls the Create Inline Task command and instant conversion output. Leave it empty to use the default tasks folder, set a fixed folder path to centralize inline tasks, or use {{currentNotePath}} and {{currentNoteTitle}} placeholders for contextual routing. Relative path segments such as ../ are normalized after variables are expanded. If archive moves are enabled, completed archived tasks are moved automatically to your configured archive folder.

\n

Task Identification#

\n

TaskNotes can identify task notes using either a tag or a frontmatter property.

\n

Use Identify tasks by to select a strategy.

\n
    \n
  • Tag mode uses a configured task tag (for example task) and can optionally hide that identifying tag in card displays.
  • \n
  • Property mode matches a property/value pair (for example isTask: true or category: task) and is useful when you avoid tag-based identification.
  • \n
\n

If you change the task tag after creating default Base views, existing .base filters will still point at the old tag until you update the default Base files or edit those filters.

\n

Hide Identification Tags#

\n

When using tag-based identification, you may want to keep your task identification tags in the frontmatter for organizational purposes, but hide them from the visual display in task cards to reduce clutter.

\n

The Hide identification tags in task cards setting allows you to do this. When enabled:

\n
    \n
  • Tags that exactly match your task identification tag (e.g., #task) will be hidden
  • \n
  • Hierarchical child tags (e.g., #task/project, #task/work/urgent) will also be hidden
  • \n
  • Other tags that don't match the identification pattern will still be displayed
  • \n
  • The setting only affects the visual display—tags remain in the frontmatter
  • \n
\n

\"Hide

\n

Example:

\n

If your task identification tag is task and a task has the tags #task, #task/project, #important, and #review:

\n
    \n
  • With the setting disabled (default): All tags are shown: #task, #task/project, #important, #review
  • \n
  • With the setting enabled: Only non-identifying tags are shown: #important, #review
  • \n
\n

Folder Management#

\n

Use Excluded folders to omit paths from Notes tab indexing and keep large archive areas out of regular task browsing.

\n

Views & Base Files#

\n

TaskNotes uses Obsidian Bases files (.base) to power its task views. By default, missing view files are created automatically on startup.

\n

Use Create files to generate missing default files in TaskNotes/Views/ without overwriting existing files. Use Update files to overwrite the configured default files with templates generated from your current TaskNotes settings.

\n

Frontmatter#

\n

This section only appears when you have markdown links enabled globally in Obsidian settings.

\n

Use markdown links in frontmatter switches project/dependency serialization from wikilinks ([[path]]) to markdown links ([text](path)). This requires the obsidian-frontmatter-markdown-links plugin.

\n

Task Interaction#

\n

Task interaction settings define default click behavior on task cards. You can independently choose single-click and double-click actions (edit task, open note, or no action for double click).

\n

Release Notes#

\n

View release notes opens the release notes view for the current version. Notes also open automatically after updates and remain available from the command palette.

\n","text":"These settings control the foundational aspects of the plugin, such as task identification, file storage, and click behavior. Task Storage# Task storage settings define where new and inline-created task files are created and how archived tasks are relocated. Default tasks folder sets the base location and supports folder template variables, including {{currentNotePath}} and {{currentNoteTitle}} for creating command-palette or ribbon tasks beside the active note. It also supports date variables such as {{year}} and Daily Notes-style date tokens such as YYYY/MM/DD. Folder for inline-created tasks controls the Create Inline Task command and instant conversion output. Leave it empty to use the default tasks folder, set a fixed folder path to centralize inline tasks, or use {{currentNotePath}} and {{currentNoteTitle}} placeholders for contextual routing. Relative path segments such as ../ are normalized after variables are expanded. If archive moves are enabled, completed archived tasks are moved automatically to your configured archive folder. Task Identification# TaskNotes can identify task notes using either a tag or a frontmatter property. Use Identify tasks by to select a strategy. Tag mode uses a configured task tag (for example task) and can optionally hide that identifying tag in card displays. Property mode matches a property/value pair (for example isTask: true or category: task) and is useful when you avoid tag-based identification. If you change the task tag after creating default Base views, existing .base filters will still point at the old tag until you update the default Base files or edit those filters. Hide Identification Tags# When using tag-based identification, you may want to keep your task identification tags in the frontmatter for organizational purposes, but hide them from the visual display in task cards to reduce clutter. The Hide identification tags in task cards setting allows you to do this. When enabled: Tags that exactly match your task identification tag (e.g., #task) will be hidden Hierarchical child tags (e.g., #task/project, #task/work/urgent) will also be hidden Other tags that don't match the identification pattern will still be displayed The setting only affects the visual display—tags remain in the frontmatter Example: If your task identification tag is task and a task has the tags #task, #task/project, #important, and #review: With the setting disabled (default): All tags are shown: #task, #task/project, #important, #review With the setting enabled: Only non-identifying tags are shown: #important, #review Folder Management# Use Excluded folders to omit paths from Notes tab indexing and keep large archive areas out of regular task browsing. Views & Base Files# TaskNotes uses Obsidian Bases files (.base) to power its task views. By default, missing view files are created automatically on startup. Use Create files to generate missing default files in TaskNotes/Views/ without overwriting existing files. Use Update files to overwrite the configured default files with templates generated from your current TaskNotes settings. Frontmatter# This section only appears when you have markdown links enabled globally in Obsidian settings. Use markdown links in frontmatter switches project/dependency serialization from wikilinks ([[path]]) to markdown links ([text](path)). This requires the obsidian-frontmatter-markdown-links plugin. Task Interaction# Task interaction settings define default click behavior on task cards. You can independently choose single-click and double-click actions (edit task, open note, or no action for double click). Release Notes# View release notes opens the release notes view for the current version. Notes also open automatically after updates and remain available from the command palette."},{"route":"/obsidian/settings/integrations/","title":"Integrations Settings","description":"These settings control the integration with other plugins and services, such as Bases and external calendars.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/settings/integrations.md","namespace":"obsidian","relativePath":"settings/integrations.md","raw":"# Integrations Settings\n\nThese settings control the integration with other plugins and services, such as Bases and external calendars.\n\n\n![Integrations Settings](../assets/settings-integrations.png)\n\n## Bases\n\nTaskNotes v4 uses Obsidian's Bases core plugin for its main views. For setup instructions, see [Core Concepts](../core-concepts.md#bases-integration).\n\n### View Commands Configuration\n\nView command settings map TaskNotes commands and ribbon actions to specific `.base` files. This is useful when you maintain custom variants of the default views and want first-class command access to those files.\n\nAccess these settings in **Settings → TaskNotes → General → Views & base files**.\n\nDefault mappings:\n\n- **Open Mini Calendar View** → `TaskNotes/Views/mini-calendar-default.base`\n- **Open Kanban View** → `TaskNotes/Views/kanban-default.base`\n- **Open Tasks View** → `TaskNotes/Views/tasks-default.base`\n- **Open Calendar View** → `TaskNotes/Views/calendar-default.base`\n- **Open Agenda View** → `TaskNotes/Views/agenda-default.base`\n- **Pomodoro Statistics Base** → `TaskNotes/Views/pomodoro-stats.base`\n- **Relationships Widget** → `TaskNotes/Views/relationships.base`\n\nEach command allows you to specify a custom `.base` file path and includes a reset button to restore the default path.\n\n**Auto-create default files**: When enabled, TaskNotes creates missing default `.base` files automatically on startup.\n\n**Create files**: Button to generate all default `.base` files in the `TaskNotes/Views/` directory. Existing files are not overwritten.\n\nThe generated Pomodoro statistics Base reads Pomodoro sessions from daily notes frontmatter. If your Pomodoro history is still stored in plugin data, migrate it from **Settings → TaskNotes → Features** before using that Base file.\n\n## OAuth Calendar Integration\n\nConnect Google Calendar or Microsoft Outlook to sync events bidirectionally with TaskNotes. Events automatically refresh every 15 minutes and sync when local changes are made (such as dragging events to reschedule).\n\nEnable **Disable calendar integrations on mobile** when you sync TaskNotes settings between desktop and mobile but do not want Obsidian Mobile to load external calendars on startup. The setting only affects mobile devices; desktop calendar integrations continue to run normally.\n\n### Setup Requirements\n\nOAuth integration requires creating your own OAuth application with Google and/or Microsoft. Initial setup takes approximately 15 minutes per provider.\n\n**Setup Guide**: See [Calendar Integration Setup](../calendar-setup.md) for detailed instructions on creating OAuth credentials with Google Cloud Console and Azure Portal.\n\n### Google Calendar\n\nProvide **Client ID** and **Client Secret** from Google Cloud Console, then use **Connect Google Calendar** to complete OAuth loopback authentication. **Disconnect** revokes account tokens while retaining the OAuth app credentials for reconnection. Use **Forget saved credentials** to remove the client ID and client secret.\n\nThe **Target calendar** setting used for exporting tasks to Google Calendar is also used as the default selection when creating a manual external calendar event from the calendar view. If the target calendar is unavailable, TaskNotes falls back to the provider's primary calendar.\n\nFor timed task exports, **Default reminder** accepts one or more minute offsets separated by commas, such as `60, 1440`. All-day task exports use the target Google Calendar's default reminder settings.\n\nWhen connected, displays:\n- Connected account email\n- Connection time\n- Last sync time\n- Manual refresh button\n\n### Microsoft Outlook Calendar\n\nProvide **Client ID** and **Client Secret** from Azure App Registration, then use **Connect Microsoft Calendar** to authenticate. **Disconnect** revokes account tokens while retaining the OAuth app credentials for reconnection. Use **Forget saved credentials** to remove the client ID and client secret.\n\nWhen connected, displays:\n- Connected account email\n- Connection time\n- Last sync time\n\n### Security\n\n- OAuth client credentials and account tokens are stored in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system\n- OAuth credentials and account tokens are not written to TaskNotes' `data.json`\n- Access tokens refresh automatically\n- Calendar data syncs directly between Obsidian and the calendar provider (no intermediary servers)\n- Disconnect at any time to revoke account access; use **Forget saved credentials** to remove the OAuth app credentials\n\n## Calendar subscriptions (ICS)\n\nICS settings define how subscribed calendar events are represented in your vault. You can set a default template, destination folder, filename strategy, and custom filename template for generated notes. Use **Add Calendar Subscription** to register URLs or local files, and **Refresh all subscriptions** for manual synchronization.\n\n**Recurring event related notes** controls how notes linked from recurring external calendar events are matched. **Series-wide** keeps the current behavior: a note linked to one loaded recurrence can appear on the other loaded recurrences from the same Google, Microsoft, or ICS event series. **Selected instance only** limits related notes and counts to the exact recurrence instance that was linked.\n\n## Automatic ICS export\n\nAutomatic export keeps an ICS feed of your tasks updated on a schedule. Configure whether it is enabled, where the file is written (vault-relative path), the refresh interval, and use **Export now** for immediate output.\n\nExport filters can omit archived tasks, completed tasks, tasks without due dates, or tasks without scheduled dates. When both due-date and scheduled-date requirements are enabled, exported tasks must have both dates.\n\n## HTTP API\n\nHTTP API settings control the local server lifecycle, listening port, and request authentication token.\n\nChanges to API enablement or port require an Obsidian restart to take effect.\n\n!!! warning\n The HTTP API binds to loopback only and browser CORS is limited to loopback origins. If the authentication token is empty, local API requests are still unauthenticated. Set a token unless your local environment is fully trusted.\n\n## Webhooks\n\n- **Add Webhook**: Register a new webhook endpoint.\n","aliases":["/settings/integrations/"],"toc":[{"level":2,"id":"bases","text":"Bases"},{"level":3,"id":"view-commands-configuration","text":"View Commands Configuration"},{"level":2,"id":"oauth-calendar-integration","text":"OAuth Calendar Integration"},{"level":3,"id":"setup-requirements","text":"Setup Requirements"},{"level":3,"id":"google-calendar","text":"Google Calendar"},{"level":3,"id":"microsoft-outlook-calendar","text":"Microsoft Outlook Calendar"},{"level":3,"id":"security","text":"Security"},{"level":2,"id":"calendar-subscriptions-ics","text":"Calendar subscriptions (ICS)"},{"level":2,"id":"automatic-ics-export","text":"Automatic ICS export"},{"level":2,"id":"http-api","text":"HTTP API"},{"level":2,"id":"webhooks","text":"Webhooks"}],"html":"

These settings control the integration with other plugins and services, such as Bases and external calendars.

\n

\"Integrations

\n

Bases#

\n

TaskNotes v4 uses Obsidian's Bases core plugin for its main views. For setup instructions, see Core Concepts.

\n

View Commands Configuration#

\n

View command settings map TaskNotes commands and ribbon actions to specific .base files. This is useful when you maintain custom variants of the default views and want first-class command access to those files.

\n

Access these settings in Settings → TaskNotes → General → Views & base files.

\n

Default mappings:

\n
    \n
  • Open Mini Calendar View → TaskNotes/Views/mini-calendar-default.base
  • \n
  • Open Kanban View → TaskNotes/Views/kanban-default.base
  • \n
  • Open Tasks View → TaskNotes/Views/tasks-default.base
  • \n
  • Open Calendar View → TaskNotes/Views/calendar-default.base
  • \n
  • Open Agenda View → TaskNotes/Views/agenda-default.base
  • \n
  • Pomodoro Statistics Base → TaskNotes/Views/pomodoro-stats.base
  • \n
  • Relationships Widget → TaskNotes/Views/relationships.base
  • \n
\n

Each command allows you to specify a custom .base file path and includes a reset button to restore the default path.

\n

Auto-create default files: When enabled, TaskNotes creates missing default .base files automatically on startup.

\n

Create files: Button to generate all default .base files in the TaskNotes/Views/ directory. Existing files are not overwritten.

\n

The generated Pomodoro statistics Base reads Pomodoro sessions from daily notes frontmatter. If your Pomodoro history is still stored in plugin data, migrate it from Settings → TaskNotes → Features before using that Base file.

\n

OAuth Calendar Integration#

\n

Connect Google Calendar or Microsoft Outlook to sync events bidirectionally with TaskNotes. Events automatically refresh every 15 minutes and sync when local changes are made (such as dragging events to reschedule).

\n

Enable Disable calendar integrations on mobile when you sync TaskNotes settings between desktop and mobile but do not want Obsidian Mobile to load external calendars on startup. The setting only affects mobile devices; desktop calendar integrations continue to run normally.

\n

Setup Requirements#

\n

OAuth integration requires creating your own OAuth application with Google and/or Microsoft. Initial setup takes approximately 15 minutes per provider.

\n

Setup Guide: See Calendar Integration Setup for detailed instructions on creating OAuth credentials with Google Cloud Console and Azure Portal.

\n

Google Calendar#

\n

Provide Client ID and Client Secret from Google Cloud Console, then use Connect Google Calendar to complete OAuth loopback authentication. Disconnect revokes account tokens while retaining the OAuth app credentials for reconnection. Use Forget saved credentials to remove the client ID and client secret.

\n

The Target calendar setting used for exporting tasks to Google Calendar is also used as the default selection when creating a manual external calendar event from the calendar view. If the target calendar is unavailable, TaskNotes falls back to the provider's primary calendar.

\n

For timed task exports, Default reminder accepts one or more minute offsets separated by commas, such as 60, 1440. All-day task exports use the target Google Calendar's default reminder settings.

\n

When connected, displays:

\n
    \n
  • Connected account email
  • \n
  • Connection time
  • \n
  • Last sync time
  • \n
  • Manual refresh button
  • \n
\n

Microsoft Outlook Calendar#

\n

Provide Client ID and Client Secret from Azure App Registration, then use Connect Microsoft Calendar to authenticate. Disconnect revokes account tokens while retaining the OAuth app credentials for reconnection. Use Forget saved credentials to remove the client ID and client secret.

\n

When connected, displays:

\n
    \n
  • Connected account email
  • \n
  • Connection time
  • \n
  • Last sync time
  • \n
\n

Security#

\n
    \n
  • OAuth client credentials and account tokens are stored in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system
  • \n
  • OAuth credentials and account tokens are not written to TaskNotes' data.json
  • \n
  • Access tokens refresh automatically
  • \n
  • Calendar data syncs directly between Obsidian and the calendar provider (no intermediary servers)
  • \n
  • Disconnect at any time to revoke account access; use Forget saved credentials to remove the OAuth app credentials
  • \n
\n

Calendar subscriptions (ICS)#

\n

ICS settings define how subscribed calendar events are represented in your vault. You can set a default template, destination folder, filename strategy, and custom filename template for generated notes. Use Add Calendar Subscription to register URLs or local files, and Refresh all subscriptions for manual synchronization.

\n

Recurring event related notes controls how notes linked from recurring external calendar events are matched. Series-wide keeps the current behavior: a note linked to one loaded recurrence can appear on the other loaded recurrences from the same Google, Microsoft, or ICS event series. Selected instance only limits related notes and counts to the exact recurrence instance that was linked.

\n

Automatic ICS export#

\n

Automatic export keeps an ICS feed of your tasks updated on a schedule. Configure whether it is enabled, where the file is written (vault-relative path), the refresh interval, and use Export now for immediate output.

\n

Export filters can omit archived tasks, completed tasks, tasks without due dates, or tasks without scheduled dates. When both due-date and scheduled-date requirements are enabled, exported tasks must have both dates.

\n

HTTP API#

\n

HTTP API settings control the local server lifecycle, listening port, and request authentication token.

\n

Changes to API enablement or port require an Obsidian restart to take effect.

\n\n

Webhooks#

\n
    \n
  • Add Webhook: Register a new webhook endpoint.
  • \n
\n","text":"These settings control the integration with other plugins and services, such as Bases and external calendars. Bases# TaskNotes v4 uses Obsidian's Bases core plugin for its main views. For setup instructions, see Core Concepts. View Commands Configuration# View command settings map TaskNotes commands and ribbon actions to specific .base files. This is useful when you maintain custom variants of the default views and want first-class command access to those files. Access these settings in Settings → TaskNotes → General → Views & base files. Default mappings: Open Mini Calendar View → TaskNotes/Views/mini-calendar-default.base Open Kanban View → TaskNotes/Views/kanban-default.base Open Tasks View → TaskNotes/Views/tasks-default.base Open Calendar View → TaskNotes/Views/calendar-default.base Open Agenda View → TaskNotes/Views/agenda-default.base Pomodoro Statistics Base → TaskNotes/Views/pomodoro-stats.base Relationships Widget → TaskNotes/Views/relationships.base Each command allows you to specify a custom .base file path and includes a reset button to restore the default path. Auto-create default files: When enabled, TaskNotes creates missing default .base files automatically on startup. Create files: Button to generate all default .base files in the TaskNotes/Views/ directory. Existing files are not overwritten. The generated Pomodoro statistics Base reads Pomodoro sessions from daily notes frontmatter. If your Pomodoro history is still stored in plugin data, migrate it from Settings → TaskNotes → Features before using that Base file. OAuth Calendar Integration# Connect Google Calendar or Microsoft Outlook to sync events bidirectionally with TaskNotes. Events automatically refresh every 15 minutes and sync when local changes are made (such as dragging events to reschedule). Enable Disable calendar integrations on mobile when you sync TaskNotes settings between desktop and mobile but do not want Obsidian Mobile to load external calendars on startup. The setting only affects mobile devices; desktop calendar integrations continue to run normally. Setup Requirements# OAuth integration requires creating your own OAuth application with Google and/or Microsoft. Initial setup takes approximately 15 minutes per provider. Setup Guide: See Calendar Integration Setup for detailed instructions on creating OAuth credentials with Google Cloud Console and Azure Portal. Google Calendar# Provide Client ID and Client Secret from Google Cloud Console, then use Connect Google Calendar to complete OAuth loopback authentication. Disconnect revokes account tokens while retaining the OAuth app credentials for reconnection. Use Forget saved credentials to remove the client ID and client secret. The Target calendar setting used for exporting tasks to Google Calendar is also used as the default selection when creating a manual external calendar event from the calendar view. If the target calendar is unavailable, TaskNotes falls back to the provider's primary calendar. For timed task exports, Default reminder accepts one or more minute offsets separated by commas, such as 60, 1440. All-day task exports use the target Google Calendar's default reminder settings. When connected, displays: Connected account email Connection time Last sync time Manual refresh button Microsoft Outlook Calendar# Provide Client ID and Client Secret from Azure App Registration, then use Connect Microsoft Calendar to authenticate. Disconnect revokes account tokens while retaining the OAuth app credentials for reconnection. Use Forget saved credentials to remove the client ID and client secret. When connected, displays: Connected account email Connection time Last sync time Security# OAuth client credentials and account tokens are stored in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system OAuth credentials and account tokens are not written to TaskNotes' data.json Access tokens refresh automatically Calendar data syncs directly between Obsidian and the calendar provider (no intermediary servers) Disconnect at any time to revoke account access; use Forget saved credentials to remove the OAuth app credentials Calendar subscriptions (ICS)# ICS settings define how subscribed calendar events are represented in your vault. You can set a default template, destination folder, filename strategy, and custom filename template for generated notes. Use Add Calendar Subscription to register URLs or local files, and Refresh all subscriptions for manual synchronization. Recurring event related notes controls how notes linked from recurring external calendar events are matched. Series-wide keeps the current behavior: a note linked to one loaded recurrence can appear on the other loaded recurrences from the same Google, Microsoft, or ICS event series. Selected instance only limits related notes and counts to the exact recurrence instance that was linked. Automatic ICS export# Automatic export keeps an ICS feed of your tasks updated on a schedule. Configure whether it is enabled, where the file is written (vault-relative path), the refresh interval, and use Export now for immediate output. Export filters can omit archived tasks, completed tasks, tasks without due dates, or tasks without scheduled dates. When both due-date and scheduled-date requirements are enabled, exported tasks must have both dates. HTTP API# HTTP API settings control the local server lifecycle, listening port, and request authentication token. Changes to API enablement or port require an Obsidian restart to take effect. WarningThe HTTP API binds to loopback only and browser CORS is limited to loopback origins. If the authentication token is empty, local API requests are still unauthenticated. Set a token unless your local environment is fully trusted. Webhooks# Add Webhook: Register a new webhook endpoint."},{"route":"/obsidian/settings/modal-fields/","title":"Modal Fields Settings","description":"The Modal Fields tab lets you decide exactly which fields appear in the task creation and edit modals. Open Settings → TaskNotes → Modal Fields to manage the configuration.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/settings/modal-fields.md","namespace":"obsidian","relativePath":"settings/modal-fields.md","raw":"# Modal Fields Settings\n\nThe Modal Fields tab lets you decide exactly which fields appear in the task creation and edit modals. Open **Settings → TaskNotes → Modal Fields** to manage the configuration.\n\n![Modal Fields Settings](../assets/settings-modal-fields.png)\n\n## Field Groups\n\nFields are organized into draggable groups:\n\n- **Basic Information** – Title and Details\n- **Metadata** – Contexts, Tags, Time Estimate\n- **Organization** – Projects and Subtasks\n- **Dependencies** – Blocked By and Blocking\n- **Custom Fields** – Any user-defined fields that you add through Task Properties\n\nEach group can be collapsed, and their order in the manager matches the order shown in the modal.\n\n## Managing Fields\n\nEvery field entry includes:\n\n- **Visibility toggles** for creation and edit modals\n- **Enable/disable** checkbox\n- **Drag handle** for ordering within its group\n- **Required** toggle (where applicable, e.g., Title)\n\nChanges are saved automatically. Use this to hide fields you never touch, ensure required metadata appears up front, or reorder fields to match your workflow.\n\n## Syncing User Fields\n\nThe **Sync User Fields** button pulls the latest user-defined fields from the Task Properties tab into the Custom Fields group. New user fields are appended, renamed fields update in place, and removed fields drop out of the configuration. Re-run the sync whenever you add or rename custom fields.\n\n## Resetting to Defaults\n\nSelect **Reset to Defaults** to restore the stock configuration (all built-in fields enabled plus empty custom slots). The reset keeps your existing user field definitions; it only reverts modal layout and visibility.\n","aliases":["/settings/modal-fields/"],"toc":[{"level":2,"id":"field-groups","text":"Field Groups"},{"level":2,"id":"managing-fields","text":"Managing Fields"},{"level":2,"id":"syncing-user-fields","text":"Syncing User Fields"},{"level":2,"id":"resetting-to-defaults","text":"Resetting to Defaults"}],"html":"

The Modal Fields tab lets you decide exactly which fields appear in the task creation and edit modals. Open Settings → TaskNotes → Modal Fields to manage the configuration.

\n

\"Modal

\n

Field Groups#

\n

Fields are organized into draggable groups:

\n
    \n
  • Basic Information – Title and Details
  • \n
  • Metadata – Contexts, Tags, Time Estimate
  • \n
  • Organization – Projects and Subtasks
  • \n
  • Dependencies – Blocked By and Blocking
  • \n
  • Custom Fields – Any user-defined fields that you add through Task Properties
  • \n
\n

Each group can be collapsed, and their order in the manager matches the order shown in the modal.

\n

Managing Fields#

\n

Every field entry includes:

\n
    \n
  • Visibility toggles for creation and edit modals
  • \n
  • Enable/disable checkbox
  • \n
  • Drag handle for ordering within its group
  • \n
  • Required toggle (where applicable, e.g., Title)
  • \n
\n

Changes are saved automatically. Use this to hide fields you never touch, ensure required metadata appears up front, or reorder fields to match your workflow.

\n

Syncing User Fields#

\n

The Sync User Fields button pulls the latest user-defined fields from the Task Properties tab into the Custom Fields group. New user fields are appended, renamed fields update in place, and removed fields drop out of the configuration. Re-run the sync whenever you add or rename custom fields.

\n

Resetting to Defaults#

\n

Select Reset to Defaults to restore the stock configuration (all built-in fields enabled plus empty custom slots). The reset keeps your existing user field definitions; it only reverts modal layout and visibility.

\n","text":"The Modal Fields tab lets you decide exactly which fields appear in the task creation and edit modals. Open Settings → TaskNotes → Modal Fields to manage the configuration. Field Groups# Fields are organized into draggable groups: Basic Information – Title and Details Metadata – Contexts, Tags, Time Estimate Organization – Projects and Subtasks Dependencies – Blocked By and Blocking Custom Fields – Any user-defined fields that you add through Task Properties Each group can be collapsed, and their order in the manager matches the order shown in the modal. Managing Fields# Every field entry includes: Visibility toggles for creation and edit modals Enable/disable checkbox Drag handle for ordering within its group Required toggle (where applicable, e.g., Title) Changes are saved automatically. Use this to hide fields you never touch, ensure required metadata appears up front, or reorder fields to match your workflow. Syncing User Fields# The Sync User Fields button pulls the latest user-defined fields from the Task Properties tab into the Custom Fields group. New user fields are appended, renamed fields update in place, and removed fields drop out of the configuration. Re-run the sync whenever you add or rename custom fields. Resetting to Defaults# Select Reset to Defaults to restore the stock configuration (all built-in fields enabled plus empty custom slots). The reset keeps your existing user field definitions; it only reverts modal layout and visibility."},{"route":"/obsidian/settings/property-identification/","title":"Property-based Task Identification","description":"When you choose to identify task files by a frontmatter property (instead of a tag), TaskNotes will match notes whose frontmatter property equals the configured value.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/settings/property-identification.md","namespace":"obsidian","relativePath":"settings/property-identification.md","raw":"# Property-based Task Identification\n\nWhen you choose to identify task files by a frontmatter property (instead of a tag), TaskNotes will match notes whose frontmatter property equals the configured value.\n\n## Boolean values\n- Enter the setting value as true or false (without quotes) in the settings UI.\n- Obsidian stores checkbox properties as real booleans, not strings. The plugin compares booleans correctly:\n - \"true\" in settings matches frontmatter boolean true\n - \"false\" in settings matches frontmatter boolean false\n - Arrays are supported (e.g., property: [false, true])\n\nTip: You don’t need to quote boolean values in frontmatter. Use plain true/false to keep Obsidian’s property types consistent.\n\n## Examples\n- Setting: Property Name = isTask, Property Value = true\n - Matches: `isTask: true`\n - Does not match: `isTask: false`\n- Setting: Property Name = isTask, Property Value = false\n - Matches: `isTask: false`\n - Does not match: `isTask: true`\n\nFor related configuration details, see [Task Properties](task-properties.md).\n","aliases":["/settings/property-identification/"],"toc":[{"level":2,"id":"boolean-values","text":"Boolean values"},{"level":2,"id":"examples","text":"Examples"}],"html":"

When you choose to identify task files by a frontmatter property (instead of a tag), TaskNotes will match notes whose frontmatter property equals the configured value.

\n

Boolean values#

\n
    \n
  • Enter the setting value as true or false (without quotes) in the settings UI.
  • \n
  • Obsidian stores checkbox properties as real booleans, not strings. The plugin compares booleans correctly:
      \n
    • "true" in settings matches frontmatter boolean true
    • \n
    • "false" in settings matches frontmatter boolean false
    • \n
    • Arrays are supported (e.g., property: [false, true])
    • \n
    \n
  • \n
\n

Tip: You don’t need to quote boolean values in frontmatter. Use plain true/false to keep Obsidian’s property types consistent.

\n

Examples#

\n
    \n
  • Setting: Property Name = isTask, Property Value = true
      \n
    • Matches: isTask: true
    • \n
    • Does not match: isTask: false
    • \n
    \n
  • \n
  • Setting: Property Name = isTask, Property Value = false
      \n
    • Matches: isTask: false
    • \n
    • Does not match: isTask: true
    • \n
    \n
  • \n
\n

For related configuration details, see Task Properties.

\n","text":"When you choose to identify task files by a frontmatter property (instead of a tag), TaskNotes will match notes whose frontmatter property equals the configured value. Boolean values# Enter the setting value as true or false (without quotes) in the settings UI. Obsidian stores checkbox properties as real booleans, not strings. The plugin compares booleans correctly: \"true\" in settings matches frontmatter boolean true \"false\" in settings matches frontmatter boolean false Arrays are supported (e.g., property: [false, true]) Tip: You don’t need to quote boolean values in frontmatter. Use plain true/false to keep Obsidian’s property types consistent. Examples# Setting: Property Name = isTask, Property Value = true Matches: isTask: true Does not match: isTask: false Setting: Property Name = isTask, Property Value = false Matches: isTask: false Does not match: isTask: true For related configuration details, see Task Properties."},{"route":"/obsidian/settings/property-types-reference/","title":"Property Types Reference","description":"This reference documents the expected data types for each frontmatter property that TaskNotes uses.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/settings/property-types-reference.md","namespace":"obsidian","relativePath":"settings/property-types-reference.md","raw":"# Property Types Reference\n\nThis reference documents the expected data types for each frontmatter property that TaskNotes uses.\n\n\n## Quick Reference\n\n| Property | Type | Example |\n|----------|------|---------|\n| title | text | `\"My Task\"` |\n| status | text | `\"open\"`, `\"in-progress\"`, `\"done\"` |\n| priority | text | `\"low\"`, `\"normal\"`, `\"high\"` |\n| due | text (date) | `\"2025-01-15\"` |\n| scheduled | text (date) | `\"2025-01-10\"` |\n| completedDate | text (date) | `\"2025-01-20\"` |\n| dateCreated | text (datetime) | `\"2025-01-01T08:00:00Z\"` |\n| dateModified | text (datetime) | `\"2025-01-15T10:30:00Z\"` |\n| tags | list | `[\"work\", \"urgent\"]` |\n| contexts | list | `[\"office\", \"home\"]` |\n| projects | list | `[\"[[Project A]]\"]` |\n| timeEstimate | number | `120` (minutes) |\n| recurrence | text | `\"FREQ=WEEKLY;BYDAY=MO\"` |\n| recurrence_anchor | text | `\"scheduled\"` or `\"completion\"` |\n| timeEntries | list (objects) | See [Time Entries](#time-entries) |\n| blockedBy | list (objects) | See [Dependencies](#dependencies-blockedby) |\n| reminders | list (objects) | See [Reminders](#reminders) |\n| complete_instances | list | `[\"2025-01-08\", \"2025-01-15\"]` |\n| skipped_instances | list | `[\"2025-01-22\"]` |\n| recurrence_parent | text (link/path) | `\"[[Tasks/Weekly review]]\"` |\n| occurrence_date | text (date) | `\"2025-01-15\"` |\n| occurrence_materialization | text | `\"manual\"` or `\"on_completion\"` |\n| occurrence_next_trigger | text | `\"completion\"` or `\"completion_or_skip\"` |\n| occurrence_template | text (link/path) | `\"[[Templates/Occurrence]]\"` |\n| occurrence_past_horizon | text (duration) | `\"P7D\"` |\n| occurrence_future_horizon | text (duration) | `\"P14D\"` |\n| icsEventId | list | `[\"event-abc123\"]` |\n\nUse this table for fast validation when a field is not behaving as expected in views or API calls. Most parsing issues come from shape mismatches (for example scalar vs list) rather than missing values.\n\n---\n\n## Property Details\n\nThe sections below describe storage formats, but there is flexibility in authoring style. TaskNotes normalizes many equivalent YAML representations as long as the resulting data type is correct.\n\n### Text Properties\n\n#### title\n- **Type:** text (string)\n- **Description:** The task's title or name\n- **Example:** `title: \"Complete project documentation\"`\n\n#### status\n- **Type:** text (string)\n- **Description:** The task's current status. Must match one of the status values configured in your settings.\n- **Default values:** `\"open\"`, `\"in-progress\"`, `\"done\"`\n- **Example:** `status: \"in-progress\"`\n- **Note:** Also supports boolean values (`true`/`false`) for Obsidian checkbox compatibility. See [Boolean Status Values](task-properties.md#boolean-status-values).\n\n#### priority\n- **Type:** text (string)\n- **Description:** The task's priority level. Must match one of the priority values configured in your settings.\n- **Default values:** `\"low\"`, `\"normal\"`, `\"high\"`\n- **Example:** `priority: \"high\"`\n\n---\n\n### Date Properties\n\nAll date properties are stored as **text strings** in your frontmatter. TaskNotes expects specific formats:\nWhen in doubt, prefer ISO-style values. They sort correctly as text, travel well through APIs, and are easiest to parse consistently.\n\n#### due\n\n- **Type:** text (date string)\n- **Format:** `YYYY-MM-DD` or ISO 8601 timestamp\n- **Description:** The task's due date\n- **Examples:**\n\n ```yaml\n due: \"2025-01-15\"\n due: \"2025-01-15T17:00:00\"\n ```\n\n#### scheduled\n\n- **Type:** text (date string)\n- **Format:** `YYYY-MM-DD` or ISO 8601 timestamp\n- **Description:** When the task is scheduled to be worked on\n- **Examples:**\n\n ```yaml\n scheduled: \"2025-01-10\"\n scheduled: \"2025-01-10T09:00:00\"\n ```\n\n#### completedDate\n\n- **Type:** text (date string)\n- **Format:** `YYYY-MM-DD`\n- **Description:** The date when the task was completed\n- **Example:** `completedDate: \"2025-01-20\"`\n\n#### dateCreated\n\n- **Type:** text (datetime string)\n- **Format:** ISO 8601 timestamp\n- **Description:** When the task was created\n- **Example:** `dateCreated: \"2025-01-01T08:00:00Z\"`\n\n#### dateModified\n\n- **Type:** text (datetime string)\n- **Format:** ISO 8601 timestamp\n- **Description:** When the task was last modified\n- **Example:** `dateModified: \"2025-01-15T10:30:00Z\"`\n\n---\n\n### List Properties\n\nList properties must be arrays, even when containing a single value.\nSingle-item arrays may look verbose, but they prevent edge cases when filters and formulas assume list semantics.\n\n#### tags\n\n- **Type:** list (array of strings)\n- **Description:** Tags associated with the task\n- **Examples:**\n\n ```yaml\n tags: [\"work\", \"documentation\"]\n tags:\n - work\n - documentation\n ```\n\n#### contexts\n\n- **Type:** list (array of strings)\n- **Description:** Context labels for the task\n- **Examples:**\n\n ```yaml\n contexts: [\"office\", \"computer\"]\n contexts:\n - \"office\"\n - \"computer\"\n ```\n\n#### projects\n\n- **Type:** list (array of strings)\n- **Description:** Project references (typically wiki-links)\n- **Examples:**\n\n ```yaml\n projects: [\"[[Website Redesign]]\", \"[[Q1 Planning]]\"]\n projects:\n - \"[[Website Redesign]]\"\n - \"[[Q1 Planning]]\"\n ```\n\n---\n\n### Numeric Properties\n\n#### timeEstimate\n- **Type:** number\n- **Unit:** minutes\n- **Description:** Estimated time to complete the task\n- **Example:** `timeEstimate: 120` (2 hours)\n\n---\n\n### Recurrence Properties\n\n#### recurrence\n\n- **Type:** text (string)\n- **Format:** RFC 5545 RRULE format\n- **Description:** Defines how the task repeats\n- **Examples:**\n\n ```yaml\n recurrence: \"FREQ=DAILY\"\n recurrence: \"FREQ=WEEKLY;BYDAY=MO,WE,FR\"\n recurrence: \"FREQ=MONTHLY;BYMONTHDAY=1\"\n ```\n\n#### recurrence_anchor\n\n- **Type:** text (string)\n- **Valid values:** `\"scheduled\"` or `\"completion\"`\n- **Description:** Determines whether the next occurrence is calculated from the scheduled date or when the task was completed\n- **Example:** `recurrence_anchor: \"scheduled\"`\n\n#### complete_instances\n\n- **Type:** list (array of date strings)\n- **Format:** `YYYY-MM-DD`\n- **Description:** Dates when recurring task instances were completed\n- **Example:**\n\n ```yaml\n complete_instances:\n - \"2025-01-08\"\n - \"2025-01-15\"\n ```\n\n#### skipped_instances\n\n- **Type:** list (array of date strings)\n- **Format:** `YYYY-MM-DD`\n- **Description:** Dates when recurring task instances were skipped\n- **Example:**\n\n ```yaml\n skipped_instances:\n - \"2025-01-22\"\n ```\n\n### Materialized Occurrence Properties\n\nMaterialized occurrence notes are ordinary task notes created for one date in a recurring series. The parent recurring task owns the recurrence rule; the occurrence note owns date-specific state such as status, completed date, body content, time entries, reminders, and comments.\n\nWhen an occurrence note is created, TaskNotes inherits parent planning metadata such as scheduled time, due offset, priority, tags, contexts, projects, reminders, dependencies, details, custom properties, and time estimate. It does not copy parent recurrence/history/runtime fields such as `recurrence`, `complete_instances`, `skipped_instances`, `completedDate`, provider event IDs, or `timeEntries`.\n\n#### recurrence_parent\n\n- **Type:** text (link or path string)\n- **Description:** Parent recurring task for a materialized occurrence note\n- **Example:** `recurrence_parent: \"[[Tasks/Weekly review]]\"`\n\n#### occurrence_date\n\n- **Type:** text (date string)\n- **Format:** `YYYY-MM-DD`\n- **Description:** Target recurrence date represented by a materialized occurrence note\n- **Example:** `occurrence_date: \"2025-01-15\"`\n\n#### occurrence_materialization\n\n- **Type:** text (string)\n- **Valid values:** `\"manual\"`, `\"on_completion\"`, `\"rolling\"`\n- **Description:** Parent task policy for creating occurrence notes. The plugin currently supports manual creation and creating the next note after completion; rolling windows are defined by the spec but are not automated yet.\n- **Example:** `occurrence_materialization: \"on_completion\"`\n\n#### occurrence_next_trigger\n\n- **Type:** text (string)\n- **Valid values:** `\"completion\"` or `\"completion_or_skip\"`\n- **Description:** Parent task policy for whether skip actions should also create the next occurrence note when occurrence materialization is set to `on_completion`\n- **Example:** `occurrence_next_trigger: \"completion_or_skip\"`\n\n#### occurrence_template\n\n- **Type:** text (link or path string)\n- **Description:** Optional template reference used when creating materialized occurrence notes. This parent-level template takes priority over the global occurrence note template fallback in Features settings.\n- **Example:** `occurrence_template: \"[[Templates/Weekly occurrence]]\"`\n\n#### occurrence_past_horizon and occurrence_future_horizon\n\n- **Type:** text (ISO 8601 duration string)\n- **Description:** Optional rolling-window bounds for occurrence materialization. These fields are part of the TaskNotes spec; automated rolling materialization is not currently enabled in the plugin.\n- **Examples:**\n\n ```yaml\n occurrence_past_horizon: \"P7D\"\n occurrence_future_horizon: \"P14D\"\n ```\n\n---\n\n### Complex Properties\n\nThese properties contain structured data with multiple fields.\nFor these fields, copy known-good examples before editing manually. Minor schema deviations can break downstream features such as reminders, recurrence, or dependency checks.\n\n#### Time Entries\n\n- **Type:** list (array of objects)\n- **Description:** Time tracking entries for the task\n- **Structure:**\n\n ```yaml\n timeEntries:\n - startTime: \"2025-01-15T10:30:00Z\" # Required: ISO 8601 timestamp\n endTime: \"2025-01-15T11:15:00Z\" # Optional: ISO 8601 timestamp\n description: \"Initial work\" # Optional: text\n ```\n\n#### Dependencies (blockedBy)\n\n- **Type:** list (array of objects)\n- **Description:** Tasks that must be completed before this task can start\n- **Structure:**\n\n ```yaml\n blockedBy:\n - uid: \"path/to/blocking-task.md\" # Required: path to blocking task\n reltype: \"FINISHTOSTART\" # Required: relationship type\n gap: \"P1D\" # Optional: ISO 8601 duration offset\n ```\n\n- **Relationship types accepted in stored data:** `FINISHTOSTART`, `STARTTOSTART`, `FINISHTOFINISH`, `STARTTOFINISH`\n- **Current behavior:** Dependencies created from the UI use `FINISHTOSTART`. Blocking evaluation is based on dependency presence/completion state and does not currently apply distinct scheduling semantics for different `reltype` values or `gap`.\n\n#### Reminders\n\n- **Type:** list (array of objects)\n- **Description:** Reminder notifications for the task\n- **Structure for relative reminders:**\n\n ```yaml\n reminders:\n - id: \"rem_1\" # Required: unique identifier\n type: \"relative\" # Required: \"relative\" or \"absolute\"\n relatedTo: \"due\" # Required for relative: \"due\" or \"scheduled\"\n offset: \"-PT1H\" # Required for relative: ISO 8601 duration\n description: \"1 hour before due\" # Optional: description\n ```\n\n- **Structure for absolute reminders:**\n\n ```yaml\n reminders:\n - id: \"rem_2\"\n type: \"absolute\"\n absoluteTime: \"2025-01-15T09:00:00Z\" # Required for absolute: ISO 8601 timestamp\n description: \"Morning reminder\"\n ```\n\n#### icsEventId\n\n- **Type:** list (array of strings)\n- **Description:** ICS calendar event IDs linked to this task\n- **Example:**\n \n ```yaml\n icsEventId:\n - \"event-abc123\"\n - \"event-def456\"\n ```\n\n\n---\n\n## Complete Example\n\nHere's a complete task with all property types:\n\n```yaml\n---\ntitle: \"Complete quarterly report\"\nstatus: \"in-progress\"\npriority: \"high\"\ndue: \"2025-01-31\"\nscheduled: \"2025-01-25\"\ntags:\n - work\n - reports\ncontexts:\n - office\nprojects:\n - \"[[Q1 Planning]]\"\ntimeEstimate: 240\ndateCreated: \"2025-01-01T08:00:00Z\"\ndateModified: \"2025-01-20T14:30:00Z\"\ntimeEntries:\n - startTime: \"2025-01-20T10:00:00Z\"\n endTime: \"2025-01-20T11:30:00Z\"\nblockedBy:\n - uid: \"tasks/gather-data.md\"\n reltype: \"FINISHTOSTART\"\nreminders:\n - id: \"rem_1\"\n type: \"relative\"\n relatedTo: \"due\"\n offset: \"-P1D\"\n description: \"Due tomorrow\"\n---\n```\n\n---\n\n## Field Mapping\n\nAll property names can be customized via **Settings → Task Properties → Field Mapping**. If you change a field mapping, TaskNotes will read and write using your custom property name.\n\nCustom property names are frontmatter keys, so names with spaces or punctuation are valid in task files. When you write your own Bases filters or formulas for those keys, use bracket notation such as `note[\"TN-status\"]` or `note[\"Task Type\"]` instead of dot notation. Dot notation only works reliably for simple identifier-style names.\n\nFor example, if you map `due` to `dueDate`, TaskNotes will expect:\n\n```yaml\ndueDate: \"2025-01-15\"\n```\n\nSee [Task Properties settings](task-properties.md) for configuration details.\n\n---\n\n## Custom User Fields\n\nYou can define additional properties with these types:\n\n- **text** - Single text value\n- **number** - Numeric value\n- **date** - Date string (YYYY-MM-DD)\n- **boolean** - true/false\n- **list** - Array of values\n\nSee [Custom User Fields](task-properties.md#custom-user-fields) for configuration details.\n","aliases":["/settings/property-types-reference/"],"toc":[{"level":2,"id":"quick-reference","text":"Quick Reference"},{"level":2,"id":"property-details","text":"Property Details"},{"level":3,"id":"text-properties","text":"Text Properties"},{"level":3,"id":"date-properties","text":"Date Properties"},{"level":3,"id":"list-properties","text":"List Properties"},{"level":3,"id":"numeric-properties","text":"Numeric Properties"},{"level":3,"id":"recurrence-properties","text":"Recurrence Properties"},{"level":3,"id":"materialized-occurrence-properties","text":"Materialized Occurrence Properties"},{"level":3,"id":"complex-properties","text":"Complex Properties"},{"level":2,"id":"complete-example","text":"Complete Example"},{"level":2,"id":"field-mapping","text":"Field Mapping"},{"level":2,"id":"custom-user-fields","text":"Custom User Fields"}],"html":"

This reference documents the expected data types for each frontmatter property that TaskNotes uses.

\n

Quick Reference#

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
PropertyTypeExample
titletext"My Task"
statustext"open", "in-progress", "done"
prioritytext"low", "normal", "high"
duetext (date)"2025-01-15"
scheduledtext (date)"2025-01-10"
completedDatetext (date)"2025-01-20"
dateCreatedtext (datetime)"2025-01-01T08:00:00Z"
dateModifiedtext (datetime)"2025-01-15T10:30:00Z"
tagslist["work", "urgent"]
contextslist["office", "home"]
projectslist["[[Project A]]"]
timeEstimatenumber120 (minutes)
recurrencetext"FREQ=WEEKLY;BYDAY=MO"
recurrence_anchortext"scheduled" or "completion"
timeEntrieslist (objects)See Time Entries
blockedBylist (objects)See Dependencies
reminderslist (objects)See Reminders
complete_instanceslist["2025-01-08", "2025-01-15"]
skipped_instanceslist["2025-01-22"]
recurrence_parenttext (link/path)"[[Tasks/Weekly review]]"
occurrence_datetext (date)"2025-01-15"
occurrence_materializationtext"manual" or "on_completion"
occurrence_next_triggertext"completion" or "completion_or_skip"
occurrence_templatetext (link/path)"[[Templates/Occurrence]]"
occurrence_past_horizontext (duration)"P7D"
occurrence_future_horizontext (duration)"P14D"
icsEventIdlist["event-abc123"]
\n

Use this table for fast validation when a field is not behaving as expected in views or API calls. Most parsing issues come from shape mismatches (for example scalar vs list) rather than missing values.

\n
\n

Property Details#

\n

The sections below describe storage formats, but there is flexibility in authoring style. TaskNotes normalizes many equivalent YAML representations as long as the resulting data type is correct.

\n

Text Properties#

\n

title#

\n
    \n
  • Type: text (string)
  • \n
  • Description: The task's title or name
  • \n
  • Example: title: "Complete project documentation"
  • \n
\n

status#

\n
    \n
  • Type: text (string)
  • \n
  • Description: The task's current status. Must match one of the status values configured in your settings.
  • \n
  • Default values: "open", "in-progress", "done"
  • \n
  • Example: status: "in-progress"
  • \n
  • Note: Also supports boolean values (true/false) for Obsidian checkbox compatibility. See Boolean Status Values.
  • \n
\n

priority#

\n
    \n
  • Type: text (string)
  • \n
  • Description: The task's priority level. Must match one of the priority values configured in your settings.
  • \n
  • Default values: "low", "normal", "high"
  • \n
  • Example: priority: "high"
  • \n
\n
\n

Date Properties#

\n

All date properties are stored as text strings in your frontmatter. TaskNotes expects specific formats:\nWhen in doubt, prefer ISO-style values. They sort correctly as text, travel well through APIs, and are easiest to parse consistently.

\n

due#

\n
    \n
  • Type: text (date string)

    \n
  • \n
  • Format: YYYY-MM-DD or ISO 8601 timestamp

    \n
  • \n
  • Description: The task's due date

    \n
  • \n
  • Examples:

    \n
    due: "2025-01-15"\ndue: "2025-01-15T17:00:00"\n
  • \n
\n

scheduled#

\n
    \n
  • Type: text (date string)

    \n
  • \n
  • Format: YYYY-MM-DD or ISO 8601 timestamp

    \n
  • \n
  • Description: When the task is scheduled to be worked on

    \n
  • \n
  • Examples:

    \n
    scheduled: "2025-01-10"\nscheduled: "2025-01-10T09:00:00"\n
  • \n
\n

completedDate#

\n
    \n
  • Type: text (date string)
  • \n
  • Format: YYYY-MM-DD
  • \n
  • Description: The date when the task was completed
  • \n
  • Example: completedDate: "2025-01-20"
  • \n
\n

dateCreated#

\n
    \n
  • Type: text (datetime string)
  • \n
  • Format: ISO 8601 timestamp
  • \n
  • Description: When the task was created
  • \n
  • Example: dateCreated: "2025-01-01T08:00:00Z"
  • \n
\n

dateModified#

\n
    \n
  • Type: text (datetime string)
  • \n
  • Format: ISO 8601 timestamp
  • \n
  • Description: When the task was last modified
  • \n
  • Example: dateModified: "2025-01-15T10:30:00Z"
  • \n
\n
\n

List Properties#

\n

List properties must be arrays, even when containing a single value.\nSingle-item arrays may look verbose, but they prevent edge cases when filters and formulas assume list semantics.

\n

tags#

\n
    \n
  • Type: list (array of strings)

    \n
  • \n
  • Description: Tags associated with the task

    \n
  • \n
  • Examples:

    \n
    tags: ["work", "documentation"]\ntags:\n  - work\n  - documentation\n
  • \n
\n

contexts#

\n
    \n
  • Type: list (array of strings)

    \n
  • \n
  • Description: Context labels for the task

    \n
  • \n
  • Examples:

    \n
    contexts: ["office", "computer"]\ncontexts:\n  - "office"\n  - "computer"\n
  • \n
\n

projects#

\n
    \n
  • Type: list (array of strings)

    \n
  • \n
  • Description: Project references (typically wiki-links)

    \n
  • \n
  • Examples:

    \n
    projects: ["[[Website Redesign]]", "[[Q1 Planning]]"]\nprojects:\n  - "[[Website Redesign]]"\n  - "[[Q1 Planning]]"\n
  • \n
\n
\n

Numeric Properties#

\n

timeEstimate#

\n
    \n
  • Type: number
  • \n
  • Unit: minutes
  • \n
  • Description: Estimated time to complete the task
  • \n
  • Example: timeEstimate: 120 (2 hours)
  • \n
\n
\n

Recurrence Properties#

\n

recurrence#

\n
    \n
  • Type: text (string)

    \n
  • \n
  • Format: RFC 5545 RRULE format

    \n
  • \n
  • Description: Defines how the task repeats

    \n
  • \n
  • Examples:

    \n
    recurrence: "FREQ=DAILY"\nrecurrence: "FREQ=WEEKLY;BYDAY=MO,WE,FR"\nrecurrence: "FREQ=MONTHLY;BYMONTHDAY=1"\n
  • \n
\n

recurrence_anchor#

\n
    \n
  • Type: text (string)
  • \n
  • Valid values: "scheduled" or "completion"
  • \n
  • Description: Determines whether the next occurrence is calculated from the scheduled date or when the task was completed
  • \n
  • Example: recurrence_anchor: "scheduled"
  • \n
\n

complete_instances#

\n
    \n
  • Type: list (array of date strings)

    \n
  • \n
  • Format: YYYY-MM-DD

    \n
  • \n
  • Description: Dates when recurring task instances were completed

    \n
  • \n
  • Example:

    \n
    complete_instances:\n  - "2025-01-08"\n  - "2025-01-15"\n
  • \n
\n

skipped_instances#

\n
    \n
  • Type: list (array of date strings)

    \n
  • \n
  • Format: YYYY-MM-DD

    \n
  • \n
  • Description: Dates when recurring task instances were skipped

    \n
  • \n
  • Example:

    \n
    skipped_instances:\n  - "2025-01-22"\n
  • \n
\n

Materialized Occurrence Properties#

\n

Materialized occurrence notes are ordinary task notes created for one date in a recurring series. The parent recurring task owns the recurrence rule; the occurrence note owns date-specific state such as status, completed date, body content, time entries, reminders, and comments.

\n

When an occurrence note is created, TaskNotes inherits parent planning metadata such as scheduled time, due offset, priority, tags, contexts, projects, reminders, dependencies, details, custom properties, and time estimate. It does not copy parent recurrence/history/runtime fields such as recurrence, complete_instances, skipped_instances, completedDate, provider event IDs, or timeEntries.

\n

recurrence_parent#

\n
    \n
  • Type: text (link or path string)
  • \n
  • Description: Parent recurring task for a materialized occurrence note
  • \n
  • Example: recurrence_parent: "[[Tasks/Weekly review]]"
  • \n
\n

occurrence_date#

\n
    \n
  • Type: text (date string)
  • \n
  • Format: YYYY-MM-DD
  • \n
  • Description: Target recurrence date represented by a materialized occurrence note
  • \n
  • Example: occurrence_date: "2025-01-15"
  • \n
\n

occurrence_materialization#

\n
    \n
  • Type: text (string)
  • \n
  • Valid values: "manual", "on_completion", "rolling"
  • \n
  • Description: Parent task policy for creating occurrence notes. The plugin currently supports manual creation and creating the next note after completion; rolling windows are defined by the spec but are not automated yet.
  • \n
  • Example: occurrence_materialization: "on_completion"
  • \n
\n

occurrence_next_trigger#

\n
    \n
  • Type: text (string)
  • \n
  • Valid values: "completion" or "completion_or_skip"
  • \n
  • Description: Parent task policy for whether skip actions should also create the next occurrence note when occurrence materialization is set to on_completion
  • \n
  • Example: occurrence_next_trigger: "completion_or_skip"
  • \n
\n

occurrence_template#

\n
    \n
  • Type: text (link or path string)
  • \n
  • Description: Optional template reference used when creating materialized occurrence notes. This parent-level template takes priority over the global occurrence note template fallback in Features settings.
  • \n
  • Example: occurrence_template: "[[Templates/Weekly occurrence]]"
  • \n
\n

occurrence_past_horizon and occurrence_future_horizon#

\n
    \n
  • Type: text (ISO 8601 duration string)

    \n
  • \n
  • Description: Optional rolling-window bounds for occurrence materialization. These fields are part of the TaskNotes spec; automated rolling materialization is not currently enabled in the plugin.

    \n
  • \n
  • Examples:

    \n
    occurrence_past_horizon: "P7D"\noccurrence_future_horizon: "P14D"\n
  • \n
\n
\n

Complex Properties#

\n

These properties contain structured data with multiple fields.\nFor these fields, copy known-good examples before editing manually. Minor schema deviations can break downstream features such as reminders, recurrence, or dependency checks.

\n

Time Entries#

\n
    \n
  • Type: list (array of objects)

    \n
  • \n
  • Description: Time tracking entries for the task

    \n
  • \n
  • Structure:

    \n
    timeEntries:\n  - startTime: "2025-01-15T10:30:00Z"    # Required: ISO 8601 timestamp\n    endTime: "2025-01-15T11:15:00Z"      # Optional: ISO 8601 timestamp\n    description: "Initial work"          # Optional: text\n
  • \n
\n

Dependencies (blockedBy)#

\n
    \n
  • Type: list (array of objects)

    \n
  • \n
  • Description: Tasks that must be completed before this task can start

    \n
  • \n
  • Structure:

    \n
    blockedBy:\n  - uid: "path/to/blocking-task.md"    # Required: path to blocking task\n    reltype: "FINISHTOSTART"           # Required: relationship type\n    gap: "P1D"                         # Optional: ISO 8601 duration offset\n
  • \n
  • Relationship types accepted in stored data: FINISHTOSTART, STARTTOSTART, FINISHTOFINISH, STARTTOFINISH

    \n
  • \n
  • Current behavior: Dependencies created from the UI use FINISHTOSTART. Blocking evaluation is based on dependency presence/completion state and does not currently apply distinct scheduling semantics for different reltype values or gap.

    \n
  • \n
\n

Reminders#

\n
    \n
  • Type: list (array of objects)

    \n
  • \n
  • Description: Reminder notifications for the task

    \n
  • \n
  • Structure for relative reminders:

    \n
    reminders:\n  - id: "rem_1"                        # Required: unique identifier\n    type: "relative"                   # Required: "relative" or "absolute"\n    relatedTo: "due"                   # Required for relative: "due" or "scheduled"\n    offset: "-PT1H"                    # Required for relative: ISO 8601 duration\n    description: "1 hour before due"   # Optional: description\n
  • \n
  • Structure for absolute reminders:

    \n
    reminders:\n  - id: "rem_2"\n    type: "absolute"\n    absoluteTime: "2025-01-15T09:00:00Z"  # Required for absolute: ISO 8601 timestamp\n    description: "Morning reminder"\n
  • \n
\n

icsEventId#

\n
    \n
  • Type: list (array of strings)

    \n
  • \n
  • Description: ICS calendar event IDs linked to this task

    \n
  • \n
  • Example:

    \n
    icsEventId:\n  - "event-abc123"\n  - "event-def456"\n
  • \n
\n
\n

Complete Example#

\n

Here's a complete task with all property types:

\n
---\ntitle: "Complete quarterly report"\nstatus: "in-progress"\npriority: "high"\ndue: "2025-01-31"\nscheduled: "2025-01-25"\ntags:\n  - work\n  - reports\ncontexts:\n  - office\nprojects:\n  - "[[Q1 Planning]]"\ntimeEstimate: 240\ndateCreated: "2025-01-01T08:00:00Z"\ndateModified: "2025-01-20T14:30:00Z"\ntimeEntries:\n  - startTime: "2025-01-20T10:00:00Z"\n    endTime: "2025-01-20T11:30:00Z"\nblockedBy:\n  - uid: "tasks/gather-data.md"\n    reltype: "FINISHTOSTART"\nreminders:\n  - id: "rem_1"\n    type: "relative"\n    relatedTo: "due"\n    offset: "-P1D"\n    description: "Due tomorrow"\n---\n

\n

Field Mapping#

\n

All property names can be customized via Settings → Task Properties → Field Mapping. If you change a field mapping, TaskNotes will read and write using your custom property name.

\n

Custom property names are frontmatter keys, so names with spaces or punctuation are valid in task files. When you write your own Bases filters or formulas for those keys, use bracket notation such as note["TN-status"] or note["Task Type"] instead of dot notation. Dot notation only works reliably for simple identifier-style names.

\n

For example, if you map due to dueDate, TaskNotes will expect:

\n
dueDate: "2025-01-15"\n

See Task Properties settings for configuration details.

\n
\n

Custom User Fields#

\n

You can define additional properties with these types:

\n
    \n
  • text - Single text value
  • \n
  • number - Numeric value
  • \n
  • date - Date string (YYYY-MM-DD)
  • \n
  • boolean - true/false
  • \n
  • list - Array of values
  • \n
\n

See Custom User Fields for configuration details.

\n","text":"This reference documents the expected data types for each frontmatter property that TaskNotes uses. Quick Reference# Property Type Example title text \"My Task\" status text \"open\", \"in-progress\", \"done\" priority text \"low\", \"normal\", \"high\" due text (date) \"2025-01-15\" scheduled text (date) \"2025-01-10\" completedDate text (date) \"2025-01-20\" dateCreated text (datetime) \"2025-01-01T08:00:00Z\" dateModified text (datetime) \"2025-01-15T10:30:00Z\" tags list [\"work\", \"urgent\"] contexts list [\"office\", \"home\"] projects list [\"[[Project A]]\"] timeEstimate number 120 (minutes) recurrence text \"FREQ=WEEKLY;BYDAY=MO\" recurrence_anchor text \"scheduled\" or \"completion\" timeEntries list (objects) See Time Entries blockedBy list (objects) See Dependencies reminders list (objects) See Reminders complete_instances list [\"2025-01-08\", \"2025-01-15\"] skipped_instances list [\"2025-01-22\"] recurrence_parent text (link/path) \"[[Tasks/Weekly review]]\" occurrence_date text (date) \"2025-01-15\" occurrence_materialization text \"manual\" or \"on_completion\" occurrence_next_trigger text \"completion\" or \"completion_or_skip\" occurrence_template text (link/path) \"[[Templates/Occurrence]]\" occurrence_past_horizon text (duration) \"P7D\" occurrence_future_horizon text (duration) \"P14D\" icsEventId list [\"event-abc123\"] Use this table for fast validation when a field is not behaving as expected in views or API calls. Most parsing issues come from shape mismatches (for example scalar vs list) rather than missing values. Property Details# The sections below describe storage formats, but there is flexibility in authoring style. TaskNotes normalizes many equivalent YAML representations as long as the resulting data type is correct. Text Properties# title# Type: text (string) Description: The task's title or name Example: title: \"Complete project documentation\" status# Type: text (string) Description: The task's current status. Must match one of the status values configured in your settings. Default values: \"open\", \"in-progress\", \"done\" Example: status: \"in-progress\" Note: Also supports boolean values (true/false) for Obsidian checkbox compatibility. See Boolean Status Values. priority# Type: text (string) Description: The task's priority level. Must match one of the priority values configured in your settings. Default values: \"low\", \"normal\", \"high\" Example: priority: \"high\" Date Properties# All date properties are stored as text strings in your frontmatter. TaskNotes expects specific formats: When in doubt, prefer ISO-style values. They sort correctly as text, travel well through APIs, and are easiest to parse consistently. due# Type: text (date string) Format: YYYY-MM-DD or ISO 8601 timestamp Description: The task's due date Examples: due: \"2025-01-15\" due: \"2025-01-15T17:00:00\" scheduled# Type: text (date string) Format: YYYY-MM-DD or ISO 8601 timestamp Description: When the task is scheduled to be worked on Examples: scheduled: \"2025-01-10\" scheduled: \"2025-01-10T09:00:00\" completedDate# Type: text (date string) Format: YYYY-MM-DD Description: The date when the task was completed Example: completedDate: \"2025-01-20\" dateCreated# Type: text (datetime string) Format: ISO 8601 timestamp Description: When the task was created Example: dateCreated: \"2025-01-01T08:00:00Z\" dateModified# Type: text (datetime string) Format: ISO 8601 timestamp Description: When the task was last modified Example: dateModified: \"2025-01-15T10:30:00Z\" List Properties# List properties must be arrays, even when containing a single value. Single-item arrays may look verbose, but they prevent edge cases when filters and formulas assume list semantics. tags# Type: list (array of strings) Description: Tags associated with the task Examples: tags: [\"work\", \"documentation\"] tags: - work - documentation contexts# Type: list (array of strings) Description: Context labels for the task Examples: contexts: [\"office\", \"computer\"] contexts: - \"office\" - \"computer\" projects# Type: list (array of strings) Description: Project references (typically wiki-links) Examples: projects: [\"[[Website Redesign]]\", \"[[Q1 Planning]]\"] projects: - \"[[Website Redesign]]\" - \"[[Q1 Planning]]\" Numeric Properties# timeEstimate# Type: number Unit: minutes Description: Estimated time to complete the task Example: timeEstimate: 120 (2 hours) Recurrence Properties# recurrence# Type: text (string) Format: RFC 5545 RRULE format Description: Defines how the task repeats Examples: recurrence: \"FREQ=DAILY\" recurrence: \"FREQ=WEEKLY;BYDAY=MO,WE,FR\" recurrence: \"FREQ=MONTHLY;BYMONTHDAY=1\" recurrence_anchor# Type: text (string) Valid values: \"scheduled\" or \"completion\" Description: Determines whether the next occurrence is calculated from the scheduled date or when the task was completed Example: recurrence_anchor: \"scheduled\" complete_instances# Type: list (array of date strings) Format: YYYY-MM-DD Description: Dates when recurring task instances were completed Example: complete_instances: - \"2025-01-08\" - \"2025-01-15\" skipped_instances# Type: list (array of date strings) Format: YYYY-MM-DD Description: Dates when recurring task instances were skipped Example: skipped_instances: - \"2025-01-22\" Materialized Occurrence Properties# Materialized occurrence notes are ordinary task notes created for one date in a recurring series. The parent recurring task owns the recurrence rule; the occurrence note owns date-specific state such as status, completed date, body content, time entries, reminders, and comments. When an occurrence note is created, TaskNotes inherits parent planning metadata such as scheduled time, due offset, priority, tags, contexts, projects, reminders, dependencies, details, custom properties, and time estimate. It does not copy parent recurrence/history/runtime fields such as recurrence, complete_instances, skipped_instances, completedDate, provider event IDs, or timeEntries. recurrence_parent# Type: text (link or path string) Description: Parent recurring task for a materialized occurrence note Example: recurrence_parent: \"[[Tasks/Weekly review]]\" occurrence_date# Type: text (date string) Format: YYYY-MM-DD Description: Target recurrence date represented by a materialized occurrence note Example: occurrence_date: \"2025-01-15\" occurrence_materialization# Type: text (string) Valid values: \"manual\", \"on_completion\", \"rolling\" Description: Parent task policy for creating occurrence notes. The plugin currently supports manual creation and creating the next note after completion; rolling windows are defined by the spec but are not automated yet. Example: occurrence_materialization: \"on_completion\" occurrence_next_trigger# Type: text (string) Valid values: \"completion\" or \"completion_or_skip\" Description: Parent task policy for whether skip actions should also create the next occurrence note when occurrence materialization is set to on_completion Example: occurrence_next_trigger: \"completion_or_skip\" occurrence_template# Type: text (link or path string) Description: Optional template reference used when creating materialized occurrence notes. This parent-level template takes priority over the global occurrence note template fallback in Features settings. Example: occurrence_template: \"[[Templates/Weekly occurrence]]\" occurrence_past_horizon and occurrence_future_horizon# Type: text (ISO 8601 duration string) Description: Optional rolling-window bounds for occurrence materialization. These fields are part of the TaskNotes spec; automated rolling materialization is not currently enabled in the plugin. Examples: occurrence_past_horizon: \"P7D\" occurrence_future_horizon: \"P14D\" Complex Properties# These properties contain structured data with multiple fields. For these fields, copy known-good examples before editing manually. Minor schema deviations can break downstream features such as reminders, recurrence, or dependency checks. Time Entries# Type: list (array of objects) Description: Time tracking entries for the task Structure: timeEntries: - startTime: \"2025-01-15T10:30:00Z\" # Required: ISO 8601 timestamp endTime: \"2025-01-15T11:15:00Z\" # Optional: ISO 8601 timestamp description: \"Initial work\" # Optional: text Dependencies (blockedBy)# Type: list (array of objects) Description: Tasks that must be completed before this task can start Structure: blockedBy: - uid: \"path/to/blocking-task.md\" # Required: path to blocking task reltype: \"FINISHTOSTART\" # Required: relationship type gap: \"P1D\" # Optional: ISO 8601 duration offset Relationship types accepted in stored data: FINISHTOSTART, STARTTOSTART, FINISHTOFINISH, STARTTOFINISH Current behavior: Dependencies created from the UI use FINISHTOSTART. Blocking evaluation is based on dependency presence/completion state and does not currently apply distinct scheduling semantics for different reltype values or gap. Reminders# Type: list (array of objects) Description: Reminder notifications for the task Structure for relative reminders: reminders: - id: \"rem_1\" # Required: unique identifier type: \"relative\" # Required: \"relative\" or \"absolute\" relatedTo: \"due\" # Required for relative: \"due\" or \"scheduled\" offset: \"-PT1H\" # Required for relative: ISO 8601 duration description: \"1 hour before due\" # Optional: description Structure for absolute reminders: reminders: - id: \"rem_2\" type: \"absolute\" absoluteTime: \"2025-01-15T09:00:00Z\" # Required for absolute: ISO 8601 timestamp description: \"Morning reminder\" icsEventId# Type: list (array of strings) Description: ICS calendar event IDs linked to this task Example: icsEventId: - \"event-abc123\" - \"event-def456\" Complete Example# Here's a complete task with all property types: --- title: \"Complete quarterly report\" status: \"in-progress\" priority: \"high\" due: \"2025-01-31\" scheduled: \"2025-01-25\" tags: - work - reports contexts: - office projects: - \"[[Q1 Planning]]\" timeEstimate: 240 dateCreated: \"2025-01-01T08:00:00Z\" dateModified: \"2025-01-20T14:30:00Z\" timeEntries: - startTime: \"2025-01-20T10:00:00Z\" endTime: \"2025-01-20T11:30:00Z\" blockedBy: - uid: \"tasks/gather-data.md\" reltype: \"FINISHTOSTART\" reminders: - id: \"rem_1\" type: \"relative\" relatedTo: \"due\" offset: \"-P1D\" description: \"Due tomorrow\" --- Field Mapping# All property names can be customized via Settings → Task Properties → Field Mapping. If you change a field mapping, TaskNotes will read and write using your custom property name. Custom property names are frontmatter keys, so names with spaces or punctuation are valid in task files. When you write your own Bases filters or formulas for those keys, use bracket notation such as note[\"TN-status\"] or note[\"Task Type\"] instead of dot notation. Dot notation only works reliably for simple identifier-style names. For example, if you map due to dueDate, TaskNotes will expect: dueDate: \"2025-01-15\" See Task Properties settings for configuration details. Custom User Fields# You can define additional properties with these types: text - Single text value number - Numeric value date - Date string (YYYY-MM-DD) boolean - true/false list - Array of values See Custom User Fields for configuration details."},{"route":"/obsidian/settings/task-properties/","title":"Task Properties Settings","description":"This tab configures all task properties. Each property is displayed as a card containing its configuration options.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/settings/task-properties.md","namespace":"obsidian","relativePath":"settings/task-properties.md","raw":"# Task Properties Settings\n\nThis tab configures all task properties. Each property is displayed as a card containing its configuration options.\n\n\n![Task Properties Settings](../assets/settings-task-properties.png)\n\n!!! tip \"Looking for property type documentation?\"\n See the [Property Types Reference](property-types-reference.md) for detailed documentation on the expected data types (text, list, date, etc.) for each frontmatter property.\n\n## Property Card Structure\n\nEach property card contains:\n\n- **Property key**: The frontmatter field name used to store this property\n- **Default**: The default value applied to new tasks (where applicable)\n- **NLP trigger**: Toggle and character configuration for natural language parsing (where applicable)\n- **Property-specific settings**: Additional configuration options specific to that property\nThis tab defines the task schema used by creation flows, NLP parsing, views, and API payloads.\n\nProperty keys are YAML/frontmatter keys. TaskNotes can read and write keys that contain spaces or punctuation, but hand-written Bases filters and formulas must reference those keys with bracket syntax, for example `note[\"TN-status\"]`, rather than dot syntax such as `note.TN-status`.\n\n## Core Properties\n\n### Title\n\nThe task title property. Configuration options:\n\n- **Property key**: Frontmatter field name (default: `title`)\n- **Store title in filename**: When enabled, the task title is stored in the filename instead of frontmatter. The filename updates when the title changes.\n- **Filename format**: When \"Store title in filename\" is disabled, choose how filenames are generated:\n - Title-based\n - Zettelkasten-style\n - Timestamp-based\n - UUID v4\n - Custom template\n- **Custom template**: Define a custom filename pattern using variables (shown when \"custom\" format is selected)\n\n### Status\n\nTask completion state. Configuration options:\n\n- **Property key**: Frontmatter field name (default: `status`)\n- **Default**: Default status for new tasks\n- **NLP trigger**: Character that triggers status parsing (default: `*`)\n- **Status Values**: Expandable section containing individual status cards\n\nEach status value has:\n\n- **Value**: Internal identifier stored in frontmatter (e.g., \"in-progress\")\n- **Label**: Display name shown in the interface (e.g., \"In Progress\")\n- **Color**: Visual indicator color\n- **Icon**: Optional icon identifier\n- **Completed**: Whether this status represents a finished task\n- **Skip when cycling**: Exclude this status from the click-to-cycle order on task cards while keeping it available in menus, suggestions, and direct edits\n- **Next status**: Optional override for the status used when cycling forward from this status; leave it set to the status order to use the normal sequence\n- **Auto-archive**: Automatically archive tasks after a delay (1-1440 minutes)\n\nStatus cards support drag-and-drop reordering.\n\nUse the **Value** field as the stable stored identifier and the **Label** field for display text with spaces or title casing. TaskNotes status menus and cycling use the configured order, and TaskNotes Kanban views can preserve dragged column order. Native Bases grouping/sorting may still order status values alphabetically by their stored **Value**, so use prefixes such as `1-open`, `2-doing`, `3-done` if you need predictable native Bases order.\n\n#### Boolean Status Values\n\nTaskNotes supports using boolean values (`true` and `false`) as status values, which integrates with Obsidian's native checkbox property format:\n\n- When you set a task's status to `\"true\"` or `\"false\"` (case-insensitive), TaskNotes automatically converts it to a boolean in frontmatter\n- When reading tasks with boolean status values from frontmatter, they are converted back to the strings `\"true\"` or `\"false\"`\n- This allows you to use Obsidian's native checkbox property toggles in the Properties panel while maintaining compatibility with TaskNotes\n\n**Example:**\n```yaml\n---\nstatus: true # Boolean checkbox in Obsidian\n---\n```\n\n### Priority\n\nTask priority level. Configuration options:\n\n- **Property key**: Frontmatter field name (default: `priority`)\n- **Default**: Default priority for new tasks (can be set to \"No default\")\n- **NLP trigger**: Character that triggers priority parsing (default: `!`, disabled by default)\n- **Priority Values**: Expandable section containing individual priority cards\n\nEach priority value has:\n\n- **Value**: Internal identifier stored in frontmatter (e.g., \"high\")\n- **Label**: Display name shown in the interface (e.g., \"High Priority\")\n- **Color**: Visual indicator color\n\nPriority cards support drag-and-drop reordering.\nStatus and priority values are stored in frontmatter; renaming them later may require migration of existing task files.\n\n> **Note for Bases plugin users:** Obsidian's Bases plugin sorts priorities alphabetically by their **Value**. To control sort order, name values to sort alphabetically in the desired order:\n> - Example: `1-urgent`, `2-high`, `3-medium`, `4-normal`, `5-low`\n> - Or: `a-urgent`, `b-high`, `c-medium`, `d-normal`, `e-low`\n\n## Date Properties\n\n### Due Date\n\nWhen the task must be completed. Configuration options:\n\n- **Property key**: Frontmatter field name (default: `due`)\n- **Default**: Default due date for new tasks (None, Today, Tomorrow, Next Week)\n\n### Scheduled Date\n\nWhen to work on the task. Configuration options:\n\n- **Property key**: Frontmatter field name (default: `scheduled`)\n- **Default**: Default scheduled date for new tasks (None, Today, Tomorrow, Next Week)\n\nWhen you use **Convert current note to task**, this default is also applied if the source note does not already have `scheduled` frontmatter. Choose **None** to keep converted notes unscheduled by default.\n\n`due` tracks commitment deadlines, while `scheduled` tracks intended execution time.\n\n## Organization Properties\n\n### Contexts\n\nWhere or how the task can be done. Configuration options:\n\n- **Property key**: Frontmatter field name (default: `contexts`)\n- **Default**: Comma-separated list of default contexts (e.g., @home, @work)\n- **NLP trigger**: Character that triggers context parsing (default: `@`)\n\n### Projects\n\nProjects the task belongs to. Configuration options:\n\n- **Property key**: Frontmatter field name (default: `projects`)\n- **Default projects**: Select project notes to automatically link to new tasks\n- **Use active note for new tasks**: Automatically link the active note as a project when opening task creation from the command palette or ribbon\n- **Use parent note for inline/instant conversion**: Automatically link the source note as a project when using inline task creation or instant task conversion\n- **NLP trigger**: Character that triggers project parsing (default: `+`)\n- **Autosuggest Filters**: Expandable section to filter which notes appear in project suggestions\n- **Customize Display**: Expandable section to configure how project suggestions appear\n\n#### Autosuggest Filters\n\nControl which notes appear when selecting projects:\n\n- **Required tags**: Comma-separated list of tags (shows notes with ANY of these tags)\n- **Include folders**: Comma-separated list of folder paths (shows notes in ANY of these folders)\n- **Required property key**: Frontmatter property that must exist\n- **Required property value**: Expected value for the property (optional)\nThese filters reduce suggestion noise in large vaults.\n\nA \"Filters On\" badge appears when any filters are configured.\n\n#### Customize Display\n\nConfigure project suggestion appearance:\n\n- **Enable fuzzy matching**: Allow typos and partial matches in project search\n- **Row 1, 2, 3**: Configure up to 3 lines of information for each project suggestion\n\n### Tags\n\nObsidian tags for categorization. Configuration options:\n\n- **Default**: Comma-separated list of default tags (without #)\n- **NLP trigger**: Character that triggers tag parsing (default: `#`)\n\nNote: Tags use native Obsidian tags and do not have a separate property key setting.\n\n## Task Details\n\n### Time Estimate\n\nEstimated time to complete the task. Configuration options:\n\n- **Property key**: Frontmatter field name (default: `timeEstimate`)\n- **Default**: Default time estimate in minutes (0 = no default)\n\n### Recurrence\n\nPattern for repeating tasks. Configuration options:\n\n- **Property key**: Frontmatter field name (default: `recurrence`)\n- **Default**: Default recurrence pattern (None, Daily, Weekly, Monthly, Yearly)\n\nRecurring tasks also use the **Recurrence anchor** metadata property to decide whether the series advances from the scheduled date or the completion date. Materialized occurrence note controls live on each recurring task's context menu under **Recurrence → Occurrence notes** rather than as a global default.\n\n### Reminders\n\nNotifications before task deadlines. Configuration options:\n\n- **Property key**: Frontmatter field name (default: `reminders`)\n- **Default Reminders**: Expandable section containing default reminder cards\n\nEach default reminder can be:\n\n**Relative reminders** (triggered relative to due or scheduled date):\n\n- Anchor date (due date or scheduled date)\n- Offset amount and unit (minutes, hours, days)\n- Direction (before or after)\n- Description\n\n**Absolute reminders** (triggered at specific times):\n\n- Date\n- Time\n- Description\n\n## Metadata Properties\n\nThese properties are system-managed and typically only require property key configuration:\n\n- **Date Created**: When the task was created\n- **Date Modified**: When the task was last modified\n- **Completed Date**: When the task was completed\n- **Archive Tag**: Tag used to mark archived tasks\n- **Time Entries**: Time tracking entries for the task\n- **Complete Instances**: Completion history for recurring tasks\n- **Skipped Instances**: Skip history for recurring tasks\n- **Recurrence Anchor**: Whether recurring progression is based on scheduled date or completion date\n- **Blocked By**: Tasks that must be completed first\n\nMaterialized occurrence notes also use system-managed frontmatter fields such as `recurrence_parent`, `occurrence_date`, `occurrence_materialization`, `occurrence_next_trigger`, and optional occurrence template/horizon fields. Occurrence notes inherit parent planning metadata when they are created, but keep their own status, completion date, and time entries. These fields are documented in the [Property Types Reference](property-types-reference.md#materialized-occurrence-properties) and are normally changed through recurrence and occurrence-note controls instead of by hand.\n\n## Feature Properties\n\nThese properties are used by specific TaskNotes features and are not stored in task frontmatter:\n\n- **Pomodoros**: Property key for Pomodoro session counts. When Pomodoro data storage is set to \"Daily notes\", this property is written to daily notes rather than task files.\n- **ICS Event ID**: Property key for calendar event identifiers. Added to notes created from ICS calendar events to link them back to the source event.\n- **ICS Event Tag**: Property key for calendar event tags. Added to notes created from ICS calendar events for identification.\n\n## Custom User Fields\n\nDefine custom frontmatter properties to appear as filter options across views. Configuration options for each field:\n\n- **Display Name**: How the field appears in the UI\n- **Property Key**: The frontmatter property name\n- **Type**: Data type (text, number, boolean, date, or list)\n- **Default Value**: Pre-fill value for new tasks (format varies by type)\n- **NLP trigger**: Toggle and character for natural language parsing\n- **Autosuggest Filters**: Filter which files appear when using `[[` wikilink autocomplete\nCustom fields are most maintainable when they map to repeated workflow decisions (for example `effort`, `owner`, or `client`).\n\n### Link Values\n\nUse a **Text** custom field for a single link and a **List** custom field for multiple links. Task cards render `[[wikilinks]]`, `[label](https://example.com)`, ``, and bare `https://example.com` values as clickable links.\n\nAutosuggest filters work with text and list fields when entering `[[` wikilinks, so a field such as `Related Note` can suggest only files from a chosen folder or tag.\n\n### Default Values\n\nEach field type has a different input format for default values:\n\n- **Text**: Enter the default text value\n- **Number**: Enter the default number\n- **Boolean**: Toggle switch to set default checked/unchecked state\n- **Date**: Select from presets (None, Today, Tomorrow, Next Week)\n- **List**: Enter comma-separated default values\n\nDefault values are applied when creating tasks via:\n\n- Task creation modal\n- Instant task conversion\n- \"Create or open task\" command\n- HTTP API (when using task creation defaults)\n\n### Autosuggestion Filters\n\nEach custom field can configure filters to control which files appear in wikilink suggestions:\n\n- **Required tags**: Comma-separated list of tags (shows files with ANY of these tags)\n- **Include folders**: Comma-separated list of folder paths (shows files in ANY of these folders)\n- **Required property key**: Frontmatter property that must exist\n- **Required property value**: Expected value for the property (optional)\n\nA \"Filters On\" badge appears when filters are configured.\n\nSee [User Fields Feature Documentation](../features/user-fields.md#file-suggestion-filtering-advanced) for detailed examples.\n","aliases":["/settings/task-properties/"],"toc":[{"level":2,"id":"property-card-structure","text":"Property Card Structure"},{"level":2,"id":"core-properties","text":"Core Properties"},{"level":3,"id":"title","text":"Title"},{"level":3,"id":"status","text":"Status"},{"level":3,"id":"priority","text":"Priority"},{"level":2,"id":"date-properties","text":"Date Properties"},{"level":3,"id":"due-date","text":"Due Date"},{"level":3,"id":"scheduled-date","text":"Scheduled Date"},{"level":2,"id":"organization-properties","text":"Organization Properties"},{"level":3,"id":"contexts","text":"Contexts"},{"level":3,"id":"projects","text":"Projects"},{"level":3,"id":"tags","text":"Tags"},{"level":2,"id":"task-details","text":"Task Details"},{"level":3,"id":"time-estimate","text":"Time Estimate"},{"level":3,"id":"recurrence","text":"Recurrence"},{"level":3,"id":"reminders","text":"Reminders"},{"level":2,"id":"metadata-properties","text":"Metadata Properties"},{"level":2,"id":"feature-properties","text":"Feature Properties"},{"level":2,"id":"custom-user-fields","text":"Custom User Fields"},{"level":3,"id":"link-values","text":"Link Values"},{"level":3,"id":"default-values","text":"Default Values"},{"level":3,"id":"autosuggestion-filters","text":"Autosuggestion Filters"}],"html":"

This tab configures all task properties. Each property is displayed as a card containing its configuration options.

\n

\"Task

\n\n

Property Card Structure#

\n

Each property card contains:

\n
    \n
  • Property key: The frontmatter field name used to store this property
  • \n
  • Default: The default value applied to new tasks (where applicable)
  • \n
  • NLP trigger: Toggle and character configuration for natural language parsing (where applicable)
  • \n
  • Property-specific settings: Additional configuration options specific to that property\nThis tab defines the task schema used by creation flows, NLP parsing, views, and API payloads.
  • \n
\n

Property keys are YAML/frontmatter keys. TaskNotes can read and write keys that contain spaces or punctuation, but hand-written Bases filters and formulas must reference those keys with bracket syntax, for example note["TN-status"], rather than dot syntax such as note.TN-status.

\n

Core Properties#

\n

Title#

\n

The task title property. Configuration options:

\n
    \n
  • Property key: Frontmatter field name (default: title)
  • \n
  • Store title in filename: When enabled, the task title is stored in the filename instead of frontmatter. The filename updates when the title changes.
  • \n
  • Filename format: When "Store title in filename" is disabled, choose how filenames are generated:
      \n
    • Title-based
    • \n
    • Zettelkasten-style
    • \n
    • Timestamp-based
    • \n
    • UUID v4
    • \n
    • Custom template
    • \n
    \n
  • \n
  • Custom template: Define a custom filename pattern using variables (shown when "custom" format is selected)
  • \n
\n

Status#

\n

Task completion state. Configuration options:

\n
    \n
  • Property key: Frontmatter field name (default: status)
  • \n
  • Default: Default status for new tasks
  • \n
  • NLP trigger: Character that triggers status parsing (default: *)
  • \n
  • Status Values: Expandable section containing individual status cards
  • \n
\n

Each status value has:

\n
    \n
  • Value: Internal identifier stored in frontmatter (e.g., "in-progress")
  • \n
  • Label: Display name shown in the interface (e.g., "In Progress")
  • \n
  • Color: Visual indicator color
  • \n
  • Icon: Optional icon identifier
  • \n
  • Completed: Whether this status represents a finished task
  • \n
  • Skip when cycling: Exclude this status from the click-to-cycle order on task cards while keeping it available in menus, suggestions, and direct edits
  • \n
  • Next status: Optional override for the status used when cycling forward from this status; leave it set to the status order to use the normal sequence
  • \n
  • Auto-archive: Automatically archive tasks after a delay (1-1440 minutes)
  • \n
\n

Status cards support drag-and-drop reordering.

\n

Use the Value field as the stable stored identifier and the Label field for display text with spaces or title casing. TaskNotes status menus and cycling use the configured order, and TaskNotes Kanban views can preserve dragged column order. Native Bases grouping/sorting may still order status values alphabetically by their stored Value, so use prefixes such as 1-open, 2-doing, 3-done if you need predictable native Bases order.

\n

Boolean Status Values#

\n

TaskNotes supports using boolean values (true and false) as status values, which integrates with Obsidian's native checkbox property format:

\n
    \n
  • When you set a task's status to "true" or "false" (case-insensitive), TaskNotes automatically converts it to a boolean in frontmatter
  • \n
  • When reading tasks with boolean status values from frontmatter, they are converted back to the strings "true" or "false"
  • \n
  • This allows you to use Obsidian's native checkbox property toggles in the Properties panel while maintaining compatibility with TaskNotes
  • \n
\n

Example:

\n
---\nstatus: true    # Boolean checkbox in Obsidian\n---\n

Priority#

\n

Task priority level. Configuration options:

\n
    \n
  • Property key: Frontmatter field name (default: priority)
  • \n
  • Default: Default priority for new tasks (can be set to "No default")
  • \n
  • NLP trigger: Character that triggers priority parsing (default: !, disabled by default)
  • \n
  • Priority Values: Expandable section containing individual priority cards
  • \n
\n

Each priority value has:

\n
    \n
  • Value: Internal identifier stored in frontmatter (e.g., "high")
  • \n
  • Label: Display name shown in the interface (e.g., "High Priority")
  • \n
  • Color: Visual indicator color
  • \n
\n

Priority cards support drag-and-drop reordering.\nStatus and priority values are stored in frontmatter; renaming them later may require migration of existing task files.

\n
\n

Note for Bases plugin users: Obsidian's Bases plugin sorts priorities alphabetically by their Value. To control sort order, name values to sort alphabetically in the desired order:

\n
    \n
  • Example: 1-urgent, 2-high, 3-medium, 4-normal, 5-low
  • \n
  • Or: a-urgent, b-high, c-medium, d-normal, e-low
  • \n
\n
\n

Date Properties#

\n

Due Date#

\n

When the task must be completed. Configuration options:

\n
    \n
  • Property key: Frontmatter field name (default: due)
  • \n
  • Default: Default due date for new tasks (None, Today, Tomorrow, Next Week)
  • \n
\n

Scheduled Date#

\n

When to work on the task. Configuration options:

\n
    \n
  • Property key: Frontmatter field name (default: scheduled)
  • \n
  • Default: Default scheduled date for new tasks (None, Today, Tomorrow, Next Week)
  • \n
\n

When you use Convert current note to task, this default is also applied if the source note does not already have scheduled frontmatter. Choose None to keep converted notes unscheduled by default.

\n

due tracks commitment deadlines, while scheduled tracks intended execution time.

\n

Organization Properties#

\n

Contexts#

\n

Where or how the task can be done. Configuration options:

\n
    \n
  • Property key: Frontmatter field name (default: contexts)
  • \n
  • Default: Comma-separated list of default contexts (e.g., @home, @work)
  • \n
  • NLP trigger: Character that triggers context parsing (default: @)
  • \n
\n

Projects#

\n

Projects the task belongs to. Configuration options:

\n
    \n
  • Property key: Frontmatter field name (default: projects)
  • \n
  • Default projects: Select project notes to automatically link to new tasks
  • \n
  • Use active note for new tasks: Automatically link the active note as a project when opening task creation from the command palette or ribbon
  • \n
  • Use parent note for inline/instant conversion: Automatically link the source note as a project when using inline task creation or instant task conversion
  • \n
  • NLP trigger: Character that triggers project parsing (default: +)
  • \n
  • Autosuggest Filters: Expandable section to filter which notes appear in project suggestions
  • \n
  • Customize Display: Expandable section to configure how project suggestions appear
  • \n
\n

Autosuggest Filters#

\n

Control which notes appear when selecting projects:

\n
    \n
  • Required tags: Comma-separated list of tags (shows notes with ANY of these tags)
  • \n
  • Include folders: Comma-separated list of folder paths (shows notes in ANY of these folders)
  • \n
  • Required property key: Frontmatter property that must exist
  • \n
  • Required property value: Expected value for the property (optional)\nThese filters reduce suggestion noise in large vaults.
  • \n
\n

A "Filters On" badge appears when any filters are configured.

\n

Customize Display#

\n

Configure project suggestion appearance:

\n
    \n
  • Enable fuzzy matching: Allow typos and partial matches in project search
  • \n
  • Row 1, 2, 3: Configure up to 3 lines of information for each project suggestion
  • \n
\n

Tags#

\n

Obsidian tags for categorization. Configuration options:

\n
    \n
  • Default: Comma-separated list of default tags (without #)
  • \n
  • NLP trigger: Character that triggers tag parsing (default: #)
  • \n
\n

Note: Tags use native Obsidian tags and do not have a separate property key setting.

\n

Task Details#

\n

Time Estimate#

\n

Estimated time to complete the task. Configuration options:

\n
    \n
  • Property key: Frontmatter field name (default: timeEstimate)
  • \n
  • Default: Default time estimate in minutes (0 = no default)
  • \n
\n

Recurrence#

\n

Pattern for repeating tasks. Configuration options:

\n
    \n
  • Property key: Frontmatter field name (default: recurrence)
  • \n
  • Default: Default recurrence pattern (None, Daily, Weekly, Monthly, Yearly)
  • \n
\n

Recurring tasks also use the Recurrence anchor metadata property to decide whether the series advances from the scheduled date or the completion date. Materialized occurrence note controls live on each recurring task's context menu under Recurrence → Occurrence notes rather than as a global default.

\n

Reminders#

\n

Notifications before task deadlines. Configuration options:

\n
    \n
  • Property key: Frontmatter field name (default: reminders)
  • \n
  • Default Reminders: Expandable section containing default reminder cards
  • \n
\n

Each default reminder can be:

\n

Relative reminders (triggered relative to due or scheduled date):

\n
    \n
  • Anchor date (due date or scheduled date)
  • \n
  • Offset amount and unit (minutes, hours, days)
  • \n
  • Direction (before or after)
  • \n
  • Description
  • \n
\n

Absolute reminders (triggered at specific times):

\n
    \n
  • Date
  • \n
  • Time
  • \n
  • Description
  • \n
\n

Metadata Properties#

\n

These properties are system-managed and typically only require property key configuration:

\n
    \n
  • Date Created: When the task was created
  • \n
  • Date Modified: When the task was last modified
  • \n
  • Completed Date: When the task was completed
  • \n
  • Archive Tag: Tag used to mark archived tasks
  • \n
  • Time Entries: Time tracking entries for the task
  • \n
  • Complete Instances: Completion history for recurring tasks
  • \n
  • Skipped Instances: Skip history for recurring tasks
  • \n
  • Recurrence Anchor: Whether recurring progression is based on scheduled date or completion date
  • \n
  • Blocked By: Tasks that must be completed first
  • \n
\n

Materialized occurrence notes also use system-managed frontmatter fields such as recurrence_parent, occurrence_date, occurrence_materialization, occurrence_next_trigger, and optional occurrence template/horizon fields. Occurrence notes inherit parent planning metadata when they are created, but keep their own status, completion date, and time entries. These fields are documented in the Property Types Reference and are normally changed through recurrence and occurrence-note controls instead of by hand.

\n

Feature Properties#

\n

These properties are used by specific TaskNotes features and are not stored in task frontmatter:

\n
    \n
  • Pomodoros: Property key for Pomodoro session counts. When Pomodoro data storage is set to "Daily notes", this property is written to daily notes rather than task files.
  • \n
  • ICS Event ID: Property key for calendar event identifiers. Added to notes created from ICS calendar events to link them back to the source event.
  • \n
  • ICS Event Tag: Property key for calendar event tags. Added to notes created from ICS calendar events for identification.
  • \n
\n

Custom User Fields#

\n

Define custom frontmatter properties to appear as filter options across views. Configuration options for each field:

\n
    \n
  • Display Name: How the field appears in the UI
  • \n
  • Property Key: The frontmatter property name
  • \n
  • Type: Data type (text, number, boolean, date, or list)
  • \n
  • Default Value: Pre-fill value for new tasks (format varies by type)
  • \n
  • NLP trigger: Toggle and character for natural language parsing
  • \n
  • Autosuggest Filters: Filter which files appear when using [[ wikilink autocomplete\nCustom fields are most maintainable when they map to repeated workflow decisions (for example effort, owner, or client).
  • \n
\n\n

Use a Text custom field for a single link and a List custom field for multiple links. Task cards render [[wikilinks]], [label](https://example.com), <https://example.com>, and bare https://example.com values as clickable links.

\n

Autosuggest filters work with text and list fields when entering [[ wikilinks, so a field such as Related Note can suggest only files from a chosen folder or tag.

\n

Default Values#

\n

Each field type has a different input format for default values:

\n
    \n
  • Text: Enter the default text value
  • \n
  • Number: Enter the default number
  • \n
  • Boolean: Toggle switch to set default checked/unchecked state
  • \n
  • Date: Select from presets (None, Today, Tomorrow, Next Week)
  • \n
  • List: Enter comma-separated default values
  • \n
\n

Default values are applied when creating tasks via:

\n
    \n
  • Task creation modal
  • \n
  • Instant task conversion
  • \n
  • "Create or open task" command
  • \n
  • HTTP API (when using task creation defaults)
  • \n
\n

Autosuggestion Filters#

\n

Each custom field can configure filters to control which files appear in wikilink suggestions:

\n
    \n
  • Required tags: Comma-separated list of tags (shows files with ANY of these tags)
  • \n
  • Include folders: Comma-separated list of folder paths (shows files in ANY of these folders)
  • \n
  • Required property key: Frontmatter property that must exist
  • \n
  • Required property value: Expected value for the property (optional)
  • \n
\n

A "Filters On" badge appears when filters are configured.

\n

See User Fields Feature Documentation for detailed examples.

\n","text":"This tab configures all task properties. Each property is displayed as a card containing its configuration options. Looking for property type documentation?See the Property Types Reference for detailed documentation on the expected data types (text, list, date, etc.) for each frontmatter property. Property Card Structure# Each property card contains: Property key: The frontmatter field name used to store this property Default: The default value applied to new tasks (where applicable) NLP trigger: Toggle and character configuration for natural language parsing (where applicable) Property-specific settings: Additional configuration options specific to that property This tab defines the task schema used by creation flows, NLP parsing, views, and API payloads. Property keys are YAML/frontmatter keys. TaskNotes can read and write keys that contain spaces or punctuation, but hand-written Bases filters and formulas must reference those keys with bracket syntax, for example note[\"TN-status\"], rather than dot syntax such as note.TN-status. Core Properties# Title# The task title property. Configuration options: Property key: Frontmatter field name (default: title) Store title in filename: When enabled, the task title is stored in the filename instead of frontmatter. The filename updates when the title changes. Filename format: When \"Store title in filename\" is disabled, choose how filenames are generated: Title-based Zettelkasten-style Timestamp-based UUID v4 Custom template Custom template: Define a custom filename pattern using variables (shown when \"custom\" format is selected) Status# Task completion state. Configuration options: Property key: Frontmatter field name (default: status) Default: Default status for new tasks NLP trigger: Character that triggers status parsing (default: *) Status Values: Expandable section containing individual status cards Each status value has: Value: Internal identifier stored in frontmatter (e.g., \"in-progress\") Label: Display name shown in the interface (e.g., \"In Progress\") Color: Visual indicator color Icon: Optional icon identifier Completed: Whether this status represents a finished task Skip when cycling: Exclude this status from the click-to-cycle order on task cards while keeping it available in menus, suggestions, and direct edits Next status: Optional override for the status used when cycling forward from this status; leave it set to the status order to use the normal sequence Auto-archive: Automatically archive tasks after a delay (1-1440 minutes) Status cards support drag-and-drop reordering. Use the Value field as the stable stored identifier and the Label field for display text with spaces or title casing. TaskNotes status menus and cycling use the configured order, and TaskNotes Kanban views can preserve dragged column order. Native Bases grouping/sorting may still order status values alphabetically by their stored Value, so use prefixes such as 1-open, 2-doing, 3-done if you need predictable native Bases order. Boolean Status Values# TaskNotes supports using boolean values (true and false) as status values, which integrates with Obsidian's native checkbox property format: When you set a task's status to \"true\" or \"false\" (case-insensitive), TaskNotes automatically converts it to a boolean in frontmatter When reading tasks with boolean status values from frontmatter, they are converted back to the strings \"true\" or \"false\" This allows you to use Obsidian's native checkbox property toggles in the Properties panel while maintaining compatibility with TaskNotes Example: --- status: true # Boolean checkbox in Obsidian --- Priority# Task priority level. Configuration options: Property key: Frontmatter field name (default: priority) Default: Default priority for new tasks (can be set to \"No default\") NLP trigger: Character that triggers priority parsing (default: !, disabled by default) Priority Values: Expandable section containing individual priority cards Each priority value has: Value: Internal identifier stored in frontmatter (e.g., \"high\") Label: Display name shown in the interface (e.g., \"High Priority\") Color: Visual indicator color Priority cards support drag-and-drop reordering. Status and priority values are stored in frontmatter; renaming them later may require migration of existing task files. Note for Bases plugin users: Obsidian's Bases plugin sorts priorities alphabetically by their Value. To control sort order, name values to sort alphabetically in the desired order: Example: 1-urgent, 2-high, 3-medium, 4-normal, 5-low Or: a-urgent, b-high, c-medium, d-normal, e-low Date Properties# Due Date# When the task must be completed. Configuration options: Property key: Frontmatter field name (default: due) Default: Default due date for new tasks (None, Today, Tomorrow, Next Week) Scheduled Date# When to work on the task. Configuration options: Property key: Frontmatter field name (default: scheduled) Default: Default scheduled date for new tasks (None, Today, Tomorrow, Next Week) When you use Convert current note to task, this default is also applied if the source note does not already have scheduled frontmatter. Choose None to keep converted notes unscheduled by default. due tracks commitment deadlines, while scheduled tracks intended execution time. Organization Properties# Contexts# Where or how the task can be done. Configuration options: Property key: Frontmatter field name (default: contexts) Default: Comma-separated list of default contexts (e.g., @home, @work) NLP trigger: Character that triggers context parsing (default: @) Projects# Projects the task belongs to. Configuration options: Property key: Frontmatter field name (default: projects) Default projects: Select project notes to automatically link to new tasks Use active note for new tasks: Automatically link the active note as a project when opening task creation from the command palette or ribbon Use parent note for inline/instant conversion: Automatically link the source note as a project when using inline task creation or instant task conversion NLP trigger: Character that triggers project parsing (default: +) Autosuggest Filters: Expandable section to filter which notes appear in project suggestions Customize Display: Expandable section to configure how project suggestions appear Autosuggest Filters# Control which notes appear when selecting projects: Required tags: Comma-separated list of tags (shows notes with ANY of these tags) Include folders: Comma-separated list of folder paths (shows notes in ANY of these folders) Required property key: Frontmatter property that must exist Required property value: Expected value for the property (optional) These filters reduce suggestion noise in large vaults. A \"Filters On\" badge appears when any filters are configured. Customize Display# Configure project suggestion appearance: Enable fuzzy matching: Allow typos and partial matches in project search Row 1, 2, 3: Configure up to 3 lines of information for each project suggestion Tags# Obsidian tags for categorization. Configuration options: Default: Comma-separated list of default tags (without #) NLP trigger: Character that triggers tag parsing (default: #) Note: Tags use native Obsidian tags and do not have a separate property key setting. Task Details# Time Estimate# Estimated time to complete the task. Configuration options: Property key: Frontmatter field name (default: timeEstimate) Default: Default time estimate in minutes (0 = no default) Recurrence# Pattern for repeating tasks. Configuration options: Property key: Frontmatter field name (default: recurrence) Default: Default recurrence pattern (None, Daily, Weekly, Monthly, Yearly) Recurring tasks also use the Recurrence anchor metadata property to decide whether the series advances from the scheduled date or the completion date. Materialized occurrence note controls live on each recurring task's context menu under Recurrence → Occurrence notes rather than as a global default. Reminders# Notifications before task deadlines. Configuration options: Property key: Frontmatter field name (default: reminders) Default Reminders: Expandable section containing default reminder cards Each default reminder can be: Relative reminders (triggered relative to due or scheduled date): Anchor date (due date or scheduled date) Offset amount and unit (minutes, hours, days) Direction (before or after) Description Absolute reminders (triggered at specific times): Date Time Description Metadata Properties# These properties are system-managed and typically only require property key configuration: Date Created: When the task was created Date Modified: When the task was last modified Completed Date: When the task was completed Archive Tag: Tag used to mark archived tasks Time Entries: Time tracking entries for the task Complete Instances: Completion history for recurring tasks Skipped Instances: Skip history for recurring tasks Recurrence Anchor: Whether recurring progression is based on scheduled date or completion date Blocked By: Tasks that must be completed first Materialized occurrence notes also use system-managed frontmatter fields such as recurrence_parent, occurrence_date, occurrence_materialization, occurrence_next_trigger, and optional occurrence template/horizon fields. Occurrence notes inherit parent planning metadata when they are created, but keep their own status, completion date, and time entries. These fields are documented in the Property Types Reference and are normally changed through recurrence and occurrence-note controls instead of by hand. Feature Properties# These properties are used by specific TaskNotes features and are not stored in task frontmatter: Pomodoros: Property key for Pomodoro session counts. When Pomodoro data storage is set to \"Daily notes\", this property is written to daily notes rather than task files. ICS Event ID: Property key for calendar event identifiers. Added to notes created from ICS calendar events to link them back to the source event. ICS Event Tag: Property key for calendar event tags. Added to notes created from ICS calendar events for identification. Custom User Fields# Define custom frontmatter properties to appear as filter options across views. Configuration options for each field: Display Name: How the field appears in the UI Property Key: The frontmatter property name Type: Data type (text, number, boolean, date, or list) Default Value: Pre-fill value for new tasks (format varies by type) NLP trigger: Toggle and character for natural language parsing Autosuggest Filters: Filter which files appear when using [[ wikilink autocomplete Custom fields are most maintainable when they map to repeated workflow decisions (for example effort, owner, or client). Link Values# Use a Text custom field for a single link and a List custom field for multiple links. Task cards render [[wikilinks]], [label](https://example.com), , and bare https://example.com values as clickable links. Autosuggest filters work with text and list fields when entering [[ wikilinks, so a field such as Related Note can suggest only files from a chosen folder or tag. Default Values# Each field type has a different input format for default values: Text: Enter the default text value Number: Enter the default number Boolean: Toggle switch to set default checked/unchecked state Date: Select from presets (None, Today, Tomorrow, Next Week) List: Enter comma-separated default values Default values are applied when creating tasks via: Task creation modal Instant task conversion \"Create or open task\" command HTTP API (when using task creation defaults) Autosuggestion Filters# Each custom field can configure filters to control which files appear in wikilink suggestions: Required tags: Comma-separated list of tags (shows files with ANY of these tags) Include folders: Comma-separated list of folder paths (shows files in ANY of these folders) Required property key: Frontmatter property that must exist Required property value: Expected value for the property (optional) A \"Filters On\" badge appears when filters are configured. See User Fields Feature Documentation for detailed examples."},{"route":"/obsidian/troubleshooting/","title":"Troubleshooting","description":"Common issues and solutions for TaskNotes.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/troubleshooting.md","namespace":"obsidian","relativePath":"troubleshooting.md","raw":"# Troubleshooting\n\nCommon issues and solutions for TaskNotes.\n\nWhen debugging, start with one affected task and one affected view. Record the TaskNotes version from the plugin list, the Obsidian version from **About**, the operating system, and whether the problem also occurs in a fresh default Base.\n\n## First checks\n\n1. Confirm Obsidian meets the current [version requirement](reference/compatibility.md) and **Bases** is enabled.\n2. Open the affected task as Markdown and validate the `---` frontmatter delimiters and indentation.\n3. Confirm the task matches **Settings → TaskNotes → General → Task identification** and is not in an excluded folder.\n4. Run **TaskNotes: Refresh cache** from the command palette.\n5. Close and reopen the affected `.base` file.\n6. Restart Obsidian only after the targeted checks above.\n\nIf the issue remains, enable **Settings → TaskNotes → Features → Debug logging**, reproduce it once, and inspect the developer console with `Ctrl/Cmd + Shift + I`. Disable debug logging after collecting the relevant entries.\n\n## Bases and Views (v4)\n\n### Views Not Loading\n\n**Symptoms**: TaskNotes views show errors or don't display tasks\n\nFirst confirm Bases is enabled (`Settings -> Core Plugins -> Bases`), then restart Obsidian once. If views are still missing, verify `.base` files exist in `TaskNotes/Views/`. If needed, regenerate defaults from `Settings -> TaskNotes -> General -> Views & base files` (`Create files`).\n\n### Commands Open Wrong Files\n\n**Symptoms**: Ribbon icons or commands open unexpected files\n\nCheck command mappings in `Settings -> TaskNotes -> General` (`View Commands`). Reset mappings that were changed unintentionally, then verify each referenced `.base` file exists at the configured path.\n\n## Common Issues\n\n### Tasks Not Appearing in Views\n\n**Symptoms**: Tasks you've created don't show up in TaskNotes views\n\nFollow this decision tree:\n\n1. **Does Quick actions for current task work on the note?**\n - **No:** compare its tag or identification property with **General → Task identification**.\n - **Yes:** task recognition works; continue to the Base filter.\n2. **Is the note inside an excluded folder?**\n - **Yes:** move it or update **Excluded folders**.\n - **No:** continue.\n3. **Does a newly generated default task Base show it?**\n - **Yes:** the custom Base has a stale property name or filter.\n - **No:** run **TaskNotes: Refresh cache** and validate the frontmatter.\n4. **Did identification or field mapping change recently?**\n - **Yes:** update the default Base files or edit their filters and columns. Generated files do not update automatically when settings change.\n\n### Task Link Widgets Not Working\n\n**Symptoms**: Links to task files appear as normal wikilinks instead of interactive widgets\n\nCheck that **Task link overlay** is enabled, then verify linked files are actually recognized as tasks (matching tag/property configuration). Links to normal notes will render as normal links by design.\n\n### Instant Conversion Buttons Missing\n\n**Symptoms**: Convert buttons don't appear next to checkbox tasks\n\nInstant convert buttons only appear when the feature is enabled, in edit mode, and with cursor proximity to list items. Enable the feature, switch from reading mode to edit mode, and place the cursor near the target checkbox.\n\n### Calendar View Performance Issues\n\n**Symptoms**: Calendar views are slow or unresponsive\n\nReduce visible event layers first (scheduled/due/recurring/time entries), then increase ICS refresh intervals and shorten displayed date ranges. If slowness persists, apply the general performance guidance below.\n\n### Natural Language Parsing Not Working\n\n**Symptoms**: Natural language input doesn't extract expected task properties\n\nEnable NLP in `Settings -> TaskNotes -> Features`, then verify your trigger characters (`@`, `#`, `!` by default) and any custom status/priority mappings. If parsing still seems inconsistent, compare input against the syntax in [NLP API](nlp-api.md).\n\n### Time Tracking Issues\n\n**Symptoms**: Time tracking doesn't start/stop properly or data is lost\n\nMost tracking issues come from overlapping sessions, interrupted shutdowns, or save failures. Stop active sessions before starting new ones, confirm files are writable, and restart interrupted sessions. If needed, repair malformed time entries directly in frontmatter.\n\n## Data Issues\n\n### Corrupted Task Files\n\n**Symptoms**: Tasks appear broken or cause errors in views\n\nOpen the task file directly and validate frontmatter syntax. Quote values that include special characters, validate YAML if necessary, and restore from backup for severe corruption.\n\n### Missing Task Properties\n\n**Symptoms**: Tasks missing expected properties or using default values unexpectedly\n\nCheck field mappings first, then confirm Task Defaults. If properties are absent on older notes, add them manually or re-save through TaskNotes so current mapping rules are applied.\n\n### Date Format Issues\n\n**Symptoms**: Dates not displaying correctly or causing parse errors\n\nUse supported formats (`YYYY-MM-DD` or `YYYY-MM-DDTHH:MM:SS`), quote where needed, and re-enter problematic dates via TaskNotes date pickers to normalize formatting and timezone handling.\n\n## Performance Troubleshooting\n\n### Slow View Loading\n\nTo improve loading times, reduce external calendar subscriptions, increase ICS refresh intervals, exclude large folders, and disable event types you do not use.\n\n## External Calendar Issues\n\n### OAuth Calendar Not Connecting\n\n**Symptoms**: Google Calendar or Microsoft Outlook won't connect\n\nVerify credentials and loopback redirect configuration (`127.0.0.1` with dynamic local port), ensure app publication/test-user access is correct, and retry after disconnecting. Also check popup blockers. For provider-specific setup details, use [Calendar Setup](calendar-setup.md).\n\n### OAuth Calendar Not Syncing\n\n**Symptoms**: Connected calendar shows old events or doesn't update\n\nRun manual refresh, check last-sync timestamps, reconnect if needed, and verify events exist in the source provider before debugging TaskNotes behavior.\n\n### ICS Subscriptions Not Loading\n\n**Symptoms**: ICS calendar events don't appear in calendar views\n\nConfirm the ICS URL/file is reachable, run manual refresh, validate the feed format, and inspect subscription status errors for provider-side failures.\n\n### Calendar Sync Problems\n\n**Symptoms**: External calendar changes not reflected in TaskNotes\n\nCheck refresh intervals and force a manual refresh first. If source data is current but TaskNotes remains stale, remove and re-add the subscription to clear cached state.\n\n## Getting Help\n\n### Reporting Issues\n\nReport bugs on [GitHub Issues](https://github.com/callumalpass/tasknotes/issues). Include:\n\n- Exact TaskNotes and Obsidian versions\n- Operating system\n- The smallest affected task frontmatter with private values removed\n- The `.base` path and whether a regenerated default has the same problem\n- Steps to reproduce from a fresh Obsidian start\n- Relevant console errors and TaskNotes debug entries\n- Screenshots if relevant\n\n### Configuration Reset\n\nUse a reversible reset only after the checks above:\n\n1. Close Obsidian\n2. Navigate to `.obsidian/plugins/tasknotes/`\n3. Copy `data.json` to a backup outside the plugin directory\n4. Rename the original to `data.json.backup-YYYY-MM-DD`\n5. Restart Obsidian\n\n!!! warning\n A reset affects settings, status and priority configurations, integration state, saved views, and plugin-stored Pomodoro history. Keep the backup until the problem is resolved. Restore it only while Obsidian is closed.\n\nFor full restore and uninstall guidance, see [Backup, restore, and removal](guides/backup-recovery.md).\n","aliases":["/troubleshooting/"],"toc":[{"level":2,"id":"first-checks","text":"First checks"},{"level":2,"id":"bases-and-views-v4","text":"Bases and Views (v4)"},{"level":3,"id":"views-not-loading","text":"Views Not Loading"},{"level":3,"id":"commands-open-wrong-files","text":"Commands Open Wrong Files"},{"level":2,"id":"common-issues","text":"Common Issues"},{"level":3,"id":"tasks-not-appearing-in-views","text":"Tasks Not Appearing in Views"},{"level":3,"id":"task-link-widgets-not-working","text":"Task Link Widgets Not Working"},{"level":3,"id":"instant-conversion-buttons-missing","text":"Instant Conversion Buttons Missing"},{"level":3,"id":"calendar-view-performance-issues","text":"Calendar View Performance Issues"},{"level":3,"id":"natural-language-parsing-not-working","text":"Natural Language Parsing Not Working"},{"level":3,"id":"time-tracking-issues","text":"Time Tracking Issues"},{"level":2,"id":"data-issues","text":"Data Issues"},{"level":3,"id":"corrupted-task-files","text":"Corrupted Task Files"},{"level":3,"id":"missing-task-properties","text":"Missing Task Properties"},{"level":3,"id":"date-format-issues","text":"Date Format Issues"},{"level":2,"id":"performance-troubleshooting","text":"Performance Troubleshooting"},{"level":3,"id":"slow-view-loading","text":"Slow View Loading"},{"level":2,"id":"external-calendar-issues","text":"External Calendar Issues"},{"level":3,"id":"oauth-calendar-not-connecting","text":"OAuth Calendar Not Connecting"},{"level":3,"id":"oauth-calendar-not-syncing","text":"OAuth Calendar Not Syncing"},{"level":3,"id":"ics-subscriptions-not-loading","text":"ICS Subscriptions Not Loading"},{"level":3,"id":"calendar-sync-problems","text":"Calendar Sync Problems"},{"level":2,"id":"getting-help","text":"Getting Help"},{"level":3,"id":"reporting-issues","text":"Reporting Issues"},{"level":3,"id":"configuration-reset","text":"Configuration Reset"}],"html":"

Common issues and solutions for TaskNotes.

\n

When debugging, start with one affected task and one affected view. Record the TaskNotes version from the plugin list, the Obsidian version from About, the operating system, and whether the problem also occurs in a fresh default Base.

\n

First checks#

\n
    \n
  1. Confirm Obsidian meets the current version requirement and Bases is enabled.
  2. \n
  3. Open the affected task as Markdown and validate the --- frontmatter delimiters and indentation.
  4. \n
  5. Confirm the task matches Settings → TaskNotes → General → Task identification and is not in an excluded folder.
  6. \n
  7. Run TaskNotes: Refresh cache from the command palette.
  8. \n
  9. Close and reopen the affected .base file.
  10. \n
  11. Restart Obsidian only after the targeted checks above.
  12. \n
\n

If the issue remains, enable Settings → TaskNotes → Features → Debug logging, reproduce it once, and inspect the developer console with Ctrl/Cmd + Shift + I. Disable debug logging after collecting the relevant entries.

\n

Bases and Views (v4)#

\n

Views Not Loading#

\n

Symptoms: TaskNotes views show errors or don't display tasks

\n

First confirm Bases is enabled (Settings -> Core Plugins -> Bases), then restart Obsidian once. If views are still missing, verify .base files exist in TaskNotes/Views/. If needed, regenerate defaults from Settings -> TaskNotes -> General -> Views & base files (Create files).

\n

Commands Open Wrong Files#

\n

Symptoms: Ribbon icons or commands open unexpected files

\n

Check command mappings in Settings -> TaskNotes -> General (View Commands). Reset mappings that were changed unintentionally, then verify each referenced .base file exists at the configured path.

\n

Common Issues#

\n

Tasks Not Appearing in Views#

\n

Symptoms: Tasks you've created don't show up in TaskNotes views

\n

Follow this decision tree:

\n
    \n
  1. Does Quick actions for current task work on the note?
      \n
    • No: compare its tag or identification property with General → Task identification.
    • \n
    • Yes: task recognition works; continue to the Base filter.
    • \n
    \n
  2. \n
  3. Is the note inside an excluded folder?
      \n
    • Yes: move it or update Excluded folders.
    • \n
    • No: continue.
    • \n
    \n
  4. \n
  5. Does a newly generated default task Base show it?
      \n
    • Yes: the custom Base has a stale property name or filter.
    • \n
    • No: run TaskNotes: Refresh cache and validate the frontmatter.
    • \n
    \n
  6. \n
  7. Did identification or field mapping change recently?
      \n
    • Yes: update the default Base files or edit their filters and columns. Generated files do not update automatically when settings change.
    • \n
    \n
  8. \n
\n\n

Symptoms: Links to task files appear as normal wikilinks instead of interactive widgets

\n

Check that Task link overlay is enabled, then verify linked files are actually recognized as tasks (matching tag/property configuration). Links to normal notes will render as normal links by design.

\n

Instant Conversion Buttons Missing#

\n

Symptoms: Convert buttons don't appear next to checkbox tasks

\n

Instant convert buttons only appear when the feature is enabled, in edit mode, and with cursor proximity to list items. Enable the feature, switch from reading mode to edit mode, and place the cursor near the target checkbox.

\n

Calendar View Performance Issues#

\n

Symptoms: Calendar views are slow or unresponsive

\n

Reduce visible event layers first (scheduled/due/recurring/time entries), then increase ICS refresh intervals and shorten displayed date ranges. If slowness persists, apply the general performance guidance below.

\n

Natural Language Parsing Not Working#

\n

Symptoms: Natural language input doesn't extract expected task properties

\n

Enable NLP in Settings -> TaskNotes -> Features, then verify your trigger characters (@, #, ! by default) and any custom status/priority mappings. If parsing still seems inconsistent, compare input against the syntax in NLP API.

\n

Time Tracking Issues#

\n

Symptoms: Time tracking doesn't start/stop properly or data is lost

\n

Most tracking issues come from overlapping sessions, interrupted shutdowns, or save failures. Stop active sessions before starting new ones, confirm files are writable, and restart interrupted sessions. If needed, repair malformed time entries directly in frontmatter.

\n

Data Issues#

\n

Corrupted Task Files#

\n

Symptoms: Tasks appear broken or cause errors in views

\n

Open the task file directly and validate frontmatter syntax. Quote values that include special characters, validate YAML if necessary, and restore from backup for severe corruption.

\n

Missing Task Properties#

\n

Symptoms: Tasks missing expected properties or using default values unexpectedly

\n

Check field mappings first, then confirm Task Defaults. If properties are absent on older notes, add them manually or re-save through TaskNotes so current mapping rules are applied.

\n

Date Format Issues#

\n

Symptoms: Dates not displaying correctly or causing parse errors

\n

Use supported formats (YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS), quote where needed, and re-enter problematic dates via TaskNotes date pickers to normalize formatting and timezone handling.

\n

Performance Troubleshooting#

\n

Slow View Loading#

\n

To improve loading times, reduce external calendar subscriptions, increase ICS refresh intervals, exclude large folders, and disable event types you do not use.

\n

External Calendar Issues#

\n

OAuth Calendar Not Connecting#

\n

Symptoms: Google Calendar or Microsoft Outlook won't connect

\n

Verify credentials and loopback redirect configuration (127.0.0.1 with dynamic local port), ensure app publication/test-user access is correct, and retry after disconnecting. Also check popup blockers. For provider-specific setup details, use Calendar Setup.

\n

OAuth Calendar Not Syncing#

\n

Symptoms: Connected calendar shows old events or doesn't update

\n

Run manual refresh, check last-sync timestamps, reconnect if needed, and verify events exist in the source provider before debugging TaskNotes behavior.

\n

ICS Subscriptions Not Loading#

\n

Symptoms: ICS calendar events don't appear in calendar views

\n

Confirm the ICS URL/file is reachable, run manual refresh, validate the feed format, and inspect subscription status errors for provider-side failures.

\n

Calendar Sync Problems#

\n

Symptoms: External calendar changes not reflected in TaskNotes

\n

Check refresh intervals and force a manual refresh first. If source data is current but TaskNotes remains stale, remove and re-add the subscription to clear cached state.

\n

Getting Help#

\n

Reporting Issues#

\n

Report bugs on GitHub Issues. Include:

\n
    \n
  • Exact TaskNotes and Obsidian versions
  • \n
  • Operating system
  • \n
  • The smallest affected task frontmatter with private values removed
  • \n
  • The .base path and whether a regenerated default has the same problem
  • \n
  • Steps to reproduce from a fresh Obsidian start
  • \n
  • Relevant console errors and TaskNotes debug entries
  • \n
  • Screenshots if relevant
  • \n
\n

Configuration Reset#

\n

Use a reversible reset only after the checks above:

\n
    \n
  1. Close Obsidian
  2. \n
  3. Navigate to .obsidian/plugins/tasknotes/
  4. \n
  5. Copy data.json to a backup outside the plugin directory
  6. \n
  7. Rename the original to data.json.backup-YYYY-MM-DD
  8. \n
  9. Restart Obsidian
  10. \n
\n\n

For full restore and uninstall guidance, see Backup, restore, and removal.

\n","text":"Common issues and solutions for TaskNotes. When debugging, start with one affected task and one affected view. Record the TaskNotes version from the plugin list, the Obsidian version from About, the operating system, and whether the problem also occurs in a fresh default Base. First checks# Confirm Obsidian meets the current version requirement and Bases is enabled. Open the affected task as Markdown and validate the --- frontmatter delimiters and indentation. Confirm the task matches Settings → TaskNotes → General → Task identification and is not in an excluded folder. Run TaskNotes: Refresh cache from the command palette. Close and reopen the affected .base file. Restart Obsidian only after the targeted checks above. If the issue remains, enable Settings → TaskNotes → Features → Debug logging, reproduce it once, and inspect the developer console with Ctrl/Cmd + Shift + I. Disable debug logging after collecting the relevant entries. Bases and Views (v4)# Views Not Loading# Symptoms: TaskNotes views show errors or don't display tasks First confirm Bases is enabled (Settings -> Core Plugins -> Bases), then restart Obsidian once. If views are still missing, verify .base files exist in TaskNotes/Views/. If needed, regenerate defaults from Settings -> TaskNotes -> General -> Views & base files (Create files). Commands Open Wrong Files# Symptoms: Ribbon icons or commands open unexpected files Check command mappings in Settings -> TaskNotes -> General (View Commands). Reset mappings that were changed unintentionally, then verify each referenced .base file exists at the configured path. Common Issues# Tasks Not Appearing in Views# Symptoms: Tasks you've created don't show up in TaskNotes views Follow this decision tree: Does Quick actions for current task work on the note? No: compare its tag or identification property with General → Task identification. Yes: task recognition works; continue to the Base filter. Is the note inside an excluded folder? Yes: move it or update Excluded folders. No: continue. Does a newly generated default task Base show it? Yes: the custom Base has a stale property name or filter. No: run TaskNotes: Refresh cache and validate the frontmatter. Did identification or field mapping change recently? Yes: update the default Base files or edit their filters and columns. Generated files do not update automatically when settings change. Task Link Widgets Not Working# Symptoms: Links to task files appear as normal wikilinks instead of interactive widgets Check that Task link overlay is enabled, then verify linked files are actually recognized as tasks (matching tag/property configuration). Links to normal notes will render as normal links by design. Instant Conversion Buttons Missing# Symptoms: Convert buttons don't appear next to checkbox tasks Instant convert buttons only appear when the feature is enabled, in edit mode, and with cursor proximity to list items. Enable the feature, switch from reading mode to edit mode, and place the cursor near the target checkbox. Calendar View Performance Issues# Symptoms: Calendar views are slow or unresponsive Reduce visible event layers first (scheduled/due/recurring/time entries), then increase ICS refresh intervals and shorten displayed date ranges. If slowness persists, apply the general performance guidance below. Natural Language Parsing Not Working# Symptoms: Natural language input doesn't extract expected task properties Enable NLP in Settings -> TaskNotes -> Features, then verify your trigger characters (@, #, ! by default) and any custom status/priority mappings. If parsing still seems inconsistent, compare input against the syntax in NLP API. Time Tracking Issues# Symptoms: Time tracking doesn't start/stop properly or data is lost Most tracking issues come from overlapping sessions, interrupted shutdowns, or save failures. Stop active sessions before starting new ones, confirm files are writable, and restart interrupted sessions. If needed, repair malformed time entries directly in frontmatter. Data Issues# Corrupted Task Files# Symptoms: Tasks appear broken or cause errors in views Open the task file directly and validate frontmatter syntax. Quote values that include special characters, validate YAML if necessary, and restore from backup for severe corruption. Missing Task Properties# Symptoms: Tasks missing expected properties or using default values unexpectedly Check field mappings first, then confirm Task Defaults. If properties are absent on older notes, add them manually or re-save through TaskNotes so current mapping rules are applied. Date Format Issues# Symptoms: Dates not displaying correctly or causing parse errors Use supported formats (YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS), quote where needed, and re-enter problematic dates via TaskNotes date pickers to normalize formatting and timezone handling. Performance Troubleshooting# Slow View Loading# To improve loading times, reduce external calendar subscriptions, increase ICS refresh intervals, exclude large folders, and disable event types you do not use. External Calendar Issues# OAuth Calendar Not Connecting# Symptoms: Google Calendar or Microsoft Outlook won't connect Verify credentials and loopback redirect configuration (127.0.0.1 with dynamic local port), ensure app publication/test-user access is correct, and retry after disconnecting. Also check popup blockers. For provider-specific setup details, use Calendar Setup. OAuth Calendar Not Syncing# Symptoms: Connected calendar shows old events or doesn't update Run manual refresh, check last-sync timestamps, reconnect if needed, and verify events exist in the source provider before debugging TaskNotes behavior. ICS Subscriptions Not Loading# Symptoms: ICS calendar events don't appear in calendar views Confirm the ICS URL/file is reachable, run manual refresh, validate the feed format, and inspect subscription status errors for provider-side failures. Calendar Sync Problems# Symptoms: External calendar changes not reflected in TaskNotes Check refresh intervals and force a manual refresh first. If source data is current but TaskNotes remains stale, remove and re-add the subscription to clear cached state. Getting Help# Reporting Issues# Report bugs on GitHub Issues. Include: Exact TaskNotes and Obsidian versions Operating system The smallest affected task frontmatter with private values removed The .base path and whether a regenerated default has the same problem Steps to reproduce from a fresh Obsidian start Relevant console errors and TaskNotes debug entries Screenshots if relevant Configuration Reset# Use a reversible reset only after the checks above: Close Obsidian Navigate to .obsidian/plugins/tasknotes/ Copy data.json to a backup outside the plugin directory Rename the original to data.json.backup-YYYY-MM-DD Restart Obsidian WarningA reset affects settings, status and priority configurations, integration state, saved views, and plugin-stored Pomodoro history. Keep the backup until the problem is resolved. Restore it only while Obsidian is closed. For full restore and uninstall guidance, see Backup, restore, and removal."},{"route":"/obsidian/views/","title":"Views","description":"TaskNotes provides multiple views for managing tasks and tracking productivity. All task-focused views operate as .base files located in the TaskNotes/Views/ directory and requi...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/views.md","namespace":"obsidian","relativePath":"views.md","raw":"# Views\n\nTaskNotes provides multiple views for managing tasks and tracking productivity. All task-focused views operate as `.base` files located in the `TaskNotes/Views/` directory and require Obsidian's Bases core plugin to be enabled.\n\n\nFor details on Bases integration and how to enable it, see [Core Concepts](core-concepts.md#bases-integration). For view templates and configuration examples, see [Default Base Templates](views/default-base-templates.md).\n\n## Task-Focused Views\n\nTask-focused views are different entry points into the same underlying task notes. The [Task List View](views/task-list.md) is a common starting view for day-to-day planning because it exposes filters, sorting, and grouping in list format.\n\nWhen you want workflow by status, [Kanban View](views/kanban-view.md) organizes cards into columns and can optionally add swimlanes for an extra organizational layer. [Calendar Views](views/calendar-views.md) are useful when schedule and timing matter more than backlog shape, with month/week/day/year/list modes plus drag-and-drop scheduling and time-block support.\n\n[Agenda View](views/agenda-view.md) is a preconfigured list-oriented calendar layout designed for short-horizon planning, while [MiniCalendar View](views/calendar-views.md#mini-calendar-view) gives a compact month heatmap and fast keyboard navigation.\n\n![Task List view](assets/views-tasks-list.png)\n\n![Calendar week view](assets/views-calendar-week.png)\n\n## Productivity-Focused Views\n\nThese views support time management and work tracking.\n\n[Pomodoro View](views/pomodoro-view.md) supports focused intervals directly inside Obsidian, and [Pomodoro Stats View](views/pomodoro-view.md#pomodoro-stats-view) summarizes completed sessions so you can see pace and consistency over time.\n\n![Pomodoro view](assets/feature-pomodoro-timer.png)\n\nScreenshots in this section are captured via the Playwright docs suite (`npm run e2e:docs`).\n","aliases":["/views/"],"toc":[{"level":2,"id":"task-focused-views","text":"Task-Focused Views"},{"level":2,"id":"productivity-focused-views","text":"Productivity-Focused Views"}],"html":"

TaskNotes provides multiple views for managing tasks and tracking productivity. All task-focused views operate as .base files located in the TaskNotes/Views/ directory and require Obsidian's Bases core plugin to be enabled.

\n

For details on Bases integration and how to enable it, see Core Concepts. For view templates and configuration examples, see Default Base Templates.

\n

Task-Focused Views#

\n

Task-focused views are different entry points into the same underlying task notes. The Task List View is a common starting view for day-to-day planning because it exposes filters, sorting, and grouping in list format.

\n

When you want workflow by status, Kanban View organizes cards into columns and can optionally add swimlanes for an extra organizational layer. Calendar Views are useful when schedule and timing matter more than backlog shape, with month/week/day/year/list modes plus drag-and-drop scheduling and time-block support.

\n

Agenda View is a preconfigured list-oriented calendar layout designed for short-horizon planning, while MiniCalendar View gives a compact month heatmap and fast keyboard navigation.

\n

\"Task

\n

\"Calendar

\n

Productivity-Focused Views#

\n

These views support time management and work tracking.

\n

Pomodoro View supports focused intervals directly inside Obsidian, and Pomodoro Stats View summarizes completed sessions so you can see pace and consistency over time.

\n

\"Pomodoro

\n

Screenshots in this section are captured via the Playwright docs suite (npm run e2e:docs).

\n","text":"TaskNotes provides multiple views for managing tasks and tracking productivity. All task-focused views operate as .base files located in the TaskNotes/Views/ directory and require Obsidian's Bases core plugin to be enabled. For details on Bases integration and how to enable it, see Core Concepts. For view templates and configuration examples, see Default Base Templates. Task-Focused Views# Task-focused views are different entry points into the same underlying task notes. The Task List View is a common starting view for day-to-day planning because it exposes filters, sorting, and grouping in list format. When you want workflow by status, Kanban View organizes cards into columns and can optionally add swimlanes for an extra organizational layer. Calendar Views are useful when schedule and timing matter more than backlog shape, with month/week/day/year/list modes plus drag-and-drop scheduling and time-block support. Agenda View is a preconfigured list-oriented calendar layout designed for short-horizon planning, while MiniCalendar View gives a compact month heatmap and fast keyboard navigation. Productivity-Focused Views# These views support time management and work tracking. Pomodoro View supports focused intervals directly inside Obsidian, and Pomodoro Stats View summarizes completed sessions so you can see pace and consistency over time. Screenshots in this section are captured via the Playwright docs suite (npm run e2e:docs)."},{"route":"/obsidian/views/agenda-view/","title":"Agenda View","description":"The Agenda view is a dedicated .base file that opens the calendar in list mode. It provides a scrollable agenda of upcoming tasks, notes, and external calendar events without ne...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/views/agenda-view.md","namespace":"obsidian","relativePath":"views/agenda-view.md","raw":"# Agenda View\n\n\nThe Agenda view is a dedicated `.base` file that opens the calendar in list mode. It provides a scrollable agenda of upcoming tasks, notes, and external calendar events without needing to switch the primary calendar into list view manually.\n\n![Agenda View](../assets/views-agenda.png)\n\n## File Location\n\n- Default file: `TaskNotes/Views/agenda-default.base`\n- Command: **Open Agenda View** (ribbon icon and command palette)\n- Configure the file path in **Settings → TaskNotes → General → View Commands**\n\nTaskNotes creates missing default `.base` files automatically on startup when **Auto-create default files** is enabled. You can replace the command path with your own `.base` file if you maintain multiple agendas.\n\n## Default Configuration\n\nThe stock agenda file renders the calendar in `listWeek` mode:\n\n```yaml\nviews:\n - type: tasknotesCalendar\n name: \"Agenda\"\n calendarView: \"listWeek\"\n listDayCount: 7\n startDateProperty: file.ctime\n titleProperty: file.basename\n order:\n - note.status\n - note.priority\n - note.due\n - formula.dueIn\n - note.scheduled\n```\n\nThis configuration displays seven days at a time, derives entries from `file.ctime`/`file.basename`, shows the generated `Due in` countdown next to due dates, and inherits the same display options (show scheduled/due/recurring/timeblocks/time entries/ICS events) as the primary calendar view.\n\n## Customization\n\nEdit the `.base` file to tailor the agenda:\n\n- Change `calendarView` to `listDay` or `listMonth` for different spans\n- Adjust `listDayCount` for shorter or longer agendas; the Bases option supports up to 365 days\n- Add `filters` to focus on specific projects, tags, or statuses\n- Modify `order` to control which task properties appear in the row layout\n\nBecause the view runs inside Bases, any YAML changes are applied immediately after saving the file.\n\n## Usage Tips\n\n- Use the calendar toolbar arrows (Previous/Next) to move the agenda window forward or backward, or simply scroll the list to review upcoming entries\n- Saved views within Bases let you maintain multiple agenda variants (e.g., \"Work Week\" vs. \"Personal\")\n- Calendar display options (show due, show scheduled, etc.) persist when you save the `.base` file, so you can maintain one agenda that includes external events and another that focuses strictly on TaskNotes tasks\n","aliases":["/views/agenda-view/"],"toc":[{"level":2,"id":"file-location","text":"File Location"},{"level":2,"id":"default-configuration","text":"Default Configuration"},{"level":2,"id":"customization","text":"Customization"},{"level":2,"id":"usage-tips","text":"Usage Tips"}],"html":"

The Agenda view is a dedicated .base file that opens the calendar in list mode. It provides a scrollable agenda of upcoming tasks, notes, and external calendar events without needing to switch the primary calendar into list view manually.

\n

\"Agenda

\n

File Location#

\n
    \n
  • Default file: TaskNotes/Views/agenda-default.base
  • \n
  • Command: Open Agenda View (ribbon icon and command palette)
  • \n
  • Configure the file path in Settings → TaskNotes → General → View Commands
  • \n
\n

TaskNotes creates missing default .base files automatically on startup when Auto-create default files is enabled. You can replace the command path with your own .base file if you maintain multiple agendas.

\n

Default Configuration#

\n

The stock agenda file renders the calendar in listWeek mode:

\n
views:\n  - type: tasknotesCalendar\n    name: "Agenda"\n    calendarView: "listWeek"\n    listDayCount: 7\n    startDateProperty: file.ctime\n    titleProperty: file.basename\n    order:\n      - note.status\n      - note.priority\n      - note.due\n      - formula.dueIn\n      - note.scheduled\n

This configuration displays seven days at a time, derives entries from file.ctime/file.basename, shows the generated Due in countdown next to due dates, and inherits the same display options (show scheduled/due/recurring/timeblocks/time entries/ICS events) as the primary calendar view.

\n

Customization#

\n

Edit the .base file to tailor the agenda:

\n
    \n
  • Change calendarView to listDay or listMonth for different spans
  • \n
  • Adjust listDayCount for shorter or longer agendas; the Bases option supports up to 365 days
  • \n
  • Add filters to focus on specific projects, tags, or statuses
  • \n
  • Modify order to control which task properties appear in the row layout
  • \n
\n

Because the view runs inside Bases, any YAML changes are applied immediately after saving the file.

\n

Usage Tips#

\n
    \n
  • Use the calendar toolbar arrows (Previous/Next) to move the agenda window forward or backward, or simply scroll the list to review upcoming entries
  • \n
  • Saved views within Bases let you maintain multiple agenda variants (e.g., "Work Week" vs. "Personal")
  • \n
  • Calendar display options (show due, show scheduled, etc.) persist when you save the .base file, so you can maintain one agenda that includes external events and another that focuses strictly on TaskNotes tasks
  • \n
\n","text":"The Agenda view is a dedicated .base file that opens the calendar in list mode. It provides a scrollable agenda of upcoming tasks, notes, and external calendar events without needing to switch the primary calendar into list view manually. File Location# Default file: TaskNotes/Views/agenda-default.base Command: Open Agenda View (ribbon icon and command palette) Configure the file path in Settings → TaskNotes → General → View Commands TaskNotes creates missing default .base files automatically on startup when Auto-create default files is enabled. You can replace the command path with your own .base file if you maintain multiple agendas. Default Configuration# The stock agenda file renders the calendar in listWeek mode: views: - type: tasknotesCalendar name: \"Agenda\" calendarView: \"listWeek\" listDayCount: 7 startDateProperty: file.ctime titleProperty: file.basename order: - note.status - note.priority - note.due - formula.dueIn - note.scheduled This configuration displays seven days at a time, derives entries from file.ctime/file.basename, shows the generated Due in countdown next to due dates, and inherits the same display options (show scheduled/due/recurring/timeblocks/time entries/ICS events) as the primary calendar view. Customization# Edit the .base file to tailor the agenda: Change calendarView to listDay or listMonth for different spans Adjust listDayCount for shorter or longer agendas; the Bases option supports up to 365 days Add filters to focus on specific projects, tags, or statuses Modify order to control which task properties appear in the row layout Because the view runs inside Bases, any YAML changes are applied immediately after saving the file. Usage Tips# Use the calendar toolbar arrows (Previous/Next) to move the agenda window forward or backward, or simply scroll the list to review upcoming entries Saved views within Bases let you maintain multiple agenda variants (e.g., \"Work Week\" vs. \"Personal\") Calendar display options (show due, show scheduled, etc.) persist when you save the .base file, so you can maintain one agenda that includes external events and another that focuses strictly on TaskNotes tasks"},{"route":"/obsidian/views/calendar-views/","title":"Calendar Views","description":"TaskNotes provides two calendar-based views: the Mini Calendar and the Calendar View. Both operate as Bases views (.base files) and require the Bases core plugin to be enabled i...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/views/calendar-views.md","namespace":"obsidian","relativePath":"views/calendar-views.md","raw":"# Calendar Views\n\n\nTaskNotes provides two calendar-based views: the **Mini Calendar** and the **Calendar View**. Both operate as Bases views (`.base` files) and require the Bases core plugin to be enabled in Obsidian.\nMini Calendar is date-density and navigation focused, while Calendar View is scheduling focused.\n\n![Calendar Month View](../assets/views-calendar-month.png)\n\n## Bases View Architecture\n\nCalendar views in TaskNotes v4 are implemented as Bases views, which means:\n\n- Calendar views are created as `.base` files in your vault\n- Configuration is controlled through YAML frontmatter in the base file\n- The Bases plugin is an official Obsidian core plugin and must be enabled\n- Views can be opened in tabs, pinned, and managed like other Obsidian views\nThis architecture makes calendar behavior auditable. Filters, formulas, and display options are stored with the view file, so they are versionable and easy to share across vault setups.\n\n## Mini Calendar View\n\nThe Mini Calendar displays a month-based view that shows which days contain tasks or other dated notes. It provides navigation and an overview of your task distribution across time.\n\n![Mini Calendar View](../assets/views-mini-calendar.png)\n\n### Features\n\n- **Date Navigation**: Click any date to open a fuzzy selector modal showing all notes associated with that date\n- **Keyboard Navigation**: Navigate the calendar using arrow keys and select dates with Enter\n- **Heatmap Styling**: Visual indicators show the density of tasks or notes on each day\n- **Configurable Date Property**: Set which date property to track (not limited to tasks - can display any dated notes based on configured property)\n- **Month Navigation**: Browse forward and backward through months to view historical and future task distribution\nMini Calendar is commonly used as an entry view: select a date, then open Task List, Agenda, or Calendar for execution.\n\n## Calendar View\n\nThe Calendar View provides multiple view modes (month, week, day, year, list, and custom days) with drag-and-drop scheduling and time-blocking capabilities. Tasks can be created by clicking on dates or time slots, and rescheduled by dragging them to new dates or times.\n\n### View Modes\n\nThe Calendar View supports the following view modes:\n\n- **Month**: Month grid showing all-day and timed events\n- **Week**: Week view with hourly time slots for detailed scheduling\n- **Day**: Single day view with hourly breakdown\n- **Year**: Annual overview showing event distribution across months\n- **List**: Chronological list of events. TaskNotes also includes a dedicated Agenda command that opens this mode via its own `.base` file for quick reviews.\n- **Custom Days**: Configurable multi-day view (2-10 days)\nView modes can be switched within a single `.base` file based on planning horizon (day, week, month, year, or custom range).\n\n| Week View | Day View | Year View |\n|-----------|----------|-----------|\n| ![Week View](../assets/views-calendar-week.png) | ![Day View](../assets/views-calendar-day.png) | ![Year View](../assets/views-calendar-year.png) |\n\n### Performance Improvements\n\nThe Calendar View uses virtual scrolling to maintain performance when displaying large numbers of events. This allows the calendar to handle extensive task lists and long time ranges without degradation in responsiveness.\n\n### Custom Days View\n\nThe Custom Days view provides a configurable multi-day calendar that displays between 2-10 days at once. This view addresses screen space utilization by offering a middle ground between the single-day view and the full week view.\n\n#### Key Features\n\n- **Configurable Duration**: Set the number of days to display (2-10 days) via Settings > Calendar > Custom view day count\n- **TimeGrid Format**: Uses the same hourly time slots and time-based event layout as Week and Day views\n- **Real-time Updates**: The view updates immediately when the day count setting is changed\n- **Default Configuration**: Ships with 3 days displayed by default for optimal space utilization\n\n#### Use Cases\n\nThe Custom Days view is particularly useful for:\n- Users who find the single-day view too wide and wasteful of screen space\n- Planning workflows that require seeing a few days at a glance without the full week\n- Detailed scheduling tasks that benefit from the time-grid format\n- Customizing the viewing window to match personal preference and screen size\n\n#### Configuration\n\n1. **Select the View**: Choose \"Custom Days\" from the calendar toolbar alongside Month, Week, Day, and Year views\n2. **Adjust Day Count**: Navigate to Settings > Calendar > Custom view day count and use the slider to select 2-10 days\n3. **Set as Default**: Optionally set \"Custom Days\" as your default view in Settings > Calendar > Default view\n\n### Recurring Task Support\n\nThe Calendar View provides recurring task management with visual hierarchy and drag-and-drop behavior.\n\n#### Visual Hierarchy\n\nRecurring tasks are displayed with distinct visual styling:\n\n- **Next Scheduled Occurrence**: Solid border with full opacity, representing the specific date/time when you plan to work on the next instance\n- **Pattern Instances**: Dashed border with reduced opacity (70%), showing preview of when future recurring instances will appear based on the DTSTART and recurrence rule\n\n#### Drag and Drop Behavior\n\nThe calendar provides different behaviors depending on which type of recurring event you drag:\n\n**Dragging Next Scheduled Occurrence (Solid Border)**:\n\n- Updates only the `scheduled` field in the task\n- Reschedules just that specific occurrence to the new date/time\n- Leaves the recurrence pattern unchanged\n- Notice: \"Rescheduled next occurrence. This does not change the recurrence pattern.\"\n\n**Dragging Pattern Instances (Dashed Border)**:\n\n- Updates the DTSTART time in the recurrence rule\n- Changes when all future pattern instances appear\n- Does not affect the independently scheduled next occurrence\n- Notice: \"Updated recurring pattern time. All future instances now appear at this time.\"\n\n#### Flexible Scheduling\n\nThe next scheduled occurrence can appear on any date, even:\n\n- Before the DTSTART date\n- On days that don't match the recurring pattern (e.g., Tuesday for a weekly Monday pattern)\n- At different times than the pattern instances\n\nThis flexibility allows for complete control over both the recurring pattern and individual occurrence scheduling.\n\n### View Options\n\nThe Calendar View provides several display options that control what types of events appear on the calendar:\n\n- **Show scheduled**: Display tasks with scheduled dates\n- **Show due**: Display tasks with due dates\n- **Show timeblocks**: Display time-blocking entries\n- **Show recurring**: Display recurring task events\n- **Show ICS events**: Display events from imported ICS calendars\n- **Show time entries**: Display time tracking entries\n- **All-day slot**: Show or hide the all-day event area at the top of time grid views (Week, Day, and Custom views)\n- **Create daily notes from date links**: Let date header links create a missing daily note before opening it. Turn this off if date links should only open existing daily notes.\n- **Drag/drop resolution**: Set `snapDuration` when you want events to drag or resize in smaller increments than the visible `slotDuration`, such as 5-minute dragging on a 30-minute grid.\n- **Span tasks between scheduled and due dates**: Display tasks as multi-day bars spanning from their scheduled date to their due date (see below)\nMultiple saved calendar views can store different option sets (for example planning vs focus), avoiding repeated manual toggles.\n\nThe **All-day slot** option is particularly useful when you have many all-day tasks on a single date, as hiding it can resolve scrolling issues and make the hourly time slots more accessible. When disabled, all-day events will not be displayed in time grid views, but they will still appear in month view.\n\n#### Multi-Day Task Spans\n\nThe **Span tasks between scheduled and due dates** option provides a visual representation of task duration on the calendar. When enabled:\n\n- Tasks with both a scheduled date and a due date display as a single bar spanning across all days from the scheduled date to the due date\n- This replaces the separate scheduled and due markers for qualifying tasks\n- Tasks with only a scheduled date or only a due date continue to display as single-day events\n- Span events are shown as all-day bars with the task's priority color\n- Span events are read-only on the calendar (edit the underlying scheduled/due dates to modify)\n\nThis option is useful for project planning and visualizing how long tasks are expected to take, similar to Gantt chart-style views.\n\nThese display options are preserved when you save a view, allowing you to create specialized calendar views that show only specific types of events and maintain those preferences across sessions.\n\n### OAuth Calendar Integration\n\nThe Calendar View supports bidirectional synchronization with external calendar services through OAuth authentication:\n\n- **Google Calendar**: Connect to Google Calendar accounts to display and sync events\n- **Microsoft Outlook**: Connect to Microsoft Outlook accounts for calendar integration\n\n#### Synchronization Behavior\n\n- External calendar events appear alongside TaskNotes tasks in all calendar views\n- Drag and drop events to reschedule them - changes sync back to the external calendar service\n- Events from external calendars respect the same view options and display settings as native TaskNotes tasks\n\n#### Configuration\n\nOAuth calendar connections are configured through the TaskNotes settings panel. Authentication uses standard OAuth flows to securely connect to external services.\n\n### Time Entry Editor Modal\n\nThe Calendar View includes a Time Entry Editor Modal for creating time tracking entries directly from the calendar interface.\n\n#### Creating Time Entries\n\n- Drag on the calendar to select a time range\n- When the selection menu appears, choose **Create time entry**\n- The modal opens with the start and end times pre-populated based on the selection, and the entry can be linked to a task or left standalone\n\n#### Editing Time Entries\n\nTime entries displayed on the calendar can be selected to open the Time Entry Editor Modal for modification. The modal provides fields for adjusting start time, end time, associated task, and other time entry metadata.\n\n### Filtering and View Configuration\n\nCalendar filtering is configured through the Bases YAML frontmatter in the `.base` file. This allows you to define which tasks and events appear in each calendar view. Filtering options include task properties, date ranges, tags, and other criteria supported by the Bases plugin.\n\nSaved calendar views retain their filter configuration, display options, and view mode, allowing you to create specialized calendar views for different purposes.\n","aliases":["/views/calendar-views/"],"toc":[{"level":2,"id":"bases-view-architecture","text":"Bases View Architecture"},{"level":2,"id":"mini-calendar-view","text":"Mini Calendar View"},{"level":3,"id":"features","text":"Features"},{"level":2,"id":"calendar-view","text":"Calendar View"},{"level":3,"id":"view-modes","text":"View Modes"},{"level":3,"id":"performance-improvements","text":"Performance Improvements"},{"level":3,"id":"custom-days-view","text":"Custom Days View"},{"level":3,"id":"recurring-task-support","text":"Recurring Task Support"},{"level":3,"id":"view-options","text":"View Options"},{"level":3,"id":"oauth-calendar-integration","text":"OAuth Calendar Integration"},{"level":3,"id":"time-entry-editor-modal","text":"Time Entry Editor Modal"},{"level":3,"id":"filtering-and-view-configuration","text":"Filtering and View Configuration"}],"html":"

TaskNotes provides two calendar-based views: the Mini Calendar and the Calendar View. Both operate as Bases views (.base files) and require the Bases core plugin to be enabled in Obsidian.\nMini Calendar is date-density and navigation focused, while Calendar View is scheduling focused.

\n

\"Calendar

\n

Bases View Architecture#

\n

Calendar views in TaskNotes v4 are implemented as Bases views, which means:

\n
    \n
  • Calendar views are created as .base files in your vault
  • \n
  • Configuration is controlled through YAML frontmatter in the base file
  • \n
  • The Bases plugin is an official Obsidian core plugin and must be enabled
  • \n
  • Views can be opened in tabs, pinned, and managed like other Obsidian views\nThis architecture makes calendar behavior auditable. Filters, formulas, and display options are stored with the view file, so they are versionable and easy to share across vault setups.
  • \n
\n

Mini Calendar View#

\n

The Mini Calendar displays a month-based view that shows which days contain tasks or other dated notes. It provides navigation and an overview of your task distribution across time.

\n

\"Mini

\n

Features#

\n
    \n
  • Date Navigation: Click any date to open a fuzzy selector modal showing all notes associated with that date
  • \n
  • Keyboard Navigation: Navigate the calendar using arrow keys and select dates with Enter
  • \n
  • Heatmap Styling: Visual indicators show the density of tasks or notes on each day
  • \n
  • Configurable Date Property: Set which date property to track (not limited to tasks - can display any dated notes based on configured property)
  • \n
  • Month Navigation: Browse forward and backward through months to view historical and future task distribution\nMini Calendar is commonly used as an entry view: select a date, then open Task List, Agenda, or Calendar for execution.
  • \n
\n

Calendar View#

\n

The Calendar View provides multiple view modes (month, week, day, year, list, and custom days) with drag-and-drop scheduling and time-blocking capabilities. Tasks can be created by clicking on dates or time slots, and rescheduled by dragging them to new dates or times.

\n

View Modes#

\n

The Calendar View supports the following view modes:

\n
    \n
  • Month: Month grid showing all-day and timed events
  • \n
  • Week: Week view with hourly time slots for detailed scheduling
  • \n
  • Day: Single day view with hourly breakdown
  • \n
  • Year: Annual overview showing event distribution across months
  • \n
  • List: Chronological list of events. TaskNotes also includes a dedicated Agenda command that opens this mode via its own .base file for quick reviews.
  • \n
  • Custom Days: Configurable multi-day view (2-10 days)\nView modes can be switched within a single .base file based on planning horizon (day, week, month, year, or custom range).
  • \n
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n
Week ViewDay ViewYear View
\"Week\"Day\"Year
\n

Performance Improvements#

\n

The Calendar View uses virtual scrolling to maintain performance when displaying large numbers of events. This allows the calendar to handle extensive task lists and long time ranges without degradation in responsiveness.

\n

Custom Days View#

\n

The Custom Days view provides a configurable multi-day calendar that displays between 2-10 days at once. This view addresses screen space utilization by offering a middle ground between the single-day view and the full week view.

\n

Key Features#

\n
    \n
  • Configurable Duration: Set the number of days to display (2-10 days) via Settings > Calendar > Custom view day count
  • \n
  • TimeGrid Format: Uses the same hourly time slots and time-based event layout as Week and Day views
  • \n
  • Real-time Updates: The view updates immediately when the day count setting is changed
  • \n
  • Default Configuration: Ships with 3 days displayed by default for optimal space utilization
  • \n
\n

Use Cases#

\n

The Custom Days view is particularly useful for:

\n
    \n
  • Users who find the single-day view too wide and wasteful of screen space
  • \n
  • Planning workflows that require seeing a few days at a glance without the full week
  • \n
  • Detailed scheduling tasks that benefit from the time-grid format
  • \n
  • Customizing the viewing window to match personal preference and screen size
  • \n
\n

Configuration#

\n
    \n
  1. Select the View: Choose "Custom Days" from the calendar toolbar alongside Month, Week, Day, and Year views
  2. \n
  3. Adjust Day Count: Navigate to Settings > Calendar > Custom view day count and use the slider to select 2-10 days
  4. \n
  5. Set as Default: Optionally set "Custom Days" as your default view in Settings > Calendar > Default view
  6. \n
\n

Recurring Task Support#

\n

The Calendar View provides recurring task management with visual hierarchy and drag-and-drop behavior.

\n

Visual Hierarchy#

\n

Recurring tasks are displayed with distinct visual styling:

\n
    \n
  • Next Scheduled Occurrence: Solid border with full opacity, representing the specific date/time when you plan to work on the next instance
  • \n
  • Pattern Instances: Dashed border with reduced opacity (70%), showing preview of when future recurring instances will appear based on the DTSTART and recurrence rule
  • \n
\n

Drag and Drop Behavior#

\n

The calendar provides different behaviors depending on which type of recurring event you drag:

\n

Dragging Next Scheduled Occurrence (Solid Border):

\n
    \n
  • Updates only the scheduled field in the task
  • \n
  • Reschedules just that specific occurrence to the new date/time
  • \n
  • Leaves the recurrence pattern unchanged
  • \n
  • Notice: "Rescheduled next occurrence. This does not change the recurrence pattern."
  • \n
\n

Dragging Pattern Instances (Dashed Border):

\n
    \n
  • Updates the DTSTART time in the recurrence rule
  • \n
  • Changes when all future pattern instances appear
  • \n
  • Does not affect the independently scheduled next occurrence
  • \n
  • Notice: "Updated recurring pattern time. All future instances now appear at this time."
  • \n
\n

Flexible Scheduling#

\n

The next scheduled occurrence can appear on any date, even:

\n
    \n
  • Before the DTSTART date
  • \n
  • On days that don't match the recurring pattern (e.g., Tuesday for a weekly Monday pattern)
  • \n
  • At different times than the pattern instances
  • \n
\n

This flexibility allows for complete control over both the recurring pattern and individual occurrence scheduling.

\n

View Options#

\n

The Calendar View provides several display options that control what types of events appear on the calendar:

\n
    \n
  • Show scheduled: Display tasks with scheduled dates
  • \n
  • Show due: Display tasks with due dates
  • \n
  • Show timeblocks: Display time-blocking entries
  • \n
  • Show recurring: Display recurring task events
  • \n
  • Show ICS events: Display events from imported ICS calendars
  • \n
  • Show time entries: Display time tracking entries
  • \n
  • All-day slot: Show or hide the all-day event area at the top of time grid views (Week, Day, and Custom views)
  • \n
  • Create daily notes from date links: Let date header links create a missing daily note before opening it. Turn this off if date links should only open existing daily notes.
  • \n
  • Drag/drop resolution: Set snapDuration when you want events to drag or resize in smaller increments than the visible slotDuration, such as 5-minute dragging on a 30-minute grid.
  • \n
  • Span tasks between scheduled and due dates: Display tasks as multi-day bars spanning from their scheduled date to their due date (see below)\nMultiple saved calendar views can store different option sets (for example planning vs focus), avoiding repeated manual toggles.
  • \n
\n

The All-day slot option is particularly useful when you have many all-day tasks on a single date, as hiding it can resolve scrolling issues and make the hourly time slots more accessible. When disabled, all-day events will not be displayed in time grid views, but they will still appear in month view.

\n

Multi-Day Task Spans#

\n

The Span tasks between scheduled and due dates option provides a visual representation of task duration on the calendar. When enabled:

\n
    \n
  • Tasks with both a scheduled date and a due date display as a single bar spanning across all days from the scheduled date to the due date
  • \n
  • This replaces the separate scheduled and due markers for qualifying tasks
  • \n
  • Tasks with only a scheduled date or only a due date continue to display as single-day events
  • \n
  • Span events are shown as all-day bars with the task's priority color
  • \n
  • Span events are read-only on the calendar (edit the underlying scheduled/due dates to modify)
  • \n
\n

This option is useful for project planning and visualizing how long tasks are expected to take, similar to Gantt chart-style views.

\n

These display options are preserved when you save a view, allowing you to create specialized calendar views that show only specific types of events and maintain those preferences across sessions.

\n

OAuth Calendar Integration#

\n

The Calendar View supports bidirectional synchronization with external calendar services through OAuth authentication:

\n
    \n
  • Google Calendar: Connect to Google Calendar accounts to display and sync events
  • \n
  • Microsoft Outlook: Connect to Microsoft Outlook accounts for calendar integration
  • \n
\n

Synchronization Behavior#

\n
    \n
  • External calendar events appear alongside TaskNotes tasks in all calendar views
  • \n
  • Drag and drop events to reschedule them - changes sync back to the external calendar service
  • \n
  • Events from external calendars respect the same view options and display settings as native TaskNotes tasks
  • \n
\n

Configuration#

\n

OAuth calendar connections are configured through the TaskNotes settings panel. Authentication uses standard OAuth flows to securely connect to external services.

\n

Time Entry Editor Modal#

\n

The Calendar View includes a Time Entry Editor Modal for creating time tracking entries directly from the calendar interface.

\n

Creating Time Entries#

\n
    \n
  • Drag on the calendar to select a time range
  • \n
  • When the selection menu appears, choose Create time entry
  • \n
  • The modal opens with the start and end times pre-populated based on the selection, and the entry can be linked to a task or left standalone
  • \n
\n

Editing Time Entries#

\n

Time entries displayed on the calendar can be selected to open the Time Entry Editor Modal for modification. The modal provides fields for adjusting start time, end time, associated task, and other time entry metadata.

\n

Filtering and View Configuration#

\n

Calendar filtering is configured through the Bases YAML frontmatter in the .base file. This allows you to define which tasks and events appear in each calendar view. Filtering options include task properties, date ranges, tags, and other criteria supported by the Bases plugin.

\n

Saved calendar views retain their filter configuration, display options, and view mode, allowing you to create specialized calendar views for different purposes.

\n","text":"TaskNotes provides two calendar-based views: the Mini Calendar and the Calendar View. Both operate as Bases views (.base files) and require the Bases core plugin to be enabled in Obsidian. Mini Calendar is date-density and navigation focused, while Calendar View is scheduling focused. Bases View Architecture# Calendar views in TaskNotes v4 are implemented as Bases views, which means: Calendar views are created as .base files in your vault Configuration is controlled through YAML frontmatter in the base file The Bases plugin is an official Obsidian core plugin and must be enabled Views can be opened in tabs, pinned, and managed like other Obsidian views This architecture makes calendar behavior auditable. Filters, formulas, and display options are stored with the view file, so they are versionable and easy to share across vault setups. Mini Calendar View# The Mini Calendar displays a month-based view that shows which days contain tasks or other dated notes. It provides navigation and an overview of your task distribution across time. Features# Date Navigation: Click any date to open a fuzzy selector modal showing all notes associated with that date Keyboard Navigation: Navigate the calendar using arrow keys and select dates with Enter Heatmap Styling: Visual indicators show the density of tasks or notes on each day Configurable Date Property: Set which date property to track (not limited to tasks - can display any dated notes based on configured property) Month Navigation: Browse forward and backward through months to view historical and future task distribution Mini Calendar is commonly used as an entry view: select a date, then open Task List, Agenda, or Calendar for execution. Calendar View# The Calendar View provides multiple view modes (month, week, day, year, list, and custom days) with drag-and-drop scheduling and time-blocking capabilities. Tasks can be created by clicking on dates or time slots, and rescheduled by dragging them to new dates or times. View Modes# The Calendar View supports the following view modes: Month: Month grid showing all-day and timed events Week: Week view with hourly time slots for detailed scheduling Day: Single day view with hourly breakdown Year: Annual overview showing event distribution across months List: Chronological list of events. TaskNotes also includes a dedicated Agenda command that opens this mode via its own .base file for quick reviews. Custom Days: Configurable multi-day view (2-10 days) View modes can be switched within a single .base file based on planning horizon (day, week, month, year, or custom range). Week View Day View Year View Performance Improvements# The Calendar View uses virtual scrolling to maintain performance when displaying large numbers of events. This allows the calendar to handle extensive task lists and long time ranges without degradation in responsiveness. Custom Days View# The Custom Days view provides a configurable multi-day calendar that displays between 2-10 days at once. This view addresses screen space utilization by offering a middle ground between the single-day view and the full week view. Key Features# Configurable Duration: Set the number of days to display (2-10 days) via Settings > Calendar > Custom view day count TimeGrid Format: Uses the same hourly time slots and time-based event layout as Week and Day views Real-time Updates: The view updates immediately when the day count setting is changed Default Configuration: Ships with 3 days displayed by default for optimal space utilization Use Cases# The Custom Days view is particularly useful for: Users who find the single-day view too wide and wasteful of screen space Planning workflows that require seeing a few days at a glance without the full week Detailed scheduling tasks that benefit from the time-grid format Customizing the viewing window to match personal preference and screen size Configuration# Select the View: Choose \"Custom Days\" from the calendar toolbar alongside Month, Week, Day, and Year views Adjust Day Count: Navigate to Settings > Calendar > Custom view day count and use the slider to select 2-10 days Set as Default: Optionally set \"Custom Days\" as your default view in Settings > Calendar > Default view Recurring Task Support# The Calendar View provides recurring task management with visual hierarchy and drag-and-drop behavior. Visual Hierarchy# Recurring tasks are displayed with distinct visual styling: Next Scheduled Occurrence: Solid border with full opacity, representing the specific date/time when you plan to work on the next instance Pattern Instances: Dashed border with reduced opacity (70%), showing preview of when future recurring instances will appear based on the DTSTART and recurrence rule Drag and Drop Behavior# The calendar provides different behaviors depending on which type of recurring event you drag: Dragging Next Scheduled Occurrence (Solid Border): Updates only the scheduled field in the task Reschedules just that specific occurrence to the new date/time Leaves the recurrence pattern unchanged Notice: \"Rescheduled next occurrence. This does not change the recurrence pattern.\" Dragging Pattern Instances (Dashed Border): Updates the DTSTART time in the recurrence rule Changes when all future pattern instances appear Does not affect the independently scheduled next occurrence Notice: \"Updated recurring pattern time. All future instances now appear at this time.\" Flexible Scheduling# The next scheduled occurrence can appear on any date, even: Before the DTSTART date On days that don't match the recurring pattern (e.g., Tuesday for a weekly Monday pattern) At different times than the pattern instances This flexibility allows for complete control over both the recurring pattern and individual occurrence scheduling. View Options# The Calendar View provides several display options that control what types of events appear on the calendar: Show scheduled: Display tasks with scheduled dates Show due: Display tasks with due dates Show timeblocks: Display time-blocking entries Show recurring: Display recurring task events Show ICS events: Display events from imported ICS calendars Show time entries: Display time tracking entries All-day slot: Show or hide the all-day event area at the top of time grid views (Week, Day, and Custom views) Create daily notes from date links: Let date header links create a missing daily note before opening it. Turn this off if date links should only open existing daily notes. Drag/drop resolution: Set snapDuration when you want events to drag or resize in smaller increments than the visible slotDuration, such as 5-minute dragging on a 30-minute grid. Span tasks between scheduled and due dates: Display tasks as multi-day bars spanning from their scheduled date to their due date (see below) Multiple saved calendar views can store different option sets (for example planning vs focus), avoiding repeated manual toggles. The All-day slot option is particularly useful when you have many all-day tasks on a single date, as hiding it can resolve scrolling issues and make the hourly time slots more accessible. When disabled, all-day events will not be displayed in time grid views, but they will still appear in month view. Multi-Day Task Spans# The Span tasks between scheduled and due dates option provides a visual representation of task duration on the calendar. When enabled: Tasks with both a scheduled date and a due date display as a single bar spanning across all days from the scheduled date to the due date This replaces the separate scheduled and due markers for qualifying tasks Tasks with only a scheduled date or only a due date continue to display as single-day events Span events are shown as all-day bars with the task's priority color Span events are read-only on the calendar (edit the underlying scheduled/due dates to modify) This option is useful for project planning and visualizing how long tasks are expected to take, similar to Gantt chart-style views. These display options are preserved when you save a view, allowing you to create specialized calendar views that show only specific types of events and maintain those preferences across sessions. OAuth Calendar Integration# The Calendar View supports bidirectional synchronization with external calendar services through OAuth authentication: Google Calendar: Connect to Google Calendar accounts to display and sync events Microsoft Outlook: Connect to Microsoft Outlook accounts for calendar integration Synchronization Behavior# External calendar events appear alongside TaskNotes tasks in all calendar views Drag and drop events to reschedule them - changes sync back to the external calendar service Events from external calendars respect the same view options and display settings as native TaskNotes tasks Configuration# OAuth calendar connections are configured through the TaskNotes settings panel. Authentication uses standard OAuth flows to securely connect to external services. Time Entry Editor Modal# The Calendar View includes a Time Entry Editor Modal for creating time tracking entries directly from the calendar interface. Creating Time Entries# Drag on the calendar to select a time range When the selection menu appears, choose Create time entry The modal opens with the start and end times pre-populated based on the selection, and the entry can be linked to a task or left standalone Editing Time Entries# Time entries displayed on the calendar can be selected to open the Time Entry Editor Modal for modification. The modal provides fields for adjusting start time, end time, associated task, and other time entry metadata. Filtering and View Configuration# Calendar filtering is configured through the Bases YAML frontmatter in the .base file. This allows you to define which tasks and events appear in each calendar view. Filtering options include task properties, date ranges, tags, and other criteria supported by the Bases plugin. Saved calendar views retain their filter configuration, display options, and view mode, allowing you to create specialized calendar views for different purposes."},{"route":"/obsidian/views/kanban-view/","title":"Kanban View","description":"The Kanban View displays tasks as cards organized in columns, where each column represents a distinct value of a grouped property. Kanban emphasizes state transitions and drag o...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/views/kanban-view.md","namespace":"obsidian","relativePath":"views/kanban-view.md","raw":"# Kanban View\n\n\nThe Kanban View displays tasks as cards organized in columns, where each column represents a distinct value of a grouped property.\nKanban emphasizes state transitions and drag operations over dense list scanning.\n\n![Kanban View](../assets/views-kanban.png)\n\n## Configuration\n\nKanban views are stored as `.base` files in `TaskNotes/Views/`. The `groupBy` property determines the column structure—each unique value becomes a column in the board. Open a `.base` file and access the view settings panel to configure options.\n\n### Core Settings (Bases)\n\n- **Data source**: Select which files or folders to include in the view\n- **Filter**: Define criteria to include or exclude specific tasks\n- **Sort**: Specify the order of tasks within each column\n- **Group by**: Required. Defines the property that creates columns (e.g., status, priority)\nChoosing a stable `groupBy` field is the most important design decision. Frequent changes to this field create column churn and make historical comparisons harder.\n\n### Kanban-Specific Options\n\nAccess these options through the Bases view settings panel:\n\n- **Swim Lane**: Optional property for horizontal grouping. Creates a two-dimensional layout where tasks are organized by both column (groupBy) and row (swimLane)\n- **Column Width**: Controls the width of columns in pixels. Range: 200-500px. Default: 280px\n- **Max Swimlane Height**: Caps each swimlane row before the task area scrolls. Range: 300-1200px. Default: 600px\n- **Hide Empty Columns**: When enabled, columns containing no tasks are hidden from the view\n- **Pinned Columns**: Optional comma-separated list of column values that should stay visible even when empty. This is useful with **Hide Empty Columns** when each board needs a small stable subset of shared statuses or categories\n- **WIP Limits**: Advanced JSON configuration for showing per-column work-in-progress limits in column headers\n- **Hide Empty Swimlanes**: When enabled, ordered swimlanes with no tasks are hidden from the view\n- **Card Layout**: Chooses the task card density for this board. **Default** uses the standard TaskNotes card layout. **Compact** uses a tighter card layout for denser boards\n- **Show items in multiple columns**: When enabled (default), tasks with multiple values in list properties (contexts, tags, projects) appear in each individual column. For example, a task with `contexts: [work, call]` appears in both the \"work\" and \"call\" columns. When disabled, tasks appear in a single combined column (e.g., \"work, call\")\n- **Hide top-level subtasks**: When enabled, tasks whose Projects field links to another task in the current filtered board are hidden as standalone cards and remain available through the parent task's expanded subtasks\n- **Column Order**: Managed automatically when dragging column headers. Stores custom column ordering\n- **Swim Lane Order**: Advanced JSON configuration for pinning swimlane rows in a stable order\nA common setup is to keep one board grouped by status and another grouped by project or context, each in a separate `.base` file.\n\n## Interface Layout\n\n### Standard Layout\n\nIn standard mode, the Kanban board displays a horizontal row of columns. Each column corresponds to a unique value of the `groupBy` property.\n\nEach column includes:\n- A header showing the property value and task count\n- A scrollable area containing task cards\n- An add button that opens the TaskNotes creation modal with the column value filled in\n- Drag-and-drop functionality for reordering columns or moving tasks between columns\n\n### Swimlane Layout\n\nWhen a `swimLane` property is configured, the board displays a grid layout. The horizontal axis represents columns (groupBy values), and the vertical axis represents swimlanes.\n\nEach swimlane row includes:\n- A label cell showing the swimlane property value and total task count\n- Multiple cells, each representing a column within that swimlane\n- Scrollable cells containing task cards\n- Add buttons inside cells that fill in both the column value and swimlane value\n\nTo pin swimlanes in a stable order, set the advanced `swimLaneOrder` option to a JSON object keyed by the swimlane property:\n\n```yaml\nconfig:\n swimLane: note.contexts\n swimLaneOrder: '{\"note.contexts\":[\"transitcal\",\"bill\",\"cycles-research\",\"astrolabe\"]}'\n```\n\nListed swimlane values render first in the configured order. Values not listed in `swimLaneOrder` render below them using the default order for status and priority swimlanes, or alphabetically for other properties. If `hideEmptySwimLanes` is disabled, listed values can remain visible even when no matching tasks are currently present.\n\nTo show WIP limits in column headers, set the advanced `wipLimits` option to a JSON object keyed by column value:\n\n```yaml\nconfig:\n wipLimits: '{\"in-progress\":5,\"review\":2}'\n```\n\nColumns with limits display counts as `(current/limit)`. When the current count is above the configured limit, the count uses the error color. In swimlane boards, the column header count is the total for that column across all swimlanes.\n\n## Task Cards\n\nEach task card displays information based on the visible properties configured in the Bases view. Standard task information includes title, priority, due date, and scheduled date.\n\nUse the **Card Layout** setting when a board needs a different density from other task views. Existing boards use **Default** unless `cardLayout: compact` is set in the view options.\n\nTo show checklist progress on cards, include `file.tasks` in the view `order` array.\nFor existing `.base` files, add this in YAML manually first; after it is in `order`, it appears in the Bases picker as `tasks`.\n\nClick a card to open the task file for editing. Right-click to access the context menu for task actions. Drag cards between columns or swimlane cells to update the task's properties.\n\n## Column Operations\n\n### Reordering Columns\n\nDrag column headers to reorder columns. The new order persists across sessions and is stored in the `columnOrder` configuration.\n\n### Drag-and-Drop Tasks\n\nDrag task cards between columns to update the `groupBy` property value. In swimlane mode, dragging a task to a different cell updates both the `groupBy` and `swimLane` properties.\n\nWhen grouping by a list property (contexts, tags, projects) with \"Show items in multiple columns\" enabled, dragging a task between columns modifies the list rather than replacing it. The source column's value is removed and the target column's value is added. For example, dragging a task from the \"work\" column to the \"home\" column changes `contexts: [work, call]` to `contexts: [call, home]`.\nDrag operations write directly to task metadata, so consistent grouping values reduce ambiguity.\n\nThe add button at the bottom of a column or swimlane cell keeps deterministic view filter defaults and fills in the grouped values for that location.\n\n### Manual Reordering Within Columns\n\nKanban also supports drag-to-reorder within a column or swimlane cell when the view is sorted by the manual-order property. With the default field mapping, that property is `tasknotes_manual_order`.\n\nTo enable persistent manual ordering within Kanban columns:\n\n```yaml\nsort:\n - column: tasknotes_manual_order\n direction: DESC\n```\n\nOnce the first sort criterion is the manual-order property, dragging a card within the same column updates stored frontmatter values so the new order persists across refreshes and sessions.\n\nIn swimlane mode, the reorder scope is a single cell, not the entire board. A reorder inside the \"In Progress\" column for the \"High\" swimlane only adjusts the tasks in that cell.\n\nImportant constraints:\n\n- Manual drag-to-reorder only works when the view sort includes the manual-order property.\n- Moving a card to a different column or swimlane still updates the grouped property values as usual.\n- In filtered or partially visible columns, TaskNotes may also update hidden or filtered notes in the same reorder scope to preserve a stable persistent order.\n- Large reorder operations may show a confirmation dialog before writing changes.\n\nThe default generated TaskNotes templates use manual-order sorting in places where drag-to-reorder should work immediately, such as relationship views and manual-order task lists.\n\n## Performance Optimization\n\nThe Kanban view implements virtual scrolling for columns or swimlane cells containing 30 or more tasks. This optimization reduces memory usage by approximately 85% and maintains 60fps scrolling performance for columns with 200+ tasks.\n\nVirtual scrolling activates automatically based on task count. No configuration is required.\n\n## Example Configuration\n\nA typical Kanban view `.base` file includes:\n\n```yaml\n---\ntype: query\nsource: TaskNotes\nview: TaskNotes Kanban\nviews:\n - name: TaskNotes Kanban\n type: tasknotesKanban\n groupBy:\n property: task.status\n config:\n swimLane: task.priority\n swimLaneOrder: '{\"task.priority\":[\"high\",\"normal\",\"low\"]}'\n columnWidth: 300\n hideEmptyColumns: true\n pinnedColumns: to-do, in-progress, done\n wipLimits: '{\"in-progress\":5}'\n---\n```\n\nThis configuration creates a Kanban board with:\n- Columns based on task status\n- Swimlanes based on task priority\n- Priority swimlanes pinned in high, normal, low order\n- 300px column width\n- Empty unpinned columns hidden, while the to-do, in-progress, and done columns stay visible as drop targets\n- A WIP limit of 5 tasks on the in-progress column\n\n## Filtering and Sorting\n\nFiltering and sorting are configured through the Bases view settings, not through a separate FilterBar component. Use the Bases filter editor to define conditions based on task properties. Use the Bases sort editor to specify the order of tasks within each column.\n","aliases":["/views/kanban-view/"],"toc":[{"level":2,"id":"configuration","text":"Configuration"},{"level":3,"id":"core-settings-bases","text":"Core Settings (Bases)"},{"level":3,"id":"kanban-specific-options","text":"Kanban-Specific Options"},{"level":2,"id":"interface-layout","text":"Interface Layout"},{"level":3,"id":"standard-layout","text":"Standard Layout"},{"level":3,"id":"swimlane-layout","text":"Swimlane Layout"},{"level":2,"id":"task-cards","text":"Task Cards"},{"level":2,"id":"column-operations","text":"Column Operations"},{"level":3,"id":"reordering-columns","text":"Reordering Columns"},{"level":3,"id":"drag-and-drop-tasks","text":"Drag-and-Drop Tasks"},{"level":3,"id":"manual-reordering-within-columns","text":"Manual Reordering Within Columns"},{"level":2,"id":"performance-optimization","text":"Performance Optimization"},{"level":2,"id":"example-configuration","text":"Example Configuration"},{"level":2,"id":"filtering-and-sorting","text":"Filtering and Sorting"}],"html":"

The Kanban View displays tasks as cards organized in columns, where each column represents a distinct value of a grouped property.\nKanban emphasizes state transitions and drag operations over dense list scanning.

\n

\"Kanban

\n

Configuration#

\n

Kanban views are stored as .base files in TaskNotes/Views/. The groupBy property determines the column structure—each unique value becomes a column in the board. Open a .base file and access the view settings panel to configure options.

\n

Core Settings (Bases)#

\n
    \n
  • Data source: Select which files or folders to include in the view
  • \n
  • Filter: Define criteria to include or exclude specific tasks
  • \n
  • Sort: Specify the order of tasks within each column
  • \n
  • Group by: Required. Defines the property that creates columns (e.g., status, priority)\nChoosing a stable groupBy field is the most important design decision. Frequent changes to this field create column churn and make historical comparisons harder.
  • \n
\n

Kanban-Specific Options#

\n

Access these options through the Bases view settings panel:

\n
    \n
  • Swim Lane: Optional property for horizontal grouping. Creates a two-dimensional layout where tasks are organized by both column (groupBy) and row (swimLane)
  • \n
  • Column Width: Controls the width of columns in pixels. Range: 200-500px. Default: 280px
  • \n
  • Max Swimlane Height: Caps each swimlane row before the task area scrolls. Range: 300-1200px. Default: 600px
  • \n
  • Hide Empty Columns: When enabled, columns containing no tasks are hidden from the view
  • \n
  • Pinned Columns: Optional comma-separated list of column values that should stay visible even when empty. This is useful with Hide Empty Columns when each board needs a small stable subset of shared statuses or categories
  • \n
  • WIP Limits: Advanced JSON configuration for showing per-column work-in-progress limits in column headers
  • \n
  • Hide Empty Swimlanes: When enabled, ordered swimlanes with no tasks are hidden from the view
  • \n
  • Card Layout: Chooses the task card density for this board. Default uses the standard TaskNotes card layout. Compact uses a tighter card layout for denser boards
  • \n
  • Show items in multiple columns: When enabled (default), tasks with multiple values in list properties (contexts, tags, projects) appear in each individual column. For example, a task with contexts: [work, call] appears in both the "work" and "call" columns. When disabled, tasks appear in a single combined column (e.g., "work, call")
  • \n
  • Hide top-level subtasks: When enabled, tasks whose Projects field links to another task in the current filtered board are hidden as standalone cards and remain available through the parent task's expanded subtasks
  • \n
  • Column Order: Managed automatically when dragging column headers. Stores custom column ordering
  • \n
  • Swim Lane Order: Advanced JSON configuration for pinning swimlane rows in a stable order\nA common setup is to keep one board grouped by status and another grouped by project or context, each in a separate .base file.
  • \n
\n

Interface Layout#

\n

Standard Layout#

\n

In standard mode, the Kanban board displays a horizontal row of columns. Each column corresponds to a unique value of the groupBy property.

\n

Each column includes:

\n
    \n
  • A header showing the property value and task count
  • \n
  • A scrollable area containing task cards
  • \n
  • An add button that opens the TaskNotes creation modal with the column value filled in
  • \n
  • Drag-and-drop functionality for reordering columns or moving tasks between columns
  • \n
\n

Swimlane Layout#

\n

When a swimLane property is configured, the board displays a grid layout. The horizontal axis represents columns (groupBy values), and the vertical axis represents swimlanes.

\n

Each swimlane row includes:

\n
    \n
  • A label cell showing the swimlane property value and total task count
  • \n
  • Multiple cells, each representing a column within that swimlane
  • \n
  • Scrollable cells containing task cards
  • \n
  • Add buttons inside cells that fill in both the column value and swimlane value
  • \n
\n

To pin swimlanes in a stable order, set the advanced swimLaneOrder option to a JSON object keyed by the swimlane property:

\n
config:\n  swimLane: note.contexts\n  swimLaneOrder: '{"note.contexts":["transitcal","bill","cycles-research","astrolabe"]}'\n

Listed swimlane values render first in the configured order. Values not listed in swimLaneOrder render below them using the default order for status and priority swimlanes, or alphabetically for other properties. If hideEmptySwimLanes is disabled, listed values can remain visible even when no matching tasks are currently present.

\n

To show WIP limits in column headers, set the advanced wipLimits option to a JSON object keyed by column value:

\n
config:\n  wipLimits: '{"in-progress":5,"review":2}'\n

Columns with limits display counts as (current/limit). When the current count is above the configured limit, the count uses the error color. In swimlane boards, the column header count is the total for that column across all swimlanes.

\n

Task Cards#

\n

Each task card displays information based on the visible properties configured in the Bases view. Standard task information includes title, priority, due date, and scheduled date.

\n

Use the Card Layout setting when a board needs a different density from other task views. Existing boards use Default unless cardLayout: compact is set in the view options.

\n

To show checklist progress on cards, include file.tasks in the view order array.\nFor existing .base files, add this in YAML manually first; after it is in order, it appears in the Bases picker as tasks.

\n

Click a card to open the task file for editing. Right-click to access the context menu for task actions. Drag cards between columns or swimlane cells to update the task's properties.

\n

Column Operations#

\n

Reordering Columns#

\n

Drag column headers to reorder columns. The new order persists across sessions and is stored in the columnOrder configuration.

\n

Drag-and-Drop Tasks#

\n

Drag task cards between columns to update the groupBy property value. In swimlane mode, dragging a task to a different cell updates both the groupBy and swimLane properties.

\n

When grouping by a list property (contexts, tags, projects) with "Show items in multiple columns" enabled, dragging a task between columns modifies the list rather than replacing it. The source column's value is removed and the target column's value is added. For example, dragging a task from the "work" column to the "home" column changes contexts: [work, call] to contexts: [call, home].\nDrag operations write directly to task metadata, so consistent grouping values reduce ambiguity.

\n

The add button at the bottom of a column or swimlane cell keeps deterministic view filter defaults and fills in the grouped values for that location.

\n

Manual Reordering Within Columns#

\n

Kanban also supports drag-to-reorder within a column or swimlane cell when the view is sorted by the manual-order property. With the default field mapping, that property is tasknotes_manual_order.

\n

To enable persistent manual ordering within Kanban columns:

\n
sort:\n  - column: tasknotes_manual_order\n    direction: DESC\n

Once the first sort criterion is the manual-order property, dragging a card within the same column updates stored frontmatter values so the new order persists across refreshes and sessions.

\n

In swimlane mode, the reorder scope is a single cell, not the entire board. A reorder inside the "In Progress" column for the "High" swimlane only adjusts the tasks in that cell.

\n

Important constraints:

\n
    \n
  • Manual drag-to-reorder only works when the view sort includes the manual-order property.
  • \n
  • Moving a card to a different column or swimlane still updates the grouped property values as usual.
  • \n
  • In filtered or partially visible columns, TaskNotes may also update hidden or filtered notes in the same reorder scope to preserve a stable persistent order.
  • \n
  • Large reorder operations may show a confirmation dialog before writing changes.
  • \n
\n

The default generated TaskNotes templates use manual-order sorting in places where drag-to-reorder should work immediately, such as relationship views and manual-order task lists.

\n

Performance Optimization#

\n

The Kanban view implements virtual scrolling for columns or swimlane cells containing 30 or more tasks. This optimization reduces memory usage by approximately 85% and maintains 60fps scrolling performance for columns with 200+ tasks.

\n

Virtual scrolling activates automatically based on task count. No configuration is required.

\n

Example Configuration#

\n

A typical Kanban view .base file includes:

\n
---\ntype: query\nsource: TaskNotes\nview: TaskNotes Kanban\nviews:\n  - name: TaskNotes Kanban\n    type: tasknotesKanban\n    groupBy:\n      property: task.status\n    config:\n      swimLane: task.priority\n      swimLaneOrder: '{"task.priority":["high","normal","low"]}'\n      columnWidth: 300\n      hideEmptyColumns: true\n      pinnedColumns: to-do, in-progress, done\n      wipLimits: '{"in-progress":5}'\n---\n

This configuration creates a Kanban board with:

\n
    \n
  • Columns based on task status
  • \n
  • Swimlanes based on task priority
  • \n
  • Priority swimlanes pinned in high, normal, low order
  • \n
  • 300px column width
  • \n
  • Empty unpinned columns hidden, while the to-do, in-progress, and done columns stay visible as drop targets
  • \n
  • A WIP limit of 5 tasks on the in-progress column
  • \n
\n

Filtering and Sorting#

\n

Filtering and sorting are configured through the Bases view settings, not through a separate FilterBar component. Use the Bases filter editor to define conditions based on task properties. Use the Bases sort editor to specify the order of tasks within each column.

\n","text":"The Kanban View displays tasks as cards organized in columns, where each column represents a distinct value of a grouped property. Kanban emphasizes state transitions and drag operations over dense list scanning. Configuration# Kanban views are stored as .base files in TaskNotes/Views/. The groupBy property determines the column structure—each unique value becomes a column in the board. Open a .base file and access the view settings panel to configure options. Core Settings (Bases)# Data source: Select which files or folders to include in the view Filter: Define criteria to include or exclude specific tasks Sort: Specify the order of tasks within each column Group by: Required. Defines the property that creates columns (e.g., status, priority) Choosing a stable groupBy field is the most important design decision. Frequent changes to this field create column churn and make historical comparisons harder. Kanban-Specific Options# Access these options through the Bases view settings panel: Swim Lane: Optional property for horizontal grouping. Creates a two-dimensional layout where tasks are organized by both column (groupBy) and row (swimLane) Column Width: Controls the width of columns in pixels. Range: 200-500px. Default: 280px Max Swimlane Height: Caps each swimlane row before the task area scrolls. Range: 300-1200px. Default: 600px Hide Empty Columns: When enabled, columns containing no tasks are hidden from the view Pinned Columns: Optional comma-separated list of column values that should stay visible even when empty. This is useful with Hide Empty Columns when each board needs a small stable subset of shared statuses or categories WIP Limits: Advanced JSON configuration for showing per-column work-in-progress limits in column headers Hide Empty Swimlanes: When enabled, ordered swimlanes with no tasks are hidden from the view Card Layout: Chooses the task card density for this board. Default uses the standard TaskNotes card layout. Compact uses a tighter card layout for denser boards Show items in multiple columns: When enabled (default), tasks with multiple values in list properties (contexts, tags, projects) appear in each individual column. For example, a task with contexts: [work, call] appears in both the \"work\" and \"call\" columns. When disabled, tasks appear in a single combined column (e.g., \"work, call\") Hide top-level subtasks: When enabled, tasks whose Projects field links to another task in the current filtered board are hidden as standalone cards and remain available through the parent task's expanded subtasks Column Order: Managed automatically when dragging column headers. Stores custom column ordering Swim Lane Order: Advanced JSON configuration for pinning swimlane rows in a stable order A common setup is to keep one board grouped by status and another grouped by project or context, each in a separate .base file. Interface Layout# Standard Layout# In standard mode, the Kanban board displays a horizontal row of columns. Each column corresponds to a unique value of the groupBy property. Each column includes: A header showing the property value and task count A scrollable area containing task cards An add button that opens the TaskNotes creation modal with the column value filled in Drag-and-drop functionality for reordering columns or moving tasks between columns Swimlane Layout# When a swimLane property is configured, the board displays a grid layout. The horizontal axis represents columns (groupBy values), and the vertical axis represents swimlanes. Each swimlane row includes: A label cell showing the swimlane property value and total task count Multiple cells, each representing a column within that swimlane Scrollable cells containing task cards Add buttons inside cells that fill in both the column value and swimlane value To pin swimlanes in a stable order, set the advanced swimLaneOrder option to a JSON object keyed by the swimlane property: config: swimLane: note.contexts swimLaneOrder: '{\"note.contexts\":[\"transitcal\",\"bill\",\"cycles-research\",\"astrolabe\"]}' Listed swimlane values render first in the configured order. Values not listed in swimLaneOrder render below them using the default order for status and priority swimlanes, or alphabetically for other properties. If hideEmptySwimLanes is disabled, listed values can remain visible even when no matching tasks are currently present. To show WIP limits in column headers, set the advanced wipLimits option to a JSON object keyed by column value: config: wipLimits: '{\"in-progress\":5,\"review\":2}' Columns with limits display counts as (current/limit). When the current count is above the configured limit, the count uses the error color. In swimlane boards, the column header count is the total for that column across all swimlanes. Task Cards# Each task card displays information based on the visible properties configured in the Bases view. Standard task information includes title, priority, due date, and scheduled date. Use the Card Layout setting when a board needs a different density from other task views. Existing boards use Default unless cardLayout: compact is set in the view options. To show checklist progress on cards, include file.tasks in the view order array. For existing .base files, add this in YAML manually first; after it is in order, it appears in the Bases picker as tasks. Click a card to open the task file for editing. Right-click to access the context menu for task actions. Drag cards between columns or swimlane cells to update the task's properties. Column Operations# Reordering Columns# Drag column headers to reorder columns. The new order persists across sessions and is stored in the columnOrder configuration. Drag-and-Drop Tasks# Drag task cards between columns to update the groupBy property value. In swimlane mode, dragging a task to a different cell updates both the groupBy and swimLane properties. When grouping by a list property (contexts, tags, projects) with \"Show items in multiple columns\" enabled, dragging a task between columns modifies the list rather than replacing it. The source column's value is removed and the target column's value is added. For example, dragging a task from the \"work\" column to the \"home\" column changes contexts: [work, call] to contexts: [call, home]. Drag operations write directly to task metadata, so consistent grouping values reduce ambiguity. The add button at the bottom of a column or swimlane cell keeps deterministic view filter defaults and fills in the grouped values for that location. Manual Reordering Within Columns# Kanban also supports drag-to-reorder within a column or swimlane cell when the view is sorted by the manual-order property. With the default field mapping, that property is tasknotes_manual_order. To enable persistent manual ordering within Kanban columns: sort: - column: tasknotes_manual_order direction: DESC Once the first sort criterion is the manual-order property, dragging a card within the same column updates stored frontmatter values so the new order persists across refreshes and sessions. In swimlane mode, the reorder scope is a single cell, not the entire board. A reorder inside the \"In Progress\" column for the \"High\" swimlane only adjusts the tasks in that cell. Important constraints: Manual drag-to-reorder only works when the view sort includes the manual-order property. Moving a card to a different column or swimlane still updates the grouped property values as usual. In filtered or partially visible columns, TaskNotes may also update hidden or filtered notes in the same reorder scope to preserve a stable persistent order. Large reorder operations may show a confirmation dialog before writing changes. The default generated TaskNotes templates use manual-order sorting in places where drag-to-reorder should work immediately, such as relationship views and manual-order task lists. Performance Optimization# The Kanban view implements virtual scrolling for columns or swimlane cells containing 30 or more tasks. This optimization reduces memory usage by approximately 85% and maintains 60fps scrolling performance for columns with 200+ tasks. Virtual scrolling activates automatically based on task count. No configuration is required. Example Configuration# A typical Kanban view .base file includes: --- type: query source: TaskNotes view: TaskNotes Kanban views: - name: TaskNotes Kanban type: tasknotesKanban groupBy: property: task.status config: swimLane: task.priority swimLaneOrder: '{\"task.priority\":[\"high\",\"normal\",\"low\"]}' columnWidth: 300 hideEmptyColumns: true pinnedColumns: to-do, in-progress, done wipLimits: '{\"in-progress\":5}' --- This configuration creates a Kanban board with: Columns based on task status Swimlanes based on task priority Priority swimlanes pinned in high, normal, low order 300px column width Empty unpinned columns hidden, while the to-do, in-progress, and done columns stay visible as drop targets A WIP limit of 5 tasks on the in-progress column Filtering and Sorting# Filtering and sorting are configured through the Bases view settings, not through a separate FilterBar component. Use the Bases filter editor to define conditions based on task properties. Use the Bases sort editor to specify the order of tasks within each column."},{"route":"/obsidian/views/pomodoro-view/","title":"Pomodoro View","description":"The Pomodoro View provides a timer for working in focused intervals, based on the Pomodoro Technique.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/views/pomodoro-view.md","namespace":"obsidian","relativePath":"views/pomodoro-view.md","raw":"# Pomodoro View\n\n\nThe Pomodoro View provides a timer for working in focused intervals, based on the Pomodoro Technique.\n\n## Timer Interface\n\nThe Pomodoro View includes a timer with controls to start, stop, and reset the timer. While a timer is running, the view shows both the remaining duration and the projected local finish time. You can also associate a task with the timer, and the time will be automatically recorded in the task's time tracking data when the session is complete.\n\n![Pomodoro Timer](../assets/feature-pomodoro-timer.png)\n\n## Pomodoro Stats View\n\nThe Pomodoro Stats View provides analytics and historical data about your Pomodoro sessions. This includes a history of completed sessions, as well as metrics like completion rates and total time spent on tasks.\n\n![Pomodoro Statistics](../assets/feature-pomodoro-stats.png)\n","aliases":["/views/pomodoro-view/"],"toc":[{"level":2,"id":"timer-interface","text":"Timer Interface"},{"level":2,"id":"pomodoro-stats-view","text":"Pomodoro Stats View"}],"html":"

The Pomodoro View provides a timer for working in focused intervals, based on the Pomodoro Technique.

\n

Timer Interface#

\n

The Pomodoro View includes a timer with controls to start, stop, and reset the timer. While a timer is running, the view shows both the remaining duration and the projected local finish time. You can also associate a task with the timer, and the time will be automatically recorded in the task's time tracking data when the session is complete.

\n

\"Pomodoro

\n

Pomodoro Stats View#

\n

The Pomodoro Stats View provides analytics and historical data about your Pomodoro sessions. This includes a history of completed sessions, as well as metrics like completion rates and total time spent on tasks.

\n

\"Pomodoro

\n","text":"The Pomodoro View provides a timer for working in focused intervals, based on the Pomodoro Technique. Timer Interface# The Pomodoro View includes a timer with controls to start, stop, and reset the timer. While a timer is running, the view shows both the remaining duration and the projected local finish time. You can also associate a task with the timer, and the time will be automatically recorded in the task's time tracking data when the session is complete. Pomodoro Stats View# The Pomodoro Stats View provides analytics and historical data about your Pomodoro sessions. This includes a history of completed sessions, as well as metrics like completion rates and total time spent on tasks."},{"route":"/obsidian/views/task-list/","title":"Task List View","description":"The Task List View displays tasks in a scrollable list format with filtering, sorting, and grouping capabilities. In TaskNotes v4, this view operates as a Bases view configured...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/views/task-list.md","namespace":"obsidian","relativePath":"views/task-list.md","raw":"# Task List View\n\n\nThe Task List View displays tasks in a scrollable list format with filtering, sorting, and grouping capabilities. In TaskNotes v4, this view operates as a Bases view configured through YAML.\nThis view is optimized for high task volume and explicit filter definitions.\n\n![Task List View](../assets/views-tasks-list.png)\n\n## Bases Architecture\n\nTask List is implemented as a `.base` file located in `TaskNotes/Views/tasks-default.base` by default. It requires the Bases core plugin to be enabled.\n\n### What is Bases?\n\nBases is an official Obsidian core plugin built directly into Obsidian (not a community plugin). It provides a framework for creating database views of notes and tasks.\n\nTo enable Bases:\n1. Open `Settings -> Core Plugins`\n2. Enable \"Bases\"\n3. TaskNotes view commands will now open `.base` files from `TaskNotes/Views/`\nIf commands open empty or unexpected views, first confirm Bases is enabled and the command path points to the intended `.base` file.\n\n### View File Location\n\nWhen you use the \"Open Tasks View\" command or ribbon icon, TaskNotes opens the `.base` file configured under `Settings -> TaskNotes -> General -> Views & base files` (initially `TaskNotes/Views/tasks-default.base`). TaskNotes creates missing default `.base` files automatically on startup when **Auto-create default files** is enabled, and you can point the command to any other `.base` file if you maintain multiple task-list layouts.\n\n## Configuration\n\nTask List views are configured through YAML frontmatter in the `.base` file. The YAML defines which tasks to show, how to sort them, and how to group them.\n\n### Basic Structure\n\n```yaml\n# All Tasks\n\nviews:\n - type: tasknotesTaskList\n name: \"All Tasks\"\n order:\n - note.status\n - note.priority\n - note.due\n - note.scheduled\n - note.projects\n - note.contexts\n - file.tags\n sort:\n - column: due\n direction: ASC\n```\n\n### Configuration Options\n\n**`type`**: Must be `tasknotesTaskList` for Task List views\n\n**`name`**: Display name shown in the view header\n\n**`order`**: Array of property names that control which task properties are visible in the task cards. Properties are referenced using their Bases property paths (e.g., `note.status`, `note.priority`, `note.due`, `file.tasks`).\nFor existing `.base` files, add `file.tasks` in YAML manually; once present in `order`, it appears in the Bases picker as `tasks`.\n\n**`sort`**: Array of sort criteria. Tasks are sorted by the first criterion, with ties broken by subsequent criteria.\n- `column`: Property to sort by (e.g., `due`, `scheduled`, `priority`, `title`)\n- `direction`: `ASC` (ascending) or `DESC` (descending)\n\n**`groupBy`**: Optional grouping configuration\n- `property`: Property to group by (e.g., `note.status`, `note.priority`)\n- `direction`: Sort direction for group headers\n\n**`hideTopLevelSubtasks`**: Optional boolean. When `true`, tasks whose Projects field links to another task in the current filtered result set are hidden as top-level rows and remain available through the parent task's expanded subtasks.\n\n**`filters`**: Optional filter conditions using Bases query syntax\n```yaml\nfilters:\n and:\n - note.status == \"Open\"\n - note.priority == \"High\"\n```\nStart with one or two simple filters, verify results, then layer complexity. Incremental edits are much easier to debug than large one-shot query rewrites.\n\n### Property Mapping\n\nTaskNotes properties are accessed in Bases YAML using these paths:\n\n| TaskNotes Property | Bases Property Path | Description |\n|-------------------|-------------------|-------------|\n| Status | `note.status` | Task status value |\n| Priority | `note.priority` | Priority level |\n| Due date | `note.due` | Due date/time |\n| Scheduled date | `note.scheduled` | Scheduled date/time |\n| Projects | `note.projects` | Associated projects |\n| Contexts | `note.contexts` | Task contexts |\n| Tags | `file.tags` | File tags |\n| Checklist progress | `file.tasks` | First-level markdown checkbox progress shown as the TaskNotes checklist progress bar |\n| Time estimate | `note.timeEstimate` | Estimated duration |\n| Recurrence | `note.recurrence` | Recurrence pattern |\n| Blocked by | `note.blockedBy` | Blocking dependencies |\n| Title | `file.name` | Task title (file name) |\n| Created | `file.ctime` | File creation date |\n| Modified | `file.mtime` | File modification date |\n\nThe exact property names depend on your TaskNotes field mapping settings (`Settings -> TaskNotes -> Task Properties`). The table above shows default mappings.\n\n## Filtering and Sorting\n\n### Adding Filters\n\nEdit the `.base` file to add filter conditions using Bases query syntax:\n\n```yaml\nviews:\n - type: tasknotesTaskList\n name: \"High Priority Tasks\"\n filters:\n and:\n - note.priority == \"High\"\n - note.status != \"Completed\"\n order:\n - note.status\n - note.priority\n - note.due\n```\n\n### Filter Operators\n\nBases supports standard comparison operators:\n- `==` (equals), `!=` (not equals)\n- `>`, `<`, `>=`, `<=` (comparison)\n- `contains()` (substring/array membership)\n- Boolean logic: `and`, `or`\n\nFor detailed filter syntax, see the [Bases documentation](https://help.obsidian.md/Plugins/Bases).\n\n### Sorting Examples\n\nSingle sort criterion:\n```yaml\nsort:\n - column: due\n direction: ASC\n```\n\nMultiple sort criteria:\n```yaml\nsort:\n - column: priority\n direction: DESC\n - column: due\n direction: ASC\n - column: title\n direction: ASC\n```\n\n### Drag-to-Reorder\n\nTask List supports drag-to-reorder when the view is sorted by the manual-order property. With the default field mapping, that property is `tasknotes_manual_order`.\n\nTo enable persistent manual ordering in a Task List view:\n\n```yaml\nsort:\n - column: tasknotes_manual_order\n direction: DESC\n```\n\nOnce the first sort criterion is the manual-order property, you can drag task cards to reorder them. TaskNotes writes updated LexoRank-style values into task frontmatter so the order persists across refreshes and sessions.\n\nIf your field mapping changes the sort-order property name, use that mapped property name instead of `tasknotes_manual_order`.\n\n### Drag-to-Reorder with Grouping\n\nGrouped Task List views can also be reordered, but the reorder scope is the current group. For example, when grouping by status, dragging within the \"In Progress\" group updates the manual order for tasks in that group.\n\nImportant constraints:\n\n- Drag-to-reorder only works when the view sort includes the manual-order property.\n- Reordering in formula-based groups is blocked because formula values are computed and cannot be edited directly.\n- In filtered or partially visible lists, TaskNotes may also update hidden or filtered notes in the same reorder scope to preserve a stable persistent order.\n- Large reorder operations may show a confirmation dialog before writing changes.\n\nThe default generated TaskNotes task-list templates include a **Manual Order** view that is already configured for this behavior.\n\n## Grouping\n\nGroups organize tasks under collapsible headers based on a property value.\n\n### Enable Grouping\n\nAdd `groupBy` configuration to your view:\n\n```yaml\nviews:\n - type: tasknotesTaskList\n name: \"Tasks by Status\"\n groupBy:\n property: note.status\n direction: ASC\n order:\n - note.status\n - note.priority\n - note.due\n```\n\n### Available Grouping Properties\n\nCommon grouping properties:\n- `note.status` - Group by task status\n- `note.priority` - Group by priority level\n- `note.contexts` - Group by first context\n- `note.projects` - Group by project (tasks can appear in multiple groups)\n\n### Interactive Group Headers\n\nGroup headers support interaction:\n- Click to expand/collapse the group\n- Click on project links in headers to navigate to project notes\n- Hover over project links with Ctrl to preview project notes\n\n### Collapsed State Persistence\n\nCollapsed/expanded state for each group is preserved across sessions.\n\n## Creating Multiple Views\n\nYou can create multiple `.base` files for different task perspectives:\n\n1. Duplicate an existing `.base` file in `TaskNotes/Views/`\n2. Rename it (e.g., `High Priority.base`)\n3. Edit the YAML configuration for that view\n4. Open the file to see the customized view\n\n### Example: Context-Specific View\n\n```yaml\n# Work Tasks\n\nviews:\n - type: tasknotesTaskList\n name: \"Work Context\"\n filters:\n and:\n - note.contexts.contains(\"work\")\n groupBy:\n property: note.priority\n direction: DESC\n order:\n - note.status\n - note.priority\n - note.due\n```\n\n## Migrating from v3 Saved Views\n\nTaskNotes v3 stored filter configurations in plugin settings. These saved views are **not automatically migrated** to v4.\n\nTo recreate a v3 saved view:\n1. Create a new `.base` file in `TaskNotes/Views/`\n2. Translate your v3 filter conditions to Bases YAML syntax\n3. Configure sorting and grouping through YAML\n4. Save the file\n\nThe v3 FilterBar UI component no longer exists - all configuration is done through YAML editing.\n\n## Task Actions\n\nThe Task List View provides interaction with tasks through clicking and context menus:\n\n- **Click on a task**: Opens the task for editing or navigates to the task note (behavior configured in `Settings -> TaskNotes -> General` in click-action controls)\n- **Right-click on a task**: Opens a context menu with actions:\n - Mark as complete\n - Change priority\n - Change status\n - Edit dates\n - Delete task\n - And more\n\nContext menu availability depends on your TaskNotes settings and task properties.\n\n## Virtual Scrolling\n\nThe Task List View automatically enables virtual scrolling when displaying 100 or more items (tasks + group headers). Virtual scrolling provides:\n\n- Approximately 90% memory reduction for large lists\n- Elimination of UI lag when scrolling through hundreds of tasks\n- Smooth performance with unlimited task counts\n\nVirtual scrolling activates automatically and requires no configuration. When active, only visible tasks are rendered to the DOM, with off-screen tasks rendered on-demand as you scroll.\n\n## Further Reading\n\n- [Default Base Templates](default-base-templates.md) - Complete templates for all TaskNotes views\n- [Bases Plugin Documentation](https://help.obsidian.md/Plugins/Bases) - Official Obsidian documentation for Bases syntax and features\n- [Kanban View](kanban-view.md) - Alternative board-based task visualization\n- [Calendar Views](calendar-views.md) - Time-based task visualization\n- [Views Overview](../views.md) - All available TaskNotes views\n","aliases":["/views/task-list/"],"toc":[{"level":2,"id":"bases-architecture","text":"Bases Architecture"},{"level":3,"id":"what-is-bases","text":"What is Bases?"},{"level":3,"id":"view-file-location","text":"View File Location"},{"level":2,"id":"configuration","text":"Configuration"},{"level":3,"id":"basic-structure","text":"Basic Structure"},{"level":3,"id":"configuration-options","text":"Configuration Options"},{"level":3,"id":"property-mapping","text":"Property Mapping"},{"level":2,"id":"filtering-and-sorting","text":"Filtering and Sorting"},{"level":3,"id":"adding-filters","text":"Adding Filters"},{"level":3,"id":"filter-operators","text":"Filter Operators"},{"level":3,"id":"sorting-examples","text":"Sorting Examples"},{"level":3,"id":"drag-to-reorder","text":"Drag-to-Reorder"},{"level":3,"id":"drag-to-reorder-with-grouping","text":"Drag-to-Reorder with Grouping"},{"level":2,"id":"grouping","text":"Grouping"},{"level":3,"id":"enable-grouping","text":"Enable Grouping"},{"level":3,"id":"available-grouping-properties","text":"Available Grouping Properties"},{"level":3,"id":"interactive-group-headers","text":"Interactive Group Headers"},{"level":3,"id":"collapsed-state-persistence","text":"Collapsed State Persistence"},{"level":2,"id":"creating-multiple-views","text":"Creating Multiple Views"},{"level":3,"id":"example-context-specific-view","text":"Example: Context-Specific View"},{"level":2,"id":"migrating-from-v3-saved-views","text":"Migrating from v3 Saved Views"},{"level":2,"id":"task-actions","text":"Task Actions"},{"level":2,"id":"virtual-scrolling","text":"Virtual Scrolling"},{"level":2,"id":"further-reading","text":"Further Reading"}],"html":"

The Task List View displays tasks in a scrollable list format with filtering, sorting, and grouping capabilities. In TaskNotes v4, this view operates as a Bases view configured through YAML.\nThis view is optimized for high task volume and explicit filter definitions.

\n

\"Task

\n

Bases Architecture#

\n

Task List is implemented as a .base file located in TaskNotes/Views/tasks-default.base by default. It requires the Bases core plugin to be enabled.

\n

What is Bases?#

\n

Bases is an official Obsidian core plugin built directly into Obsidian (not a community plugin). It provides a framework for creating database views of notes and tasks.

\n

To enable Bases:

\n
    \n
  1. Open Settings -> Core Plugins
  2. \n
  3. Enable "Bases"
  4. \n
  5. TaskNotes view commands will now open .base files from TaskNotes/Views/\nIf commands open empty or unexpected views, first confirm Bases is enabled and the command path points to the intended .base file.
  6. \n
\n

View File Location#

\n

When you use the "Open Tasks View" command or ribbon icon, TaskNotes opens the .base file configured under Settings -> TaskNotes -> General -> Views & base files (initially TaskNotes/Views/tasks-default.base). TaskNotes creates missing default .base files automatically on startup when Auto-create default files is enabled, and you can point the command to any other .base file if you maintain multiple task-list layouts.

\n

Configuration#

\n

Task List views are configured through YAML frontmatter in the .base file. The YAML defines which tasks to show, how to sort them, and how to group them.

\n

Basic Structure#

\n
# All Tasks\n\nviews:\n  - type: tasknotesTaskList\n    name: "All Tasks"\n    order:\n      - note.status\n      - note.priority\n      - note.due\n      - note.scheduled\n      - note.projects\n      - note.contexts\n      - file.tags\n    sort:\n      - column: due\n        direction: ASC\n

Configuration Options#

\n

type: Must be tasknotesTaskList for Task List views

\n

name: Display name shown in the view header

\n

order: Array of property names that control which task properties are visible in the task cards. Properties are referenced using their Bases property paths (e.g., note.status, note.priority, note.due, file.tasks).\nFor existing .base files, add file.tasks in YAML manually; once present in order, it appears in the Bases picker as tasks.

\n

sort: Array of sort criteria. Tasks are sorted by the first criterion, with ties broken by subsequent criteria.

\n
    \n
  • column: Property to sort by (e.g., due, scheduled, priority, title)
  • \n
  • direction: ASC (ascending) or DESC (descending)
  • \n
\n

groupBy: Optional grouping configuration

\n
    \n
  • property: Property to group by (e.g., note.status, note.priority)
  • \n
  • direction: Sort direction for group headers
  • \n
\n

hideTopLevelSubtasks: Optional boolean. When true, tasks whose Projects field links to another task in the current filtered result set are hidden as top-level rows and remain available through the parent task's expanded subtasks.

\n

filters: Optional filter conditions using Bases query syntax

\n
filters:\n  and:\n    - note.status == "Open"\n    - note.priority == "High"\n

Start with one or two simple filters, verify results, then layer complexity. Incremental edits are much easier to debug than large one-shot query rewrites.

\n

Property Mapping#

\n

TaskNotes properties are accessed in Bases YAML using these paths:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
TaskNotes PropertyBases Property PathDescription
Statusnote.statusTask status value
Prioritynote.priorityPriority level
Due datenote.dueDue date/time
Scheduled datenote.scheduledScheduled date/time
Projectsnote.projectsAssociated projects
Contextsnote.contextsTask contexts
Tagsfile.tagsFile tags
Checklist progressfile.tasksFirst-level markdown checkbox progress shown as the TaskNotes checklist progress bar
Time estimatenote.timeEstimateEstimated duration
Recurrencenote.recurrenceRecurrence pattern
Blocked bynote.blockedByBlocking dependencies
Titlefile.nameTask title (file name)
Createdfile.ctimeFile creation date
Modifiedfile.mtimeFile modification date
\n

The exact property names depend on your TaskNotes field mapping settings (Settings -> TaskNotes -> Task Properties). The table above shows default mappings.

\n

Filtering and Sorting#

\n

Adding Filters#

\n

Edit the .base file to add filter conditions using Bases query syntax:

\n
views:\n  - type: tasknotesTaskList\n    name: "High Priority Tasks"\n    filters:\n      and:\n        - note.priority == "High"\n        - note.status != "Completed"\n    order:\n      - note.status\n      - note.priority\n      - note.due\n

Filter Operators#

\n

Bases supports standard comparison operators:

\n
    \n
  • == (equals), != (not equals)
  • \n
  • >, <, >=, <= (comparison)
  • \n
  • contains() (substring/array membership)
  • \n
  • Boolean logic: and, or
  • \n
\n

For detailed filter syntax, see the Bases documentation.

\n

Sorting Examples#

\n

Single sort criterion:

\n
sort:\n  - column: due\n    direction: ASC\n

Multiple sort criteria:

\n
sort:\n  - column: priority\n    direction: DESC\n  - column: due\n    direction: ASC\n  - column: title\n    direction: ASC\n

Drag-to-Reorder#

\n

Task List supports drag-to-reorder when the view is sorted by the manual-order property. With the default field mapping, that property is tasknotes_manual_order.

\n

To enable persistent manual ordering in a Task List view:

\n
sort:\n  - column: tasknotes_manual_order\n    direction: DESC\n

Once the first sort criterion is the manual-order property, you can drag task cards to reorder them. TaskNotes writes updated LexoRank-style values into task frontmatter so the order persists across refreshes and sessions.

\n

If your field mapping changes the sort-order property name, use that mapped property name instead of tasknotes_manual_order.

\n

Drag-to-Reorder with Grouping#

\n

Grouped Task List views can also be reordered, but the reorder scope is the current group. For example, when grouping by status, dragging within the "In Progress" group updates the manual order for tasks in that group.

\n

Important constraints:

\n
    \n
  • Drag-to-reorder only works when the view sort includes the manual-order property.
  • \n
  • Reordering in formula-based groups is blocked because formula values are computed and cannot be edited directly.
  • \n
  • In filtered or partially visible lists, TaskNotes may also update hidden or filtered notes in the same reorder scope to preserve a stable persistent order.
  • \n
  • Large reorder operations may show a confirmation dialog before writing changes.
  • \n
\n

The default generated TaskNotes task-list templates include a Manual Order view that is already configured for this behavior.

\n

Grouping#

\n

Groups organize tasks under collapsible headers based on a property value.

\n

Enable Grouping#

\n

Add groupBy configuration to your view:

\n
views:\n  - type: tasknotesTaskList\n    name: "Tasks by Status"\n    groupBy:\n      property: note.status\n      direction: ASC\n    order:\n      - note.status\n      - note.priority\n      - note.due\n

Available Grouping Properties#

\n

Common grouping properties:

\n
    \n
  • note.status - Group by task status
  • \n
  • note.priority - Group by priority level
  • \n
  • note.contexts - Group by first context
  • \n
  • note.projects - Group by project (tasks can appear in multiple groups)
  • \n
\n

Interactive Group Headers#

\n

Group headers support interaction:

\n
    \n
  • Click to expand/collapse the group
  • \n
  • Click on project links in headers to navigate to project notes
  • \n
  • Hover over project links with Ctrl to preview project notes
  • \n
\n

Collapsed State Persistence#

\n

Collapsed/expanded state for each group is preserved across sessions.

\n

Creating Multiple Views#

\n

You can create multiple .base files for different task perspectives:

\n
    \n
  1. Duplicate an existing .base file in TaskNotes/Views/
  2. \n
  3. Rename it (e.g., High Priority.base)
  4. \n
  5. Edit the YAML configuration for that view
  6. \n
  7. Open the file to see the customized view
  8. \n
\n

Example: Context-Specific View#

\n
# Work Tasks\n\nviews:\n  - type: tasknotesTaskList\n    name: "Work Context"\n    filters:\n      and:\n        - note.contexts.contains("work")\n    groupBy:\n      property: note.priority\n      direction: DESC\n    order:\n      - note.status\n      - note.priority\n      - note.due\n

Migrating from v3 Saved Views#

\n

TaskNotes v3 stored filter configurations in plugin settings. These saved views are not automatically migrated to v4.

\n

To recreate a v3 saved view:

\n
    \n
  1. Create a new .base file in TaskNotes/Views/
  2. \n
  3. Translate your v3 filter conditions to Bases YAML syntax
  4. \n
  5. Configure sorting and grouping through YAML
  6. \n
  7. Save the file
  8. \n
\n

The v3 FilterBar UI component no longer exists - all configuration is done through YAML editing.

\n

Task Actions#

\n

The Task List View provides interaction with tasks through clicking and context menus:

\n
    \n
  • Click on a task: Opens the task for editing or navigates to the task note (behavior configured in Settings -> TaskNotes -> General in click-action controls)
  • \n
  • Right-click on a task: Opens a context menu with actions:
      \n
    • Mark as complete
    • \n
    • Change priority
    • \n
    • Change status
    • \n
    • Edit dates
    • \n
    • Delete task
    • \n
    • And more
    • \n
    \n
  • \n
\n

Context menu availability depends on your TaskNotes settings and task properties.

\n

Virtual Scrolling#

\n

The Task List View automatically enables virtual scrolling when displaying 100 or more items (tasks + group headers). Virtual scrolling provides:

\n
    \n
  • Approximately 90% memory reduction for large lists
  • \n
  • Elimination of UI lag when scrolling through hundreds of tasks
  • \n
  • Smooth performance with unlimited task counts
  • \n
\n

Virtual scrolling activates automatically and requires no configuration. When active, only visible tasks are rendered to the DOM, with off-screen tasks rendered on-demand as you scroll.

\n

Further Reading#

\n\n","text":"The Task List View displays tasks in a scrollable list format with filtering, sorting, and grouping capabilities. In TaskNotes v4, this view operates as a Bases view configured through YAML. This view is optimized for high task volume and explicit filter definitions. Bases Architecture# Task List is implemented as a .base file located in TaskNotes/Views/tasks-default.base by default. It requires the Bases core plugin to be enabled. What is Bases?# Bases is an official Obsidian core plugin built directly into Obsidian (not a community plugin). It provides a framework for creating database views of notes and tasks. To enable Bases: Open Settings -> Core Plugins Enable \"Bases\" TaskNotes view commands will now open .base files from TaskNotes/Views/ If commands open empty or unexpected views, first confirm Bases is enabled and the command path points to the intended .base file. View File Location# When you use the \"Open Tasks View\" command or ribbon icon, TaskNotes opens the .base file configured under Settings -> TaskNotes -> General -> Views & base files (initially TaskNotes/Views/tasks-default.base). TaskNotes creates missing default .base files automatically on startup when Auto-create default files is enabled, and you can point the command to any other .base file if you maintain multiple task-list layouts. Configuration# Task List views are configured through YAML frontmatter in the .base file. The YAML defines which tasks to show, how to sort them, and how to group them. Basic Structure# # All Tasks views: - type: tasknotesTaskList name: \"All Tasks\" order: - note.status - note.priority - note.due - note.scheduled - note.projects - note.contexts - file.tags sort: - column: due direction: ASC Configuration Options# type: Must be tasknotesTaskList for Task List views name: Display name shown in the view header order: Array of property names that control which task properties are visible in the task cards. Properties are referenced using their Bases property paths (e.g., note.status, note.priority, note.due, file.tasks). For existing .base files, add file.tasks in YAML manually; once present in order, it appears in the Bases picker as tasks. sort: Array of sort criteria. Tasks are sorted by the first criterion, with ties broken by subsequent criteria. column: Property to sort by (e.g., due, scheduled, priority, title) direction: ASC (ascending) or DESC (descending) groupBy: Optional grouping configuration property: Property to group by (e.g., note.status, note.priority) direction: Sort direction for group headers hideTopLevelSubtasks: Optional boolean. When true, tasks whose Projects field links to another task in the current filtered result set are hidden as top-level rows and remain available through the parent task's expanded subtasks. filters: Optional filter conditions using Bases query syntax filters: and: - note.status == \"Open\" - note.priority == \"High\" Start with one or two simple filters, verify results, then layer complexity. Incremental edits are much easier to debug than large one-shot query rewrites. Property Mapping# TaskNotes properties are accessed in Bases YAML using these paths: TaskNotes Property Bases Property Path Description Status note.status Task status value Priority note.priority Priority level Due date note.due Due date/time Scheduled date note.scheduled Scheduled date/time Projects note.projects Associated projects Contexts note.contexts Task contexts Tags file.tags File tags Checklist progress file.tasks First-level markdown checkbox progress shown as the TaskNotes checklist progress bar Time estimate note.timeEstimate Estimated duration Recurrence note.recurrence Recurrence pattern Blocked by note.blockedBy Blocking dependencies Title file.name Task title (file name) Created file.ctime File creation date Modified file.mtime File modification date The exact property names depend on your TaskNotes field mapping settings (Settings -> TaskNotes -> Task Properties). The table above shows default mappings. Filtering and Sorting# Adding Filters# Edit the .base file to add filter conditions using Bases query syntax: views: - type: tasknotesTaskList name: \"High Priority Tasks\" filters: and: - note.priority == \"High\" - note.status != \"Completed\" order: - note.status - note.priority - note.due Filter Operators# Bases supports standard comparison operators: == (equals), != (not equals) >, <, >=, <= (comparison) contains() (substring/array membership) Boolean logic: and, or For detailed filter syntax, see the Bases documentation. Sorting Examples# Single sort criterion: sort: - column: due direction: ASC Multiple sort criteria: sort: - column: priority direction: DESC - column: due direction: ASC - column: title direction: ASC Drag-to-Reorder# Task List supports drag-to-reorder when the view is sorted by the manual-order property. With the default field mapping, that property is tasknotes_manual_order. To enable persistent manual ordering in a Task List view: sort: - column: tasknotes_manual_order direction: DESC Once the first sort criterion is the manual-order property, you can drag task cards to reorder them. TaskNotes writes updated LexoRank-style values into task frontmatter so the order persists across refreshes and sessions. If your field mapping changes the sort-order property name, use that mapped property name instead of tasknotes_manual_order. Drag-to-Reorder with Grouping# Grouped Task List views can also be reordered, but the reorder scope is the current group. For example, when grouping by status, dragging within the \"In Progress\" group updates the manual order for tasks in that group. Important constraints: Drag-to-reorder only works when the view sort includes the manual-order property. Reordering in formula-based groups is blocked because formula values are computed and cannot be edited directly. In filtered or partially visible lists, TaskNotes may also update hidden or filtered notes in the same reorder scope to preserve a stable persistent order. Large reorder operations may show a confirmation dialog before writing changes. The default generated TaskNotes task-list templates include a Manual Order view that is already configured for this behavior. Grouping# Groups organize tasks under collapsible headers based on a property value. Enable Grouping# Add groupBy configuration to your view: views: - type: tasknotesTaskList name: \"Tasks by Status\" groupBy: property: note.status direction: ASC order: - note.status - note.priority - note.due Available Grouping Properties# Common grouping properties: note.status - Group by task status note.priority - Group by priority level note.contexts - Group by first context note.projects - Group by project (tasks can appear in multiple groups) Interactive Group Headers# Group headers support interaction: Click to expand/collapse the group Click on project links in headers to navigate to project notes Hover over project links with Ctrl to preview project notes Collapsed State Persistence# Collapsed/expanded state for each group is preserved across sessions. Creating Multiple Views# You can create multiple .base files for different task perspectives: Duplicate an existing .base file in TaskNotes/Views/ Rename it (e.g., High Priority.base) Edit the YAML configuration for that view Open the file to see the customized view Example: Context-Specific View# # Work Tasks views: - type: tasknotesTaskList name: \"Work Context\" filters: and: - note.contexts.contains(\"work\") groupBy: property: note.priority direction: DESC order: - note.status - note.priority - note.due Migrating from v3 Saved Views# TaskNotes v3 stored filter configurations in plugin settings. These saved views are not automatically migrated to v4. To recreate a v3 saved view: Create a new .base file in TaskNotes/Views/ Translate your v3 filter conditions to Bases YAML syntax Configure sorting and grouping through YAML Save the file The v3 FilterBar UI component no longer exists - all configuration is done through YAML editing. Task Actions# The Task List View provides interaction with tasks through clicking and context menus: Click on a task: Opens the task for editing or navigates to the task note (behavior configured in Settings -> TaskNotes -> General in click-action controls) Right-click on a task: Opens a context menu with actions: Mark as complete Change priority Change status Edit dates Delete task And more Context menu availability depends on your TaskNotes settings and task properties. Virtual Scrolling# The Task List View automatically enables virtual scrolling when displaying 100 or more items (tasks + group headers). Virtual scrolling provides: Approximately 90% memory reduction for large lists Elimination of UI lag when scrolling through hundreds of tasks Smooth performance with unlimited task counts Virtual scrolling activates automatically and requires no configuration. When active, only visible tasks are rendered to the DOM, with off-screen tasks rendered on-demand as you scroll. Further Reading# Default Base Templates - Complete templates for all TaskNotes views Bases Plugin Documentation - Official Obsidian documentation for Bases syntax and features Kanban View - Alternative board-based task visualization Calendar Views - Time-based task visualization Views Overview - All available TaskNotes views"},{"route":"/obsidian/webhooks/","title":"TaskNotes Webhooks","description":"TaskNotes webhooks send HTTP POST requests when selected events occur.","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/webhooks.md","namespace":"obsidian","relativePath":"webhooks.md","raw":"# TaskNotes Webhooks\n\nTaskNotes webhooks send HTTP POST requests when selected events occur.\n\n## Prerequisites\n\n1. Enable HTTP API in `Settings -> TaskNotes -> Integrations -> HTTP API`.\n2. Create at least one webhook (settings UI or API).\n3. Subscribe it to one or more events.\n\n## Event Types\n\nTask events:\n\n- `task.created`\n- `task.updated`\n- `task.deleted`\n- `task.completed`\n- `task.archived`\n- `task.unarchived`\n\nTime events:\n\n- `time.started`\n- `time.stopped`\n\nPomodoro events:\n\n- `pomodoro.started`\n- `pomodoro.completed`\n- `pomodoro.interrupted`\n\nRecurring events:\n\n- `recurring.instance.completed`\n- `recurring.instance.skipped`\n\nCompleting a materialized occurrence note emits `recurring.instance.completed` with the reconciled parent task plus the completed `occurrence` and `date` in the event data. Skipping virtual recurring instances emits `recurring.instance.skipped`; materialized occurrence skip currently reconciles the parent and occurrence note without emitting a separate skip webhook.\n\nReminder events:\n\n- `reminder.triggered`\n\n## Payload Shape\n\nAll webhook payloads use the same top-level envelope:\n\n```json\n{\n \"event\": \"task.created\",\n \"timestamp\": \"2026-02-21T10:30:00.000Z\",\n \"vault\": {\n \"name\": \"My Vault\",\n \"path\": \"/path/to/vault\"\n },\n \"data\": {}\n}\n```\n\n`data` is event-specific.\n\n## Register and Manage Webhooks via API\n\n### Create\n\n`POST /api/webhooks`\n\nRequired fields:\n\n- `url` (string)\n- `events` (non-empty array)\n\nOptional fields:\n\n- `id`\n- `secret` (auto-generated if omitted)\n- `active` (default `true`)\n- `transformFile`\n- `corsHeaders` (default `true`)\n\nExample:\n\n```bash\ncurl -X POST http://localhost:8080/api/webhooks \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"url\": \"https://example.com/tasknotes\",\n \"events\": [\"task.completed\", \"task.created\"],\n \"transformFile\": \"TaskNotes/webhooks/slack.json\"\n }'\n```\n\n### List\n\n`GET /api/webhooks`\n\nReturns registered hooks. Secrets are not returned.\n\n### Delete\n\n`DELETE /api/webhooks/:id`\n\n### Delivery History\n\n`GET /api/webhooks/deliveries`\n\nReturns last 100 in-memory deliveries.\n\n## Delivery Behavior\n\nCurrent implementation behavior:\n\n- Webhook processing is asynchronous (fire-and-forget from task operation).\n- Each delivery starts with one attempt.\n- Failed deliveries retry with exponential backoff: `1s`, `2s`, `4s`.\n- Maximum retries: `3` retries after initial attempt (up to 4 attempts total).\n- If cumulative `failureCount` for a webhook exceeds `10`, webhook is auto-disabled.\n- No explicit request timeout is set in delivery fetch.\n\nBecause retries and duplicates are possible, handlers should be idempotent.\n\n## Signature Verification\n\nWhen `corsHeaders` is enabled (default), delivery includes:\n\n- `X-TaskNotes-Event`\n- `X-TaskNotes-Signature`\n- `X-TaskNotes-Delivery-ID`\n\nSignature is HMAC-SHA256 over `JSON.stringify(payload)` using webhook `secret`.\n\nNode.js example:\n\n```javascript\nconst crypto = require(\"crypto\");\n\nfunction verifyWebhook(payload, signature, secret) {\n const expected = crypto\n .createHmac(\"sha256\", secret)\n .update(JSON.stringify(payload))\n .digest(\"hex\");\n return signature === expected;\n}\n```\n\n## Payload Transformations\n\nA webhook can specify `transformFile` pointing to a file in your vault.\n\nSupported file types:\n\n- `.json`: event template map with variable interpolation\n\nIf transform execution fails, TaskNotes falls back to original payload.\n\nJavaScript transform files are no longer supported.\n\n### JSON Transform Files\n\nStructure:\n\n```json\n{\n \"task.completed\": {\n \"text\": \"Task completed: ${data.task.title}\",\n \"vault\": \"${vault.name}\"\n },\n \"default\": {\n \"text\": \"TaskNotes event: ${event}\"\n }\n}\n```\n\nRules:\n\n- Matching order: exact event key, then `default`.\n- Variables use `${path.to.value}`.\n- Missing variables are left unchanged.\n\n## CORS and Headers\n\nWebhook delivery requests are outbound server-side requests from TaskNotes.\n\n`corsHeaders` behavior:\n\n- `true` (default): sends TaskNotes custom headers including signature.\n- `false`: only sends `Content-Type: application/json`.\n\nDisable custom headers for endpoints that reject non-standard headers.\n\n## Testing\n\n### Local Test Server\n\nUse repository script:\n\n```bash\nnode test-webhook.js\n```\n\nOptional custom port:\n\n```bash\nnode test-webhook.js 8080\n```\n\nDefault server values:\n\n- URL: `http://localhost:3000/webhook`\n- Test secret: `test-secret-key-for-tasknotes-webhooks`\n\n### External Inspection\n\nFor quick inspection, use a request-bin tool such as `webhook.site`.\n\n## Troubleshooting\n\n### No deliveries\n\n1. Confirm HTTP API is enabled.\n2. Confirm webhook is active.\n3. Confirm event is subscribed.\n\n### Signature mismatch\n\n1. Confirm secret matches webhook config.\n2. Verify your verifier hashes the exact JSON body.\n3. Verify hex digest comparison.\n\n### Webhook disabled automatically\n\nIf failures continue and `failureCount` exceeds 10, webhook is disabled.\n\n1. Fix endpoint availability or response handling.\n2. Re-enable webhook in TaskNotes settings, or recreate it via `POST /api/webhooks`.\n\n### Transform errors\n\n1. Confirm `transformFile` exists in vault.\n2. Confirm the file is a `.json` transform template.\n3. Check Obsidian console logs for transform exceptions.\n","aliases":["/webhooks/"],"toc":[{"level":2,"id":"prerequisites","text":"Prerequisites"},{"level":2,"id":"event-types","text":"Event Types"},{"level":2,"id":"payload-shape","text":"Payload Shape"},{"level":2,"id":"register-and-manage-webhooks-via-api","text":"Register and Manage Webhooks via API"},{"level":3,"id":"create","text":"Create"},{"level":3,"id":"list","text":"List"},{"level":3,"id":"delete","text":"Delete"},{"level":3,"id":"delivery-history","text":"Delivery History"},{"level":2,"id":"delivery-behavior","text":"Delivery Behavior"},{"level":2,"id":"signature-verification","text":"Signature Verification"},{"level":2,"id":"payload-transformations","text":"Payload Transformations"},{"level":3,"id":"json-transform-files","text":"JSON Transform Files"},{"level":2,"id":"cors-and-headers","text":"CORS and Headers"},{"level":2,"id":"testing","text":"Testing"},{"level":3,"id":"local-test-server","text":"Local Test Server"},{"level":3,"id":"external-inspection","text":"External Inspection"},{"level":2,"id":"troubleshooting","text":"Troubleshooting"},{"level":3,"id":"no-deliveries","text":"No deliveries"},{"level":3,"id":"signature-mismatch","text":"Signature mismatch"},{"level":3,"id":"webhook-disabled-automatically","text":"Webhook disabled automatically"},{"level":3,"id":"transform-errors","text":"Transform errors"}],"html":"

TaskNotes webhooks send HTTP POST requests when selected events occur.

\n

Prerequisites#

\n
    \n
  1. Enable HTTP API in Settings -> TaskNotes -> Integrations -> HTTP API.
  2. \n
  3. Create at least one webhook (settings UI or API).
  4. \n
  5. Subscribe it to one or more events.
  6. \n
\n

Event Types#

\n

Task events:

\n
    \n
  • task.created
  • \n
  • task.updated
  • \n
  • task.deleted
  • \n
  • task.completed
  • \n
  • task.archived
  • \n
  • task.unarchived
  • \n
\n

Time events:

\n
    \n
  • time.started
  • \n
  • time.stopped
  • \n
\n

Pomodoro events:

\n
    \n
  • pomodoro.started
  • \n
  • pomodoro.completed
  • \n
  • pomodoro.interrupted
  • \n
\n

Recurring events:

\n
    \n
  • recurring.instance.completed
  • \n
  • recurring.instance.skipped
  • \n
\n

Completing a materialized occurrence note emits recurring.instance.completed with the reconciled parent task plus the completed occurrence and date in the event data. Skipping virtual recurring instances emits recurring.instance.skipped; materialized occurrence skip currently reconciles the parent and occurrence note without emitting a separate skip webhook.

\n

Reminder events:

\n
    \n
  • reminder.triggered
  • \n
\n

Payload Shape#

\n

All webhook payloads use the same top-level envelope:

\n
{\n  "event": "task.created",\n  "timestamp": "2026-02-21T10:30:00.000Z",\n  "vault": {\n    "name": "My Vault",\n    "path": "/path/to/vault"\n  },\n  "data": {}\n}\n

data is event-specific.

\n

Register and Manage Webhooks via API#

\n

Create#

\n

POST /api/webhooks

\n

Required fields:

\n
    \n
  • url (string)
  • \n
  • events (non-empty array)
  • \n
\n

Optional fields:

\n
    \n
  • id
  • \n
  • secret (auto-generated if omitted)
  • \n
  • active (default true)
  • \n
  • transformFile
  • \n
  • corsHeaders (default true)
  • \n
\n

Example:

\n
curl -X POST http://localhost:8080/api/webhooks \\\n  -H "Content-Type: application/json" \\\n  -d '{\n    "url": "https://example.com/tasknotes",\n    "events": ["task.completed", "task.created"],\n    "transformFile": "TaskNotes/webhooks/slack.json"\n  }'\n

List#

\n

GET /api/webhooks

\n

Returns registered hooks. Secrets are not returned.

\n

Delete#

\n

DELETE /api/webhooks/:id

\n

Delivery History#

\n

GET /api/webhooks/deliveries

\n

Returns last 100 in-memory deliveries.

\n

Delivery Behavior#

\n

Current implementation behavior:

\n
    \n
  • Webhook processing is asynchronous (fire-and-forget from task operation).
  • \n
  • Each delivery starts with one attempt.
  • \n
  • Failed deliveries retry with exponential backoff: 1s, 2s, 4s.
  • \n
  • Maximum retries: 3 retries after initial attempt (up to 4 attempts total).
  • \n
  • If cumulative failureCount for a webhook exceeds 10, webhook is auto-disabled.
  • \n
  • No explicit request timeout is set in delivery fetch.
  • \n
\n

Because retries and duplicates are possible, handlers should be idempotent.

\n

Signature Verification#

\n

When corsHeaders is enabled (default), delivery includes:

\n
    \n
  • X-TaskNotes-Event
  • \n
  • X-TaskNotes-Signature
  • \n
  • X-TaskNotes-Delivery-ID
  • \n
\n

Signature is HMAC-SHA256 over JSON.stringify(payload) using webhook secret.

\n

Node.js example:

\n
const crypto = require("crypto");\n\nfunction verifyWebhook(payload, signature, secret) {\n  const expected = crypto\n    .createHmac("sha256", secret)\n    .update(JSON.stringify(payload))\n    .digest("hex");\n  return signature === expected;\n}\n

Payload Transformations#

\n

A webhook can specify transformFile pointing to a file in your vault.

\n

Supported file types:

\n
    \n
  • .json: event template map with variable interpolation
  • \n
\n

If transform execution fails, TaskNotes falls back to original payload.

\n

JavaScript transform files are no longer supported.

\n

JSON Transform Files#

\n

Structure:

\n
{\n  "task.completed": {\n    "text": "Task completed: ${data.task.title}",\n    "vault": "${vault.name}"\n  },\n  "default": {\n    "text": "TaskNotes event: ${event}"\n  }\n}\n

Rules:

\n
    \n
  • Matching order: exact event key, then default.
  • \n
  • Variables use ${path.to.value}.
  • \n
  • Missing variables are left unchanged.
  • \n
\n

CORS and Headers#

\n

Webhook delivery requests are outbound server-side requests from TaskNotes.

\n

corsHeaders behavior:

\n
    \n
  • true (default): sends TaskNotes custom headers including signature.
  • \n
  • false: only sends Content-Type: application/json.
  • \n
\n

Disable custom headers for endpoints that reject non-standard headers.

\n

Testing#

\n

Local Test Server#

\n

Use repository script:

\n
node test-webhook.js\n

Optional custom port:

\n
node test-webhook.js 8080\n

Default server values:

\n
    \n
  • URL: http://localhost:3000/webhook
  • \n
  • Test secret: test-secret-key-for-tasknotes-webhooks
  • \n
\n

External Inspection#

\n

For quick inspection, use a request-bin tool such as webhook.site.

\n

Troubleshooting#

\n

No deliveries#

\n
    \n
  1. Confirm HTTP API is enabled.
  2. \n
  3. Confirm webhook is active.
  4. \n
  5. Confirm event is subscribed.
  6. \n
\n

Signature mismatch#

\n
    \n
  1. Confirm secret matches webhook config.
  2. \n
  3. Verify your verifier hashes the exact JSON body.
  4. \n
  5. Verify hex digest comparison.
  6. \n
\n

Webhook disabled automatically#

\n

If failures continue and failureCount exceeds 10, webhook is disabled.

\n
    \n
  1. Fix endpoint availability or response handling.
  2. \n
  3. Re-enable webhook in TaskNotes settings, or recreate it via POST /api/webhooks.
  4. \n
\n

Transform errors#

\n
    \n
  1. Confirm transformFile exists in vault.
  2. \n
  3. Confirm the file is a .json transform template.
  4. \n
  5. Check Obsidian console logs for transform exceptions.
  6. \n
\n","text":"TaskNotes webhooks send HTTP POST requests when selected events occur. Prerequisites# Enable HTTP API in Settings -> TaskNotes -> Integrations -> HTTP API. Create at least one webhook (settings UI or API). Subscribe it to one or more events. Event Types# Task events: task.created task.updated task.deleted task.completed task.archived task.unarchived Time events: time.started time.stopped Pomodoro events: pomodoro.started pomodoro.completed pomodoro.interrupted Recurring events: recurring.instance.completed recurring.instance.skipped Completing a materialized occurrence note emits recurring.instance.completed with the reconciled parent task plus the completed occurrence and date in the event data. Skipping virtual recurring instances emits recurring.instance.skipped; materialized occurrence skip currently reconciles the parent and occurrence note without emitting a separate skip webhook. Reminder events: reminder.triggered Payload Shape# All webhook payloads use the same top-level envelope: { \"event\": \"task.created\", \"timestamp\": \"2026-02-21T10:30:00.000Z\", \"vault\": { \"name\": \"My Vault\", \"path\": \"/path/to/vault\" }, \"data\": {} } data is event-specific. Register and Manage Webhooks via API# Create# POST /api/webhooks Required fields: url (string) events (non-empty array) Optional fields: id secret (auto-generated if omitted) active (default true) transformFile corsHeaders (default true) Example: curl -X POST http://localhost:8080/api/webhooks \\ -H \"Content-Type: application/json\" \\ -d '{ \"url\": \"https://example.com/tasknotes\", \"events\": [\"task.completed\", \"task.created\"], \"transformFile\": \"TaskNotes/webhooks/slack.json\" }' List# GET /api/webhooks Returns registered hooks. Secrets are not returned. Delete# DELETE /api/webhooks/:id Delivery History# GET /api/webhooks/deliveries Returns last 100 in-memory deliveries. Delivery Behavior# Current implementation behavior: Webhook processing is asynchronous (fire-and-forget from task operation). Each delivery starts with one attempt. Failed deliveries retry with exponential backoff: 1s, 2s, 4s. Maximum retries: 3 retries after initial attempt (up to 4 attempts total). If cumulative failureCount for a webhook exceeds 10, webhook is auto-disabled. No explicit request timeout is set in delivery fetch. Because retries and duplicates are possible, handlers should be idempotent. Signature Verification# When corsHeaders is enabled (default), delivery includes: X-TaskNotes-Event X-TaskNotes-Signature X-TaskNotes-Delivery-ID Signature is HMAC-SHA256 over JSON.stringify(payload) using webhook secret. Node.js example: const crypto = require(\"crypto\"); function verifyWebhook(payload, signature, secret) { const expected = crypto .createHmac(\"sha256\", secret) .update(JSON.stringify(payload)) .digest(\"hex\"); return signature === expected; } Payload Transformations# A webhook can specify transformFile pointing to a file in your vault. Supported file types: .json: event template map with variable interpolation If transform execution fails, TaskNotes falls back to original payload. JavaScript transform files are no longer supported. JSON Transform Files# Structure: { \"task.completed\": { \"text\": \"Task completed: ${data.task.title}\", \"vault\": \"${vault.name}\" }, \"default\": { \"text\": \"TaskNotes event: ${event}\" } } Rules: Matching order: exact event key, then default. Variables use ${path.to.value}. Missing variables are left unchanged. CORS and Headers# Webhook delivery requests are outbound server-side requests from TaskNotes. corsHeaders behavior: true (default): sends TaskNotes custom headers including signature. false: only sends Content-Type: application/json. Disable custom headers for endpoints that reject non-standard headers. Testing# Local Test Server# Use repository script: node test-webhook.js Optional custom port: node test-webhook.js 8080 Default server values: URL: http://localhost:3000/webhook Test secret: test-secret-key-for-tasknotes-webhooks External Inspection# For quick inspection, use a request-bin tool such as webhook.site. Troubleshooting# No deliveries# Confirm HTTP API is enabled. Confirm webhook is active. Confirm event is subscribed. Signature mismatch# Confirm secret matches webhook config. Verify your verifier hashes the exact JSON body. Verify hex digest comparison. Webhook disabled automatically# If failures continue and failureCount exceeds 10, webhook is disabled. Fix endpoint availability or response handling. Re-enable webhook in TaskNotes settings, or recreate it via POST /api/webhooks. Transform errors# Confirm transformFile exists in vault. Confirm the file is a .json transform template. Check Obsidian console logs for transform exceptions."},{"route":"/obsidian/workflows/","title":"Workflows","description":"This page describes practical ways to combine TaskNotes features into repeatable workflows. The goal is to show how recurring tasks, projects, filtering, and scheduling fit toge...","product":"obsidian","platforms":[],"version":"4.13.0","generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/obsidian/workflows.md","namespace":"obsidian","relativePath":"workflows.md","raw":"# Workflows\n\nThis page describes practical ways to combine TaskNotes features into repeatable workflows. The goal is to show how recurring tasks, projects, filtering, and scheduling fit together in everyday use.\n\n## Habit Tracking with Recurring Tasks\n\nHabit tracking in TaskNotes is built on recurring task notes. You can create a recurring task from natural language (for example, \"Exercise daily\" or \"Gym every Monday and Wednesday\") or configure recurrence explicitly in the task modal. The modal recurrence controls support frequency, interval, weekday selection, and end conditions.\n\nOnce a task has a recurrence rule, its edit modal shows a recurrence calendar. That calendar is where you mark completion per occurrence. Completion history is stored in `complete_instances`, so a recurring task can remain open while still recording daily/weekly completion behavior.\n\n![Recurring task calendar](assets/views-calendar-month.png)\n\n```yaml\ntitle: Morning Exercise\nrecurrence: \"FREQ=DAILY\"\nscheduled: \"07:00\"\ncomplete_instances:\n - \"2025-01-01\"\n - \"2025-01-02\"\n - \"2025-01-04\"\n```\n\nUse Calendar and Agenda views to review upcoming occurrences, and use recurring-task filters when you want a habit-only planning view.\n\nFor richer recurring work, such as a weekly review or maintenance visit, right-click the recurrence in a task card, calendar view, or the edit modal's completion calendar and choose **Open or create occurrence note**. The occurrence note inherits planning metadata such as scheduled time, due offset, projects, tags, reminders, details, and time estimate, then keeps its own checklist, completion state, and time entries while the parent recurring task keeps the long-term rule. On the calendar, the note-backed occurrence replaces the matching virtual parent occurrence; dragging it reschedules that note without rewriting the recurrence pattern.\n\n## Project-Centered Planning\n\nProjects in TaskNotes can be plain text values or wikilinks to project notes. Wikilinks are usually the better long-term option because they connect task execution to project context, backlinks, and graph navigation.\n\n```yaml\ntitle: \"Research competitors\"\nprojects: [\"[[Market Research]]\", \"[[Q1 Strategy]]\"]\n```\n\nDuring task creation, use the project picker to search and assign one or more projects. In day-to-day planning, open Task List or Kanban, then filter on `note.projects contains [[Project Name]]` to isolate one initiative. Save that filter as a Bases saved view if you revisit it regularly.\n\n![Task list view](assets/views-tasks-list.png)\n\nWhen work spans initiatives, assign multiple projects and combine with contexts or tags for secondary organization.\n\n```yaml\ntitle: \"Prepare presentation slides\"\nprojects: [\"[[Q4 Planning]]\"]\ncontexts: [\"computer\", \"office\"]\ntags: [\"review\"]\n```\n\n## Execution Workflow (Daily)\n\nA typical daily flow is to start in Task List for prioritization, move to Calendar for schedule placement, and finish in Agenda for near-term sequencing. This keeps backlog management, time allocation, and short-horizon execution in one system.\n\nIf you use timeboxing, drag-select on calendar timeline views and create timeblocks directly from the context menu. If you use Pomodoro, run sessions against active tasks so completion and timing data stay attached to task notes.\n\n![Calendar quick add workflow](assets/workflow-quick-add-calendar.png)\n\n## Maintenance Workflow (Weekly)\n\nA weekly review usually includes three steps: clean up completed/archived tasks, verify recurring-task completion patterns, and rebalance project filters/views. If calendar integrations are enabled, this is also a good point to refresh subscriptions and confirm sync health.\n\nFor teams or complex personal systems, keep project notes as source-of-truth documents and use TaskNotes views as execution dashboards derived from those notes.\n","aliases":["/workflows/"],"toc":[{"level":2,"id":"habit-tracking-with-recurring-tasks","text":"Habit Tracking with Recurring Tasks"},{"level":2,"id":"project-centered-planning","text":"Project-Centered Planning"},{"level":2,"id":"execution-workflow-daily","text":"Execution Workflow (Daily)"},{"level":2,"id":"maintenance-workflow-weekly","text":"Maintenance Workflow (Weekly)"}],"html":"

This page describes practical ways to combine TaskNotes features into repeatable workflows. The goal is to show how recurring tasks, projects, filtering, and scheduling fit together in everyday use.

\n

Habit Tracking with Recurring Tasks#

\n

Habit tracking in TaskNotes is built on recurring task notes. You can create a recurring task from natural language (for example, "Exercise daily" or "Gym every Monday and Wednesday") or configure recurrence explicitly in the task modal. The modal recurrence controls support frequency, interval, weekday selection, and end conditions.

\n

Once a task has a recurrence rule, its edit modal shows a recurrence calendar. That calendar is where you mark completion per occurrence. Completion history is stored in complete_instances, so a recurring task can remain open while still recording daily/weekly completion behavior.

\n

\"Recurring

\n
title: Morning Exercise\nrecurrence: "FREQ=DAILY"\nscheduled: "07:00"\ncomplete_instances:\n  - "2025-01-01"\n  - "2025-01-02"\n  - "2025-01-04"\n

Use Calendar and Agenda views to review upcoming occurrences, and use recurring-task filters when you want a habit-only planning view.

\n

For richer recurring work, such as a weekly review or maintenance visit, right-click the recurrence in a task card, calendar view, or the edit modal's completion calendar and choose Open or create occurrence note. The occurrence note inherits planning metadata such as scheduled time, due offset, projects, tags, reminders, details, and time estimate, then keeps its own checklist, completion state, and time entries while the parent recurring task keeps the long-term rule. On the calendar, the note-backed occurrence replaces the matching virtual parent occurrence; dragging it reschedules that note without rewriting the recurrence pattern.

\n

Project-Centered Planning#

\n

Projects in TaskNotes can be plain text values or wikilinks to project notes. Wikilinks are usually the better long-term option because they connect task execution to project context, backlinks, and graph navigation.

\n
title: "Research competitors"\nprojects: ["[[Market Research]]", "[[Q1 Strategy]]"]\n

During task creation, use the project picker to search and assign one or more projects. In day-to-day planning, open Task List or Kanban, then filter on note.projects contains [[Project Name]] to isolate one initiative. Save that filter as a Bases saved view if you revisit it regularly.

\n

\"Task

\n

When work spans initiatives, assign multiple projects and combine with contexts or tags for secondary organization.

\n
title: "Prepare presentation slides"\nprojects: ["[[Q4 Planning]]"]\ncontexts: ["computer", "office"]\ntags: ["review"]\n

Execution Workflow (Daily)#

\n

A typical daily flow is to start in Task List for prioritization, move to Calendar for schedule placement, and finish in Agenda for near-term sequencing. This keeps backlog management, time allocation, and short-horizon execution in one system.

\n

If you use timeboxing, drag-select on calendar timeline views and create timeblocks directly from the context menu. If you use Pomodoro, run sessions against active tasks so completion and timing data stay attached to task notes.

\n

\"Calendar

\n

Maintenance Workflow (Weekly)#

\n

A weekly review usually includes three steps: clean up completed/archived tasks, verify recurring-task completion patterns, and rebalance project filters/views. If calendar integrations are enabled, this is also a good point to refresh subscriptions and confirm sync health.

\n

For teams or complex personal systems, keep project notes as source-of-truth documents and use TaskNotes views as execution dashboards derived from those notes.

\n","text":"This page describes practical ways to combine TaskNotes features into repeatable workflows. The goal is to show how recurring tasks, projects, filtering, and scheduling fit together in everyday use. Habit Tracking with Recurring Tasks# Habit tracking in TaskNotes is built on recurring task notes. You can create a recurring task from natural language (for example, \"Exercise daily\" or \"Gym every Monday and Wednesday\") or configure recurrence explicitly in the task modal. The modal recurrence controls support frequency, interval, weekday selection, and end conditions. Once a task has a recurrence rule, its edit modal shows a recurrence calendar. That calendar is where you mark completion per occurrence. Completion history is stored in complete_instances, so a recurring task can remain open while still recording daily/weekly completion behavior. title: Morning Exercise recurrence: \"FREQ=DAILY\" scheduled: \"07:00\" complete_instances: - \"2025-01-01\" - \"2025-01-02\" - \"2025-01-04\" Use Calendar and Agenda views to review upcoming occurrences, and use recurring-task filters when you want a habit-only planning view. For richer recurring work, such as a weekly review or maintenance visit, right-click the recurrence in a task card, calendar view, or the edit modal's completion calendar and choose Open or create occurrence note. The occurrence note inherits planning metadata such as scheduled time, due offset, projects, tags, reminders, details, and time estimate, then keeps its own checklist, completion state, and time entries while the parent recurring task keeps the long-term rule. On the calendar, the note-backed occurrence replaces the matching virtual parent occurrence; dragging it reschedules that note without rewriting the recurrence pattern. Project-Centered Planning# Projects in TaskNotes can be plain text values or wikilinks to project notes. Wikilinks are usually the better long-term option because they connect task execution to project context, backlinks, and graph navigation. title: \"Research competitors\" projects: [\"[[Market Research]]\", \"[[Q1 Strategy]]\"] During task creation, use the project picker to search and assign one or more projects. In day-to-day planning, open Task List or Kanban, then filter on note.projects contains [[Project Name]] to isolate one initiative. Save that filter as a Bases saved view if you revisit it regularly. When work spans initiatives, assign multiple projects and combine with contexts or tags for secondary organization. title: \"Prepare presentation slides\" projects: [\"[[Q4 Planning]]\"] contexts: [\"computer\", \"office\"] tags: [\"review\"] Execution Workflow (Daily)# A typical daily flow is to start in Task List for prioritization, move to Calendar for schedule placement, and finish in Agenda for near-term sequencing. This keeps backlog management, time allocation, and short-horizon execution in one system. If you use timeboxing, drag-select on calendar timeline views and create timeblocks directly from the context menu. If you use Pomodoro, run sessions against active tasks so completion and timing data stay attached to task notes. Maintenance Workflow (Weekly)# A weekly review usually includes three steps: clean up completed/archived tasks, verify recurring-task completion patterns, and rebalance project filters/views. If calendar integrations are enabled, this is also a good point to refresh subscriptions and confirm sync health. For teams or complex personal systems, keep project notes as source-of-truth documents and use TaskNotes views as execution dashboards derived from those notes."},{"route":"/privacy/","title":"TaskNotes privacy overview","description":"How the TaskNotes app and Obsidian plugin store data and when optional services are involved.","product":"shared","platforms":[],"version":null,"generated":false,"noIndex":false,"hideToc":false,"source":"tasknotes.dev:content/policies/privacy.md","namespace":"policies","relativePath":"privacy.md","raw":"---\ntitle: TaskNotes privacy overview\ndescription: How the TaskNotes app and Obsidian plugin store data and when optional services are involved.\nroute: /privacy/\nproduct: shared\nlast_updated: 2026-08-06\n---\n\n# TaskNotes privacy overview\n\nLast updated: August 6, 2026\n\nTaskNotes products are built around portable Markdown records. The storage and\nnetwork boundaries depend on the client and collection you choose.\n\n## TaskNotes app\n\n- The TaskNotes app opens every collection through mdbase and requires a\n connection to read or change it.\n- A hosted collection stores the authoritative Markdown with the hosted\n provider.\n- A computer collection keeps the authoritative Markdown on that computer.\n TaskNotes reaches it through an end-to-end encrypted relay that cannot read\n record contents; the computer must remain reachable and run mdbase Connect.\n- TaskNotes keeps only a temporary in-memory session cache. It does not retain\n a separate offline collection after the app or page closes.\n- Reminder notifications for mdbase collections require explicit permission\n and use content-free event payloads. Task content is refreshed through the\n authorized collection connection.\n\n## Obsidian plugin\n\nThe plugin keeps task and note content in the local Obsidian vault. Plugin\nsettings live in Obsidian's plugin configuration. Network access occurs only\nfor enabled features that require it, including release checks, calendar\nproviders, ICS subscriptions, webhooks, and remotely loaded API documentation\nassets.\n\n## Analytics\n\nTaskNotes does not include a product telemetry or analytics pipeline. Services\nyou choose to connect may keep their own operational, account, security, or\nbilling records under their respective policies.\n\n## Removal\n\nRemoving a client does not necessarily remove its authoritative collection.\nUse the hosted provider's controls for a hosted collection, or manage the\nMarkdown folder on the computer that owns a computer collection. Back up\nrecords before removing an authoritative copy.\n\n## Questions and source code\n\nUse the relevant TaskNotes GitHub repository to report a privacy problem or\ninspect the implementation:\n\n- [TaskNotes app](https://github.com/callumalpass/tasknotes-app)\n- [TaskNotes Obsidian plugin](https://github.com/callumalpass/tasknotes)\n","aliases":[],"toc":[{"level":2,"id":"tasknotes-app","text":"TaskNotes app"},{"level":2,"id":"obsidian-plugin","text":"Obsidian plugin"},{"level":2,"id":"analytics","text":"Analytics"},{"level":2,"id":"removal","text":"Removal"},{"level":2,"id":"questions-and-source-code","text":"Questions and source code"}],"html":"

Last updated: August 6, 2026

\n

TaskNotes products are built around portable Markdown records. The storage and\nnetwork boundaries depend on the client and collection you choose.

\n

TaskNotes app#

\n
    \n
  • The TaskNotes app opens every collection through mdbase and requires a\nconnection to read or change it.
  • \n
  • A hosted collection stores the authoritative Markdown with the hosted\nprovider.
  • \n
  • A computer collection keeps the authoritative Markdown on that computer.\nTaskNotes reaches it through an end-to-end encrypted relay that cannot read\nrecord contents; the computer must remain reachable and run mdbase Connect.
  • \n
  • TaskNotes keeps only a temporary in-memory session cache. It does not retain\na separate offline collection after the app or page closes.
  • \n
  • Reminder notifications for mdbase collections require explicit permission\nand use content-free event payloads. Task content is refreshed through the\nauthorized collection connection.
  • \n
\n

Obsidian plugin#

\n

The plugin keeps task and note content in the local Obsidian vault. Plugin\nsettings live in Obsidian's plugin configuration. Network access occurs only\nfor enabled features that require it, including release checks, calendar\nproviders, ICS subscriptions, webhooks, and remotely loaded API documentation\nassets.

\n

Analytics#

\n

TaskNotes does not include a product telemetry or analytics pipeline. Services\nyou choose to connect may keep their own operational, account, security, or\nbilling records under their respective policies.

\n

Removal#

\n

Removing a client does not necessarily remove its authoritative collection.\nUse the hosted provider's controls for a hosted collection, or manage the\nMarkdown folder on the computer that owns a computer collection. Back up\nrecords before removing an authoritative copy.

\n

Questions and source code#

\n

Use the relevant TaskNotes GitHub repository to report a privacy problem or\ninspect the implementation:

\n\n","text":"Last updated: August 6, 2026 TaskNotes products are built around portable Markdown records. The storage and network boundaries depend on the client and collection you choose. TaskNotes app# The TaskNotes app opens every collection through mdbase and requires a connection to read or change it. A hosted collection stores the authoritative Markdown with the hosted provider. A computer collection keeps the authoritative Markdown on that computer. TaskNotes reaches it through an end-to-end encrypted relay that cannot read record contents; the computer must remain reachable and run mdbase Connect. TaskNotes keeps only a temporary in-memory session cache. It does not retain a separate offline collection after the app or page closes. Reminder notifications for mdbase collections require explicit permission and use content-free event payloads. Task content is refreshed through the authorized collection connection. Obsidian plugin# The plugin keeps task and note content in the local Obsidian vault. Plugin settings live in Obsidian's plugin configuration. Network access occurs only for enabled features that require it, including release checks, calendar providers, ICS subscriptions, webhooks, and remotely loaded API documentation assets. Analytics# TaskNotes does not include a product telemetry or analytics pipeline. Services you choose to connect may keep their own operational, account, security, or billing records under their respective policies. Removal# Removing a client does not necessarily remove its authoritative collection. Use the hosted provider's controls for a hosted collection, or manage the Markdown folder on the computer that owns a computer collection. Back up records before removing an authoritative copy. Questions and source code# Use the relevant TaskNotes GitHub repository to report a privacy problem or inspect the implementation: TaskNotes app TaskNotes Obsidian plugin"}]} diff --git a/app/globals.css b/app/globals.css index 740372d..9bcce4a 100644 --- a/app/globals.css +++ b/app/globals.css @@ -967,6 +967,35 @@ video { font: 400 0.72rem/1.5 var(--mono); } +.app-walkthrough { + margin: 1.5rem 0; +} + +.app-walkthrough video { + width: 100%; + max-height: none; + margin: 0; + aspect-ratio: 3 / 2; + background: var(--color-surface-subtle); +} + +.app-walkthrough figcaption { + margin-top: 0.65rem; + color: var(--color-text-soft); + font-size: 0.875rem; + line-height: 1.5; +} + +.walkthrough-transcript summary { + padding: 0.65rem 0; + font-weight: 700; + cursor: pointer; +} + +.walkthrough-transcript[open] summary { + margin-bottom: 1rem; +} + .media-frame { position: relative; width: 100%; diff --git a/content/app/collections.md b/content/app/collections.md index 0afac07..0c538f9 100644 --- a/content/app/collections.md +++ b/content/app/collections.md @@ -13,7 +13,8 @@ copy of your Markdown lives: hosted online or on your own computer. If mdbase is new to you, start with [mdbase and TaskNotes](/app/mdbase/) for a plain-language explanation of the format, Connect desktop app, and hosting -choices. +choices. For a video and written setup steps, follow +[Connect TaskNotes to mdbase](/app/connect-mdbase/). ## Hosted mdbase @@ -39,5 +40,5 @@ mdbase Connect background service whenever you use TaskNotes. See how to ## Change collections later -Open **More** and choose **Change collection**. Opening another collection does +Open **Settings** and choose **Change collection**. Opening another collection does not copy or move records from the collection you were using. diff --git a/content/app/connect-mdbase.md b/content/app/connect-mdbase.md new file mode 100644 index 0000000..465223e --- /dev/null +++ b/content/app/connect-mdbase.md @@ -0,0 +1,150 @@ +--- +title: Connect TaskNotes to mdbase +description: Watch how to connect hosted mdbase collections and existing local folders to the TaskNotes app, with written steps and a transcript. +route: /app/connect-mdbase/ +product: app +platforms: [web, android, ios] +--- + +# Connect TaskNotes to mdbase + +
+ +
3 minutes 53 seconds · Silent walkthrough with on-screen instructions and visible cursors. Use the player’s fullscreen control for a closer view.
+
+ +Download the video +· [Read the transcript](#transcript) + +These instructions are for the web, Android, and iOS app, not the +[Obsidian plugin](/obsidian/). + +The recording uses disposable demo data in the LAB test environment. Account +sign-in and OS-specific installer dialogs are omitted. The folder chooser and +Markdown editor shown are Linux examples; the connection steps apply across +platforms. TaskNotes is in beta, so some labels may change. + +## Choose where your collection lives + +- **Hosted by mdbase:** available online even when your computer is off. You + need an internet connection, but not the desktop Connector to use TaskNotes. +- **On your computer:** files stay in a local folder. Keep that computer + reachable and mdbase Connect running while other devices use the collection. + +Hosted collections can also be mirrored to your computer, so you can work +with local Markdown files. Mirror setup is outside this walkthrough. + +The same TaskNotes app works with either. Read [What is mdbase?](/app/mdbase/) +for more background or [Choose a collection](/app/collections/) for a fuller +comparison. + +## Connect a hosted collection + +1. Open [TaskNotes](https://app.tasknotes.dev/) or its Android or iOS app and + choose a collection. Sign in to mdbase if asked. +2. Select a collection labelled **Hosted by mdbase**, then choose **Review + access**. +3. Review the named application, collection, requested actions, and setup + changes. Approve only if you agree. For a collection needing TaskNotes + definitions, the button reads **Set up and allow access**. +4. Return to TaskNotes and add a task. It is saved in the hosted collection. + +If you do not have a hosted collection, expand **Add or connect another +collection → Create hosted collection** in mdbase. Creating a collection and +approving TaskNotes access are separate steps. + +## Connect an existing local folder + +1. Visit the [mdbase Connect download page](https://mdbase.dev/downloads/) and + choose the **desktop app** for your operating system and processor. Follow + the current platform installation and beta security guidance, then open + mdbase Connect. The standalone CLI download does not include the desktop + interface. +2. Name your computer and choose **Continue in browser**. Sign in if asked, + approve the computer, then return to the desktop app and wait for it to + connect. +3. Open **Collections → Add existing**. Select the collection root containing + `mdbase.yaml`, not just its `tasks` subfolder. Adding the folder validates it + in place; it does not move or upload its files. +4. Open the collection chooser in TaskNotes and select the collection listed + under your connected computer. If TaskNotes already has a collection open, + use **Settings → Change collection → Connect another collection**. +5. Review and approve the requested access and setup changes if you agree. + If TaskNotes subsequently asks, review **Apply reviewed setup** as well. +6. Add a task and inspect its Markdown file in the collection. Completing the + task updates that file’s status to `done`. You can use any Markdown editor; + the video uses VS Code. + +TaskNotes does not open the folder directly or maintain a durable offline copy. +Your computer remains the main copy and must be reachable for remote access. +See [Connection and availability](/app/connection/) if the collection cannot +be reached. + +## Switch an existing connection + +Open **Settings → Change collection** and select a collection you have already +approved. **Connect another collection** returns to mdbase to approve access +to another one. Switching collections does not copy or move their records. + +## Transcript + +
+Read the full video transcript + +**00:00** — This video shows how to connect mdbase collections to the TaskNotes app. We’ll start with a hosted collection, then connect an existing folder on your computer. + +**00:08** — Hosted by mdbase: available online, even when your computer is off. No desktop Connector needed for TaskNotes. + +**00:14** — Hosted collections can also be mirrored to your computer, so you can work with local Markdown files. + +**00:21** — On your computer: files stay in an existing folder. Keep mdbase Connect running and the computer reachable. The same TaskNotes app works with either. + +**00:29** — Start with hosted: open app.tasknotes.dev and choose a collection. + +**00:37** — Select a collection labelled Hosted by mdbase, then review access. + +**00:50** — Review the permissions, then approve access if you agree. + +**01:00** — Add a task. It is saved in your hosted collection; no local computer is needed. + +**01:14** — Already have an mdbase collection on your computer? Connect that folder to TaskNotes without moving its files. + +**01:22** — For a local folder, first get the desktop app at mdbase.dev/downloads. + +**01:35** — Install and open mdbase Connect. + +**01:39** — Name this computer, then choose Continue in browser. + +**01:49** — Sign in if asked, then approve this computer. + +**02:00** — In Collections, choose Add existing and select your collection folder. + +**02:09** — Choose the folder containing mdbase.yaml. Its files stay where they are. + +**02:15** — Back in TaskNotes, open the mdbase collection chooser. + +**02:21** — Select the collection listed under your connected computer. + +**02:35** — Review the requested access and setup changes, then approve if you agree. + +**02:44** — Add a task to the local collection. + +**02:59** — Each task is a Markdown file. Changes you make in TaskNotes are saved back to the collection. + +**03:06** — The task is now a Markdown file in your existing folder. + +**03:11** — Keep mdbase Connect running while other devices use this folder. + +**03:15** — Once both are connected, switch collections in Settings → Change collection. + +**03:24** — Choose a collection you have already approved. + +**03:37** — In the local collection, complete the task. + +**03:46** — The same Markdown file now says status: done. + +
diff --git a/content/app/getting-started.md b/content/app/getting-started.md index 81ab6a0..29c5ee0 100644 --- a/content/app/getting-started.md +++ b/content/app/getting-started.md @@ -22,11 +22,14 @@ The web and native applications use the same task interface. ## 2. Choose a collection -TaskNotes opens every collection through mdbase. Choose **Hosted mdbase** for a -collection available anywhere with a network connection, or **Connect to a -computer** to use a Markdown collection kept on your own computer through the -encrypted relay. Read [What is mdbase?](/app/mdbase/) if this is new to you, -then [Choose a collection](/app/collections/) to compare the two options. +TaskNotes opens every collection through mdbase. In the collection chooser, +select one labelled **Hosted by mdbase** or one listed under your connected +computer. Read [What is mdbase?](/app/mdbase/) if this is new to you, then +[Choose a collection](/app/collections/) to compare the two options. + +Follow [Connect TaskNotes to mdbase](/app/connect-mdbase/) for a short video, +written steps, and a transcript covering hosted collections first, then +existing local folders. ## 3. Create a task @@ -41,5 +44,5 @@ Navigation belongs to the current collection and can be reordered from Views. ## 5. Check collection status -Open **More** to see the collection location, connection state, last refresh, +Open **Settings** to see the collection location, connection state, last refresh, notification access, task model settings, and appearance preference. diff --git a/content/app/index.md b/content/app/index.md index 70331c6..b07b3d2 100644 --- a/content/app/index.md +++ b/content/app/index.md @@ -37,7 +37,8 @@ changes require a connection. 1. [Try TaskNotes with sample tasks](/app/demo/) or [open or install TaskNotes](/app/getting-started/). 2. [Learn how mdbase supports TaskNotes](/app/mdbase/). -3. [Choose where your collection lives](/app/collections/). +3. [Choose where your collection lives](/app/collections/), then follow the + [connection walkthrough](/app/connect-mdbase/) with video and written steps. 4. Create a task and open **Today**. 5. Turn on reminders only if the collection and platform support delivery. diff --git a/content/app/mdbase.md b/content/app/mdbase.md index 9bb6077..775878c 100644 --- a/content/app/mdbase.md +++ b/content/app/mdbase.md @@ -53,7 +53,8 @@ saving changes require a connection. | Connect to your computer | In a folder on your computer | Both devices must be online, and your computer must be running mdbase Connect | [Choose a collection](/app/collections/) compares the TaskNotes behavior of -these options in more detail. +these options in more detail. [Connect TaskNotes to mdbase](/app/connect-mdbase/) +shows both connection flows in a short video, with written steps and a transcript. ## Use a collection on your computer diff --git a/navigation.yml b/navigation.yml index b6789aa..6d761d1 100644 --- a/navigation.yml +++ b/navigation.yml @@ -14,6 +14,8 @@ navigation: items: - title: Get started route: /app/getting-started/ + - title: Connect to mdbase + route: /app/connect-mdbase/ - title: Interactive demo route: /app/demo/ - title: Choose a collection diff --git a/public/assets/app/connect-mdbase/captions.en.vtt b/public/assets/app/connect-mdbase/captions.en.vtt new file mode 100644 index 0000000..dd0d7b9 --- /dev/null +++ b/public/assets/app/connect-mdbase/captions.en.vtt @@ -0,0 +1,79 @@ +WEBVTT + +00:00:00.000 --> 00:00:08.000 +This video shows how to connect mdbase collections to the TaskNotes app. We’ll start with a hosted collection, then connect an existing folder on your computer. + +00:00:08.000 --> 00:00:14.000 +Hosted by mdbase: available online, even when your computer is off. No desktop Connector needed for TaskNotes. + +00:00:14.000 --> 00:00:21.000 +Hosted collections can also be mirrored to your computer, so you can work with local Markdown files. + +00:00:21.000 --> 00:00:29.000 +On your computer: files stay in an existing folder. Keep mdbase Connect running and the computer reachable. The same TaskNotes app works with either. + +00:00:29.000 --> 00:00:37.600 +Start with hosted: open app.tasknotes.dev and choose a collection. + +00:00:37.600 --> 00:00:50.833 +Select a collection labelled Hosted by mdbase, then review access. + +00:00:50.833 --> 00:01:00.033 +Review the permissions, then approve access if you agree. + +00:01:00.033 --> 00:01:14.067 +Add a task. It is saved in your hosted collection; no local computer is needed. + +00:01:14.067 --> 00:01:22.067 +Already have an mdbase collection on your computer? Connect that folder to TaskNotes without moving its files. + +00:01:22.067 --> 00:01:35.933 +For a local folder, first get the desktop app at mdbase.dev/downloads. + +00:01:35.933 --> 00:01:39.933 +Install and open mdbase Connect. + +00:01:39.933 --> 00:01:49.467 +Name this computer, then choose Continue in browser. + +00:01:49.467 --> 00:02:00.400 +Sign in if asked, then approve this computer. + +00:02:00.400 --> 00:02:09.400 +In Collections, choose Add existing and select your collection folder. + +00:02:09.400 --> 00:02:15.133 +Choose the folder containing mdbase.yaml. Its files stay where they are. + +00:02:15.133 --> 00:02:21.933 +Back in TaskNotes, open the mdbase collection chooser. + +00:02:21.933 --> 00:02:35.333 +Select the collection listed under your connected computer. + +00:02:35.333 --> 00:02:44.566 +Review the requested access and setup changes, then approve if you agree. + +00:02:44.566 --> 00:02:59.300 +Add a task to the local collection. + +00:02:59.300 --> 00:03:06.300 +Each task is a Markdown file. Changes you make in TaskNotes are saved back to the collection. + +00:03:06.300 --> 00:03:11.500 +The task is now a Markdown file in your existing folder. + +00:03:11.500 --> 00:03:15.833 +Keep mdbase Connect running while other devices use this folder. + +00:03:15.833 --> 00:03:24.833 +Once both are connected, switch collections in Settings → Change collection. + +00:03:24.833 --> 00:03:37.066 +Choose a collection you have already approved. + +00:03:37.066 --> 00:03:46.066 +In the local collection, complete the task. + +00:03:46.066 --> 00:03:52.599 +The same Markdown file now says status: done. diff --git a/public/assets/app/connect-mdbase/poster.png b/public/assets/app/connect-mdbase/poster.png new file mode 100644 index 0000000000000000000000000000000000000000..783c394a1d6ae00826c2cfd4f03a7a298178c895 GIT binary patch literal 40247 zcmeFZcUV(h`!#3>MT&|bT|`j2(xoaWs0c{!Aku53h8AL>s5Fr#U3w?<4na_Q?=|!q zAk+j%2;au%eZTq5%pddbTr&?wuVWH&a`xW$TI*i-z0a4|$_nIH=&zhPbB6rI^QUTO z&RqO?=FIs9(sSUMS4%HW&YX!SzIggX!##d|%GHH>q^Wtk#u3V{^ZCj3NnSB(t7N|` zgNx~#1rg;)&*V+M2%7s5G~9nKGxPY~X7#0-t9G1%o!lCA5Uq(TYwg7>@9puVLN_O4 zx+Eo>6;!8t?}O8TpM}nXIjLB7gU47>vA+lJ*RQ?%=S^d5GyfbE zD>R(_dt?^+{`}vAR_3!Le-FM%{rf?G2jbr``ga|jE`)zW zY077$cH*DcAEW0eC>kUo{N9MVz`yVB{lmm)zkr9xh?*A%u)u6Ks*zWNVKenLER`n? z6F09!iMg+|W_0P_3u2i-UHmJ`37_82tEKYr_q4Tjb$55QwY7D(fq!{RYk+Q}!CP+$363!Ee(RsttwWl#`PaB%o`ke0^_kJIsL?3kzhz-cdqlZ!=)NnPYUUY>ND~ zWsil!bdexCyRZ}+8^0*BxVX5W9@W>^*VQF_SFBRMqQKFyPCn!o4ef+t^6OIF>{nso zaTTU5-Qe5({P192xBI?@u2Wy0?8#AA3}l(KA%%RT0MK zAIvQLcC`1GgM))-=HdS(rmpfDq^n6C?(M<}Rl~g(LPA0?Nc`~c%kx5VIk~xbaz+!U zZ9l5H;1Q!l*P*L*sZqSf+mmGc46%-FD$}tjKLu0M`LB_1!rm_bJ>_@-^CJ)=&PxW) z^ZO%oRgcH(O_xumJd(a#d@$#aMtE)eSzZm+%+^2;Lk?zJk|>#!9UN7!_`O~DYyu@t z+c)`>Kg_+FKSJmn8XOd|vXa%*j6@Z2!}YIℜGN5I**q-VJexu~k3 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

HXL8-$v-*j`oG}qz>3xj9Pfix-?M%w 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%0DsB@?7N>~hRI^PM`jQFrdD>E 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

wd z!5XPGDK=p=)984H?R=0kg`0<4C=2{U7%IS2XS5Sxi<>Y2wF{-a%@@%BW~ zH*k|~wf?Vh8f$MKB}Lv!lL+>Xy!FA=Q?B<6Qoz=*#O#xKrCo`lcdpcNeGGimL`wik zebs22Zt6kgGT`aqb`_S?S^i-#13CqL%RbW-BA`NbyUEwI^<~bxlykj+5x;cyq{@do zy>d-$p*Xg*tm%D`wGQW$wh~{#^}I`R33+pxnw*4^c7=oBYROkUuDXR~dRnI&%}>di z^fh2gF}}C@e0pcNp=jm2n9SZk211T~W$BR8m+9k?DM(S_(1x+E+?n=z1KvUBBZfH+ zxb830g`!AVxg{&)UPmP_Ri~AL^k6}i<&SQX2XJZzpbg9vR|j}Zk~{E{K|;>$agQ;w zRUhA<;wI60e=4AGeFn>yH~AqyAyJa2nBQddjW2z0e|AhwW)6ff2D3O%;^*g zvBVGQzS|00qxw-`=062c`};Eh%0|Sh)DJ8Q_mE@xnWIc7-Gp| zV<;~Dg&D6{&}p!bKN>I9Me5x6vTkdi{;uD()Ys6WqPI&Jhd#VV8wSGKtuK>#La%_F zjcE{e^J;gnmo`pb1iAkMP1oS*!##5qC$1-`fnL(L{toQj?t5YTz!8lZBRbY8+9#+R zt~dCw((@m8q+Fl}(I=T%RvUw?b!p)#JN%_V=D}^v(6~}!95A8@o~a#|xSxvIh|4X! z5ueNhLH*QXn4@vn*`gC%;kJ2I+Shi#tgKPPD(d^`bT(zu#Zo$UX$m-eA2`MdFw9`Y z?^cw3F09pdTG!)c=)wW_>%I4aSObQNKf-MKlOMABRRP$EaXN>@u{`+ZoRU`r+)-Yf z3m1V2LiW$zgTL8ICb;o-?*P()@Xp;tj8*{*J5fECIY7#yI{!Vx@yTe+G5sK~*J6 zyFP)XyCj9_=%Y1E)0vZz3ZCP;nI>0m{&2TUj=PQG1+o z2p4mn9_>laW>3P*i#OFod^6TvwcjjETir_Fdv1P=Hw?&a^nqF0AQ~o9KPTB}3-&>w zVH+)RJy=$rcucseRPP3Sw84^RdKt8^#J{*7gANP85YkZjs-dBEd1A%CEiWB10iiT{ zQ`{L8cS$*&e5Qh4x*^Mz9RNQwWz%y7b@5S?qKNgH+iNuV8Tt5!p1$!sObQC|yccS1 zjYKYsd@nNGu=_xf!@iFWxe%5Hb0q$iw0$9sf<}Wr@!aOuR@@xyPM)I781t|Dm`eoZ ztc2uwse)A;C7akgv;=StpI6|>zyx)=^}ddhe03~_J*~iPbW6nfWargtmms2P+zlo* zDmurTCyJ|eDyXTAkkqfW3 za0R2NQ^TS>TtAt4LPb$detpHbo0nKqK^faMx_FH9@w~p9Bj!P#G|HBmoR9oSI13p} zltCVp{*|lT604f_{K<^jB$s8<1k0wHh%pV_Gcfz)j^a)iN3omJ(d#k5&*;EmVXGBw zhTAZ6$^cP7#{>WT2;1?;4dW|hYu{ZuUB{9>iqh-H*gNi$4p$69l@IFQVQCDbv$Ya! z?@5E9d9ESF6?2jOuLNZY>??BZ>n|aOT^M5_0UFJEzS8@#X%WFvj3Wcz)7--chvukr z4dFt9Sw4{q`@W0-zJAY(rkQYynY(uIRD3||u6iwsQ3~xe>xC%R1qr_g<1(#Q;cda} zjXdq00qrpD$xxLqZ-BPVJwIGQpiK-S+@ZZ*ju&6$G_EpMEkpR|QRoALAuQj<9JGb0 zXve%8qBiLoP19My?B^(V{g+#5nZJQf1v=!)njb~OU{DL7o%fYyasirEl=EJ{Y3 z-u2!a_C3x1LbI5=$Cl5-o8W{!G1S$KM>I*o)o&?Fp8RX$$~%5MIqnanPztXzMsb=> zUz#R?Kg`Uj>si5{`$)3BeweG#aXbZSnN(|<6yeybEB#TP6Wz>wjj3~a@S;*+x{q80 zJYgp9`9Zr3Zx(gJTh?u8A7T-boV&(nB&M$^^F$`|0@5(cE5lJe(vCPRh#UhUOGA7` zYcK{>{z$89mP8iybJ-WRnxQ+IIg~F}M{tt`G%rj$R76MMV8S3DlVBjUmm1^3v+>_( z_&agN(V)n7?&|;mQN=#vo4ykh1GgTspoNyuok;^z=1>kV$gAS~%KcE;#*kx5A6p2fE7A8YCj!Cr_8PqioC5FVq;k<1p^z)tA;CL zMp8AGf$XWjqFR*mT==2OQFHEh1P0LZ0PW@2{O+(GE5N<({)2&&FoC)*+R$lAWs zY6wM`GJ14DwI`!&ZNeTd6R3@G$Jin)&T0OAU?nclY^gp&XTA4$Rh(ZwnklL(Z$9R2 zhRlwp?ANes3@*)i-by3~&rCr0`6&gn-XOb&a0b)ntCL&$i=9-WD1Rw(W(eJkAj#C1 zpjPxcvbuowC)EbIW^r*+w-JyMO^LI~ek6QYqweW9L>dzv83eq`bZ8EuOde0|j4)86 ztaQbpFR^fRJyWOt;3r()pJ{s%JaN?udCTB)2STgV)X)aTsJC0ZzF{@c@fDsOR1ar= zm7$%`W4}qu6MQl{Vgbx6cd^m-LkhoQXL`|0SZ*p+(#hCU{?<0%n^ZaF2;Giq6IfG>d{TPBkGanaJq3^!RobSv>D8kB;ln#$^iR7L zU5wVT=h<|0Hn}SyVdxC;+68!2utI_hJrVQ9j2ioIhszSPj$dxS;2jBvj4$BYAdJpw~2UgDJN*%Ufw1DmUwcygMbpgJ<$+SIT=HJCmou z#J16UuF!j$j1K$Jp@NE=7S$jug8wMkC3y~-{jyILq|FYB@4CkGS+HL^b}_C*nW?`D z5nb|B@!i73UT5*B*!r+-Q5O7U{mO>g)Q&kZ|}X~BHMlhRIG+*7U5L3$z&B9 zE+NAd)Vhq5-bYAu(H?~8^2g!BwStU+K|@!pAbL@+4h;sh+=UR_1p1~bkVT>1MG=R= zo_W6KzboT^4?sV`&04a{I5TC$N_x)ap)b8VZ=7}}WhcWcd?zB(&}%Q@!7L4UWTE&` zFd$YULV2@~4eo2KFNa(E9=o!wh6yif`_1M&UveVPK<5F13Kt17p-X(W?>O@vAdo7x zW2_IKn7%HtXaldhjMKOvJJvI?jw_?N-P2ysYI&O5lC)SUP_{nu0)3xTYzZ=|J7IPF zr8geB$tkdu=rdrS)CUYK_-jaxUwNhz*+_Jk*fktMEA-)7mzWrL6$rn33yTaDf5V{x zsf!k$rNd4#B+>qJ+y!Bi+is0cZ@5P!4kl;J*-D~-ZxQSBjjgH>bbv+`z+dOqNmmKo z)u0qt-VY!nYLxTbC%%%fHFnKw!jmyRVfXNQ)ygiGdsK%}Ifrpl@NU$5OOiJo%ILBL zatUM|WmW};>Iyw##oIW4Iq~fIx@=4B6N;40y5y^JB{3P*^2q`h5d=$AxL^Pp$$bC| zS6Nta*W0%e-)Yr3;3QrA+KTTDcY}XuS{EVvf!%Jy)ptf1hc6}(PVJ@DTU~9_-N=7w z}y7RN5$(j5P; zQRw~DMapyZZQy2eb`hYVcaP^yg*>fvqQwozXZlJfK(w4k=?$#4kLw%Z5+~|+iH|U^ zU0@;yE$eA`LI^RhsmzP`+oX165sX|L#_J(OFL3D+COx$P0O*uZj=}%Da~O0{);kOi zfjR6VMBp0}@^-uPZ^!S00bp=(lmJugE^!+HR#O_m^_Jz^@PP|?)8~-5{SJ3uGPezk zLhJ(=vu80PTmowIi$hunPsDo0cWlHzZTFK8SZv;RP{)t(RM!3o zc?R)y+#dX5>nfp1bB{aF{$jhq3Oguco($3UbbjiEkh_7Np49Q?wGXr4#I8e@Sz@Pr z4f2wN&APOW>}!z$@j-88cb~mh$bw~p6>nI>i&y2j{bo@YN1LM8yqX(x8sQBOue;bq zcDrZCv+es$#f=S73@n>{&ENV1Xew{oU*x`Sib#``N0Ymjvn z=WSt*BJ35#1dolhsqy=TuOKFXx#d7!Izv?YR6DVINxYNfnE}~jdqA6U zXtxf*Z95G+?JDxYu;kRT9+18>^<7&9Uev&*lpq1?&XA0dZhEU<$Hve?p)L9h3-fr! zC)|!)t!Mjojs$@=F#eiXOdpfiC{4#Y24VxIMW`?ku=uG#H3v2QuC8m|)}IF2C(1@D zP}k6+45o*(z`Tuj7_i|Fy!LtK{2Qmb|;Y3Fh1DWMNhJaNe9G6e6Q$JiPjFDIp3eA$oxe4gw#>%=^1%Fsf^ z$!F?uC}7C8-?}(!J55tgDn-}1?lfv1d%!nK@VKb+8idr~@m>1@(jK+G5&uv&?rE&F zuZl-(uJ9CcD;3)a;J=>7Oou-n!I$RIz-uTWeuvv&3%p_a#US_=Gl`8eH@^B|u9xCz z70S6uY#F*%*}0B#A#@ZBmxu@ic&|1<4J0S<7gu#dfDiG_03c?p$BD{cfOl|%0YFQ7 z;OWDIx=#0ozY>12>H#GAnR#4qC1Q0b0AQB8r`H*{ELY3hG7jt3lzjjg7eJM8Ae0gI z%R9RPyFJAK7$*~-!ovIEwZNsiEHz4!Pw^S4hNaEjrgqGdF^GY#E`FbCrWlJmabE~v zqV0_=u%Lc4Bt&6=MLX&GDV7E4>kS_2u3UB$m*(4eK>2ibT47UUVItzQkF=sS<<}Ua zKS9wIa>wrJx{p8m0~}3~5*2B~t-!WNkj{Y# z@+r!qy2G&;f)SF1Y)bzPmlb_7qJkMDIC8f(rGkf1M(j-pi1(GIJ1O! z>e0!D*($|*UI{T(?6kXO3YbZ-3k5+8b7~jzX~e#3v=&mPCh7uEDyQ`aoIDhKd@sHv}g7F^5&lGq$88@EiEjK(>O8RiTAr%Q!R&5j*89t(>P6|s?OoCvh>Ztag@v6mS6N-$+PvdY);Z~lp zh~`irjOKa!d4C4_(b5E0Ds#Mvux25;I}fSpG25wg6y7k{21&mPlPg<$^>dB^QNB3= zpJYq~M}-HJS@^4$PM^emmy}3TA*(%Ziu4e5S51K7E;S=eiyNLAZaB0SnHvb+2umkQ zWs0tkzM8#h56<^U!9_*2RrMPb@++Bc^nQsqUx(jquHS-644mPvGuVa-G77^8_5zm? zuTW0O|FnLPdAEd7Ed_EATwf8-VVav;zS2Y#LM$qRjP3hsTSXN-)oK)9#i4IL7w7qUVxMBt2&@15OZY-(0%njk>>h_b*2`XFRYWYEi7So`0av& zRWDwK`T<7Mcj+?`Utku!U*Ns=NR?hzDf$(`ewWggc&H1pxonE{E?J!-b&;d^EXi2# zS}w;d+w$$A87lnPt&0={@(&J(;qE zR9gdW1%hyKchrLj@HIq0f8cU)42f8;RPuL8nP9-p<`oA{yc|-5<#h3&{j=G04KY80krxTDX%Q7fsO25-0l3NC#5f+-P70ivn=pvm$lGp_?9|slX=R@?Tf78*2jO zxo4pZKjVQ$zZi731bY=7w4eaq4#~VFsi-Pp-8lHL2bSgeB68^PDvX>d*&G^6Srp*p zZ}a#_MxppP=p5ND3@&YmLJA^+PD<|HDZ8>+zUiR+_BDg!hu6Jd#mz$zj2BQ7=(E7dR z6eID*QzQTz@1y&ByCa8gj7k@d*xNq6tt9((7#rMWe+i0@$s|bF7pe2jv5i+z)@$#sPI;EjO!|d!Jf&;`Le&yz}oYQ#$qMP>@7H)PZss=#y5*aaqNpu zfHPwv7cr2(>_WK=zZCNy%=tq){a+og!CY}a{pSQzxVT-s}wAhsq`lV2;Z-RcB>8bHmw`$Fku?@Naih7F{``T zR?*BuKPl5J&#RBFJRp8w_8lnwmNnQnw>7BjrI&lVRq7CIr~{J-E_^Vu5`b%7~70O)u6I}U+ zIdl90{>#*eQh#`2n-5wGr{&9TnttmU6XM*W;$Qqjxj?@&~; ztdpFIfttK|zw_bYFY_S>=P&Xh2k$TO!9XYj@F)22-)6^e%5PsV7qjJUGiu0vM!L&e z6m@|*dQSU5V^3}Z2|7A3-OF@kFmNNRdN?@h-=OCR{B`Kse-*m!UxKa&JUsbNK>vp+ z@He$#UWLwv*Ct_f5G9OiWb4(dCbVz4HCNTdawk%ylY?9>B2w%3JMdp@zWjp@{I4v? z?;7EMMz{af;vW*fsXzK(M~eT@^!My<1UmmT{QHCEe;T~MX@qXqr>&GEkbzB+=!gK< z9&P3ugq*%i%yJ#oz@4B`;DJNUMO(ka{dzuLgD%?0!(aItzYNW|dt5K_P2VgK4C z`eT4!!TzP=^J{|NVgDI_=Xd(QN&Bz6H~(w>U;5O+1<|Dkq1GO)+xHvnKj|X;y|n*~ zbMSX4{<2e`^}pd1$oswT`z~3+*$fa!_US+=mObu8Z6s{S4Hf1a(^ z{NJ(lk=pdEcVbs=sg5%sz`Jg}YFyzREtLS2v|MCcvXYU%WB$*x@9XR%9vk8|eQ)lMMv@@0;vjs&D`dM)RIO z&k!q;+3%qLpEB3~#DV{N1>XBR?EgG-4V3l2ZLa^E0{e+$-rwM+49f`7|c z0~PpR-i!DzWBsQT_@4{r|4&+KpaTE*!}ovUhyM=+{-0;7RsN-|1^^KDTg?EhIHhpd z0n7XfcP`c1_W7V@k(aW`2n@IjSA>QinuFLb${Vg=T6Z7-mS;-f{J$;d-2Xf?ZT&CJ zG{~&)djOjDIG08{BsA?_1$z=~_`Z9(6c$^WQc3e_o)?^)IdV z-^WFuV}D}<81S17;Fj92-d^~n#swDs9}1vZ|78IE_kez;J$iq~@}FmBfmnW;S@_qN zCK|tgeC%KH`424rd7&=r@75FU^`%1jPeB1(`~N1F|G@Yah(&>|=u>#m>q~jcp8^B+ z35W$4C)@v(T`gzzPvtJ9jH%6DJ}TCMH&T7A6*U zV4<0llN}EuqpPbcgNwP5v8|Q94TG(NDdW#k7|fikt$=N8?VQYQZ5(-s4D}844f&ag z9E?r)S%{2`4XkVpE%}*wn0T0o^lkL5+#QYincP@;nB16|S&6KT`OS>oh#Z{_fGG|l zJ4bgQDezO*!HA!kfeA$G^02ir=4WB1V`e5Y(RXyxwR5yIxBJ=R_YUms zbZt#c9F3j$=~;-J%p8Cej{K}dR<^d5`ewk4?jL2$M2=SGhQMd}qkxIX#^JXy49%_e zoqj%txs8*tgOxt85wP6A%Gp8RUDwdo+D_jIm^TEn$jL$9+y>YMu%Uzg&o(9w`qsuj z$1~8ia|fo)jev|Z(A786xBH30K-a)r-|^=l<_^Zc;c_)LH#KuI0M^;s8QbWZ+S&nY ze=qzA%F@^!*f&25JJa8iy4L14z$}rYp|Opzp|cY|8`ICnbkP6FQU_y4Ga$Kxq3(ad zZvWrA3MgM$LgzUMwe8yox0M6H!!_lX4`lis>$ZW>>kDuodYd(w#h?ouNd_eB~Z!3#nLzsK9 zJz_8oGR}7q&*oe?`ub>K&mBO|%7p&TynWkqnl%n=tT}Ws)4;WOn*ePZ< z?6y>Z7~7rGR7;GeT(uo${mT@N5)J1;nljFls7kjZTIwi@&JT_3uLlzq_WlRMQ|#NDt;I@PbiB z`FGw2*jUHviTxcO98Rf>C>srnTrot&Q&J(^c`)CkCV@v2 zIu({il_s9L=YaI+PeP+x3J0HyM=NYTv+~G`A$Qwc+!#ex2s%+F!&Z{8UhOYTCNze} zq2Ir|@Gn0Ti;5~IIkOja-8rLo@WG{YPZ?VY#?R5#G_1zfNFGN zLb?H_$Jx3J6*bR+4P>B-WS1e!LD;=rZRf?y^Zdk3s~_wvn!7!BZMtKJuRs6$`c^dA zeRq%rUTo4Pt`+My%!lcx6%xjY6&<{46ro+7q@YsL%A(jna015GC#}l5#~d5a+2z-% z>B9&{)`z93w+pndPZ2EG?gC%sII>s4lLTd}GXNCM>0!4@9?j{Dol6anGp7s#;F1BPM1rm_irE70s7aL_}JP#{>Ze*txEXPcND^ zB4oiXuTg>6+B}+t5J_UAw*LD{WZWT@e1_e4JZIH?>UbRpPs68Z)9azRfv#afHrIOF znYmW5dfT=SS)FH%<6dkfw=}+XVXg{N1e~J$czztw)MSFLB*`1-Os=DWgiG z*Bjmo>u=&W);TYCHs0Oka6P9fU}$twC2Iqsd*5mRU+bf}fw?40)~lrN(PUfmE@k$X zn3@7TC@{M<-}Ha$hnbG4vZe=vq&^ubim7n_jaV$^2m_8A2~)TpDr}YnAQfqZ+Xa+o#6!Nd2mlAW>{EHyvF>r&|_T5H5x1jJn8J?s$-MpW+MwYQm(LO**j)IXFY zR4nT?KQ@cHA%!to+v_|mkOp1)z69UGrNl-feb~V?gzENrP$!5DhxB-jZEt?m?Sm^h zkhpD|p4@0ql3`q@4P@tQHIq3q0Ay+*k6M zGGu-A)3nN2MA(ozR_pg+!A)2o_seQ$fpZ@4Q*ZCcpY4xm^ti_GlOlD8Oy(%91TCMO zJ5it3NZf+D?S8p7*y>ILop6}0{GrlG0sK82ZO^O(_1&9s31jgFcf1jY&hJ&@6n+y} zV!R<~ zZ$ZI27yVqi2-5ojFBjn~3Q6OV0NP|Qk2mpqm%<_QU0kfZsza+jEnjD1d>;$RPL%D? zv*{dduM{_>6(n3`!MBiX$G0navQ4X=#7sCZH`R``K5mzZ*A20`&}@K=u7jID&E&nl zi{qd$v?BI$4s+z+EDE}4FkU(SG?P6Zr`i;UDXc{eJ7q)`Q1aN@w#+enMmt{fE=p9c zKY8hpr}~?(XF)hUuljMi4e#cwXi(|u;2`bsN=e-Y;qvMouCqhJ*|OYun7E$jYlST{ z@uYTB#$r^Xqu0^VdArLOA>$(hcL>>&?nMU}*Jm|CpAAipIaG~8mcj4|q~k#Gf=HK&Z<2#`2XX~*RGEFXW}Wqo&yG4%{N?Ab zQ2w1(-Qq8Us|C?|UeycyWZ8S@YhoMYW$Eol>(~!<7$Yzt=*0fwRxvOd)+uqR@iw2i z1=^Qi6x_HFNl2%LKcKc*PFe;%F+`7B6+D{)5LlY^8MkxX576n*~4rs^_5*OsySHJ5r<}zi|jmOh4nb zjR@Lu{HcLFp6~-1fQ;l8rHnbE@Jo@ z+5hhoU_0B$e}!#M#xIwh0!H zp%^LaFa|?BNv#WQpXwm&l^ojx_{$396hTuVv}yGngD2?i4JpDO;iY$2Z@zE(Yvk$2 zn+6HSx@w>3CVxxkdmjEO<4Ns1%!>*#?-q5W({UOdtDWNg{orM-Z1OrKiK<`474czA zkHy4K!j%Na{1`&i?D{kfx|f3p9284_=)0O1wv)N5=JdW^Fzy6u($<91%>`q#@E&Rh zxOQ3>KY?5gU#y#?{ign=pl(YP0gNYuh%udrPaTwZ{A>%`FgaI_af?WgOaX5d{m2*u z#$A;+TjFCIYqbwJ%J!lNpZNyHoMVFbwDE^^E8r@PERI4fra*k~NnG zkT3mleowBgoje^xpZx6zgFNrskWf11Cn88C2_uF&sA#taH%ASPN#39?bG9&)suP#7 z_%uTJ+dd2`agZ=jjoLLwYR1juqi?j-^>F$Nw((z%&4s%5S0MEDmP+`l7oEX+^Q6ft zk2NqNVUyfl5C=+JYyhp^R zg!O~h&wYuQBxZr)$ee=bf*A&%=dsDJN0_{^&`y1xNGAJg@|@+pAfklCSdObXt-0$* zks=pjaH z6l7yg<$E-zX{m%)0WETBERQXmuWwtk>aS-$8@CWhYhGZmOX30#WuC2O9may$B8)IQ zrhsx*uazNng^*t@Z&EhOF-G3$Y8H^=P5MUM@zf>GO%}od*s4+SP*|TsG>2!PZL_C1 z>zgj|3bSbC)g0lXV25CD)V$&RBp|9ptKF(g!qkAEb}!6I`G~XPyr5v!b|*Vc2e(a2 zz$1~EU0M%5t@*jvzZt{l6ZHo{G`Mq7kmY*t3@uV)O>ZkJDQ!Ac%9lFZ?Phzoojq(` zTX$CjCgiW*j#wG^vNA~IJRrK&EuqcU(hH#@zRpyaRPxgK6Try1xoYN3IJ9-aRobfYAJLR<^5;q@#^?v#e=lS+k^uY!tFLFa7vaCS+Y446EYsyjb=CoeXR#p$IC& zx9UKGWVbhE4iT^0$Xbz=BohZ<+x^kl2n9?$4#(*zO3Z*`kx!rP$WlzZp33TuWON!zAU~XVz!3tQM#Ojl<1tOw9d~sU~l7k4%E}N<_9sQil=!{d@DM zwurGFg27nxcjfrrxYrT8pOyj`YVLH0VI!IL>(R=^Deya+qOY^1bN zqW$!Qq$BupX(NTV&%Mhi@)2EuxYk(kUb=cY z^qW`#40gf?YBgTV;V~OD?pO_2v|J6#@8ta5P^3CBC<QwfvU1PG2(DZYiw}nB_ z3A+?|-#3OP`s7L?@vU8RGRVxPsGhLtz#za?3n2GplpjW+Di69kZKFaz2}tJ&o?-g+`LAGvY;AOQm)3x zTK*=?wSq#Fw01UXw*W89Wqa>Ueuk!Yh7$X@>4#lx@6SP~inXrLJz9~8H(WTl*Hs9r zF+tsKD(9@RBH|iZD8efNX>ub-S#~`Ml+o`t?^kuB{LN1YyecSQeYLmLm21+eUW#MA z7UDjzR=P-tc+4-^pkLk2betu-TO*Z? zEs77jY^GY38c%JrQ!V9+x2u}Ye!Y!+eRf>DDQ1WsMEWdyj_T#*ug7Q6K-n^dS4;}r z3PWVA6IC?-j4vdh-0WK>4056RIXg2~;avX*dEUZ&2poFU-fnXKr;b)qDu9xDFHeJo z1J|sk4J8{VEYhsWRq&+mN|r5N9FH#Fc#CuSE$AWpovsbeZt$&wsGd<%4>@eko~4tN zvN~*GS?q^q2PGa7sl%NQp~9k=pUEuINQDQaf^86er!%O_)NoLh*RF2U<3r&6Ln3!8q$DR8uc=8rzr5~5j z&2tUc5bgK@c0MMu96ivWp^!Zbt={%LOK9Vi|SbcijI2)>67?zu;;<+>^6z5fjU-7?~cE$_iK|&n#+h4k8#m~3}OGgO0^XME04&HYb%EfYI zjml=IQ5Kw!BZJg_TsbQYUVz!%C0>=pC0L|vc|n&soTt1Jl)8r{TQV- z3@?dH{njbn&i$R3jN9P{JIELTI&bm!%tR)_%y^DP{G(1Y>)J?qp$|hrPmThE>Yws* z-V?wV1fYTVYzC*57PReX&#D2!UMh8Rk-F>!Y{R|0_`9yqQ^dJT~XclPiAh=sTFB5 zZ>br+d@`xl6-m+d$Zd)P^MXiIO-L>7IY&6*g>=anOkY~ui z&?_RuqB>(0=9SjcI*W?dk}o-ac=YrO*{|3Btf)P(;GgV#lSYJV&EH`tJ*njS*g>JH zPLL~tQn-2_u*7}3H`&Ci<9)WQeumWoxw2%rIWGf1*0z)zVQh``;{`Je*R(k0^y3`&0%E}HJfXnf6?YMB zv9}&9h~LJ^FVEqb9)!)7J2SRnFW}kSU3!R(y1u5`CCHY;f4(|3z${@fDM!KsZUzUw zH)w}qB0QvPo1aeX^O-B1_g^5bt|2AoGR(gRWyx+Pwc6q(LKWVKipD5wyzmoQVf_C9 zLqNR0YCCNklDTRG5p2lqa|-(Xngj~_06F%rdH^9~^J{_;wSFr!XxRFNE)hG-(td2B zBhf?#@Vz6>$AI?I>liLy*b4ys8Kmnct2C{*r^GDOOWF6IU*W(#@xPWTStPx%O9AJ>-F6vQP)J>^sY3; z{pipT}S`i z>Q3XG-@vV{Su>`_iJfe)7@3J17K9;Wd-6$_hFHaPFjz0Nm^^}+!(EUwrlx$8s9&8c zbb~>aXvpP9ML(XTP?NJOZ)fX4t0hxpFY^N2;sCBBQOw)0Tt4!!-1brnD@_oK>ONp^ zFCl|U(E3)%#f83VDdW@k5~yS}o7{T&^!08EVr~%+#?>E^w32?8i>kt66h;K3=s-@s zv)j=<@EosBdYC-iZSPArePNE`7OY1;aV_ zG0ZV8Bc@s)m!+&&sp_8ClH=LUuo6kCPA8WyX z{a^7}GY8)N@yE)!B1`KifW*ZT$A7p87d^cRRuk0un2aN_Dky_q<+{r;6?V~n8;0@vz7&}l?R3Kc>pvYG%R{b zCHwLaJ{QyWFaQ7p03jE-Fd#otG8MPm3+;es*>eZs^uSU^zqHNv!;bgox1fD1 zac$8idQXuyfd~oZpg4VT?%*4`l%#@OYXHffpUyJn%n|~)YU9;8=uj<(QO{l?88d^N zHN#- z&v?j6Gn$VsK#BTQFS<&I;XQEsR^`l#)L#{vqTqz_cvcuF_kwj8*DCR%I7yxwS7f3A zf8I&@Z`Gsg|8Oj5}}#cHI182 z`cizE#gv5hc+8pg^AN1xkN^sR3NV$3_3zdHY5AI6K)qfa8nU*-*=!;mGUmuOS&s2l zh5!fiV2+5>i^v91`ZhHY?__!*(~IFC)3QksAi8Zc7Wn+E`a@dn zQh+1i5zUrj@v$adVdB{9WI5c~!BM^i{?M-|z|ekBaf=$I(4s)!xD)$Iq=}Vl$g@QW z1Wsn`1JHm$Ghu5f&S+GI!|f)apgOtqXh}+?62z5^PL4GV9LMZcHGE&QUWfE?A?O~< zRx3~q+U!LL{tgs6g2s^GFP36$rz!|71R&BRGgKrjCR6M-Hj!`XL<%P#``#C>n} zU_pDpV?VFb^>IV}q*lD^mThBUM5;dxy(72DGn|D%!BvOa3v%rk0*;rH!cs5k7wAir zwo*i=1~iCVYVkDgb)(HszrCGyQ%mheHJAS)$?O|Z8QBIG!!D>EIlr#WR)Rp-W8_zZ z*4%=G#c;WQVm7Nbl2S0$Cp}|*n&%#6X79eMai3!Z_;iDh>EXM-3Ea@uPE?)@jB9Sg1);ZK1G>?bf@Li*hBPCU z>?u_m-5bWoDH+n7&C<_Jl%>IbL|{9fjPTlr#`i00Axx4-WgqQBU9xdCqVVp88P5|s z?QDdnG&|p+$wEfyoSt$VQ0{1KHJwI#BR=F;u*ag&)-%ysC7BwA6Pvdf8elE@1(biA{UUpfD`zxR6?GW7UB9O^Ft&E1rwSE@T@bDA;lR zIKQ?ab`fpkX*VC1{(;Ad*Ti~GPeuEjXjr9}t-d70FKERgJA4_7Cq421@slTaEM~OMEFlX!uUk$hY&GSe-S5}W*0U-^=wb+7AoBy7+#*{ zu-b4y3j|b`k8+OSY8Y3t4Nv>3W!Qj}$>fqvPJ0ZC!41WK_hvyQ64V>R0be?6ZySnp+dJc?-~M~*UBAwrGKaG=#s^1 zPFoBd6VDd*;<7@Ar)!}pJ?>q+m%1ZNJEp zPWWpoNF)y3zBR$PL^pdWUk5JM+X{{mj#N-`;>n8+Wh z$JGSpJN>Qh46L~#w)&)~Hc636HC{zf8|C!rRY@4s+$aW-vamKtRUt;s(o2B_!krDp zWBG(pXU5kjW(kc3mye}XLAe2=oaFf(To%=CS7Wwv(6Bxp!G-IHg^!y0*q7jJ{oU#} zDXH_XP9;L8bQIcujswJyuLyZRUr4ugun~Q9i{FJ^kB_Wb#4B&DN4KDAV&UQ78vHv? zMz9qE&c23Pq76(h43==heXx?Lbt2#Gt^5#XKzuZyl&XeGwkX9pw&1if%#>GTi^cK{ zMm`l13k{>GH7@50CHvw{IF9O4rRq$-uhH)fZS>I-2k}57f77F|Uc9DJgV+#?_E^#3T{OBA= z5~6iDb!Y3a?-jtcuED{;K6N^XHe_z7OZPkSN`+=@M2yC3{etXFqr!zCSqb?*QjNyB@+|tEuu^HTUgni&?#GwKk=vQvk}#MJhzQC9JxT^d6zVC*AR|(u zDJ{sqi;IVwzG0>%ftC(XPX2{^(eh*~E2vTd4J{|h9nP_eIw(yCwK+tZtcC@;sE9t< z4qc#rjwXN+tEZ@&u4lACh_i=Qwh!WqX@Da$1 zG?id^PP*U_M`u`HV)$v)0DoA(j&k=dCwxW^glH(qB0QqOSa)v7k}Ddx+kUfq(|KC; zg8s~-tL~#{1WFU2Cxv6MQwk+&jTCRzV1rM4uaTAKC(lSq=wAS*p`uo=897k#^CPef zZdmevZr_-KHnSo&q}9;oRZyfiD{PElB&1~9Nc~kLN|P^oAdo{{}m7rbN0r*40>$uE(UrT97yL1qIlmXWM7x z#r-9UXVurrSTXI5%`5e9TFNh0>!{=BPEM7lr{<)swD9wy)*s)<7HIB5%0-2HM8nMd z`WX~oF`G4sp)&i56T|zSQp)g;a&smDGYlBmkdxbxlPsgcc618qV`n;^{Ddv>j22f*GmV(mq$@o_ zU#+d^JkLoU`udVZ3^cl!W`Sddc5KO7l@Y^4YTap_;cX93m2(`!Ia@qSzYi_?s+qRbZ zPs=W&FRtpb5#%T=jEDuRHU^Yt-skaxu3! z!P_?|_{>2WDS(#+!1Ktw#KkiwY@7ddx95qJKI3!{ICq`m1v^NO@dvlBhtRa)&^l?+ zp+7@%>5US1f7?<#mk<1@5mL7;nnH0FQ{>5ZBNS4pZCq>EwEZ6y)xQrn@&71K5EZca z)i9#yl2z#1r^z+SVKsN>_gEi!0h|Z<{k>85d&PTtY~+tE#HxURG13>Wcu}ocBF8aC z>(Y|TTYAuj?Kp<8TkY-~Bb-R&9wvucZ;BT~`o3?=Ts~qWyZF_kRH$_}o!u{Di-Yru zb@NslPftbUFWA*Ulen((KWdzm6sSX!QBbX1kjBj90Bs@D7<&>IW}>r5w|?HyGP=|o zGuvztz*+p>=EqOM`zKeCYfpeitNaxEhKQn{95^m({|&`JX+;5!J0)VECT(Yhvmh>r znd9>6!%jjCgKfy;LT+4aAgSfxV;L(`74iMAJP`$!XI9mqk=#jWyUE3O>>pijh=70q zNsHlX{9cl2j9g-!cz8QC9krAU6_yN5NKTT+HPW?e1;? zycB8wi{)CrPiQ~f8?G+@KWgk-(PC8wDItWxF|pgMCo`W_S`_7bd`$w}^ibJcSXT z?ic?}QX;>B$$m~4E!bK4?0~)r54AJ<+M5)ks5olLxa%7*RmW}U4aVbQXzz5NU1@59 zlzU-M#j~&!Nt>`;pvU#BnqW0m(+1BwQpHg!r|-+|1j9oq;~u)4K*Je2n+yK_BLW7F zDiQ+%i0!a^7#io3&@hthyo6N`q>m`}FRk_S|NV7g008HVKfXbQfmc%!J`;n$BnyKyEtK=qQa5_5(b`C|J_6Ke;GmL-EFP7wel;Qol!lJJzI-ZUb)E1 z9xN7}UCpQ)e^FCB@7hST({LNp&DQc^EZW|jCVA;$a zDp)X=rYVJs(dV-LGe{JbChISdJO^j6aiV5k=N+R|M&$pXw@4;@O%{fu%f@r$Db0gH zUaAA%`Qg1fXbMP0bP*WbAFA4aFMak6xlzUdfSYQ=Yw$__j4@s9vI){qUo1800-kSk zIaBGNEPxNcX?;(1NUlP`b)@1dvG{g|73OQnmoFCzQZUyX!$S}0x&2l2M zZt;rfK(=isRVdzfpvv~@PQQP~?K{&}8bwBYh|WX0>zZGflKl;ge;LaGqrpW4_s-h` zm`MVs5lWD5oi$`&<3PSt{ft|_w2tfiZ~flSJV%G;MTu(O5Ix+O>&&h515KQzilr#z z8xLeU`{sA=6t?j9Ruhxb85a4U=4*_)7Rj2ADyMv~fy~~an^x(x)*_^OPK*EckNq#` ziz+^yIbwSs5H>BLd0Y8ors4-E1L6dbRdtetpL#btC4VDgsUMC%PGEKtPBN_40E7OZYV&+0pFe)S_4l@!H6~pRbmB zNpv#dF}=eHn`8!9EYD|)QoanP*vj3Rx}P5)=-`K5Ip`A{cD%65l}({96A;$xK>IL~ z8b_~N<3fEp%^|Wno<5~%?u;d)fz8m;G5?pRI=)j6zev+BymYx27W^HRTs;K@OM_>W zu!DRJlmxKV%&7b`0{rYz+OLl2<7{f?8Vbz=}ApF_{=!H+S7JsFZEPxcx|evKLLXMt~dQh z#P(V94gqph>*MVWoz3LtC_N%o*`!n}$aDMt5EOH2T+Kh)d5?6sMV&b+;`;Ub1f$GfQWfvQ2D$(wU0c{ zW)q+6VA{rf5dKC9&lJfj+;i1=iX&tCng*rs9?5?b%CzYLrdlxunTm^t$5bsCD@jA1 z2dQ%X;^Zl1KYBRw0XFAfq{|JXI+xceO_qKGtUD5|yBFem!3mPgV22NzC+K1XcdiPT z#0xI)VNmtoU;cdozo1sw>0*_bNC^zb4r-olqDfc0>g9%?e!MX#iR?Lxu#zH|VyIb< zq=q#->E!hsT+y-uu!uiHFH(Z^L(}bnS^TxRQ~R1THWU4Zs!2Xc-RqXr|QA|1r73T8d^>Ns@n1}>QnuzFuJ`5>9 z#N^MZg3gKEZAweKgYyB~F^pu1^9yg)PyM!_BN$mcmC4PfVO})M%>FXZh`;Z<8J&Wr@QvHfG+Em1lkS!vKbk(QZFCQGfYxiB(l{3FFlKeO1Y zeo*n?WISF^Kg|UX712~*&)^><>!#=;OfV0<@>+W=4S4CCIwy+N3mhUQ6dcY;x zb-8DoAyxD_+4yxsNej3QnI$dO)>MT|E%f{1V#i!{A1in;4vayl(erq#Ad;D&+Y5IzB8P*|%u6;g~ zQUEm`pj-6f-4~9?#qc}@JuR}Hg1waq`gd(U)nrP2fD8dp%brbk?i%oM5oRc?;F*_@ z8mibk&976FB?Kw^*pREj1h?)sWOu(fL)PHsZC_%?_qwayRn#~L*cm-|`)AsoRaY1k ze0*z#^2kD$RYE@H-0QO4*ok#9WT`%7K6;=vH#+MUHH{tc9}SHs6sa(FW+UX$;qt0>qz2{k7;W-nTPPCi9a-L{(4fs;W?gXRrPVKJXI-KA8Otqo+A%@k7N zm7KoW(620_K&H|wpFqp(2B3o`_zNt^ok4OgK`j19-r0_tI5N^ctpEz5nqi9<2Q%WU z0SY&kSjQL`eDojx`+6uf7*Zu`d|81>Ti`UJN1Ny0ap;N6zQlrdHKHkTtw+3Us^ivE z)1NP8nLnuFp}^=0fv(+&i`o?AHufyNsja8D)!|$2+aGjuvNFYB>U1`?0}iWET4nL|5_nYXLEyA!Y+ zN7K9-J}lt|NjJhB@TBKWrllGJ<#@t-nvSo#ZOl zUwm;Xu?05B#b#QM=HOJcegoS^@$Tb%s^z^XLDgLtcPtgcqZ2tYeLvck#i;Ns&zz}@ z=Bz>uQZ7&wcTkpg9LQDH5WE?kSngY4exQ}XRr{+K8H<9kFuixog5|&#)fJ;3{^0+9~D~M=K!F@=Rpn zw{2lGG9~av57I%?0};xh!)0J7@2Qd*9-Yo5W-Zjf5$D=_Ip|GR_gKwtisA$^U;fGz zZVCA=liJ}yQn~Jjf`j$o;BhHOvryLh=8aHH!7{i$zMop&LMpd1OY)=8$ElWOrPd%O zBJk?+8HoNPFm$ajr`1&$5u%^WZaxfO+sY=$*(L++I<4n)e-JB)5pwVLfGFOixgyzL zMBCdL3A`Bm_Ib9Qv!4J!)YP`{H?}Tj+~dw-=Cvy|c-JS=fr1@8O5L`L(Z^KIx+b3A z|Ng(B3d^{|mtegX&eQ&&*=*WN&x+<;8P|xHTZ#wdpTp^2Z~l3VJP(-brNTcD+Q)s{ zVcioV7HlPZ2WgNqCsK~@!91>VhD2IQwD+DUHgDk3Yr$$w?OZ(%5v&gK+Datugtgqd z1Pb9pY6W0EnIolDKY7*f+XKVqAPnSBYOANVrRv{3Gyh8leNE@vd;t}LV_E=36=wUF zS(gO0xHQ|L0F}r53h+8t$bGi_-Nw-%u<{-TFXMvaJ|&VFuG$RN^AJeq-Wr~beOiv5 z{zo*~I%L-79@$Qt6^(vY@Z*q-e3TTEKBPbZ3d<*-%_@%h>U&%vUh}O&i_4;uf|t&L z{n9^;Tdp^*|5#O*;=MO09>B24`>T;JVVHz*t<3{c-d>EYPIU=du$RBu)HCR8I(JH! zu7ez1pNfUJ;m*u|TRpfL#<>+{#Uv@%wN;>VZ@(tQrEiJXM3~NPrK?k9Uw5>lt>8G~ z=+Ze34$^WRjTQgj|rX@NEsx{(pE)A67FjFry#9dzeEFjT11y9Z_GWFh8H z|KwD{l8pvNQ$`i9z{tl{1V1}~<=PYJ-5N>0DILy-2dl^&F{_}8^fjln80YA58HN>g7nH7D&_uv1 zpCYt(bFm2uH=-^jsHr%C_qSJ|GEigYcWz}$)fcZv>hB2YB+p3~R}!K@$GY}Cez8(x zyt$7aVefku6LG<+yl7@Lf>@n4D|z1D_fe=`pA=aDAIrp(+yDRtyX2072x%AN%zz#q z+TSpau_ssOJ&5=<@=l}x^8f%P*6-1BA-NSVznVw@8F7-cWDjb6zL{-IUBSaUYD;}ox;ScoOe(N3?vEFGrq5!K(^dWnp*QX~1D^r^<_e%22Z-P`LLAZS zHLfq2;^60&Uy_9f;^Dsv`}N3exV*9ErRgDMak@1#VmPf}a~9JEK~K@RNJz^{`EI8F zEd7Gyl?n&+4n#B5EEMg8`tFpsMwd3F=TOTU2za@;S?7gy^3iB|mol$iQo1qsLKMCl zlW(ug3bd&{Y-?I-$rF>*w)s>XC)q;$v1l1|R^_~jf=E_*nKk_g{DiiCVaYg1=KGAT zsx0#8`Mb~!>HMU8_%mD|O3^HU>o_OY*RmgJ&2#F{#;5@yxZfndMMV8N`VqEkSMCzw z_K#Oiw3KOdYF7V$$2$E)Qr9dcPzr29^X2np0fONgMO>t_~p zlCEwpphW)Rhp{R+-J6#Hvs+}{zc4j2>#|gY>)q|}8?|ZMckB-d)5xmDzyJ|II2#)f zj~>|@2anO<^4;m@TShA+V}V&l1bbmRayfFf^qWuL7KLAPZ0}0n8^BzVhDq|uYg`$E z_&qxgXB1FTHrEf0-o8FuyICe8bH8B-$Nx8BT_Nj(nnK2pPN4x!4Fe^BhU37DBSN#F ziD0@2F*u4d&#PZeIA&|wqGc8mqF`{66sXGo8~?WheC)l{P^%FleB;A9uc>=T1x>di zsrdlt0E7T&h8#A416AOSPwb$6tTsVk)q;_uX%SVW@q8(9SA+BWuyvLb0woVrlhgao z=;KfS#MDWU&51r5H}}?$5#NiU4E5m!;irANl~kt81SVkmoWtJbLlz$g1b1g1$>Lbe zk^C76QBt{FO$33m!0Rm}G$O`15`2*%p=h?^VmQ8O@EwX&|rqlkU6=>pT=^m*700RI&Qo29s`+lw5 zTv)+x$9v^Q6w0o0}{n8Is$<^pc2(s6CakI*hfD0;v%&;TPoR zgufKxn3ZR~`NL!7d_rAT+2!@``3@2g55Lg|uw;&4GG+b)PMUIXohG_zBnihg)iGSZ zo&CXfsRHCme7XO#U1{Fmn`gjc&f`|KS5Ak1cgH!>Sd+T%JK|@K+A577rV4}VJLdlf zcOO;B3@&2|UO0~NyE2hG`QWOB(_E(OM;)7b#*2cA##N2-A!yu$)H`O{C=54q(b5c3 zmqhm&!rcvRM>gsoN3(rgBjKuF25wWgCL_w|y zpnJ)KGXA84-%3S0QIlwJ6*FEe3&cDIMd}Wt6?XUdrt3KOd}hNx|Xp#p~by zzqaAj5S?`OzBJR6nxr8OAD~f1Am@;JVJZRGH?`x)_gpYl2b(H+*}z{_tb9y$O86@Jf@DACAbLSrWf~yKE29<-^i^{2 zZV_O;d3VOWY~@oD1u>& zCthMKRknuGLCQsQ!<`sdGpPK`v2(MX)6%;?r)<;C=|HQaX=zM0!WsBEf@5T8#-NUa zyyQ6u6anEI-|O>TmQA-^(jxb>1+rt3SNS=_`xp-Q#K}6qk<|B^*#H=FKmY&YCzPV% zp56qpUj)^jIX5cVtt7y(^2-KSZHV@@^l-E6R~6A70Sr#IK4N$?@AD5emr#{70Hmt9 z=?M?6GrqM@gD9uBB^)bb#_LQRHui()wUI}a9DMB8!!q_J|JD)i*tE^-ou&A% zo;WL)pTJ(Nz^*kh!U{tPp2zx5zAJf$t&!311f_qmJ&*I~$R5!^bZmEdrUaxMlDQ}$ zEvKPZd(YA9l)MIT3r_9>JHGOo6^F*351oQe=mT+(NEafCI? zvr#5pmm;PO&vTV{zyAv_L?lj5sayRxhknkN|Jq{coWw*ZId%U;y)IK#`T-}^lBV+! zDyJz+pZzJX9z2}M`DthZZw}_hxEUfJY?%kwu!EY~1NO0WFo%s2u9LQlsWraJuMX(^ z0iYDR(_R-90XoL&L=NpKj6z#r?VG+)45pPgOG(z?@eI70{jrmGatP_-FtZ(<>8Zo)NaT{?<9B< z&FoI_sopFi_k(Mn9(3~1)av%cP8xI`57eVPlceh`(r0OR%KG{4~n?N$97XVLUBKW8UVeKUI`>iW~nqsy)HnljG{O_$4Jp zTF|2#uVTq;j;^8N$+j(ycQQ&uI;1WL-%2NZn3L3go@}d|@PN&~r15VtgWspi35Ejf zo(uFGE$UD`9DMY2S?^8?PKuS{8f(t|i8XPZuU9={h<3vQHJibljivquE!mz)iu9Yzy^` zWxi2$ORNJ{e(M^(b}7^@Pyf+L9*M1H=}g$vdrWOoY-$gR@FA`>)3=IrjMo43@ex%> zoECD^v&tk4W98cz$~sMLGHf5~f-tT;cDo9ucKI z=x6``{m}SR6?6a_2CU?2U{UJNf!MI}2*zne*NLLv;daXn0<;om;%uqCs+NnXP!q-^ z;FJ@$vgJ&&2?DcLF7>TvUsM18?9pV#RiZOJ;8whHPsX_F;1vsDZ3(q3Y&0T<8G)uc zzRj9c6<~*GjpkWVI0-w;q1N7}ceXcths^v*uDx6>8E7KrMi21KWU)(RYurjhsS-~R zUJ@WNu%{bxub`50b(dx0Ylh6=d~3~p zaqW4Y>#b+L%e3Q!{`@RdKgKs27V&p09^}OCrGVCG7P3q@UyA_E(1MHa=oHtpWLhh? zVaQAgFLSC?P)qf}J~URw!sHn4QA1yuHVKa5QJayR2ASG6Hn!rIOKBEKT-a;>tHsYa zb0_=4Bt_TV!;KmzTT8&>qf!TKc21|M&#_x{=A z`z9exG>?%ZANZ8Q#1*dk5{u6!lw5-ux5^Gys7^5fi^hx;hW^nplsH@1H#BB_12h%q z_r4Mf*RN{jF&HOeI`xLJQ)BHz~;T<48&_FAMzVR|ceW7BgA8hL(7s)niIs%=c zQKdMahy+rl;<0T3rsx|<%&V$M7gwRbSNnt_l^xWMabQ{^@Mr={vJsU9M0R^_Vj1}s z`T(hiBo2LS3Z>m}7TZc$L>m~uqn+9EHXRb)_P%DkX>gO+P0eqHXBP0jBIzLH&5?hF za++3nS>UbQWaSn2u5S63I+rAKRe6(7x4H(a+(YLh5>;7gQS?_{03`ll&^M$$`b9w% z#8BGoiSdAdIGkc*rP~bx_e^Z5Z*q_P1LSQzYkC`qv)zyEoe;Cd zk*unWZP$c)72P84xc}i9aqI+NNczlzY-|On!+1hw)tV~}=% z<=|rM6q5QkU71zhIcbcA^+$q?&&KwO2ugPJa((3dv4Yl^O|tb+X>JHTLglz5}m5X@b@Cb=Iaj{ukA zrrF0iM|Z+~!4_0_|3_d}OBok4ke8Z`f2+^8;lNfYF&azIP}`UY3`&WS4+iFCesBL| zrT_o~003B2bWUkvY^%1os;%^4pAY~JRTw?0=l}(c7|_tXeSiTVuqS-*w8O*#$QG+~ zFJiV#HV)Boad(Xm=1b0v@Dy4ovd4ao31i$7>ElPtO1TO2Q5~PH!QQZMhR+%Rr*JSX zxGpkwTmsWzipU?K`RiM|b)YowyPv>d%|n7!BOL70)Re1C@oHR}&ok}!T)+eu%kRI4 zp#LEu?hFPDfk-E_#l*t*)iYA>kK1#K4P-GB2E`Em2jjxs6>am)uQK4EP;cT_$;hGK zin1;u7YpN~-CldyqoMGN{nD$wo!(U8!Q8ur^uuj8Kj| zwYh%tK;Oz*CVa~n#N|7u%Mycn+px*oi29JAbb{LcyOhkpsvRMau9^$sBQ!(Be~5MK ziPrv+*wH=(u1CpekC%0*1NL+ z`F!`d4~se^*8x(AXkgoGzWplJhov`)$O4aCeN;lWsK1dtluZ)3`Q#`3JExAuSXD5l zrUpW<$4m~y6KPQ$`{)JDm2TFzv%|O=NQX$aVVb#~8)r)#Zi;4e-|5HD&3@3QcsLWq z#7i`w$yQb@KrV@XOys2GZa!P)UumhABQs`XU$u-DXg%hiZ3T*8o6~|3r0d5(%f7d& zpLTOCR)tQ3nOW`0k{#quRW80*lHT!o76voG1n3&@djO+&)?8Kf?zq6ieAK!#uZ*79IvC=9QAw;py&wM6AFqr}|*KJgKk^f161f7s^u)6?XmTGS=T-B80zDeYn(o|Ep@Wtgn&($}eYt78_YniSj8QxZHA? ze42dN%|rH7{w_^uhh{gqDLT-DwB5x0RJ(encxcpjiT04_>z81+eH|U`hVy%bzI_zU zPLU}Xv#Hqda*sEt>dbHp`CaD>k|!=*EyW<-IhlK;d=ULY@Boy_twC4NuFI2rTvPY& z$+A+PE4Abym1Zib5ZeL=!T9S-ZZPUzGLq`8iAM@@W^Io|s5F602KRDY@-kQ+{mo%+ z+Vl}6@86G+UGb|YwYaFEc7(RPzFeN^zi|FYlMNzNcLbE{aqI;S?&qy+_xQjrMY+tm zAiSEWUz*$Q(OIqs__Aj%qD*>NPINhZTb>z^hUSZN^SOy;Q+2F!)X%zq`6w5(?^bD2 z7~g%r^Sv*n5rWNjQ9C9uvEwa5m=L1#oJNe?dZ+kwHX;nxEHpRs@l@SlhxYAfeL}=` zSWC`sl~C)yQKP5qn89KG&wGq|Qnh1^qQW(HV*aRP#XoLB=tjG@@20oFO>*&Ls6nsm z+PM83I4oNp$~s5)uo#_IH(#Snrd~HDrO*(am`T>R2P>gH#AJhJIwx$=>OeB3itc#8 zWDE%E++}8Sqpedacj;nDG42j%C_%{6GnKdI7m$g5XrEx4P{L|`kF4OqXRU6e){9TJ z?@GM!v;MD_TCgzlz{} zBRU}($~Gs0pAh<}g9KkI{rqqGlw0cPs(F{Nr?}HWnk=8Zu?3lQ2WZ9jsO$@#8wHeO zbeDVkJxHJtury>*O-H+C3im9EQd$ywq_LR*fQK4gyYrXLoJF!|gD^+bsdx^Eul&uM zPNb5u*Y56$K+VR(Ey*pBfG|I7>o{yM5Wr1a;82|tCDkf{8T6y8yO1dD| z7cdI*ELnZRDx0r>k>HLX(}_{k_l7VQ=~2aD0iXHw9vVrw5TFx zM_y3+w1?HViAqDd-_nvakj5(U#yr(2tkXUPnm=1JS3O-hiO{NJMyYwTeto{Q(3dkG zCxXX|!qub#t8Qv>t?my_P5ZdR?VAl0_9n`%?SA;}=DGhE#xUHbqc!kghHp_}0k5eD zi7(=cciboE2#1Gp*3ce3cIVD?iU&g9_`EA($tXt<7@2R}L+$CbDZ3}OvwG^Pyp1q# zu+{p(l#+n2^1$5e8c50$$-O%xq^f9e`zr--7G$t}zBG*(n+Cnjq-8sgc@|)oS#EZK zK>Kcky>Z)VeiCWwK#hGRy0=b!NOd-WNoJBNKO($i(jA1s1X4=4xCt+pi?(9FjGC_w z3+a52&;b&jFUprL!E4Ri|7;ULGH3P^PHrw>v>O4@@i#3A^F_-7077Xq{E@BIUU*-F z&2O)5$q;P@eNwdjiogFW?egNk{N`@L%WnazbNq$nGSJwo|5RQ3RbofOqyQAe1@VZ$ zSB5y;3(Ex=3^g2rap+utPCMj_{_k_S;6FdOv;Uw4vg$G(McF6C;8^eRX7y=MF)Vk5 z-7a&003?R=$6r_0TMu$7Nf(&FewB0{%&6z5Vo&kA?J2;V3yfR+6t~gHbrpmKLH9SdDCJ*LALCOI2M+={#)WK! zPUSTl8lZ1p6uq=(FkWB^%mBrQNFU5P9f(m}cz4{1t>i)%=*e$wh{z{g={y!0T z!}=r(?io!P$#zcQX1G`8nP=P6`z@^YUhD0!!hW~3SAf|aS{2qbeHBPXa)$txxlu7? zl<=y#JB1hQUtHT|3%mJ@3yN3O@!Q{zfh~fE0v7;!jw*hmSzS^t0_-&j9V+`##Bq;H z1?Z4yR$G=Cj8x_8O^M&!DV!ca!`8OQ&Jvs$YS1U*@;lR~Z!r4yqtr=r~X zSAr&7HxqD|BS^rUzJ}h&o{PWIq8GUEaCP?~sI66eYccfI_C^bT7rF^9A$>2kZKN zIPw2xlbok8NeuB|r)IOqw#oJfU`nuY2-&`^JOWqa8vHu0Kn%>f z8?`61d!-k;%MDky>n$PRgWGQcx%-Y#ik>__w@_qj6yMMuR5{YI|NP%>T7g$fs&BE*NaW=Yjo0Vdklgv~binn_=6jH)rgVMN(q2oMk+!Sju2;ud?XFu6OsWj(@wI z|H3uh#E3Rrpb1LwrECd1C>`#Ou2%wLzj>q&PUkBt|=Gy>7eTbEt2 zy5Yx2x>KE4)i2a4Y1-28rK8Kw%0VGQL70j%u*?YoXp(G_a#}+VPPyf}OQ3sC#n@32 z!WE}b|HYOHq*^#_e=MrHsslYJLJ>m=yWSn-Jv16xNUQ!#`$*alYR+$2o zDu=U};^bD>gT#Qx5`jg~r`k@eE=tzyUhdI!*e}Qg-#^{BG#gDkb%EO^_w0~>A1H8( ziIa_X>55Fv!8YLrEzkF&Ha1hty~yQbt_p(%rR~-kf$b9`ZFxDk(dUJd-Mc}MpoztQag&U&lu-rpAP8K2Cg;5Cg}}AG7uF`3OS1FPVGT}40Zzqv_ehi66h#v?4|98>R90?!9$@oo(Lhf=*zvd|_OC0=W_VOO6rj zyJpJwpil86D_bz&PuT;x{FIoc@^M;&o+juv9g4n+F9F-nM*$RCfB*me^6u9>x7MhP zTMulrQ&q|}Fk7Htyl&6L(ux`a}hTzI_CmFw`{D~;@iX-l3M?p)O(~e zj43L-tpKOg%bW4LN0+x?Xi4=(fxNE&oelBQ-o4HeLr&ZL4#^hwVKyGf(^0QZVnQ=hp&%R0GcTsOWW*kWpO1x(M>!f6!)@v-kAse z-Kh`$f_2au0009300RI4JTg=>*dmKnTT=SqwU1z2+!P%4^QZpb=SO17p1@N?=Sg5{?RJa73>og}xZMn{L29|K>Nv#r6(J3pOV5u`!Onl=RbiT5IYr7R$mW+3-@ z6FdEUyYQTRC4=}C%!PXKdKH7bt||br%8IMO859rqxEW=xu=-TBM#zqJ?F{0;fUX2w z2IGgaq#lpYyd7pfd`D$h6{&>XN6H@FFdD)t{nAjoW<1hj|AB#GmWHx!#1E1DLnH42Q~&EJ)` z%{6cgKD^W%Ic$?2kEJht6FC^vR8mf?5q>2bO zW~7o z*oiUe+RnMC8TtP0%{QrGFKHMzoR*1b4LD$lWB~tNAhi3kO)3LzVJV^MqZ|0gmG_c| z6wW7bIx8e)a=w^uV3V;ch--VuBKX<*qf4?HN7qFUX4II)tN;Fy9EAZ#@-E^&N=A?Bh3`MG0zc*%~{m2E}m>PP%snDrGC zDU*4x_(}fL9O(46tqnQ2cuSWjQ`ldcuSwIZ&VThFcIL{KBD~qs-2xk2mOZ{W@#mD( zb@yE7t4L1~JFFJyEG>iN>CDX|}KNs&mP|+|y7%`{V% z`K%}<+c&RDK28WUUHdux>HrLQj~1*fE^aS2$)`1IwA?Md9+vwylg_%CPiDpZ)N+>i z{;qL`8ge98@arhnh!Op~GLQt`Zpp0M(d-Q(Oe=Z3_~Zj`dUAwltZ^PPnPA*_zgaNQ z;6nC^5<^%RC?k_?kGBTX$nO2aDVhI+n7E4IWwYq<#5lK=u*a{tl8sk7cj()*pqla= z$Fy6T8Y_qd00093qUAz5;C5xgqn*yQygM0GzlPwST!F{6otMtkAnA}YVS{}nxL+O_E54Pt^e$o{&n?H1O5A$3j;=A8W{bA8_8@B&r;8c z!usr<_qTBs{Lg$M7@Yzu-YpC;jVmKh>G*jixENGg5B!exB_`iVH~&eZ;%ORPB`m+~ zE8mY+j(h^nb6CF+=rumWb2NxQTmQwz=|2F5yfU?#Sm7QGI3hk_^fb>=^ZiI8Lcu>P z2Mr%8UA-fensOyeMJI5GoVvoM`CFN`Z`(g{ut6)N4<0*FxgCa*rh9c*G$XJis(4`4 zjqO2-L+3S49)t-*+Dc|Js{PZ=uo17DmaU2ck%ftgkb(eJC~P z3+HAI@eZbh#@r_WW*MLiWP|0)ZoMS{{bs|CnJE}i`bf`R`tBdmaCDrqh6O{()<;eVnrwV?)adW`W;>zmB&dB7 zeAgQ9xRc{^63^sF=9hPeQ|Fkd+E0GoqKz)U{2I?Ms=NYV!YmRaM^L7dvAYHtNhR*% z|7^YA^k+s#B%!N#sWDX$H%hxe9s?d{k9#Ycl-jL~Ev1n-wrl@c0gPI`18$Jtf;x6X zLc;%e*LY07mMhlfXXevQ!8_vK-z7AXaB+(~=ZB+)*Waak2!r9CjXOa8i>;(!V`CYc zR%l_ebQsC4EDN!t!Yi@RyGl%0?NpXrer$1J*@m7`7e7iyKc6708s1_p-4tGkgkRu2 zbWWm6$feA3`$PE4v^{$VK}yfi>A|^Cv7yFs19pzkI`WNG4RN!U_V`$;XNdz1wj(x@ zA^j}wZSk{;yVD_hboZ~}F&LmF3QOE1B0K0IOxOMOKI?xC84ANy0M7vj#NJT9${`IT z?PD8@?a8ALw$<=(-$MKJm^0d58J{i|HP|NZ8;ganUfb4GqM zvS}w9C%op`AY$%9?llolx^mfA{zfLzs@bB%0>yG=CLPQfnEx=?vK0LMO(%T;8)Fl& zSbz2yl`$Be2!jDiUU}~-Wljfry)G){5l(cw!K7`2@(^<}LcP8zM4w(@o|P<3&BT^Y zyDF1Eh#71d8teHHJ5e7&aYT=Sn~%}}#2Qic;2_W4!05=CAi!;!>%Lq)T<{DJj*}?_yfw9z_&5-+WQhYFPx+5v_@ATOeK2{)?!;>coG=x`Zo?K3^I3o z5h)ySEZC|W%*X_zxqt=%wtoeOUrk+^-LJ93a}zIn`m78O}HcQSS!ia8TJclN-tjk#4Zq zD;%rRyU2j1=ulC;(0C*YK<6i1+la;9B?p3&7$|&ez2&WF2OiLJX)%$xv3ttvCIRcn zHJluRY{Ia0d3^d1G@To+JYZU zOy?G}TX4<;e!BLl#xEj2wfKcfCC_&%^!N22tcOHx^{s**QGFKSK7DU36$I8&vz9lJ8x`( zW2nxI-&z`sinWNWJ~k*?hf>uUST?;8pIXW zTR$vj-P{q5QpW}t`#yjE_(1u-168H0&*}fBx&G$v25~f+bN_nrGLJU16}OKrfNgeL zn4>&{{W%?uRDKeLHtl>3Nsp;5t>&$$0?}*s zrMqB{!?vS3%GPikUs}od$-E{iI|no5?^EmEPQ*}{d$ebc8KZ7Ix`GYJ$x;7Iz51RL z!1hXb2Wz^J;5L0o2%BmH2dghuznTSSa!zpP|F>zwY=zS+wLu!)Ipv8=BR-6xa1@kEvnTN6NC$xd% zwo6CHo6q$n)tjQStGYh2PEBFD|qoi!wYp-TByV^$viC*C1&Ca8EDJd^&k}SXm#(17L!=4)(%w zaeFk9R=w|@QL5`F)56vGE&A2nW!k7}ObBqO65118kN^C|P{is)0oi52X}Z!FSOe3R z3I%Atvr2t4+j9jT#0lh2$qGnW2DxOgX#fpF11zM>R+nsfjCbxC3VMf{NQ?)Tyww5B z0?K`wS7u$m{WK)FFm@B|v|nKxRf-6ag937tOiH1!^E~{sY9EllDB+5eq)n7=5}}W` zrWBkqA2|Mpy>L3^QI>uW&MgO(xuf?%Q?4uXv{UhO1rM@>2bLfomh9Rfa4Q*K$1p5^ z@MboVqB`9wV%t8>>Q#ULy@4_MH+ND!TW&Coh%~bQTnOoc{VDy%rzV0>d7^C^zjA2b zo>WSdeMFg7V$QS97T^vlOGU-&IOjil0o?iMv~=bW1)0UNw=v|qbZg&xrId!9eNoGF z$wva}8$62E0d{A>wt8?F@m?yi>{-T(Ot9IKya+ML0N^dOR&hdFf(J-hp6Fn)CjKEh z8VOV9ZxN<7&lmM4a-7^M;w=KXIbzio+l>!mT_fXNwb2*5*dC5x015b$9wIR))J~y) z)eDCKKl*?OZ{4X%ZWzNI@EN>~U$Roo4BDDC9GA-!!n$-Md&5OxH(+na2U|z{070}= zZ(RF04R{OI(XI@-A@5egPqoICjGp&o3ItI4KPi)^m6dG2Bz|P z>;$$fTuY>4Lv#loGurL2nNn4(}G$srK{6cBYMsBB*i zEy1M~397iVs}EBQ8Vt`{+@zepdlS#*1h?Nmd%lkHDWh0WO*erIm2NrWp)weRS-(tx zQ20Radv>iS5}!Y+-1c+tIZ@*)0d&Yn7+X)B4Pc2{ZB?5;jcGrnw7Mqp$dsNhb!3j4 zwjuxUX*Av7ww`7uzF&ppQ5r?r(WdF}A1HNw#=lEMj_hKZP3}x6PcM_X$t}Fc(mx)O zQ}h~BP2|4+hVouVMy=@m{q8xXw``b*V|skf=YD_lMs%11c8O}}UKIjTz3@hOm@fjp zqWa3v7mGQ7>Y`!9dQY~&aAsBGgy*(G@YaL0HuU8Rq=fpmLa|heLwoytyYqm`@oSxjPF8b&s>W@x-eluSTg38!u;)Oot@|k zW3cr&b(zoKi5N|%gLJt?j#abLH#>3^>Ps#wJr}0c>)inHgCv3S;9plaj|T(=6Wsup&EiQgMvVD7XM-c9uBalglB?EKDUHmf z(wzJ4w<&X#wu4?2OzSUVU+SADoq#5vZPE7eD_<+SK^>g-MxR3n^z`8ffSB)uEz3rP z!pC4QU7!1sh9-aPy#{;HQtU2>Z+ZevkXa~8xj19P!oL+G{cT1LVr=%Y;OErcO=dK; z_><{0JO9Okobs9z)g_7=31Aj+u5Kn;3q-qM^zD4gP5UT~J%4>|DdaNRuY)H8M|cl+ zox)wib1S60(ks)v5Wpu zx%PDPk=%pN%Occ>SSW+G(;ch$(F5@&!EX?$>`~+(|1g=RA}v91e-~1_nA!qW3$mb=)^EBDgQ> z2@Zl!G*Z3bV?1NIxmwzyIgUXa8;w*AdK8_Bp4CEcjG#ux zH6~w2l-v9y@h5}1EfNO<3R8+hP*UX)7ixFWR$9=uk(NmhHK>RPZB-qE3_gqQ+IgM5SDh8;FVTQ?`j2Pqu zCFAh*A;m&<`V$9zN|s?{O9R$}p7-e{#-Dg;nwsCoF5NNnvBA|Xpeq+*Iyk_C;`7w5 z#i|fJ>s)n!!VFjI38H50X_;le-zjJ_tJ@t@ICsha&#E9CVl1;=NKZPK3X{P?mPx?K zcg-j(xE+^lY$=wxr6cOX8XP`&?P)=whQG*}dvO2F9AvR?l?X+i*GJ&$uAG zp%Wpp-4p>Cfu0A84+52CMSXed7T1eKDVht8s`*tZ#+x;*xJxvM^|#QeLXv9(5t?8B z{SU=*Jn!ato)ysq2MCFkJt2fxI`WQeoI#~h?|G2ZNwHxrX{G4A_vl9V2-k2UDYDG| z0Pw;(iu+tFjYzRTNA8UI#s{|Agq)`QW` zbeg4bOthNr9;uK300RI4+j0IuWJPa0-q9p;<=d3j*wOo~{3-RsCV!Sjcxq?==DvO? zJb@d@Y^N`9besSHy>|+Q+nQ(iu97|34cusK-KFQ&MysO=E?n3_{bu^^K=xr`8UX&l>-V{&BI&eOk;qE?lo?;ZM)X; z{vS76r{7dcfO0hPB~+DXTarvxNK0C!I47G$nfwwH9-zO z_YXC}rckE>*K+R`cb$_G0{mFkB)|vXv5hU0KW(inkPjEgF8HS%f>JIk^@IFlvSM6B zHj6VB_sHkZeE(5w{Q!|w1aO_0r^u+BtWGXdm)5eBtrUZwktC|~&SO$tO{v-BH}J_& z>Xu=)cPu0kzM$4UawSZ(W)qm0%KZC@W(q<8b)9%PJ7bgp$~&bM75ppi^f5lr`>qmEt1%$Z%*sJ!}|wCa0Fvs;eBqk@JT-VU-GclO5Qn zGkK7hlg*N)a4ALT4yf|n_c1j#?2z+e9Q1lWQWufbubJ87D?R}PA%K`3zT=w`LE5p4 z*XisF{Ez(}v|s zYh4kBpZ@>p6?ExO|Mguqfg}9#YW9 zw$tYU`bL)jL2vN*u7-RfUk4D*OLfZR(~hw#$~Ui=Ev8Ggi)w>)P`ZW9y?s5;mnqRs zPka>M)wCW^QjDHB$efxIFQU#Q;PKc~+0^7W%s>A3Yap*oZW>S%bICdJ3_peLo3zNv zo4fWPXZ@k=oDU=G^rEcoX^hDo3ub;+TO9z5r8CtZI+K`{%vL1n4I2}wYTjx|;Fy)ez2q1Jc9t}xMFHkx zBGuKhJd(}g?R2=Qpd%e?H)%zE0s9AY9weh(uBxjp2m0X0518?kyG+bMvImN~KUsiLxJ7X)V;(u}|=#NrQfKBYA#AvRe25|Nm;re6;NwP)w2NtNMgB>#R_2B2`T{_%CnQjB>%j zHqNuke^<+`^nfm#AYq^C&WghEnZ!(Kawysz8q}}<|NsB0MWDK{hPpS?IK+^%m`UMx zY{9!qX+R?HNt%7-$lwCLkPgzzh-rVfA7Z6YHsH{Y?E&)f2u;bY?E7kN3v`RDngd88 zbvpNXm5qaLh`Nt2Q8cJSV*wwzI$ez9w!-+m7q|FGc7$?8p~NJ{$^ZZSl*CX=jU+9< zX4NMkZmH;|1Qu42eM5w4|Ip}|=XU9XyWQ(&UTIaME%H5nG0P+bg=g(^un4Amg}z_^ zmo)BXc6anst!_d*WWwa8c)t6aXE#k$OyHZ3>7sxxX?mZvYyUCDC8F>`H;aFCMo^nz z>bSihBW>ocA%n8^zOK@3MHMV0_x3Is=!;hE3PDo-{+UBDJ&P=cV*c$Od#K~#aALe9{d%=1CQvk+3aqvZ3zI z=+AY-%r)UMr%J3IK{IyWhR%h#QIZ+g(j&2c75hKD2PA{-bT4#Gk^FnT!xhAQ6?C%J ze6(8?uZ2!ti1-2%G+h19_P82bOB>7y(zna{T$|NsB< zYdz2RlklUsOe99sIhWm1HA>zRGDdBV;G^DXl%b)JYuWa9W7p+DK1;J*$3+tDsh_D_b zm~SpretpJQ)q}%{+ zbzlg7xN>!u!(qQqL=>T|w&`KOO5T$Sv{OUr+dm~=} z00RIwm!t}qL2Xq11>_yH1s>~q@K-^V)tmWte4_~>^x|y+jUl%S$0@up83DR0FBBP# zbj0XVLT41-61@mbxAb#kOXu%>zbXp-3lgX*Y*!05&> zQgE-iz=S`iAbMyq8n>@Z-Md{(&|(&wiKB5gVEF1*w6t#xNQ}y#*gCg z?lIFVb_lX^x8G!8hOHW)6^Z4>oCLx;qZg=8*?7)BX+np-Sc-*i+mJgM=)DFbSvm(Q z*)IZSp&0mrb6WXXcmt@~sJKk+Tn|s)&K$gyB#)$woeYghNxyAVZ&^#pURF9eEqS z$Q5apibh;ms_Gok%z2+{{6NI8Q3{jns z331b&q7FIo$^=?+6OwtPYRWHw4k~rNAj^E4v+7qqXqOtK8w`vEk6eaLhQ|esrMCw)ItzF`WY``(lBO zc?oLRA-fb!>OPmKV)$V1FyMQi$xWNT z@2}t10kcXZD(1loE;_z*AWt^cZ13N*fo-8FlNH*;M+rFoTmQ>0(t8*?SwVmUbb*Yc zlAkU9^eQ)tlb;sm72v@$_+;$Yng##=s?U&TSGUS&P(8NPm{o!1HVH{AUMp{f5OefV zJrt%Z#3f{p9^X@5?bfunUgX@m$a>U zC-nLgsr9dqfh<-li48}?FHAQqH*`VC6bSt}wuQyq*uBa*teDlN{WVF~H~+S#Sgswg z6zoDD`du!7tiFrKL%s|rKRPgy&3&275S+)mu0J%aQC-f2BeSCYZKaGB^C2;s6-S59w^5co zY3M!{;VJnK>wLHQl%N2tG;3shL$xS}l)D4+;e~Z*TPW&B>6m;CB$|>FAT9s-CW4*| zgb5}t_MEJm0e6!h_0X5aB zUdD=sG_B#D5v(ztIlLB@8la@JW-`cl1gW@I$KjdPgZvgNnTq*BSmGOe1R+oSsi% z922SZNjJCji3P0fM;K4dRAy*d4{-o;6$YKORcZlbZgckfrP<%-UYPiI`2PgGf%Qlf z5*!f)(=r9@w!6-YFEt|uN#sSp*-ZJRB-_||JpZ*aZ4G6Rjt(7C@W`+S?i_%)rB~mh zNIc%-nT7|!)cA7 zxAGM<8WWEG!qOuPUIgeWbQ4Nw0hl5hLmg~~Kxd|bsp7qtzbQNY)ClSZuZrE~<^_X} zyaI{k#iw^vvHpOr(A|~`(P@JjVqbl^+K5pqs_7fkO{wx^LMWTj9fxah)bP+g z6oo0-Rtq?X-A_VL>`zDWDuhe;SKn0Z+@9#~iudc)*t;ip>$TTUT@D&8#5jL~yn3w7 zRSxL1D+4@&CFZ-N7g6Hf%mvSP?H^PI=yGvhOSxMt$dUN(Zba3(VTJtz;W)WSIHQW4 za&)d6vLTAmHefNG2vL)RG|#L`>65vpA89^Ulu^>R1Lk#!2T$GYxO(&0yN51xg%)wF zK9W&I#O_;DPR}YSr5>OIb;Q!*Cbc6eKCaJpMJ=r%p;8swPd#R)=b;oMiA<772RPLe z{hO9~Z)ts)AWOLn*uZ|xl6S2pijR7uQBD&q)#N)T%w2JhbvI7S9MiUa885l%X>ju% z*yVy=Nrfc=ItXtO3>?1MuzW}ABtlDTAyiQs$(m1mq&0e_Xz=Cc$as?RyL0MHjhBaP ziMv-ujsU?Kg)j$j?A;?2u2`sW5A+o+E*JzOmMAOA9vSNyR7HZq9@swdQO$gBc8}uV z0Jsoyk8UE1X>fAdZUX0H&qD_IfS%aIL$7{vmYg)i;A+}gmaPtnkmDaXfH^$f0@m#_V0 zLXnR(E2nf}wxLXsRJ+UDb33Oi3qnWTxnPwTcm4uFQcHY@6bV~ZFPB&0z z0Ak(wByjMSA&xG7wY;kg37RpAnTm{gx*INJ@cMjfgEh|ko)JvAc=Np{dmr)Qb~EiN zFKcxgNs0XAZj*mBy3r%ro3Cw{CubBG{YES)W=Swqsa5Aq_E&HIqX%zEW6=}(tax7s zo3+>Tb|<;Xe}@_AxcVuRrY z!8ZQF$TD>*<+T$Y@W+-Vya(s4Gznvv4SzPVkDlDl|8`h>AAe2hIjYGQdxOfg8#~43 zz(%T0=9L?)_QD+nIFMRHU|NJv71lKJ%609;{EUVW7 z?A{9KBP2dOjl)oQ;@?@x$b7AJos^QHaA#pJ6+F>1*0@2?_gA6t;X?L_^?cIK78ENYu7t z3Vn|!@f%fE(eO*w!gfEE~Iv^NbebyfhX0$k~N_X z>)80#rUgj9|Ba7Q*?;Y;Rz^SyG4}GV4+)fnZKn@4XUg6Tl+LQ5coV#08_yGzQEB{X znB~mAPb~^NF_Pk21|amK^y_D5$DX(rbBw3tOSmGc%(D}5+_pXff)(p}pUR?t0n%em zm>DzF6%{?xsk8c3{S4C-7XY=Rc-X&LiOzezJfG9=v-lxRnOj>zTu770?2qd`tHL~# zkPwJ#;@K7!r1(*Yf@Oc1?};gw`>scJ;@f}#0!7}{H&h=o!hU3AMBKDLL+N8S%|Y#t zF|bHOIcLSR&5MLb|74kU2qW@w3VzJN*}ulpyteeooYsG}tg*OLQ1 zgt^Ik5W=cN9$h-z0gLw{sO>l!8xxZJW?8@LA~AJ_GQAp7t9m4GdDC@XS*m%9%sq@b zi5Ugm_XnJg~9PNkegTj(k~c*8PAxU|KV;vWXXdGlklhzBEo3LRq&;VIJ)#r^L=@7_pgR zTAL_%g*H!0@QDu##vy6A0G}O);5sCww+dz8RCU8eOfpx5zsIP>=zxvTN&4U6-BXqo z5(1!hEu!?dEg6h+g5uwTCs+ama2-~bY4)QB3L^eeEMT2kHf`1Y0z@7%e)nE(8bRtp zr_~1SS4Z?Zc%vef2Y4ypq-@O7XB~U}xp+DDD$j=bun`BGyntt>juqssw6=uX0@@We zvXXWOY8y>cD~PnWJdjvMd!F`4oCvj|QRXV`NFC}aQ9!0gymJ#Am3xZdduO`+5Q?Xn zy(z0*ottXDzLPSGn5pTynvoBbI z{x7LllnqzhdLu{D7v#F@#5UJIg%yGDTgOR5hN6ym3k`Fyv2NaMBryh|t#eD5alM zYs1U;i7d^tgdQVz%qtplAp&k;+DB4Ye2}tnId_y@Y406ScuI+Z7m7rx(>*5?#rPe; zRw&8VL^*YWbE%g5DBqOa-n*rS%*Ig2ROSsif76y1C?d{diXxUxOBFJg9vJ+}!TZSS z(zSDU=n&jc%eE5IkoM+7wnJ$(9RN8fa;ILjeHCA>9qhZJId@t>gZ0cc68(hnixG@3 zbq-X2`UPaVp!0qJ24wz09ib78*VAM~EALjqmTU;=(lJA2(LbXKcn;Opuu z!DCh7ET(e}ldyCY=d!Sjl4km_BHF_;mr2Zw^CmSnUl|Ei*>qYpl)}>$6Zx4MbG1a+ zf7?K}3|bHBBP-N<0Ih#;wV;^70S+-WN%0qIzH(qwJkSp~r<6ABYtyJ~!!jWC>#7M2y;PBLZOARJ6R19!qUN3|iBF9K zwGwaWef^am_-Ah!{2DR8yGZ4G9)Llu9@6127gGcA9+jLh9NVm$gt={<50F=*@S1pR zGgVdzs>fO`0hRKpBEPB%T)l0^QomtYV{$lUG^vjaVW#rkI4w(-AE$&Zv#W5WNsPhp zDp{S^UOh*vbCN9e4tYQIFSrI(LO9tK7cT?SXyu z=pRv(Tjp5R;C?bp`{+|$1Q7W1gYFy3oug+zcP?a`Vt}b~Bj1bn;%QmZ^fwYkpEDsk zW=ro?-oOwWLOwJBw0Ogpwa?jGKE_h|l$r0rLe_L1IirXaLn z!&Qr_@-4bfMB~^_Tnb=erKOV^fqC9#3b7=7>M4Cb%G_9s0hU!Iqzdiy5vCyQb#4>! zzWf&eb3XEtYKN@+e=ny?T-!i7?1<}!LIKEXl z?Feszd2d##*x`*Ju{4DVAt`>1bbGO-ufn$4-N2AF_YXewPN0N`f0u0&nc{v~Ke%zQLEC3n@28oQv z$PMc4Vn$QYZMpyszld1+LNZT0Ww-QlLJubr;r_nENOf*?l>~nj+BZ_H_VPh0h-X9Z z>>nAi(`)HJ{f>$R-n=nQ`)zYsLm229x2I;rPbf)b?4+W2O9HL$W;(sNlmqph>t|g3 z-8qrl(Erf^Tz@j#wp=yW;Kb}M(q~u8A!j}ioI6{YA47K&zT&+~-qeb^p zzUr9f9OiRdw#^Ia7`c*of#;jReXXM<2*M;c)1fdoo`_`*K6G*WNKt6ijHC-fB5t<0 z+E1^K+Nn-%)e%^Rm3Wty6`|5Td5B8*YNpswBOwNq){NH;XO<+tz^@2%`77oaCik6@v-ZJ%krKnAP<=6}qil#|Q)gs^OQdbiKu3f+h!8Izov z0^x;B7yU@1$wk4O%c9VX@mwqAT4b8H0U1Zj1mUNL3`nwkE61{+IV{-w2`eSpBmHP78?q3K_dwMj3?|L zmGIc-Xp*KT_2a`2{ovSb6)PP3cRZ55#m{!eV9zY&%&!d!sQhcF%8J`%oI7KAY44X+ zNyC{XDYJkAZvoRRAkv8_#mCCTow~-)$@eHv&DopmRm(@xR1dR4*8CsIzJ-d|zsGZ?}PKE8lQk z{xAp!&;!Xfs{SNMBsS@$tO6eggDTMqgq+l-mJkdm^F$wUW1{zIra$~h$$$wYfQf;8 zM>>PKz^$AA14{edv>m@q|KfX#`pQSvd!e%J@eEBOJCqBw%(C~1(^9KSTJr*-LLm=! z2(bP`WB&4rwIBcPIb#Mqo+>p~{t)BjM<+~}@QRe*xtp-fQ%H3V`~6v4rzd-rah!2b zCgEF=r{Uq1ZG}@D`N~cPdpv8u(%E6_{L+7!ENRGJCoYc4Wg4oG-%ZcT33Pk!0r#Yf zc=)=(B3)&~Y5-ES% z)TBPAAy}DsZ6Z%Uc>a{|-je?RM3~3|l%?KUV4Mp#XdxuO25}cL&{nglPQqTe(l<&o z;K$#?|8J&d=^=uA@@Ec2lyrXh@sv^=9mG&No6rmn(4W&qo@6$gq26k`-aa)Ww2Kmt zMoCAIRkeBXIhu`Nzw4!Z16k^@l0gKmy+(Tq`6(7SN^kT--upchmagXrP(Q~eSw)L+ zSYOa_Gb32K?s*_GG z>PYMLK#duBD$TuA?;vScE&b!pOQ`5DCYsQ{Gu95LCHjR;CdPZ$|FQ3SBz{IBP58WD zQ<7RH2=vmW_!G+b{L%+@&<4tS<&+=jD~7T57tbW}9+g7`bGcQR8D}cVa?BTTwZJrg=-69f1W}5lmTM^FuFd>GeFG0ooIWaja6bf<}Nk)RYv zw+)Il@d@aZQy^P7__#)QdkkB;SzmC{#vfXPer}4GLb{owzh{)}d$uH)61Qn8$b_Ac z<;P>{loyjOdq{LOI`@5X(S(cWkyQuOdN!qEi^v}IYggu@8r-{ig5c-C-=B8)LLnF99^ExNkr<-C+)`C&@d_9d_kEWi~G!X z@Gbpl&_XyF00`781s&D-SKa)8tjye9uMvbeC!Ps@=_q)uaxLo7Jit5(2K5J-?xSVO#BoV;1!0?_gc@3GAtCQQhcGT2`RhO91`!}!PQE7;C3WBdB#^wem_bN zkz2i2_a>}RZhUnS~fi)&| zMbCE?5IMX9iiW;HGqV*u%f<@(h-8{;{*4oK%>|z7-4(9Dc=MDB$o*#BoDMiplsJ2**FZ~?viNa)^&$v21VxrC!5#lKjD5g!e<7Iv#{1?x6}pNTjnNSZeVJab^rQ_ zSrfy$K82zg?KV-DQc+gq_Sr#^5yWBsy@+~-rqL*4DLrgTI6pLXryi3I8S?u>3|U!` zZ;HcS$c`$-U(Z|0XE?T!oiv3TR(l#3r<7sgQO}}sD*4B_Ds2{JpOJOAs&i4qD}a3_#>Iy;q4@FY&PVKq1|x(=*U&j%x)IyWJLP*-E%ido|#k%L9xRs0L6K2k>f8A zB=&Ry1#^y9%v@GFdO^1?*YPETXDz0HrJbkpV3(g*rwM!X1L_$n-~72to^gz{`cUCL zI3QTv4$=X|O8f61@GuR82KsMyY>7*{@PGu98a%PHlo62xZXG9r8ErUid0z0n#+dh1 z7QgB4w8AiR+SRvQ!vwXPA(E>$0dP{X5mE&NJq&b5S3l1`>x(2>vu(*5A1-ZExZZ#t z3hC@G6`;ni6>>&%W~qA!fuDjij!TiBVC}-u)cz2*VkIX?(zz@W{18AhCFzgdfody2 z1||A{e%Qg^{4rd?f0`p}iVeK$yx>ky9|5t0v%__klF9Tc&jcnUy2?OFufHt799s9y zF3u>k?f|gvj&-hu*MP-Uyf2yO({{niRLP!86_9CofU3o$g7o9^EJE;>3&-s4Ii)C= z|0|oe`O?DJxvd+E+c2IIw{n9zu9+Kzdj69LIK3;x`5gE5m-yTP#CXL^6Z}U$EpzWs z7Y!I|9cdIrn}RbjFaLXE>%VwC+s(BQt6!C1xtI_Tcx~k@>V9(Fyz7xX7b6Y||gHF+|!bJCiw;)NjH!%!A6O%lxw5rmxWMLN1=7_U$Tx)pr{ z`}AFWSystM@qC#aF|=Eh4z+15LFFvg-`e2K`JB#!3l#M4ls>vU$m*mrnb!!ov0P%B z*SG*)+O;X6r3m$ljHvjui_eeRXhDmV{a(DOpr2z$gW(l>wP~NT@fy{5LV}UAWltU zd$F@y^$Te;Epb}c)75f$rb09BTKOUNv2N4X$5WU3hBWcVK zPIkdr8Xt%qzXhI?lalE02&Yp?qQMZ&1#K)sK?&y;<5e#r$~P==+J`aKye9<(oucL!*^bIqrOz!93F;lf=3S}O zQe$KudoQ4PMN>Z564|J6!4&q22=nT6^JHCmD-SUR7cQ?8k=DV|oF~C48w;W2u|zNB zU^_I2$zxVS41@xq@&X(ETAt;yw^{gbc6)H5O`G3rN?o`IQH{XSkhGr2Esu4JM*>qelI;rm#>fFE^nd~P3pBLI zE>flJGO&uC;T|au&BStZVr70M(4sN051tn!m>BzibF$Tls`Lbq5d8K3LBWJy`U1)E z`1)UBU(BBpKpNBjs;#__VOpS`jnXSRR{&Z|R7BT<#>{A7=R8{N-!6aH9Kx}n$QA(r zj`q;}S?7(L;HJla38f2=@1VIQ#?$*z#uFBmj zI^4%Vlkmk?BeXR0-ul3?NRLIIo+*g#XsrETH#^Ks)F2=l!O*c)49dabK<;G8T@x)L(-}87owYcn1u{LMcUnLupCUl5kvj&a}W`l^5Q8sQ*fTSYhpwoX2N{G==Cs z>Cy71RJJ&ut8TAs%L_xXiZ=ex=@|*KPH_>79T1todL>)D?GOo1t6_T-nxZ~zGj_~X ztHNQ;zD*@go{!X3OA42BH^qg+wIty@a>l}W&{c%Sq@y!bHcq5@;zp*gHDpUN8cGck zXbx_VQg?Zx-wwXFg^C+QxSuu9YrsO{`_Iac1MO7LU`2NsDoy#DQ9#sYq@hnV~(_J#&Zro`DL{X zXBBmdldevDD~h7u5-z^W{zL%c#)5JW;Ew={g!M3N)EfbM!}4}}T8T@?l^oW}jz|aP zP^iC;))SD7*+4q#E$(qi@$wQH;Z3mFyc&-Q^xXZ|0B_~4_X+F=_2unx+IKQbvrA=$ zU{;PwzU>tPHA)w9Oj}z%NS6|~()yzzoB1w4Vrn$V62hE5RcTP00J&{rOA-H3*i~3F zvlN&D%A)~^3s`>r0ziQ;XHUHV_WoY7T(uKRX#<7(jVF%$hrQ7k=D)_OLw_in3~2g> zfVBY#<;VGd(5y`!+kHrALY(dg^S%I5s86N6*|)Hh+Al8H=-h|i2j5K>M>Sk}=pG643$*%cU=d1Kg-_)6< zd>M0tPt%@{ZHUU9ccgYjSRiNYP7nb}D?kXRWu|w+ad&aj8m08Ls1ZJtXO;e^t@1$? z;(nl^HdBs*%uOs}>)tcOkH`Q7i+II`_tpg`VqiIZ2nW2)8PM6kHG%5Y_Z!A(ODnrJ zxGql#H}BG3Y~hKkc?D!1IGd>hBzfUeN!Wz=H(UASw5pkR{h1(GS!CQvExR zpR_xmd?&ha+RSKx_=J=xjqNDiq7l=L7%T~ z?L$r+=4;}2(Q8%!C2RFtn4{|d?sl~}-O8Alt70&T^J||YZjl%);85&CUOG7R zeZ3yP7F5z-86A%AideMBMs7imp8c2q?L-C^me>9k4i7Frd(<<0@eG#4-@P{$<_dV@ z?`JWBh?LO7L9kwr`bX{yW_YCuqmqvP;tl?-25rhKtU86Z$hp}Ra80hDQG>`@&}1w# z&@TUR=NmV>HYEr++wL>pk5f2oCXzP2&it?tpdv0?@!@C5#23^SjQGcw=Pt*5Arlht z;CECZscL-={Aq^PX|;E32$VA8!E@VE3I%k8Fj1b=9fO)BWrkSn$*}T`EqBIML~Q@+ zV^wN(T4M+ORluL(_|nqoi3ut)gl<3vInc@gz9Sl+oJ0O@yLcgPID4!S?>%3L7)}E_ z+0LO86RDLP-MQRfS0-HkHMxTe^hIBViFt`$;->c?KjMQ(heJTcrusJGvOVe7jX~cm zVvX%SHd*VE1PTPSzwA~w3jlUxEysX=<{Y&rqrSsIaEkL5%Vihurm?AnI#LlOnb_qA z=VXdxr{S+GB~n(9W3Ui+cawY2<>xY`d(R&lhj8X>`g(T&`)P~R$aUp)qAUmh;>=_3 zU;p+F!u6n6i^0Dx_^KgH|CzJ=j>tgL34aW~P4$NhO`dkkGGzDipijgg8!3A74R%QN zz4IK|PM)oPLSj$f{MLjwCHxnv3G3fpK5S@;H$VRq%|eWb0MdlYLaN+0V0S*JAFo*y z|ND}o7F`YMk6%9?JY#`Y`CP@!nrh%zCFxM$K-qFFqp^ERGOWOF`HKihmq3inH8Jo| zBYIViZafmFb>s0eB0z@vWX#UIch`~7M=W|WMEnf%5Z>9KvVKj<^Swy65CXK%k8)Kj zcb%!xxjm^BBxDha)43>baV|eJRYtSP$)`zb;X^ie50d6wue^C4@e3v>%^HfG44pt- zqXgC3w+=y0jD2K7DnnzK&MJL!vI75J#Aj)DN23hUFSQ-9~IvO3}T{tEmODG&a+^>nm@wvyHLx1A3 zH3?+;^4D*zPxV{l3{tA|KvvaHpf_N$MM0e%@#y~%hHT&2?h%Tg^rz|^b=$pq@*rYw zzE)~SU)CrKFCnI9379on(!(?3yILrq32G8BV z7R?e|Snv0wxzsZUa8XEnQv=e0?`Iy8iC_Q#0|E3e;a69}+FbP(^b!av51!H>dq*5I zwZ*V10lsr({O1=jH+neiB9yXud`R3MjuGSQt?o`8)g=LCYT{bd8Zhn^{a@5U8YG3E zu{~w%_A9x`l9`_bV+!?KpvWCwSOf9M^Aq7_5Py$JR7pCw%!=I3_EUw0z_k@$5p!?!jm~x|VDhhB2^V|bV5GyMLs#!&Y7Ifi+TCT!%`UMfM4RH*761f{ z6@O3oV)=gZ>Y}Ff#!Fm-dXBGY;kOZ6+FF(9U_7rEF(t0*1?Bf4AX+W@hyF*XoL4I` zJn-Q4D3B9#puB&pR3<^6hW3mzFtIXH`2{SOEzMI4b^qxdb>tZ8=1RY>x71>Mq_$VlLWoH(;)kBQ@fMW!&uk-j@#>-ucY`f@y@|A-B`^=U1#nk$HC_+lE%>-YQeKVTwtpr zY(1dB(mj6hU(`{bodi)5*e<&% zHYuOWwA~^t)V*_lG7LQsMs#Fj!|(kW1(x%!VDjHXp~knK4QtY_?Wm%$iQ#kAI>`v3Lopd4y?J_8fY;a?_PfkdM{^)4dX&;yGj&-+vR2gG2iD zihKlzL&dc*0y6gdY zjNWq@{pig%hDHV)kELKDljCAlREY8z1d(ao zbau!$JNTaSqF|K05ZiA&TRO0xe0Z+$?CDPJoXAHRiG;bA8NGe1C&j3s3OzkOj7niN zA-f>Z<#ktc9_HCofoKn0d4CA?K(mpuKj>@t@HmBc+Peo(t^R-XlZ&b+%{jV`UacoB z-V$#t@OAUzXwQ3{z2J>7W~o8r!~1KK9fcsk7W$#YLbp6L6k>OY^ca#Ekz10s#8UY8 zimFAy=DZf`iMsO?AC{u0GljamCQ}vBvwwz*zZmeTnNv#l4gXTO-DO}2S>%1%R>y|K zBHm4MMKAbNRzdy7jz`AU$dS~p(RY1Tn>p=|=!|LNVGOWuaqbn$-V`J&F)(wJ`DQ-= z6i%6B-oPTs<__7S`lm}xx1(SA?Jqyq2_s~?qd~+Gx(V^(Gg(5}3#Rh}V02wDxiHq| z9}t)2wyvm^aUSU2R*(uESMB8<%X&)6D|^4VD(AozqrnH=Q*w7mBKgMMPMt*~K){tu z@K(68G(rBGhgxQ$G48-)=9Y&M!UFZq#7QNjy$DQ;pemu%dm}pwWkRDe$bB5JHE1N5t@j zO)d!26Y9o=d-_qHjO>He6kAHg6JzqEA*QOsIBNhs%lcZ5!X;)z(Aqz}1gXi^olBmn z1~=qC;ll=Jy3{S5{k;081^eOrzPM4He;4uULWi+nTNU~(m+^2~%OnYYutnt zP*}0=&0s=ZVJV!v0}0e z3k?E!Yp4P5%m4nxim={+@Icdl_E?k{wQD#}>nakwP$PlgqOc3IN|wS44=6_hqhckq z8cbRbkgRV5|BGEzH=;7x04&1IFJ+BCu5~K_?PRI>f=fp(tWX1H!DoN5AZ(>2?eVBf>R(c!)o4SiePGe^EZY0~-!Tsz< zdI&C*k)eZ5g&~sWoSbHl-1|_)X|CgQ#4eBg4D97pf?(Jl!r+4AG4?PU&)r|9Ke^Cz zSALwlVF{4u!Vn33t;SFj8JfoLg5`9oO4I&x5I~iQ8xo7|#A|!WoeSqVRr6-ldn5-6 z2E_k?Wc+MKq?;gXE#utjC5tmSZ1GNZ;=5h`OFYj{5CkS3T|clra0{?JCsu_Rj{a4xY2Q2wbesvdR@pm;cy>-4AL&o-p6 z+r;j!xZ^kA4%tTSvF2yJnwz%zkcZFFhtutU%j5~whCBsbC7y2I2j=)nJe7YO!d{2@$i>|fe)i0TO0GH<782;v15%Hab92c{t<%r%n)QyiJD`!d>H%e z61j$@566GzsPoFtyRc^pNmIpf*}gBn9O9Gq_!yq3Ey3(l#Gl!rv|>PqmUu0=sP^Ig zb}=0(E^0-~wtWWOWZ}$Psnfq_dwX&Oq95p1Jm)ii<|^;P!~E;l=?<@#WhGI&M&hz_ zJ)lX6Tlhrav-5)&=S@stLF`~NaVrL~=ImYMdHKu(ezA|WN#Yrn$w9ksbn+u#Twi25 zb}!J!j+uPdYw8tX8TuB1eJH$W$XUhxd`swrEqf0k$NJ{@Y}W7*n56v<=8k~EG+xcm z?laigEZ0{47E69p=&39-EJy044%M}3V!y|oZe1J=@|$VYiY#5XV=xttvBe}*Ua)?CSz;@yrkN(8~s5Th^ zOw@H_A<~R|Z2(n&J{TBbkk0BJ)dWt^n}I6cXcnU)N7*9nIcol zvE|dtYUeEthQ0o@h=r`2b{7od_;PpLGj^JhDSb&|{ldqn-K_ zR3HdWm;9Cdk+eNXHbUPJhT(4RF!R``2;NXrt}-dmNwAGVPl^+>zDbd zE5+xE3kp5zv>5GhctlM2Mj&8>5optLu}cG3N>sZa(LOyJ01oEULoQJm2_-$W8mXy1 zkS&QUS#PdSsZ~{56xJA995fO`RAWpLr7dpE^Q)}a|B!P-faRH#d^>{ZA*yNTVwpO3 zO{+WN)sk`Ht(yOpzisPQJAgxioqT(&+xqz!18*u5LbxVUb)m+C?pKy^C|-P;ag;QWKS&YjTGJ3W%sYuJ7@a6 z5V^CD;NDTkHWE>F(umW1cW+@s>#w=c9aE3%*z?toG2@%Co`@^l@vJ0-#!$B?9-y1F z)E2Zxe{N2DSgxE=@}v^z(v|;x~TPq!GbXcw{mYVuLht((e}|`x zm7;uVI!kKY1p3;?J0Ag6E*>FO9a@O*koJ!J3{*Nxt2HMb3M2PR^1G@ErUDVFGM#PD z?f2NTELlx{wrsLIGW=Cu=>CISdG<;IW>BuST?&!fw{m)508R?{VH$5QaV{0fey}V=}kgn{ic%?mU_rlT;m!_RDIi=hb zfB*+jjSc>IPkR`J7$Hljopc%;u%1|?w59(^=c&ohZfbTmzdlr0{Yc&DITjZV;U|u>eHN1jcKbCgYc;qD-I~^D>toO@$}1obxL;>O;s+<&ny~VTTMxC|8fzG zlTG zeg)Lon6Tuub~R`4psWJ(+qT9nIplbM7btmS3B;+DDb)6L2*2$iTxZSgwbA6!NFW|`w1f&81#4`P*Gd+t%5r2+;Ypkk{(qa8*^ z-sI5<(gZ)bM>TkOd7MhMk?fb*Go?T^`%fJCJoG^W;}7fJfAt)#QbKv~_1>H)&z_z* z+?vbMasc4f40d1kT_8Nl8^cuG`iwYDGio-FF~uEYQ%b=pc9G@~$3A~N*!M`?O9ycZ zQZI>@qPX^AG9yxBD~V^D!FgZTdz?XFk@TD423jFy`lZM2meVC>y5uZ4)}Q=txdkf~ zyK|LfI?MLgJIg#fHS@!*RyRBcxlC5m<2EHmnPNAAE%}W5iZM3R-xM#;9kt`t?fHm_ zM@csdZUY0vgi9*7HafR%7;Xx#I$`rG(Jd(lg#&&P!#WTm6GqyI;n+!BCHr3~`GVfr z0>n8D2T~18Ph`Q7dI1)~s&aPizjJ)C@UIsRYkq4o?Tre}M5z*pWvSGLU6ZNpLhJJ!0GHdZ99A$y3O> zBIE>0N^imfsB%FtXG2sDo#dy5N_Ts?tONOl=$n8v+@@kAt^`kJdM5g9^C$>crE1-S zt4#b7??RIlkLIjbKA<=MpA^i@doB!=r=K8f-<5;J@llnTg#)E#;d{6Y1NHqV+ zz9hDcGD7lA{1u!~9?qUhU@$WkC)O*yVr}%7l4*!U{d~Dz zDD2Refkk(I1q&q5w7et};N3K=!Zy1L{V-67>qa zY6bg$vitDh6W%+NUR>UdxDX%7{eUnT^Vp2HQApZN2>m%Eo^CKcf4H82i#mmx-q{QV zqq5$l4X8w&t~P;DNt~P@CYoYQ{#vaff-`ZflV+G)BQ@c>aE|y?=+{AG#G=OI&V4kk zWGd`|k;KiPd|OOw*yyJ9mN2H+k^D(sKh$utSc`d(i|-<(fI~Lb3)4OhClGa3Vz47US+>1x^l&&(zXID-+isxPNI^x4Rqs#?Y+eka1cGV6c?kmzW)grU92h{V#AGTz zT3X4eoJJA~^Q3J&iLjX+5C)L+vxZ5C;p9u1Yzl!_q(}iBaZ$xUD4n?s#T(yo8P3kk)P% z){3E^->o8MwgUByog(ookd_*1eCc$s`08%CBIvk=n<8B?^1YOaEPkLpz=B}`?1f?g zWj@16+M?336K6ka%`oOnKk6{$J)0=I46a<^y)Eo*h?H^#c{~kLS25lun}tV7USH0K zjcvsalJ{ZQV`11`FQ`2Ag&l_l+b=E_BPo4J*WH+rnXxF82EfUP%62z3 zHP8)5vn2(<PS10BTF3-lHxgZYWxFq#$pjN?q zn&sibG^M{|RZ~T?%m!&?S=?C85nUnN8}zxz;@KeNsGG)JO8mGf5Mge{wt@dX4*1Na z90=42?P#k-1VWFLx3{M|Vetal_;!EU7H&o`WH=SGKz<@cr|vf8<`m8ReuO~uRd+!C zE;k8-fZ)IgL3Yc$*|I_cp}RJ`7fS$YBoF9)niw^+_5~*^;JwaBDyR=6V|y!uUaK{p zCToE_{Z2h{BM8EjjxL9WqtJ+}3=dn%{_`>LW6qbi#l1YKig_og1wMBmOu@YEKU@0; zi;|LP#@R@jH8>|f}=HbBq)gt9|= z(B1bJJ$AmIxE(cvpoE!1sEXOEas{c*?HUukf?q%Hh*uMU^S4|HjKkD2wVc<`H%A6! zD7y=t=~C%*Q{r~WQll}Jl)XlEN~C`X*m}Q{O8=IGk>+~J2gh#A0 zXoyrRXUuXM#ca{(d#Z<@7ryoizwr^RMekG32QB2x=4lGgycurh7QER)3&m=;;u#qd zt){Mn%%syI1Sz?)=>1q>s?H&lM|m2Nb?4XKTpOr}I|Rmqo^MpgE=c(Jzq^Me^8RL; z0Xt(lAv+vYz>3J!#39saaZXX{7Pt{g&{C0iyHw9g1N;VQgmjssqd>*qHZ!azgM@0A zNqyn~l8;;Wo^dG`(zXY|?U^B3_m(S%^=f@C^bZXW_pF4e*7XtY!iQjs)h~ zHofZNRG~5c#b;8S)UZHDHs~M8EwvvzH_)g?H^4-4iXu>7UIZ%V?9b|0G7hvC#>T{m zc;q3z%Q3U77ROM>5oJSAjSJW zN(&E0rqLgQ-$gd9!VrOJdEWG8&B|-k$(!vXKS8{IlJWAwh@2i4+6h-&tpw$-Uo`@? za5y)zOPHuG=fq!c;AJL7%R^3hnV6SU_MH^aP6X&%TquHT;*M!R3(wUZW2kO_)0eUH z+S? zO?-0=dnlmRV9>PE%x^&ub^4HPUPq z8EU3ep!x7d^*;e(5$*bHusXIg43Fm8ZMia|5b=FIXN3emv8DdT8GG=E$QBph4orQ7 zd-)!nQDF78uHi`g-7bX!++v8j7AT1$wB|{&->6i?F+~>Ki30la1Grc z_{>IEocV+*jTpF1AYeXOm$2;r8$bMKmnsvehOsWoAV2*GnS7#cs869A{qEj%KHJJq&d(jzk9!R$viq~bP>#qp7nBoZKAER}YiMs}r}u~U z*Z8V))pd^2)Wo?b9gne#{5(JcSfVEIS1@zjq>L_;hz&(C%&C95YMK)iHkFS6s~SU9J|bwf1vZxU zepxe$V}H7B)&!D6t+`TL-o3|K{dr4u1Cj8*VWA~^gITweoHD^?#aF74!GRqNYeFK8 z{!FbCeSyWllv9ShvYg{tUn;9EN6K*-s%TGUp3aG9)M~SU5>Czw1&D3)TG?uJ*{GN94-;S9jDX)or7$vWXel{uNJDo2e3XC7AKNBR6CK{7| zQBDmu!{W9It^fcaq(2`~=H=v>3u!~;iyIi&V~5E?gYiX?SyTxr000T}L7F6NLx29Y zDu4h04*jT=baNo5eeidY;gU+Jv`%=803k>!tEtDr>brV~FV{cIwPouv9kme9^B9}qhLXV>*Zd)mbSMe8~EHE6(le5Vd)5b4)nDJmn+#qm3ZM5#B| zox`E$hG(Di5d$H;D;LOqHo2OR$rkXk02ilJ-f3)&_d<)MO(`oPGsEYA$VT zrQ{)~WgM;gBPs_m>EnC-P^?C{*}x}}tQP2anQ6t5xsGg`gl9oWd9j61C=l^6FQFAt zor6cvjZ@G$vIxOL*nJ!p4ugah6!@(F2kN~aaU<{2K~?I^T&FN6QEI7?Umb#XBR zPF-4@!6+AYhXWPEg~&rl$+kg=6L^%VpQ;n@)6@!C1}O5UJ|Xhp(0Qjxe&m!M@jx*8 zh1qPu$AXT1F>C%4#wIy5nWDfHhvs`#qx zI~CN6AfLS{#$5`zq@<3svWB`$ijiUOLw!rKQDX7QUZ?D=uAyps(IuUo2>;^7MBdim zCEG0{kPHM#n$1|j!Hs3VXTB#QWG4Ui<_iArnckBraV()-oY`UZ{i*|JuI>uRqBZTJ zX+PZBu7o12+(0Xe21)*54;MC)a@#rAkD!0Z-dQp6`m<}Tf9!YRQj8oDfW6oP;?}Kk z+jMj#_)VKOyU>^&lN(?n1N#i7xFo2nmOG9zKciRRKqyKLbz~9A6*j_WJ}L$@alg5>*RbF=n{ ziT@4$^zFU4fAS9Rs27xWTBH{Hv1@o30-(bdfXC4fZ526hxJaRxEll5N`VZD5rSH#Q zgQwXJBI6-h=yIv>1D%P&-HI8Rt&SMwCINo{*^M_$0uT)J$p99V&YCdoaCKhp(df{h z?W1nT2Ukl|?i{;&)Lb<{!&jU*WCuZw&kWP*I73rgo?L7*fW0){J^X%S)k!|cW)-(E zL)B3-f&Be0iOWZR|8H;kCu|;(FJzVCm+-Mtwmfe2jbo8CEl_OAJjaOQ|W~4l}GJ9UHR=x)7(N76=6Ep zWSB}Vg$?VacxFC@GC+WRG;tu`GVQMiu93T@y&QkDYsZF_U_NG@dbs%!y|M9C3Sp*? zysoNEu%Q`yz3=qg)rTFMAx$F))vw}0Z`Ll{yTl~}6cz&S)1^O3+$@-4sMe)LCWbV|Qkk=<4DQC-1dz{6g*gzbwP#>!w z_mDC@(bROm9R((9K@%%~V&aRwt>R6178C_9heY_Yc$QBIXXz3v47HbDfRKU&8JOoY zei&HiKL2b0$w`Cmms*ZkK_rncYfd>7O!ch%0S1Dc$ z$>WtoIdLFns5O2PTM3Pmb%3YN54KOE|70di?g6^CQI@y3kn;A+e+$B`6&Tp|lyg)d zE;?*<6T^_I+SMEW*=%LRYUl^m&g&8B*F>4&4O+Ny%y40FfRa_!@`HWgVhaN3Yvo`f z*!h3j*X5dCYN;7e(i`!FM(-)ZYXNBWh~axNT-UqPd!Y$<&Ln)EFn^dGXbp@|$o#{g zM{j`}BYI%a$9)cBq_s$hkt$*nYfa6XA4XFGeua;}Zs#}|SO)*J|2VEBhThxGElo+w zJC%RVSMrpF`e z>o{vwhmyV(P!=?69F2jCgbphAm|UmcMf$?P+I%bG6s-xP|J3=oAxM30`IF%9s`r{Uri+^XTwx8(~pT84z#5cO4)c91C~#J zleqZOki0dQb8Sj+2t`)X+#OgnY3@YItG^q+yftP;t~Rz`#MVyYI7)a!=p(tVAzY>FvYWvSwJd=5M97*<d zp^oCO{C@%BFj2kCy=7D+*|IiV1vKt7?(XgmjnlZhTjTE9xO?N$xVty*4h=N!?(X_B zbMBmb&v$3ecjn(+tA1pyRS}s_?1<-y%-Xp(@AHWE9oYR9vFghAPAQYxN)R>>6*tgZ z01jsGz;43fdiR6Zy%R1n7dqXNRy-fPJWO6Qzh!(=b<9XfR*ItA+qv zg(exN_0CjcbwcdvselSbBnJ zDwTiveJc{b?tCX4RkW+o#UmkyM{A~Ex4bN_8bf%2luZOBQq7t4$uzkAYvm}#!2b8J zap3ZgLkZDEy|_9Rbrm5T%%rn%VRE^upc##Cou<5^#4FoV#-|^Ew#s(DRlo!EGfvB;rKpuci?NY!?j7m2xg@Pnu*E9USw=3uU z8eHZO#n#8ha_m{Dpfo)wyu_E%Eb;*z# zdT6cSriS{A%_kExA1{QTUZ z(j?QIjHom4Rn-JW_%%M?q3iuHqvwpVrf$ozm2;NBXmo`VN{c!~&d}4piBogi542B? z`3t<7+MG2@ZGx)G97e0*PBnl9s(obTP?k89TNH|=pjKFuOHj_q%3sHEx~nEZ_z4By z)l(;b1?4iC2}1z@0Mvk)hQj1;zo+SYrvAkT$YJLy$nF=wFj>W=M%N@IPW{{}q*m=C zs7tdyo<$qtP_E~9lcf;vew{Q=iwA_-<`htNt8#C~W#)aZ5_1Pxe^b#2h#LDi&o8P&k8h@)d7_11f76>e(k>1eMVwGU-Uk~5T{cN zFY7vVju@*BK?UKM?)qyv68XVOkb3_3be-thoXtcyu)6v{hO@hgeb@DwNhb$2B++zz ze6Q26raYIzF7=msIFf#F-ez&WNTQ&`Ilq8K#{%S&g)(~zWt!g)F4zqAB=aZiZ4Vu4 z|LKq3pUv#P8^g}wUvpiDb>T$WIW5<7@%X3Djf)%>8IEeYeBQdCn&L*4sN*_63cJHE zl`FtVbhN=x9BD=-zrY2`eVi=h7DK?t*N&ij!ejjDshZ*pd#Ok!MVOccelgaH5WPhc zq)pBJ@%}y@9dtl#1Ny4925Fkqs_-LciR$qE8Xe2!bn|C02Y{)gO0#Hk5y(^1bU?70 zNB3>y%MPBvb=nrsG}%T$mn@E*pJv=i1sp0a|p7VZSI?EOw4^N>`Gk^!5 z2Lbc(ZX5%+n4iK3r+JYO-t{F_qm1reA{@rnGxT>tMg>l z_tct{?XVb`{f^4HpCpIu&xsDFV~H5X3NPe}%Ne5Lq`=N#xQPa`@xTP`1svmaRh_U_ zya5=y3U|wGm7+?GWfcax&tqgJHC!7|IFdisGS=0mXck$aA3LWr_rR=AQL&Q^xqF#5 z%iHWTvxCUyx}|z^dK|t=)6`=!5rZ*N@bhwXgxWA$g0x_qnVT4X{E=_$F@D>9!%p}E zav2qnQ>F22)Q)>Jypvja`_cUa$EG8MQUkyy4@G>O`5gQ(S7<_6><2dtnRmUO%nKh| zU^#fo(xuTdH5rU5L&f8ErJ=r26PiHx#*CfsKr1Iag;XSO>nZDbE*U%u;j|aY>x#<9 z#MG{Z0|!)g5-L0<3Lai5L2`IIFwfIT%wgGe`u9hWdX| zPknq7ev9YihvcE`-}nf66k6M?CF%Q!zoB@K08d^i?&CzTb>rDaaoqG=1HZ~EXsM*p zlH!`)mv1Psm2-L|!C3guU|2r|VKesHiqXCNs3WpGy$nA;{|flGsn2F+rF?B1PpY~SrVF(< zLDlB2i`^7tT$S?HotW&4HmLEwPD$7HW(F>(Ib_1TH6mhfGup!n7c82a>*jh`z($mx zV!B&3UcK;<@HyxqmjZFQo!voc~xzzFs>s#lJ$DgV#&e#ieolS>7cDQjh6x7@Rn#T&~hMl zTObGAFFa_USm7$#Ob4ZS;46+m0)?)$^PKn%K}3DHm`$_wLNHWG8|@{qmSsBgQ9ShOp7s1>iFP03b?&sipraf}ns8V5x0@ zDt5Yg&`ixUnP0bZfQO%YKlQEbJ`9iV(nu6E>LO;qTlV zJ9bM=cuOV2?UJ7B*B?p43xihSRA~A~966i|JIIEdj-wm#PhB0qkNv2UI`7l9_~Jtd zb6{6%1E>jJ^pzHs4c6kPQOw#}ze9licHCO;K|At*AQ1xm0fahhjS z>F`65JGJs-Lquh-k+=qb&1e4r4#Sk&yqU0)_qZIw4H0OuF|?I5lys4(bAp|l7? z(tBP31O+pP-giFx-~9PsJzRkXyMHGDex5G4u!njzZy)GrCvl9VwAUaIWP$ijDIf^% zPJDowhyT88frvjtfYk?aIhcDV2LPC)Dy#227t2hMA9>cTy@DWKVJA zI5l4!lrX_UHBw7<3&RkYy46E={BUsSp4hr4TZ^VA+B6y!n%Qcwd7~iLej_yyzIWzO z5KKLOuMfEYZW4d%L4h33j649ASc*d9{85$`GS`TV=xiWIU=w<)Q~;T0^Lz=V5&%G4 z`=+}Ck|+l(22mUGiE4m~nCyy=*aJT!THaD9bv$* zaxfFO5x^@QUj<=Uo#&;6xGrP*L0>r+tXu6X8WZL*06XucdrpflI6Y(Hr2mHmu}T`P z#<=UsPvsLC|FNhD4MSvxQ~|zQixgVvHVXakY|g9Nw@X{nnk)xb96#k^V=|2O@TZVm zzhX_1ny}1Thh!0hx+=tItA_G#&~IVulHy#|t>LqSbtOO=hHaDDF|9}&U5;F*QcIDo zv0fm`eac`7!yPG1(}weK=E+!HBA9LUZ$QYFW|@)8bdihT#(X-X`2fr6&Ji8CW4+fx zFX!ZHICMW2)a=G@TzOBR2Yh{xYLH+W0xt>}^S?&*4-{2b)2CYubib4t*92kz z%MZ&qV9=;R*3G!}{jWNLgHzd>HJ6%Gl6`<2Rfdhsl?lcEjN_^1Tk0B>BZhq2Zhb*+oID^CFT*GwwxqNe^Y{KF=Ev42N0| zWEK-=fnK_$Nu9(Ww526^2$(x3BOfD!LYCq6vp*vMwo&8VCUYe3U`*OVsR>PU_A674 zphqpmX%4Cn%kII#Lz(x$A2b7SiyH-X)>)!cD7pcFge|ROLC(lE_$1E8Y8y%>i_wn9 z6-k^1|1o4q$fFptOQt3~Lb}d%F<6XPY$HPNYV7VWo+@Y&6&*poKV6FGv{w84XhQJ&C|3Ht`(_7b z$^5(W1(DlMGmXR}$2BBx7$s(7TmRh@7V6#fMlen8f0rEqTqPcKzb4jaziq*=$j+XO|Xki7Q zC{U+m|qZHB!r=8{})ni?!#HUdc#Et>9Tkx({ZjW5Jy7^_0m!XrllX5D;}ceL1HqC_*XWk zCF-k}v{eZA%JE5e-Rq}cj+2F!z62(VCLo2b#RNZ%ejqd(mi5aD$h@|-0tkPX2#}i~ z8bJ7tpJk~uP4nz3HWYP3uYcbCC}*XL<4zc~3FqWhNyp+KPRV~fERSw}?6^d)@J zD<>*E4{E#(Ixjj3=lg_wM16=~!I<%MI)li9-fX+om7ICLOUX}|oM+yJ*cI46X16rT&9H?)z1JlRw zwauttBX{=dDHmC1G1Dy#sWUK?37Za!rn1}2gMyULOj_rgckui(cRdsY^eI9f=Bdk8 zD{nr0h!parqb3_JDSt32FX8(&Y67#W|GHaWHC(C#gCwRG+Da$a8&`0UAVVa`>tjD}&q{$Ku~T;JV)2WHj&Wt9`ZzhKZn2)+ih zFgNI>o5gSw2LzKrztETOq)IKe;JCD$PM6-UJc8DEja2}L{1(t54$&fa_8QBcZQ-gq z=8Fw^vRD9VjBIC)!P5O3WWI0MmNE$RWYB29~_;Ozb~bocFrYyiZxf*nkH6bnNh5=G9B1=q?0Z z6Y@Iri>4V}Wv9P|N&u)#?zd`+txSV#=BK_*3k35YH1?Q37H@f9=TrcKgKv%=-0L z5eI51A5HV%6~N4#lUq3OPx$^3hWEDq_}#WrFm3LgU)cXE4)Dh~AOY%0G7jhe{k!+p zhYD_LJ~y>}!nrng1!I`owIxkc#9uR`~xM?K)I&{az^@Rp|VC;_;A zsG?@C@tl^PqMd0Yd<*Iu%N2hMqeE1)d1cg}} z;{&(b6z%z|?0M}B*|c$C))s_!B>uXb|Nj1k3oa3A(h$BI{?6$nL9adJvo;c5eSJw= z(E_&jItAn`eEU-6{Qm5)@fh|H5gKi&30BYc$4kA{ps#tgSqnMUVttj*T_57NF{$|> z7$Tyt^uY4%+>cVSXlVBXY+qYvXbUPr!1|}v??jmbk^V7JLnYkU zB3S(4;(TU~bfff2U*uAlSDs^OTJvFL6;Tv@kL90ss)cOM%$R8az)1izb9d|2 zF0Sd|EwGf(0iTS&9?ZIrC7B@v*PPBx!tV_eym24h^1sQ{XE@S*4L3w6kyWYfTv=+q zpa)}q5?=}EkXW-3)xfPN2bHrb^uOD}O5hZo>WGmmr zX8{1f%Pal@7$N)`Mm&>docgA3E9TM`11U}X(tU|M6>;17q5eH7)de##MUZ&@v%0doyKa@ATV!`k&>RRe!AOUcbD;M}V*HjN zATsaHrGS|ne@=fNq@&m6(r?l|$?u=9m)ABBT3r)_pO3H*pTVKZhlox_OHMETr7l3| z-~Dj{Gr9h}`dG1*bM@vwniVRuMCxwQ<#zthYXQ&^yc<6Wrt<$uU-Mu24EN2^$AjY| zkeTb7G6N>o@i~hMEA(JQ=wrj>COVUxm5CNBb8D!18)kroEF?&BJvzo{M^UjC_p*Wd z6ewIzl4l`QVv07Nns&{Ni```!lmX6|QO#@$$~qiH(ia0!jzlJfEl*z3PC=i(JKe@5 zH1_&x@9-9tWlxc$<5`Fk!UrOJ&W;e+RsjQhGH0t<=3|d;*nC$t``3?MW^ib7)tMpL zpsSv55=QsSAsa#b`43)Y4rFdFu~8VSBwC<0g_q?smv+=jE7nLzvqXvjV76kO2>kop zasr$;U(WYZ28au0YX9j|wf6v!R$e7h2tABDXGYNBTSq%(VG9^(t#up8+~e%r|4SqR zj$QA*1c8~Je?G3PP^?FAM-A6`RhnPY@LF{vJdPB-?Su1u|HTW4&bt$4V5aw94d!Rd zi(FR9pU3}d21@nYxdl@V|9TkzNlpgkqn5v)ldR&(7hKH=O83Qv!FdJl)J5>!3B6#Z z-@m&>{->MY4}hBQCbYoJ>_5l+-;DT&8F1qt204F@?=K9v1yc+E17v@k1g4ow4ssCc z`c&*8RQ(^A`u;wq?Z1m@_item7fe0+4=@?jPx*os9FEsJ!W2f(pndMdu?>Bmq~#kR zNeEUR;3M%H_#I#t)ZYe}Me#QQW>NhufXaet^#2LK-_r52pFx08sA=Ff&Ke}LQutnq;aENnjNpao_q`5$Pd|2|sFzl+xTZ=vNDOmp}T(Edw`_Sjxm zqCbSH{R30%-^Wz-cQMucEllEqX^sB@rawzj5xIY)s7bK+`X4F!>+b`+{<{Eg{}w=z z_a^Q?0r>w(Q2?Zw&n2Dl+xtH#R-}pA|6mx*zm4v%I)J|*!FQVd3yJ>=gLl^aH?sam zCjQg-Pgqm??_>H4_50^p{(10+68weI{quMKJow!}|4%dyD9G^a3dqMyXpV6xY5iT= zARAY#h5XqB^?v&nr*!HR=)s%zONO*S;4<>$-eXD-)G+y+ncHaZItHL`(-8L5Y0h53 z%+d}Z`AwhxPikQBztcbjp+`A@1MAlx>&6fPLn}HnL|ufPG_D>bGb#WzUP6b{{Ec5=H9MyIT^< zFRmm6HyEXa9Pf9)%4@Te@Wua#&;LC=4ft0*C4q-3xt79-3<(?m?*$Q;qeF2s8Z0FkVW!jEMu+u5mNYq9T8=PP5w(Ne4?KYx^EoSz?wNDgYbC0f_efJvjddwb3J!VyhFP z98;oLL*P9`AWNf5A?6q=tVRKhx==Bw%ZlSs<>B?uSbLK_E8WhkzeN#TP=EGBPMu*w zPz33HvI-~w?y}goUEED$w6}RXP$9TO4}PMsmuQ=-Q4WRSJroKT0%(Ur z93iTU`?Ux?<IJ4&^^d6SeByj1idizdHqJIB@|~7;)b}F{1tcZuB0=zt=64{A;)Hdmwuw zltN@w`Pa*-_LYoRf?UcYZU4ARPiI-fuCX7tH#*{m6Sl{%8Hj zKNB+MA94I!O-Wwi|7c2DBP5>JgsulJjtCj@8b!%>d+oj7-}OH=F2Y({fM7byK%ru# zs*Z!j-q?2BcNu4)85Md1+j4*xIyll=S9mF4}yy!L<|2Ge^IBqs%mm)q!W}UwREm z;W8#twrGy!#6u~f>1ERS%6#wA^7;wZIF*qB5>UWW!e*h{We_+FGf7jhsb~XH1v>8@ z>WViIZ7&en{A7fp84YC{WB;Lb3s8GUD-4<1_M;K1tt8|*(MkLL)I!mo^}^cIIeQjB z(I|KmLA|@nWuK)<3{oxpv?ztf80-0;oxhISoBNfcQshaY zlVr6XXS3D@76xKA@)veYhe>idT|(-d@)--S-F19W8r9oNc{1qs4+gDbdcR@vaX)STCEebw|yzn~Q;C@_|=daMEcboL9m;E5_@cXN(MDBd-9*dKx}lj${|#Kw#^ z>_-C4PFZc{%dYG4009naYXeJj|NDxTyo!n3+E7jGKl78Px_&sSkf3{(7Snn)KpouS zR|Fi+4RIS6iZI&QZ@<+>c7V1HCEjgV&WKrfp%py9);VLdI`_E_J4;#_LO~N7ZgHND z4)rOuq40$JVrh+Pf$EI9n+|){qL29p7i40dU^X{b5=u`JkaJL$*+dB%dxXaKd^XSJ zmhF_h26iA%tt%@2YNHEw$8jlrUd*Td$#$DotrEC)Uz47GATQ?1QqQTalkg-SnTx*q z%fXO4mM|A%i2Nh(R_BgaV3>lPcJ6R1}#^fJ6+I4wWA)`{?B1pdbc1y{I0`1U$U#N*1TjQ1CljUxdKsII?As zd+Gd!I5zj0J~Q;7ZrlSHDQM}g54`n{0Q=$i)i$;v3RNR0KaB*OWC7afOWUJKjT!MfKMc7 zgT%iPy7Ejspow?gc`nZ~NbtsHH+ep};G~yVy9pGqFhObLngTGxIB1;1peX4NN0^Z> zS!Xv&(RYMyuh3TNdSA)q_!1`t##PmIN_h9&9fIGsB7bxGoH-whiLGDil)x)>4DTQq zuCKu=-7~JE#m3t-Qq&JB+CVzqiInuGDuQ^nCF67{e1f}zf4dRX%~Fti4PMI-AB+kN zjC@xN(FGBP)Pj73s-l3sSlEfu74x?=eUd`SD04E^23bo*Po7dM$K%AkJ?ZK#h7LLy zGc`5swfbch=m?^ZhY)kyT|MX;&!RFbHN;ru5S&^^=#;vhve}uRrIUJZz-{eJpRRCn zy{pgHh&@;&eJ+W^H%byBo4bS%QV^8ut@hN{izjGxEY31IX%|SunSNToEe08wO#nyw zf^=d-RDI1n^PoCkOgR6-Z=-l%Ua__}bwHnIXb$ji=CguHD&;Ox- zphidv4Z}8Fia~JsFLzrRLtWL;Ct^1I&yJsTC`vWXr4PrbbZI5KZqF>N zTmEK|B7rtC6D}g7AhAMgTeSD96j<+}`%oBha(YSi32~uNg~?$Y%{|hvxj?eZ!;PKu^5&SE8A~A&wxX_6rKH0S2AXe{6arO!D z>E63NP(8hY?`B5#g5O(PlWE-^!*?X*nMb5(F?Vr!)F;K);xipE4yNzb)}5cJbl#)j z+%+oV#RCt@LXv?F;AJzT%sb!MN*VN>u?9mdT0M0(&wLjLZI0IAjX+v*JexqdRV^QqyXwTR{SwME~A{=(2mt%m*r=bQM8wu8ykykhN{rRSywUq=uGy-UrY8u|HMv*>&E1B;Ca z8gupUA`W;G!P?Jvwqow%aTTe$mhlp#aMe@}VxLY$V7c!ZAaYBA9?G|`1%?LOa<8wiv{eq z($jgw>3Gr~A{V+kyNEw`5Tf zmSFNLI3o!)QyyUTMftFChY4zrKS#H@B$>G7NJJYe4%={J#n;M#D z-iVBKn>Kgc49;(I7QS;uc2ylEv&9|f=>qJ%unv*AW%NXTe}4K2>Gv`^mtSUL61Txi7nxzGas9FlA=l;BmGpmlHq6 zE`svGcd*Xh^3CQ71Vy!F*GS?`xZNRjcz&yUuvdr6Z)5m}-}ma(4$ea>?IZF;r&~X8 zfxb5FZ@qn2Yj<`kiIus``@m;2)LPv}{o(Z#DZQt2#FsyX_!K$=|0UEEBfH*^TY?`* zqu4O_jrbTE8}-zL989tZ4$Re@jKHD|LKV_AP& zM5iz5zPMT9G*MuMiC6Y2N@YvNPFWm;Prowzn0{V!OGB9Oz`6z{?7>_94*)GOxc*iB zH#<--ML0hSWphj_oWLDx#~0Ua7ir&}Zlp z^aw300vH!tXA4z6u?l&DQmm`}vHg2elLEv^JT|`eDK>i~40-u%HuiaisF1I5H)-WP zY0U-2rrDk3qx~A_%vQ6x_(k>Gq}22-1F-4>&u9E~XNRaG00Uw>Hu!IM;M5<}z2Wub;gEaz^7!}E zO2Nge`T$YI@sfMoR$cNX+7{4m;d>lmZV!gYN9XnanL8@WU^j1<5IQ+|LmbhZB#^oy z7L3h0?Wq|3{XYFluN?}h8EL_E==m^Bi^Mh~!R*0w!161uA*L7Ob14(V1fs4hryux> zn57w3KIA?6IQyl12mQ{+Ebhh7DGJsb;krExk zA}!j&YSO!@DF|udtCm{@7j<$H5DDkl5E_6l1|KDNvcgU&T;AQGMP!!>vAUl-weXR? z^@%X0C!Lh9hx@}@%r}3LUqvI2F;-S=u=>^-Y|$n+(%gtk*afFOxDg%qGZf49S;s^- zyx`2|(Qahf`HC5_GujZQdon~4q!vk5VpxmCNp<}ha;{A0Cxt|-#Wf?gO5$tvx-5LP zTGnm~0D;$+2z~)(x9?$(bzqa!XWzEB%$w89A<*^|O1AhV3qW%|J@w5>!jVkADeet! z`oR+Qur^g~%%^Y9C5w6`%I*~eeCEMmb>YB6uL=r_p0KaKlxOAsBw&?-4%2voPj^8jLROkyiks!{jhh5#rWB-_8A%m&*uRCNzyz6G~zRDBa^~ ziPwsF6G#P>NlJ80Q@~l#gZurpRu{Oc8b(V8kzxueTxbiLv4NOJ!-CX;R{U$Ma8N{T z>Nc5-UT*e(?2Ls``NmH>I2&{cE5(B7cuY)hlQH-tR&jETvZ z)YN+^Hiv#6t}<5B#rmd5Lo!3hfN=Q1KM*6o9I0EqxjhfmDnv>V4FQFlxuZBn@g(P~ zR8iiNoI9=)%i8Q5X^+X(9o-A7oQ)>l3_8<*cP*}xm(M5mgqOOVE%vcuP|Z}H@}y2})sl<9g?R9Xb2JQ(bK-o|4s!k3Y0HA~DdH>~%jXtkDC4qd8T;-NIR zU~+8~#ZrRmm=>mG%|FOIm>qHEj$lrDgsEX*;1B$o5!i;buRodI*$}SnZHhfagZH>d z!gdS-Qh#8122d?td;W4KRb}UUOCq@y_K}pD_t4Ub0zW*+f6n&G?ztt2uBCx(#_$v_ zNRkdV**Mo^IpFmK`*n_jvo-7_=sPQ!=OLwQ36UJG02Udyy@q1$r79g`|?n*8!a5AGl5Z4rF~cPq`bhG8p) zCuBmQf=dwtS>R!6$Ff?cm5a2{x3uG}%>DL|EHqC>B^P7`al^vyXj2K&=9?`Pl^z9s zR1yu8wf&(X6$y4HZkKxknS`{3QN(IR5dm);CT`nIYkQN>F3Bc(9^<;;;_Tiq=SI*;d;y<9YJ`Njx<=3P@B-}p6(#RJ$>8l`fhYCr@@5xeqyb4cz(j_u?#4)l+0mZOsjK*r=Oy#fJr$R#pjoL#A*e` zeJ|jZPMWRQ+34+3K1}U#9Jz9)Fnd<64BV<5`2zc$S9WZr+`uG-arfM@gGE!XHpGO` zh)u(j(=PDC5II?{F(#)Wix5^sCKJU(cAFt$1(zr#dsnNF?a!#rs+=9OM9(~++eJ#5 zlo`iW!=7ei^(p_1eR`9M|Jn>DgmOe3-y^b(RJYQEhX-CVIgdF>F>%1F)yTc-+5r4(*m_@JtRX(h9WdbCgf{~w=OBLpa0qE5!l9}$u9q&Y~ z77GiaYME$GkD0;{>6)ES{lo68!4ommzT*pdbyJj1>P^zo)3bI2%w`pJ(~&i0>kgG! z9voF^T4}CBx)YZ_OZJo7@^x7+khX}HZP zmXFTB1TW_-LnQk__@{>kZqbY6%u;c0HW80C!ZX#;MqxgHxO9lR6@9q%f&Yl9c&e0b z{pT}11KKvqlQ~c~Fdi>VA1^Kb-mB5A(AQA~H<1X~HJDiBX-6>Z=WIqjnwwrucKENy z=9RO{r_TD>Z|BK@b>`O_Lp!&PU-{okMBzs4hFJQyknN_1HK{aK;Z^r)pmE9q#ct}# zoJ<8r5>6#UdDRiEn&zV(kY%BE>{KMF!vt!n!UvDogF9K78m(M;6B*Y9@@^r6DA_G% zv(|$s3T%2tviM~%zU!lNCtab&gGh84TTlsD^q#hTE@zR>7l*G^bNR$c4N|Wk#l=>+ zymO!&9>ME*S6jzP*?P?Y#5};_&i3wDZn3^q{`Qo8mzuBVY26beT3AM_4H<>KylaP< zzlYTHBUjsZop>I*zAA|Xl%yOS3#%$44L1B+Lr9S|*#^MusEK9UfF?gFLacUyPPG&? z!i3u~#2h`hs|vC;bZq!XSFC+O;6ZPf_o56o^c ztCN1qNIVR5LaWIQOY_U)X!^GzIP@K8y4m6DT$!(pD0_QPxy_ZP&)!#$dOfdZ=QqX$ zw0LMuCmGNm64Y)c?mff54_z7^P=KBKAMCycY!iOcZ!Nj9pKX_T-GYvVs#|)_9P?jr zUW62q8&_6o$X<*>md~`jZNL)gX!vz9BD2K<=s?z)j9-+9E9PJsoJJjOn@3VoXZrM^ z*RNGg!QPGVxXfj-jj%TB<#N(RPkF|<NENef!M4QmV()fX0ox6@(rd(uz#%lM|=H+a5&ap6yMQxaQys}jPK3zpp{koy@b~#2xl2LhiUBnF>dFvr?a&OB^3CqU= zE?vcHoNlAVC3zt`G5rwitGXW}XX_@k&{>%?Fis=%LN{h36cSs}fxAa|uX$87BRr&Mr#>(LqId1ToHS4imQLp67yCN%gtwzV z67cJG+Da6!;*Bo;?Ix?g)Xp)Bgo+cv(zs%AKtlbM zQ=Y0*FsQvsc(C>XiDT?@C18Uo~3J=ue^z@XL@0;CITGQC@CS#c9^A)I^|Bp zCIh^eO3CqXLwnMZ)|$j9?A#l*Ii+vvGxWB?%% z(j+R>NA;^YM_iz9uRZsm7txkUw4T0Ew99Lpf>^DaQe>zc;AELIf+KLnv3wpRxLi}0 zF{|TB!Xi+0gCC2Pc+;mw;%n@?RvX_!1#$t^Um#S_NiCe|UCj6A=?B5q_*a@(uw|nv zexAn%s*kPjgGYUwDY8ZH_{lODTmezFII5nIEOE*Qm5NxB9M=xY4(DT9ueYmrx&z~L zD0q?GVB}AWZ7*ca2oIL%f+4~Y69Z$6298>mGC9k%)pFgh#qWJCLofV^yYj+%BjtHm z22^dEWMq=e>AUf-HM3XDj43`Z4ouN><+j;@hRsjsjuH{*-<_^UGtIx7+&opkA)(A? zOsrG#%Bm}OlwPNImSQJ|TOJg9cowL&vqGRZ?hqJ*r&xQV-)Pm9)QHC&T@21=R;tMy z-~@bhvz9CmnAG+iqIlmu_uEdM!Ub41@av}Ho5GP;Z*6B9|J$<=9h{VRK?D4TV%g>E z5b_BVZ$lo$^C&A)7F(b1rJ^l~f2y;*n|Y_6l+ZN(5fK5a?T25pFiy&&P1l`LxL6VA(4VvoiX+_u8N7P2oEixnB^+F|fU)4e;~&?p1&f?!t)G@oD%W z8T8TARp)C=@p!+^eQhA&RiXK;-25Y|N-&{2?fONSyx1D!0<)r)KWw0CTse6T8X*>{ z)Gv+Sl@2W%3)1izkoF`yapPGthhF1VlGupdRJiY%dKn|_R?0HK+o>OCt3StR(qj5! zy}DA$eY}%0(P_8Uv&r_%BrsdJ`E$+^aJU z!RSlTTtQ58>$nEWslDbt&Duo&WorA{+q6raYVD!0c&J9}M|Ef4H75Fcy2ol8AK;nM zO&b$VB6t<`s|mFN1oA})mW~_uVA=CUS~x1%Vo=!J$J(OVkR!}1P*Puk-i(`M-Y|dg z#?o+=c#B81frr|9FGf_)&MtvHaRx584W#Q9Z7z*dS8XN->gQA`6@HXn&+;NqyTCQ{ zx#*($qR#OJY3Rort6JY07WG6etl}2s$naw)B^DfZr`0KNS2!wn{?cDzXfh8x3a!rz z^oI`m4jAiiZuQAmvZg;ZB{$9o_Bj$)DJnYnvfNn$LLESK^2e1d$bdT9pLD4p{Mf-> z3zTZue_mwDcqe6t)HmF<9pzT)Rc}b&tr}NikvZ&jcz|+|XnLD>bPU?&!_X0r3?8s^ z2dH|>U?sR}8WG67Nx1Q6T&K0X&I*8$6R;J3gr6`=PS-ZpJEIP&sOdxNqv*t|#KtxX zwfNqy!8%oQ)mo(FPm}u5T_yBoq=>xm(tC^Ka@I)3eb0 ziR|-bX6u6kQ$%J+L-~l+i3CrQJ}b_Uomc^NF(JP~V6rhrVJuVrCOi;35*;fEgR}w; zhnj3Rpp@+4%(n1TkeHK?U{(B5y*`FN+t9SDLd_2TPiYPT*FA<|#2p_OG>%bf3CP=< zwEe@JuK2m8sSxb7mf6Pe$^JO}!tZWT=$Tefg1ic^h92mix>wqvI?$*iA+7s8u12+D zmBi7o#@RALQ1uZlY&Ugp?dy$>9}MmJ)&eZLF40uLXS8oP55ZBgAFDkCj0k(kkO^=Z zpVo_gD{al*_;YsP zsGmOEG8)YE7}$zq7w=}A;6ArqB*#X&jODA)XXTMpG_# z?PM#=Nvdf%PI1tmm+5iGFkqyg>(#ymuQQtB zM;b^6dP^z9H*{I~ame4l%Va-r)+qBs3H8s(vK6PMaOO6crYc-#o(-@jE~IRhsb+G16$C<54LCfecBm-xy1R}G1jch9##~2aFS5{T9 zs!){DgI1Z?eM*sJrbfP_w_zW%#v8{3A}(C4Er&Yk(eyZG$)NjTdHLx4AVB1xF<-P~ zW$>6Kk$I`4+i^bo^=7mAhn4-L%Jvh9qE*M9mRo58uUFO6k{PP*?2k{lCmuq=ZJJA4 z%VLky+X>lQ!KLBfTflE6u-})R-T5Mn4sp#7EAyZrl;hpTt7fV_VS%^gQlbWt^EzUJ6);?O_4HI$XJPwE6{oi3&Y4rGgOe-mJx3aTW z@m_ktmH&nQTi>F*fL&H>bW>s3wPk5|v+UFWn@NdGZWUF-kRQqqX^!Tn2=$@uBfmXF}PeOOa8wkz6!|noxo8J|CV#k%oa{Bb1+-|hU^kZCVPzb8RG#?*czeZk`Q13E?2=W;Zc`ozc)2!{lWy1iK*Ba zVa($|2-7J6C7k|G^yhdjEHUi?i>k}p!Qo~S z!%)DgLMM#t+ic8brow5V_yIm3ZzOy~>+RXViEhLzwAom}LrDTpe_jEi!lg54n;CK_ zo?DfEu|zDESQj9Wdrld$g~8Zx^!DbAr3)ktI}gc3tpKn67H+TS*Q6&_h_Iy`^kcX+ zS6N8Qa;L4$0om{y#ca`LtMUfU7&gOd8BI>rAR-2pXjX89V?7;@DhUzyKB3gyYk;SR zxH5|MBlWbPI3p-+i)k`_+AhnWI9spDL7uzg+5|AbAdN-GKvE(%vKsP-X+T-xhX zB7P5$oGFAlYaerR`#795&j_8N=$>ok&>GvFzQIOTn*}{lzvcANAQp`c8~_a9C?3y0 z!XuP+(L9wlK~TD7(NoS4YR1Hq$JQzlQB0SIXz_A;RT{id`j;Ku!@KcNDu2P$-d!yT zfHIGs*Wbc{yGlvxd>K>E0*}*lRP!X6bPyPf4p+Nc|9DTGx&@3U!<7 za|SSEG!%>4H(WXDe|z>*X(J-Hf*eL#8PcGrZ2o@$OF*>04qaNi4j&RAhpTH)YZ#XX zR>mygx@o7ov;|*Y-?|HA*LB2Fd_i6sjYnL1X1={#lq{?p)#He+c0jB?YlTbTTbTK6 zeTf{G&Qdw$f+s`6G@6n-xQO=QtimjEF&J4?%xw z@w2D_+@$f*2+X&omJ$R8Ag7|**GpS>BCh;!Q0~Av();glG$63(xBY`Y_7fmo9FW#Z zC4Kjljrw~nPp@{nk!}*+0=EV?&q7$7QV7z51^&)WIz4NkII$xPGKpF_EDlhF&B|f| zUEBMZK+4f+V|eps4mxDoVX*|;US{?YMrmu&9@2IhL+hmJ?O;KizW7iEJ%D5S8Kx+# zO@AJFYVeUP-zZ9d0e=%l{gC#@*1D2Q? zWSg=QE{>i4DNm|&o_+WUt1O>&C$WeIqQM&%DikgkMGE8+-R;;7k%L!lfGYQ{iZ8u& z?^>n%bC-kPcDhp5+y(XqdU$wLNCdI*HE`>PqG&3gzW@LAb5Ve0zS5Rb4nSkVK->8; z@A6f}8uB8=W}=~7!tj?%y?3e=>aBVNw{0_^Ned!rH!W$5s+j&WuO|<*Mi?~G~ zS5iBVMswFK{wdKZ>i@MP^j~Q0 ztSp)*AlPv95sWHp%YsS@=)Qw~+uq+$!aRV3>2|;$XPjzQM-PFp;EGCz@(Td1c=!vY zDQl>^4kucXQM{l2+ClO=Gnoj!ru{(NsP?gUzFQK|GrBUNd>s|D{8cX${H|_v#HlEM zl6j47WP8`J0kh>tgzfjA{vjJk-jMv_Z|_2lX&g>$VI|;In4vG?Xgd6M2vIzmt>_X} zT5Uinzw2oy7GK2Oed!~t(ezcFcEv8E^0f*>G`zy6v-|H<;~bGL*IU#`M-?=lbKDZn zuFk4Asc-twY;h90P5!-yf{NK4T-Y(x!KlGoz(c_CMc?B_pj ze}o5{GSLlf9Ev0(h-0>{Q)yJZT9m?wr#v+hyUSXAwh=#6OWw=vev#J#v$PwtcMXLN z3qL>f{$ebEI{2&7LNU;1iHF4mq=ZiX8hQ42yt}$GWTyeb&~BrcGAoJxAxQE0>kIP5 zl+@fTcM3%=oY&o_QTKcU7k=3mJf#j}t>{qDomYH-A52O_?-I_+`pW8>8BU_%UmptX zb^cjz3ucV9Q7cP^3R4o4pZ&W|w=Tt!g&n2Ts)+~g)VeN4;h14AJ47nVZ=52Z8S=V% zSBt@?Ot-wYgNZBNaj#I%I4u^LP@M!ZOmoADS_zM8o9%%>*1cnl07pz>L)@xxemKg2CO!K~3%;}kuXcSkTe4EN zhQT(z+9p(1*dj&CUI$b37k1U^NnNr4zP10>bo}!rJnqtP2zJX}dM-#trknw+j9BF9 z-q=gl27mse6=tqa7) zp6j)Tmv;3&x)D3BLjB4cCJWeoc+GkNp>{3eqT_w|^N5As)k3@po2ny9cnW}xNl^Gt zzbjqLUAk0vlKYQcT$MHPh5OfeUY?w8X(iy{{;=Hd|3?3gfUPYXk4Q4?wAGsJqzH+&_=XHe zFrgdhdx!hq^ByyXd*(`hYnovW zdBzC&D7CC{Y6Ro2_OVjFh8Vz&S^GkVbA#1a<^cv_7A5&4LessBoTI6tixr^t%h3tM zK@8v&ScGEptmfXTJQXP8`2tJ~ld&MlD*UQ-Wc=|?c<{vMC)Nl|(EZc8A@s0pfSm1G zk9;;01v%_)e;_X}gVO;he{5<)jUqDoTIzT^q{JuzK_a0_B37HyRg0(yu z5RdaPn%0>kPKDnl=6?Mbn%=V_eGbWJO@|6V^s!=K1z;!YqaF7U)g5;Qa9m_k5Z~~Z zlyfe@Ro>9Jt3U+~4WDX!%t*QKuMs*^ z6uiv_6CO8SXubGbAtAC}8WfimYj(uCyU1h#t1CO6zqUkdx=bn0|BV0y`U81#*~!*& zVjHE7z-ww6MZkT#U6d#_J@jrq&K6e4su!k@>v&HX_Z#2BNDkoHxLhixho}WPJ|ZS_ zS@aryEIVgRG!aEDs}f$#L(Mbdg;KTCrt8`1JK&d(CHaPm#JS@5LC18+Duceyst)#>)3 zOLoa2#0qx5tfIyE6Y0JB<;aXN7H^Wv<*=a~wYSf9ktPd>>Jz;jC})*fRGvL<%_?B2 ze=z89KC+6z0oQatQBD@6->KuYgekVVIlp3yb`;2 zWGS#5pxgz(Bl|td;dV+Ab_epJMuSe=_;NozpVKCNqo{gu`p_E73Ua6yghoHHzU?EF z85Xg%Rqr5`2g+huZa^$Fi-+XjKT`q)kjf7;bAAWkCU!_EKh@}s`rYVaN8xX72y@TK z2xrh4nI*Q56Uf~sgWcP}Z^5V97xg2VlBJ5>-X7X>j^nUwn`DNJ`8tz;;b9BUN7e=i zpJ~?6u-V81pRt1I959RVieynfMBP1e)u+~8+wQ#FoZi1EjiE@m8w5Z1kc&D^3kozd zA<-6DW6Z3BAyZWCvBt;ILwB5MR~F%f5I8$SGA%Drw1b5E zRAj>@mJPLVawg`l$?9h8WHCKbVUb?lb<#TBlBiPin-x{ye+36BMZ+~yEIO?;@)>Pc z;XD^=5FYP4gu9LO@lu^rPc9{nP%-nEu&>>RVB{#-L#&f#6jV&(yIEj6SCidgvb)K{ z8-6{#yB%Nxvn?rkC16*y8XQXzRQXgmhxSov9GfY#965Sk**~sOi-U`m#ygK{kOsQ~ zwV1aVwq=MHj_PP71>Lp$GkF z(HP%4XDTJ}tz4Ut$+kxPO*Py9$(rB0A|pf+C+7ocpIcE$$A9t7yqC0EC{tW`nEA0{ z3tYR?uG31#!ZVp)M#8QvqyH&aID|^#$K?)1N%XhzABF7<&qSCJ(MU@8?A2*rF}4-| z^}D9T0#j#-`35YfH02A1yUdD^8CCVy3Jf#r0`OmvWTgd`z$Rq&7+tcM5NLf{ABWZ= zC(vQ+r=uKqIxoH&SX>fPDk#vz4Q;%;ahJ}FI`loaA>chX3Dkn6d$XOD&_97u@N^-a z7lPba+y0%$X>Uh^I`e}WU9u^9pU^r&TFEhKy%q*4Igb>RVxyy(ey@{Z&HjrY5Cx)GvA_)0az)V4>vxc(S6Zr zw=p90M?cE4~&Rge%;D_jDvojDFKNdcT@OgohI*RZws#mG_JI$P*=^ zuDtH0sA!E4#F41ZPEdCHM{~ETuV>XT>kfa_ujr9_UczzaAy}KzU!HWjhsafEu{YQV z6y@ed-UBK!naa#_B|!PyZgfQD=Xls%!u!iEyDkV&aqUpVM`7)3VQjP*v1j#`5#MjC zr5)e0l5AxgJyTM$@GmxH+Q$LsQsGigkfoAvG9B|u3hiBu-&*;u$#{;+8%TI!NhMum z2h6Xg*2Kq{iWngRsiDsg#I{yWSo7Sx;Za?B&Ywp65n@7cJWVqKOWr|@;^LhCP0me3 z;s?~{NaDy@;UTEcg}bL$9;6n&dP}|~jF1zEFaPoqA`QfGkuT9zK>cb2DSw#b0^nos zK>&WlW=6#8p5bv^g8Yaao8#$Hj;GWI!$rz)!)>|%jt3d%awgYZ#k9297K5YyLmFyR zPnz}w$%|vFi#4gtCPj^cjAO>7pxFJ*4{sV&MPKyif=Od*B|Fv#PWH2_vZF#ABYs4ZhnF#+= zew<#QWpqMfS4OS1S4vAvcGLuxU36>O@wR-cVK-K^n%24dsPpiBn zSB);sHhyNY@hQXqZ!0_j80~({x6?Rop;bT4!f?p9<`-s6TB>wkQ@Y~KDQ6tt`1bsg z>Yv79J!7obpM(+^Wyahu7d8#Qy?w3S%n-3Aq_Nr1Q|=@3nD9|0$mQbt2LG}L341(q zgtg0tFOK^P-9E)}R0bS_*6WB-*5~Ql^BQt(udgu07s=TjcV|QoejwAKO&>3Cn?g{J zH zL6HglKcq5(9OWw?jvrh`>kPAi;-GjX#?#c?x32CGJff$a^JhBY>k9}a+P^@|CSyF? z?m{QA2ji`E_>ba$s}fCQ%gl1D(3P)$(m+ubjGjiQ&#>XC`T8u!hc*UK@k!pfQ{rHe zyI<_UZBp=N)gyeG>`t*9b#_`(7xNBF7bf>B6TsA;)p|CC2KRp`INAfSqO&Id7-GG} zH~R9fe2zeXk_t^0LNOUYxd8Yxy1w8rpFQkV@+q!=%ox*qE|NYXGqL{INW4treOrLA z;n2FZozXS$k`%rENe>1+A*4%|Lx)$kFrh%Ai>s3XvJzmImAXr>`FG*Z=2F-j>NtdzLm!bSb+K zSjug^x~;uBNU!_KJB*3T2B}f&)!e{Kn`b1KZ{=K0H2sb9^&I9R>V0sepKxz*R(7>u z)1#iZe|+_X_9-3S-9C3y*{zd{Q3w1ZOr+c%(I3hGozRgy3xtx=*AA$f8M!VmxM{+o zr5mdz2cGs{CECTcLA@gDBn`cNJU=pkO3u6XiEI+reDl(0Q<054(9gm6J<4B< zmhxd0%-sse1_v4;%zAUF#IwB1f`QeR6TyFfXDT{-z}gljs7*#(;-v7UJw*{Qx}9{0 z){DjMC5<~n$(yCa^p9i4c(MSw&H`X^K)dC0XxS@A*H%nNuAp|%I-Mcx?7$f z_F}OoKyheNM*Qh#xE8R!00YBoakF~2jDXT^EKYbKv&k&pF4s$n$hAMVd+$F^K?b_^ zTqz2-7XC0}dP!Rvi35Ae2_c2G6KzdjAH62-GP!aws}93vEDmhfA_PwI%C$VA#;0sn z>M{$x7uWyZr)TE3jH92Q76Ek^7fMmrMoOM{=?;@^b2t>+2dc* zz>HC7gQwMhzK~S%L`qMKTJ zt$m;GfgT0n>)+bSFPet`5|TPv(>G))bl`0!+JFC=J<_P!JL_m59VY+(`*w!m!ox66YTCiiM8ADPn(8Ss z13r62FDK`BQE^eHof_~{(K3o<;bZz2QN?!{hYsA;ram@an!4<=bbUZK z(eeU{;ku4mWPYjpiC9yC{#WxWYXTLXIf8f7s?7lZ9T$zZnG^^x8N zpgbS=L@)G-jt>ujcZ3mz-qP}X&Pa0+c<)qh<<|w9C}w=!?Tg_gz}9hd6MO&e|Nd;0 z#< z5D4{3JHhn%Rql2}{^_t_a8etN)b`LKR?hnC8B|2YL;m*6zyJU1oqa5XTxPJU4H0fL zSDX+)AE*h>ZK?vu?lV^9ROCB!M}C_$e+a@P?+lrv<$1bmhF%xX5R1IBg3!5)je2@( z-_zo`%qE8|k)s%)_`y z!>G2L&na+D6uBUydVP6Id;R!nG6zr58l%XAeaoz^8qhLhLE;G`*?+hf#Wcii)kFjh z{y0%P|5&p)-3`@ez@B7XK<7Y4pP~fo-G+m-N0YOh8AwOrDn)lkgd&GJsQBYfz}ph& zO~Czd9#%3Vv8>-_h#yqjPbc9bjkPqi$!YdHM~P3>eB_d;fugfL;e!s>SmM~!h2%`{uf13>yD2$oKqG3bte9m!1^U*N z^fw6gSmP~_FJ>PL^JNGh@-oNKa=c5ezrU)d+Q)eoR>uqT4UD8S3PKwLPpiAc(DwGu zysi#hhzRq0uL)NgMhIflM6Q#K?&D%wlpbQC&jEawZDswP-Y&RW9@ugw`@phV^v(r$ z-%2uBPK8AXpL$Xd);^4PXhz&hyg+O{>>VIY@@~W?$v4yeF1X1q6V|Pj%psmy2@@vt zQCZLvFZcee@?(qdO2Ovar>^O~_Q$dZ{ZPkl8Y_@#CX~#6-$+puZuWa{J=Js#Qdh+)i1C$;Ffsri-8ey6yNOc@Bx) z{$Xr__Nkdax3Uk33EVyWXz)_)IJ&aDzjNeE~42At%B-95L zW%=XCtvt$YD%Lkfhj;hmaDoo^Bt5&O!oh#QB2YD(NzJFYN&H-lBa+S9Sat)}Wa@hI zrvF^Y03TS~28CDF<$U@)_dlx!GD19s?|Hd{S&x6rWA;NB~66- zOP;;2h|Ru@4rBJZW@hqt815tPr<6}f;6qvdqgxbM({Hc{%ZPke;>{_FqD(nHn6|Bb0e0A`rQs-@We;K673cL zQ#0%VZ=b+A{k2Cht3N^Sj08Av@fr8ZdkIB=7U1fj4{>#rV!BXt)b$q-Z6_;ZR-9Tl zkL*2z`$pu@7S^Wm4;+9%P-W9XE287GwbYHFQE zCdkv_YRTjMf$vl8%S}y)elU7cEsooOG{0y77BX+)s+kfAkaEPR6s9j5=;faY-<1=X z=W;$h;TCLG)~IB&+&z4NPo3Zk3HcmgPS`&2%4noxKYRJLFf1NN$6+NLkQg|2JdY*^ z?X9@Ha_9J+Lmho#=apBg&&Z!3$#u;lTv}PmP9&{4RH`?FaKSmeZuMpg%`pQ9>IGE zcMR#I;XrZLy8H@$FiA`9Eh|or5Z9#1d)O~+L8ms{W%pRu1W^dB`4&nXZk{r#VZ~;9 zW)z(o+kh7rNkj#G+$M77SL9ryl=z)ILPr!}`hsO>k9939iE+aLa~h%~fPk?PT+KR- z#xyOqA=|Y$>a(=#C@N}Viji&(#%F7!uKsid?~<$LZE1Vx^Sv=kjai}W)gePTJ`M1T zr>%#=hI37Furp>_&(%SkQ$Ac|0VrdAP0S)`weUY0vXw*$B{t#!kj^tg@N7PvNj}}E z*t!Z_4}cN~P3B#UhO4EToLe8>mEBd7$Hn?h=ET^}EcFgj=Htq2P$Lu(3rvp9$mszt zk3~YjM1`m@Ya)e#f1!#d^?X0}-?h8z?UftC?g!Rwj9!5=tPj&Ox8Y^5t+3g=e$17a z01I#mUh>wN!8y=jZ;gHM304^w|2vUSYpg6DkO-&Sy`bfw8?R}W?u*a0F&@1rBR~qL*(W6ytLNw1Ye0MF zPV|<+Ysb%HY+MC*YXD%5^bC(};szQ)mD{Aeyr(Zm`PnB7W_St|CU^%Ah&`>BjmmSv z4`_bgPN0-CT*$ZSH`v7+S@b+z&tP!}zeBoz#77W;3iu&cWpLfGViwn3DQ>*h(3eQnO)3qnT%#m~ zsp;wcF)tj2J`b_%&n+iiYIJa%$?1ggdnxcBX52-PQWnUk612W4G215Qj)+SnZsNji z4967EBxO0EH=-82T&U6(B#+KPUXS@qSt3dTR9^q@oU2{B>s*<_9d@LR*S6 zY$WN632<^kZz^^X03W|P_e2$hjJ3OE&l&QLX=3|Ol@YUB<8@OIRIR?A_aExz{v061 zyV7)-j^eUfz7$qWm;z*)#uR37=6MWqhD2N!aHLCsAz6V-`xX|0u78j)%^5QwPId)@ zf9`gBjFyTMPcyrslx8b;c1sB$rKz&uHoDYT26raz2~f(n4&nFMOJO6GAe?OVKU2=L zp30Raoa9IvX)#w(=&oX#ihA6xG3qIO{<(OJQxnl%($vvjzKQFr9Di~C^Svl_l;aoW z24QBoBF-1}mgaVQ3ZPhGA_ld<|BmPQ?ywIS+vg~>1baKkiuT5O=M<%A%b&N470pQt z=Z6n_d6EktO>1*xo(Mp1mP4OprP%I@J{oENDVI{3$FEA=V(`rr>_70h6DP_Q!n%G8x1 zFCVqTPmI6R+3Oip2z`#Q?qPoPoT%4{tD9}+l6`Ub&g8PI3LRE-05%h3wM(fGo+z3t z_l0vT>#7WqC>Xy+Yx)jvB?n3+Y@LY z!t``CA^odoZ>hohA(k@=jq>s=-8}ia2+uMQ`Mf|&wxrSw4Z8!d8H5wWAq?!pJg22d z(lU8MHuSB`gGA!@Y8ri%#tu2q?=*0`A8V3JfU@{oV|nnf~X@y;N_UCSlRJF>{`!G7W}1A96j0h%+_lwVbSE8aX2IX59N(okbzT;T)#ajtxb^${ zy;v^ZQtnZ!XiH$J@pI8!V^7q}a$w~VhYQ&K?c&?6%1$Z5UQLsyurl*&$~>>SDZ#1> z@0ZY19fseDAhO{Y;nMtc%5`U_`6jrk9MtdDbodLJH(0VJ#o3AnI~oeqMUX}-`;^9H z<^%eg$K2vXUcLHp?W#I=8rDIxv{~Am6N7g&*JU9GhIQATGfFuW`f@=eeD`&ZSYs`0 z-o{|*w`@?Qz82j8adke|%#sdfIyn{2Xqg{7yRGSOaKqRUS$s2$`VK)AE!JgG*c{_y z25#03Du!?=v72dd0FY`^`A{00`tCCl?BX?+mRaG1^x%|&uhh4(g$KXP%p_0RU~XUj zL{);UM7M;v3GOgl*QLe7ZhIFz?8PJ%7Kk^k`eu8^I;Kc*-6Qu(S4I!&-ryK+24HLJ zAglKG5#M|4(^BRX7gRGihM^#+DVw8{JMxa>!&c(hR1TOH$wsU{@&25@<8&^Lytoi* z&8!nQXN^C}qUro3dSFt;k!~DuN|motP~*4y!qDK+I76H*V_;r^9~SQ04N&Mhm1S7F zF_-)+IQ5~D(3@?A?}E8-?B*RKeaLj_M4dfuy^4=sDe2uZ=0#EMWLfjc+O7pke?#ILwksDAoL+tNYv6f^S~MkHa%9p|LBG}lL5-QbQay%X=BE##R$SS zHxL8o99;^}U~}%L5@#iZ+%AuN2m>Oj<=8H*Z_bYhaHtH6Su1wtby2VE(WdAI7Qln+ z5mk+l+t0CjAyxd90CyIwDUfUB0%fXK^ZaxVS&0*PLF0^Cd<*^${Rq~d|Nqp9?oyKL zpRJVf;yiBaJ4Z@2e`8<%E~)oI_2HC^c_{rCZ)t6@ZHLw$PB>DK)R zlk)@L38rZW7HNPNpI}qZ0NbGqZXIuc+D8?xM}GNhYA;G_nv28ET`YGZb>MG;UQ`q5 zV!asqh@8`tzdR!^-0htt+`C2J#xUb^|eRg7hm-MGl7Bh zR&f<@?Y6LCnkS(+v-)^MQ)sI>XxlsmlwY@bRT3i!X3|;BntFU za6;>moL_Wj`4F<3xq=`qN-6r&7$J6fu1W7cJ&NAVm!>6DD$aKC+(%Rb^qzWM>Pw@p z9#NdyH~}L!zb`s4wU}}ayogqkoDcKxex0vcqM^ME7y-g}p0mVz9B=El9z90TA!b3T=$NL(CzJbQk1z`dlxha%E>oN2^QBLmvH4a=XkgzwPz%W=xF7W#>Z=j*n zJ?6c0myeqq{CP{4BJ%w{d86^Cj_GqkvQ3bsVUY#r-p%3}Q~miv#xKB3?TH?u&;Fdw zjSa>3zO*xriJ~oDt0^D*gu+x@+6OqCHb6N64VtHt;_RG$lPF=nqWb^;eeNbo8`9T~ zqd}c0UwRPqe;;dHlCA=A&x%h1z~>{K47y#0wLDh=TL1qFiV9ylWfXZ;5QF^m$r|Dz zaUX+==$*dSyL6W)VuAcDoFM+uL&|)l1T;hww7I2gJAjViG(q=5A#QS@V9%WGP1OG| zlzJqwdb1l_*Z=Qip0K{?&Hnxd#;CAiCINfIPy=)gAsLb@VW7(=^?8>>ud^W2(Wvaf zjlK3fK*{cwVy&N+vyJa2AbC*~7;)BB>->}I^d@JXxCCQO;)<3z1&h7?gGZ1=kI$`i z7C+kONOSiqU>du#k@@IlY8z6RjTEWsGYrsxD&ASXYDwuFyr=pKgY$*#Ai z8o#_wNET)}ix3vknM^*R0%Pjl@`-Mna2!ZnOn*2%QE?1Ko05s$)*>p3%*}&zy@fJ;hp+SoK@kyly_e@Q6=lz1J2k znid9v5B>c=$o|`xQHkov;HBbmDXzb?wY=Iu0N@A^5H#5!^D$)=ka4s z-`*pWPjeJe=8gAYjLjT-MP<^ayaL0!x$AmOBg?${9;3qDm;heptZ4j9XpyQ?yRsw4 zP@nt9PnBt#WKzO75*toj^coDtmw!(7L4$~CLsDLSC_WPZE{Q-4+9`q^PZvtQ8QwdZ zHvFsAViP~k8C^9B7xX*m#Vf=uk@+8(pCxq`dH$725Nt~Yr=6~sGMG8k zU0nrj5IBItJe?L$mN=jV9`a0cAa+3EbvUIRn6I@}DiIloevNTlI8pw@R$G(2GAl!s zSG2zn7KjbV$TLVM*x1o9Cv{q8dd=3(Cl#xqujI_6gtyEAHNi>A%k9KxLAYL>Cw8JD49MCWjMI;I!SiuciCLWf9BpG3t@8{+)xid2GZ&%>rNM zfStx=;j9%l*XIXL0%q6$w#Vtf0%fbt!%l7McT+g4o9yzOz>tL$3{Nl*uk!r0BUlG# zYoTs+@1JfsJgGyvQqq>M(aNraWut+NK3(80a>sY}cu3eh^f?6Yj70Kma3Mp*TUU$% zXDe2^c9F>!vWo1tC~pk1yP&%VBev}3+6{%YLC3ByO5L+E3#IW;0009300RKTvTBR= zJOExtSNylC1=?W|AsEktMnFNNwS9Og72UO>^d1qRacPSo)J(^TQyE;APgWG@x?<-EK?Zsr=sOCNSwc24}+KN zK#9qJ-%p^{nO@mAI?(j1+G7(=+>aQmf647_iJjH!m<_2TAKQ)9m+_f6-#^M+9Qz?m z_jF!k1}(`$jN(43m%yBF{h!m^jylwYS3DTcup^&qV*y%eGycL*2XR|(2$WGwT)pWx ziyg+ShH<4O7$akIln+t7(_|zjg56)$I|Dx+tMR1cD-K_p2ic3sT=xS1(VQ>h`=5xP z<5fAi&;Q{URE%Jhd<$69@fT(k6h&kb9yNvFalM^>gy5Vfm}|jyOmcxp4_$_~Nt8s9 zb{K^S21hO{zy)9zY@Re|suTq?;ITpD%vZb%^Qh1AG_vIQXKcr1?$8CGtQ6~0(p1hH zZ-;IDl?Ci(_qO{}Osi%wSA#@!uL#a6yWB}yCx*%gDl+a3BB_goroxPpGE)Q`Uh~sE zpbr=u{C_Sw!%I~@e4fX$o?I2?gvdO@ckUPHy@PlOUM0~G-08Z}4A^dAP^qESquN4T zFQW(B0q64~(gI1Ju$BHsVnwJj6$mH!yvkKXkmNz$dKJ zn-3Ya=$a18Q%IGI3?O~{r)8+I5LoVXQ6ToGOzK!{eQ=1ot=ZK2E9?qwIYW&G~tIUdR>Bevv*8hc2Nmkg@4m1 zdtBwlwG^$uX8@8n!aEQ{1q>`~ha%w-q^3-EAw730_wkpK|6WDbFayaFCfB|g7s%@I zEWiMtna3S(hQ^R(Uq9gz*mtsm-O%(>3$A(y)cAMZ_s?=I=E7@E=Zf zNknXxg~_WpciG|3PqZbgfsJcBAg;=nOq|%=9WC&h@H_<;vHmWlSvEW(_}mf7aoA-o z1}F~IQWbE3f*~6$oLTgd%RiO-*`7(*X%x2O$YSfsgEn5<+JS^b&9vRig7^h0tCbY! zE>tHc_u*2Wp2@*}UVi6gMtPp-+o{AFazV9U37W_no^wSnRu*?ojT2CLw%GRcoKZkd z8tA7hiPpzVAgyce(<2z`<+zT`J-;gtG;lA@Fc7Xku-Uq1j3Ztfr#7>4ZFdccQtWj5 z&jxz-;g(S&^D2lB5aqi}iBo%DCVzXcX7n#d!LXuuyXTaXm}~> z4}5J3k*bEEAYl_uZUj56xr^J(&>NmfCxXr82llI3^H(Z!rKGg5h~!|M?s6;tXk%>N zEI;-}t4Jv0GY&H@wAKjYYLw2=+Rhai<8+)pS~klPUB~>^E@Tl>QnWCD3`x&Nih*wo(S}R4Pq6AJS03m4-sDbfV<} zf)(+m?KP}#qn+$fVgY0EY`1DCY=R1p2wH*76wGzbHfAmAZ9>X=dQgRbtkm;^Lkwto zkKFpnUj9X=>}0|0Z2FisN@#|GLTUmBfylynH9!MHZ||QA0GEg^GNQ8_pyn7R`Bf9H z>>2K@v^Ru3qSbIUa_!jBSjS?qfliy(Hjs*Szj>TSdUb!+dK1=Q>0@z5^R;d+c9rH+ z%AQL+4RgA^%C_@5C+MJ>@NA}kB`u7q*f;K8m;b7j#%XGIlvT-N zZ2p{st-t1`6Z}6i)PzJNvS&4yD63ALD&@AI69(;kO0(lN0Sz~^JTDB~BLW!f9(6%w z<`WWuhJ+4-ZXgZhOD&=^l4nE;Z?b#Tn>r^tlmc9Ea&3Dt*+o(j`P<69fnUNu@tWSN zV(Q_AFX9B_(Dd*l&zg8sjL|B#6RGsO(9j^zG>xC$NLlQn5RUA8oQRp(OzLF+2Jb!B zIbX;JvtKpc10P9c_DZRWgr{EcH@Vr#RraWEPD(2!6SmX;!X=TLPUri{>;pW$&eQ@2 z)u}`J3YUi3`BtW!M79Im6`uPEYKLlI={N$_AtBf0jLC-<@jH32NNGUC+otQ@QMq(* zcZo}NK>Wg=?2LuA6^hA-;<7#7kEU5~;p-FD0a42L_tOoy^hIBCcI#nC!!2i#d}S6V z_E_gv8t27pP5X{BVRke`9M?5pB2vX??PXzOH+wRINa$bB1z992Md?_&vgdSHFulz( z2H5eO)5`x)FF|-(yLjl0kg^s40ETaRFCq&Mq#F10L78h039>Fnw7PnNb2V}a7BG&1 z3tKRj2fk^Pe0Ul09NcI24F%d_pq@W%0DL=IApax>x&S|wS(_|X( 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%0Aa#b@4_Ip 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 |negUn%BkmSpmcc2?+>y)--U$4$ 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�rClG*WfozhjnogG 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𝔢FM_?qSGIq`Rb2DWe$Ma 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�ES@HZlWaZ}eO9`k*&3c~kN_y5oo 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

}{9pAZ2-aFt!X|NU z{EW#bVF3cWn%Cw4PGN|wx=uNi4$|? z?04MrcoF~H_#;qFk9S$F$wFqchTs@Kjer<2n zc~w~zUHzAy{-~}G##dbL{}utc{=5ztpzNamF)$!N0K;e4%NIZp%p!)H+Hdlyd2vUz ze-LOKkdW~nKr;*nWf^GB*&1wC8qu1gX9HRnjPXSI;bpGgHLfpB*51tNe-G3n2TuA5YY9P3maxsHz>NavDm)vJMk zNn$&m3qz-yCk5a85`i$Vx&;M(cJLY3ks-DHBj|*GcyfHrJX(Fr%PnQ5eGKVlOD1JC zIX=gAYAgsJcmMdl(<%+RWk~Ac!6yQ(b5_BZ@IF4{5|}a(jdCR+JY?sc`~tdIz1RQW zvH!=CfeRF_|5piI*^f9dfwD{f#{z-?UQgjt{Fo7d+I3*2jV1;FAU0&MxT0y2%3LU? zBGT8!l>mTazrak|ML5 zRR@1%G(}9xxuY6t=9}c!rpb%ww7Zq{ZqHQCOs2v%ky|@HxewdOo=)s=!qT3R=|eEGbqF!chJ#IP6soe_3UT z!O;R`Bk*XQ;9a^QeY)~Mb*%YbX5{teo~jZY!B{`r_-RH9=-0tl60FpRNG%;-Ph7kb zG*+y*{g)^}06-Cz{Qp$|@$w@Z4}tW`|1$Dm`yAiy9{`HiznZ*0;mA5U=o01123JC? zu3`ne-7}z7TYnqj7;X{RfY}Czh2}#m>brBME&N69H~34AfVqfV{<#0sye4kuSwIP1 z#%;m1MThs}5-x}a_)92e#pl*mFN9s*j87`Fo-KuP;|CV#Na)SE0q<{qvp^Fuar;)w zgDCswVx5xIU@gjB)9E`oVIR&UGY>PK?3QB7<1*cjPY4ad=|$+>>*IFqwX)0Rk4t9v4CTzjhNL1leh=6p`-}^m-R? zN!Kpu*r*IkPxE||_GMdn(`ksAVIMdaNj(#u9&hLP=QaW_e*_utR!ihoOWJ&%fCOCX z%8a8ebkr=&qU-ukjL3kVK9n5alaUfqBVAO3jfEB?C1s3zrCm*~pLqm{t6;%e&L5KY zcr)MXMvXW+)<_!&%&9MijwDcOb$@|nSc|oXV`C^B$$J>`b*69d#Q1>|qH2yxgdB*! ztIsJr2R*i@vk~BnR6u}h5l`0LTuhh@SMhAtl?ljSLUO@pOrH9xrRn<#!dVY~|7D&4 zVC7#wdC&iEi2|U>0{{S=K-p*ipSc2{i^&>zG%#u|dm9C=(%;_^{P(>e0K7b(+5fsb z*6&A#0HEyi|Et}=h==JJt{-@Tw=V!9YLCK$XCw5v!O_fXP3xabsj7+tzjH%-B8Gnd z4Gdg!_OxeAvOuh{2{_~21}m77H-d}Xu6g0sr0p)B2Qk{wxqriDib34$>$R5DVl&Fc zbE(Scd(2bAD==+XkZ^5biFtrk!(P!YU(KZ~dZme2ZjMv_m5WzE)~#5Ghy270ORHd| zYCxSlu3fRSxkl8WDj4~;BxE-i4$W7otK@G;PQgcmsYLegh~aBxhg= zDZFsfrTWZ0ylZ%gUoc@OiYNlD7NpAo_x~{Wl~H+Q+1fAe9^74nyL+(U?(XiA;O-U( z?hrz7cPF^J6Wrb9{pjiLne@zb-+RAx?^?4KKZ>Guaq2ny+2=WXpE|`n1s>gO2s@;Q zJi9^neri|3R`UH3#iM|ux=y@T2s+cM2%=b^sv7G;ikoHxkd3;_Am~!6LH3O9VII}6 zhFw5s+fb?%F$>$}qI3(JaLCxzIrZ@gLfQ}1o(=DPgt{$J?Ub7rDS-|I3_5L*;1YWu zNSnji4|6v4{n^6#15qQOOps$6RW$}m!o4$GA-;~cB9x-^S^=!94D{zWZ};wdI_tKb zPPLUw7HeRL0nmirCv1-4)bvIw+};Xy!`Tx)+zo_)Cbp8RBT$;d&Nbt6ERwMr zJyA?_v?-z%@NZQW08kNldjJ524o{=jAF?ndk~{&h5iLtZ!1!^D@MwS@?40Nep0I9Yp8h*SRS$1S+}M_ym{0^t(MLi{^l0VJh3LiK4t z80C2YH&vLOBGh>48j7y9{cQ!Nx96?;FWa-h0wxru&pTSKM#?# zZZ6YBqjI22U*gTxJs$F6amp%$=wG{f@>tzO*mbM0cdaNoHmh~N_wsNZh_cfSypiZe z7g*JcD;*em!N@NR*sS6Ik#5J8hj6=hVw8E13h)6*+tdO^C7R>4&ZX?BFd> zK83}GuP*&hH~8t-O~2QBaf4(r{6>1f+rf6rPS5IcQ$cxq-o}*3*PSqby8NGx7kpo5 zHlRXjtbd>j2(lU_l|gy8x{tQqvX1c?`O9E;o;-*m9?r%sEEY!|DiOoCZ=bl3b2~=o z%!ou2>@Eav-Wzmto!9K!t5CtV)_r#tT zw|F!J2`g?^0GhXZRc3qsB5dFB)}{1gG!Il$#Yg+*g&Vt`iHXjW0tN0UZ8DaNVfAab5h?n9_f^Dz-t0O%`jOKcteW*%4B;+IU%{}t zwq*}ME$ZpWe(*GVS1OkXf!U&sS1$O5`Qu>{sF-!*IRL;pLG5?>N@jeaEX9A284UC> zWoTdK8NEm#&%XD`84!pe{z?(2HrN_%?>G3evnS49gif*#=VLeBaQ&|`Q$rRc)hiS_ zE-`L#0>QYGn$gh#*yg_2(mOfVgF@QDJl%4!ZbTJgGHV;h&ZGyUUW0{0*n5>)l(8a{ zPY&4KqXY+1+4pM|c7B#x#G#4%eblCy+ZRgT`;!zbvF3%c!su}x6Sv`NEj+`_v7Kxb zXCT$=nO$r(2Epb0tcL^%$Tjb5J+9mxpO;$i+{hU{IG2UqBpm#I4lpT(u z%s^406Ne%mgyK00xn&zuB;L5>5RdTUu`7#eGj&@JLjR!Iz#O_CmFzaZ@s6Nzn4{|K zPJ%Ene#EpLt$`$P_UEw*+(CnwSLnCk3SXtJgIM3u{J8~?YS zn7UxBS~?p8{eg4up{|e2OA}6d>Gdhg{2KVBB@V?kI-i`c<7ryZHv~5` zy|KZ46X5w}fcI{lYpE)BlmVGJp@|Jw>P>9A?~6Eyd@e{mM!Chnd4@EPctTvF@1K!J zG%S=YFpp6#V6$dv;c=~CTT`px`o0Vbrx>an&5EFrM9%3YJ)A(>XbsUahv}jgMsv#> z15CaP89Y5Fe>(iM#?W`0TUP3mU3R7u)p(swPz(@%CQ>Zx)0AGdG;VJfBK9>aN(C*w zS~6g}WT<*8C2b#SP<^8&D2u?VRTeVvg=>ZQ;(!KnUSbRSG|3eJ68UaNjE_$erbJA< zJW1aMKA!Q9ZT|L%Jp|hy~h0w^*zA$w~TwHEP|WJ zlITXsfX(Z+puiMkui)$`f}%4oSjZF1j6K@ZqFz-N`9AJ*Zi;*;4HH5h5I zS6uzk7X&_=RHQ>MP|ZaG2jO0=4x)tpO0vv9?r?BAkwY=0iq79I41c*u#PQIWp(Fs$ z<*nbdN zE*?&jV&4$F1bQp^u^q!s`#`z#V~yT-r)_IrcLmXsn2@K|#J!fl-hg^E{1H<}(So5? z6SCbZ`GsdQ`;I?zUXUpO0Kf&3Rr`DV0t3K+&#qogtLQ&&m0t93GiU#~s-`A>#TFGL ztNtJS2Q1hy%8^ z0}XtE;+YD9eD!M0weBvx)h6X*bDP7N!H#>>n`oX*>-kg(Bg1vu0%`-8S-y9HNR)Fm z)0=a0CxShj&;TXgz{s7zP!E&>b49^-){yamqTv=n-H%;`PU6^~A6QNOS%d)%pNDa( z;y>gg5*i~qI+;x+$k-@0`O&ln(D#Kq+nvIY4m6i|kyGP^Wa@1+oA48l zar^K;9R$0JG`$GD>1SE&FqcNlN^&;)ar7JraI<-KYW~3_Em@v5h17<+p|8cZ4Cv0k zqfNA#q>DLV#C@rA>EoTg=U^81ZX>*jL%8Em&TzPFG*Ak7o9O->=7uGZsGaj@YOpSqpnpshi?oHRS4yVZ+{ZP z>V(cSA9Bxq2EEUBnD8WswkzIT!l(n;vciRB(7``~zE?10(xalwZC|?1voS7nXxxnm z;NMbc=WR^WbTj8iY4XFDS#YE+KK7WeuGaTUXvx(oNq7B2sZN0?9c!Om>o({hDgXCw zszBfR8TeBom_^_?h_cZ%m~9YtDqGa*-RqW;;ADd~U)iUMJoS>I|S+p#)L~49_T=%&__18!DhP_H9$dK8X) zh#(P5vJCJJYi`gx{T6U6=8p>Sba?MC4@XaZ+P`A&j~MCWCU2q*gXQTV$su>T4I#4{j0=jvw0p4F>+XaF$3P^Wc z4A;wNW7?=y6VRIujfH1MM3otEnVh{MOzDh^<5mOqx&}{3iL#_PyH=R$k;tP+DJjG| zBv5Z2Z|*DI!($ei^Gd|%IV27J03WRNpHi&jHK+qVfn?qPBWeN0jG8!~E476(U5RQ@ z=ez(!78x`h@fJKU1C>yZ`tMYlpyPc6f&|yIQp8wd4_aoUz{=rf!mU}@v)=@eQY*~F zg*jcrmjtlza|lnMz(w5WFE;RJIV9N@ZY=o%`Z)X)aK4lKsZx*GR2VY;X~TX=G62{? zvL1hmh=cx;$HQLJ31d(hv_^kw2|n`bAgMxW>;Doppb!Ay#hJw(C>LrfkWdX<;W`sa zBlTOKEIxL!cPgs|(j#_he|xg?M~E$~?FiJ~vcemP4tp0pip%^yfO}6*iOU%@JiX{e zw`@j9i#=JQDy&;Rh3btRLXOx??z3iCyqS$l*QLh=OteEsymwU$K#Cfr4AQAwj7RoE z%{;opF6_NXy}FBW!KU`g1t;Ata_>-h=F8&iXN-a#639O$2cMz*Ovd9=vCQSzZIjxl8i6azc) zc9aGPS_J1ZhKZ^v-+(WY$++fH2z~<+AiwVY`l{z+D@0;%6Td=aovf}qIL2{Vg*=#F z$d!D1!$@v|irrk%m$)6F5i<{^J3k3df*B2iPvl60*(3Z8q#fo3KjDl#UlvWXs_QxX zmkvWFvW|Q0R}P^}f zvVs|#djPDPdjke44!On(!l0frVxgh&N@5vIru8Ebkkv0>WX-fHSiS(< z=w~v%?}@9hV*0PGdwus%_zwX7^#i?Xzh4mewFLZ^m;QvntHG~T-2bjY%2GwjTo zy1$?Q9f;p^;(!0cpB?40qFfQMgjAo9;s4jPt~xqL{zcVIzr zkA3wP)@V(bBf+?HCS2z=R$s^f*Xx7z*fUMNM|M5f)mJ0XmMn2ZR-HVhX0rfka4UKYYT z3#fnb^E(WGPs{w})vq`D%^QABW&FkMe>brE*E#>cj~y4XMf$keu%K8RuVEbww0t~( z*k`1doFOn^vQ1se%Hx-lnbSnRH9a%zAFa!numI-ln7TADNPJ!x)q3aFuLv;zs1W)U zhd)eZ|BF`s%8H+-cmIXKZ|?B(lpL~ti(!_20P1cB$EyR07rZr0v7tr0khb1<%1wNGuCwtAa)zsz{hxYUeFf+7UY@u zD+qrS(tq8=-$3|TE&jE^Zy@}v;{Iy`n?DzC|85|81J3Am_PT6VF9$LKBqAJiT>f>} zqP^?#SJexB(C-g=iJ_J^Q`XR^50bsA~p2pu$_$NK`*KPbQ zK>n;l{@UPI6#j<_#O}`($p6ns0WkVuF5I)FQaU#bU_}p$*@L(ourH@v7^>HQrNpki z;IBCR=gErKf#T;yVZR{#??c1?;z04bw&?d7`CqgAm-zLYJNzFDhgTSWUN-R$82%+P z{O=7EKP?sbZ^Q6^EE`@~@yELJpLxUo>Ok>R3HC3U{ttKfzt#=*|Ee2a7be)65}~4B z1UNWuH?|%~j}61+cA9qP7nD~%;(p)m0Dx?swxbPmHF$T@^2$kmiav8knEr)MOx(V7 zLj--mo_M@f8UXkO-gO?poa@sj>{!el+%FfXbHD1S|4ijz{;$db09ddp0Kmvninusn z_LrfDu`2>7$aKtK3vfua)R;0Zgv%RHJ2yZ<#2fnR*XZ}!rFLmHaLb4E^c`8TfN_=X zoOsB`9<&!4#|I?uR|O3p)g$WnD**p_l0o}lBm)GTm)G58m;&hS%@=5Xg9E|=Pc^8b zn!i0Li?P$7d`t@`8ht{fxL?QL&f(E`0sz|I4!v00VLnSjy^f_|V23>QLuu}>hrjgt zf1X58|ARyTRcdH|B6r6EHE5f&*g`+`1pw~g-Le_{Qm#iWLQ(dGu=YIxwvrDUTx0e} z2&V!yzdrX*R0esYJ@nCcYc%C=5Bwjf2F(AU20-Nx(+*?}Iyy`MP4&B|8W}P zl=){30joDbTz6yR$8@7!O6w9 z%|rHSYR+sry^`9(lepOf*1(2zGYo;p164#E)r>^ep*@#c;T6ed!L8 zvXJ;`UK^4x8kz9v!MTvL>8RjU@biYG$E$O3wnplxDKk4C0%8?|G$9v3^`-*mG;e4<9{)ff zFU0Ljk6vl~QzD2H+3nA}$8v@s@*90=GC zv&OT}yJP|%l&6g*G@wiq(`dtmkUJC;={@MRwC!A)Q~A(K8Kk{7y-O%crQB>KnfVQ@|N$lb*Ee9Mb73`~HomA0b`^>Hd$i*+MO{BYS5W=l1j#< zZcs|q2a$APIpJJ5AmtNSKF<(Qn^U(T4Wc4pbNh!}xNK#$La~YXs%`Z?PUH{_`G1)* zL1J@dgL#7c;RZ^hb2>Tu21ym}5H;T2kS~(kqSyEL*s@=o#Y|5s=fl$hT#TY11B@6? z!li7{ku(XBhF_~77o>zk(7`+MLdjHIO}u_Ds)xUmp(*`n8`vxjzPGisHAT8Msv6Qe z?30^|v^ZrU8>>jqw3TneGhjQ0e;AxPHF+lC5Zn6TaH}T_9}i!jL{2FQch>VwJr|}F zRNIN0ILKq2De)@dV!(6NN4K#x1_*R6*mUFYwZ`^G9_PK27(@k$=GBO`BxXdm34kOE zz}PA8O;p4-eyx1(T`{kO(~9R7g<+gU=V&fr2I6e(5>iFIlVA+zEE0j#pEnnQJNs$` zeGWwqT0rmXVp8ct=Pr_bg0t`tChTeWSk3D*tH1O)o0j|9n_l2tU~LW@mOG1wMQlp6 ztp3i17X(YivFx#ey%zSmy@`82H57N5s&Y=yP8edkFCmWq@Pu%RsCrQ&4ASU%Em!J zy(`LYQSTT6^P!q*%K9>)M!K|n<4t40i?b-|lf>`J8JG2_|@W+yU!bWtJaC#spJeM*kVM9&Tn%|el3ul?K_Gb$zdevNoF zC4#?S;TjBe*qfTk>hU1QcX^iE7}oNm@`s0h8v0L!rQW`bGK@I6{j8rR_N!-xx$?~n z(2RULBu*08KmXpBj*@eKvui)OfyKHbpW1_w0HUY>noD}!qX}t8l_e~+c8#XM4j^c?5;M-p zo-{Km+0|NjnnF$IyyMPr`s(&Q&|mw?*pD;a2AJk5vK0PF;0&CJTGe}QHQTlEyPvx* zV}s7jEZ2_h7@o6*FKq~B^*{$cIp_HsBD7p#(4fFTBzvdEU=x`fv*FbcQadChWG-W~3@kHy4t_s} zxi)8H;_X>oBLU@J)a2uTF6$m&yoh;em~CYc1Za%5JgCHDhQjskwK`cV9-hUz8#Uas zQud+otWH@H^ctsPeniSAVGM{|Y=P#Y?pNOpFzRsDMl?&`NG$~mbJO=!7t8N6MPZ`C z$lIlyyA^=}?`w1Ecc=p~tVHg?fn&0xhW#ej#x2>nfv{ma7%h6Kw@E7bYt zl$DA8a=SNt8zA-P@#0m~lK}>Iu|V3S369x@1LRrGPok6^XaQKCdrl2Abw@0M=su2R zFhroEMmgo#%vaVtb(ZLhRkhsnST+>;zdKj<*a#+CR!5~ZD|krj@<>a?gf`@rP3j|1 zyCXV0qM;4pFJ+6q8=OhNUM?BZ2r5c(ejA<2?F96rg?I$cmZiP)`c4v#u8QfbxcJ*Y zeGEr!vv69P5el422$rnlgG+ZBtWpsqwF71ew!>%8OmBU<#I zDEUy-#kB_!*bL`>{}d)HN;ri)H4cw__PUY06C^ZiRmz!>w;V%8dg+(}(se!7)TenQ+&+EO0cFOfyY9n}*Qfuqr>*?#F4(|=z z7Sn_U)v@fTbg79&ZEN#KZz`C7Xr>U?U-4_ex^fB%b@Edtllsv(3 zt_5_i8}AP+JW=OWA54_uiFCe3NJ!}_WEEWOg3d3)Em!L;Wf%mS7NfeGwN}@b z;!dJ6D!oaB9r&QHp8{ndX*@W73Jk+yZ?&Q*k2V2zH@-X1;O>Q@h2$SI9nG%9B5c zvJ)(8Uqo>a>$=D=0_07c{8}u@wAV+UWRD5GhbF>0W_&K1COKiWO};oHB{f$OoK1;9 z+6YX#>@)C5SQ7OC7#=hu-cx11Fvldbk5^eOVr%vpDrtwq&v`CcAT3kvV7<7)s1g7W z1L-M<^lq;Guxa1|mBlq4P>B+8Q=2|~yHIN(@(WK05 zLSc>f?-S(48Hmi3C!;sKedtRWWfpG#IxbYJ@S)x%T?E)CKEWr;qfZ#6ZWTIGS!3bz zK@_{K6A|PRP+E?-m%PB@w6n#vGhuv981^RJtojmg z_eDHwzPTAAHqQJ=U9Y~nwGFxXzAd&0trVPAh|-7rjBqz@S($dC=|@+K2R6EPvzrRY zVeid@7FfWFz()L#G(2$?iHpxovUp*}8B}nUeOfSV zS`_k4-T5$#*PdF$vB>g1i=X5PdD!3%G zj-hTdXSK&jp(BwPddvVZOB7&t8R?lh@YVyov$5LaZ0ZT_kFx$7?ruFfpg~X2e&^Q` zL&J)V7v~*17egFuhUG%1V7%aEXfwsK{!;!#>I@&)qX=ZXxbseZ)?>deeHi+Hkak-$ zOx5HXnt8`Epc4xcJVCfQuzz{awMmK6;Fd4-?fV;Wu6TnHQrxefN++EweIQ__kED3o z`*RaL1;{zOwHY5(dWe5eJ7<^&+1*cM-;v)r`^Y7ERW>GqBWivzn}Bxu{sNH4zN;V4 zR4PO))N@WfqRSscHPVeGxAr4*-3U~MA4z%B9=!BcqZ*YXuP(b%cnn6aH4cxwM9CR8 z3sugil_CQnB%);L^VS*->9@*E9+5dc(WZ4T@R{#Ra^B>dtGY4SC{ex6Um}5YXqdxXW8R=&X|wLT`-UwD7C2$w9Dvpl4BEsvf1TML zxU4VL(?8B-ZB(OhJtYvp1_ukgDv7=&qBdYUX6Y25TWxJQ#gx~cXWjz+nuB}Jv6b3c z5Pb@|W^pl7PwaRp^>t_sB_FQ+^GS|FN1NqJN+JyDI#E6F7I>^6Katjy*^?gdoy6#^ z3gsK8_@KSDE>PAv7hn<_t;4lM|0tnBc7?LBccc*0&a=yPdPJ;_bC2?ARZt27Xfjb6 zhS<(+;kwYMx;BZ^Nv)T=k@nTpY)3r|oD)i>L$h*27G+%<8m#IFlF;R|8X(8I!eRv6 zJ~}kFuUc~bR8Cv+5-)q=9bvxEiw&P_LH-$?)Gf!7EfSh7@t0g#u#WbOfm74 zC_Y>nrQ~RV>CX0*Br1bA86uZs;7z$HZo25x`OL3Rv$*tnQ*0`imQhvLJ$CDDo|e8@ zrh~a!1Gt?7EgLg*&^0qO5qK_dZF|)byY$Qk;QDc>u87OJm4py<5L+eXq*D4YOO}T@ z8=#TyemH5$N#4mEZi5AcCw&SWELKZ&E6q|}K)B>le`~+AUl6G%jW5hQOs1(Ht)$d3 zvWV4V?RqI3SZFSuvvVyQKJ#UMV?i$8z#E~xws(p=+H5p{!rU2$w@5&;^ahJ-01uBW z?ctq$kWa4P3~KYxWktpe4?r@=cPoX9LO#vs!+c>U{0xc5O4}tnTjkCb zN*>Het$O2%ASf8sNSBf$cs1H!GHAjw8l!J*4jg3KyIk(pE~^z{7#D2mqq&PTUm8{; z>qKgZnmG!HdLK^fbm>lX=0i~;r;p3dyaIK=JSU-|{10+ZB%C6EXRiVd!Xs^ajT8sWLur8$VzOItgw6Xk?4AVKe2dT7C8F%p3& z5oT(X_y)R4AN^Wq9v3P-M_ThfzWua|QuGMb(#}p8SkD&61X9#J)(w$Oc+Z+fasLr4 zo$oCP!X9}qusaUDT`O&rX(3Piu;OYt`jRC0W;hRcXq7dL9S7LfeSNQz;QSL5et9(K zlNw^NljVkjofVTxNb4tT^={NwYA7w*9E;D1N_wK--Ee zpJpr2wDyB$o;#&^l58|G+c^Li%hxeFvL@e7@O-^9m_U z{3bw76mJto?rdq)0k-97|BC9zJDmqQ{!#uOyd_UFjN4lPgAKXdK{5!Oc;l;VrV@jFwiW~ZD8l8mcI*)}1XJHzaF5Da zuc+G8zEtNNQ&=wN{gq}~x?emwh(=aZ21~aUtthe3RL^VgOU86$0lGJnq4X^{C;r;S zP7c}344kbN5Fa+Xz9Stw^Q&45eP3$-Ho)h&0JZyzcr|&RjTMb4sY_wfaAPLRfU_wW=R8xMI#a`N%of$^3q-b8{me7H9maQ#e@vy~?SSF~+3%+8Hf&QtkKPvy4ikP1J041` ze%?iUZhgOullz&kXFaC8O%h?XjM~)VmXrG^eY#I*zS5S7WI3wUD|4UZT)r7x_?~d+-WBhQse-&(O!%?S5UkbN zIo*WAEhddyCAD^ZJvb;FHTI?%SajxfC>Os%wnlJ7uR1qh#i^FyI`dVJby~bR#f1P6 zxKWA2uUw3Z5IfI-dH4p(ytq;pVKl-9HG-Tj#w-qm8?hOI^1g`ET2oxj5L%*6tK3Am zfXGim+v-8t@oospFa^82PAClWf=Y4NLkPO%n;mJ4>zf5sDLGofZZr`Ct0cuEu(3VZ zEkwDE828)O8cpf*((WAYf}#?QCS@8YiP$xMCt!r?iIlw6H_k!X)e$*W#mRCBDuT{5 zXhs1F!Mll_vc*LC3bMEGXmw>AFiCbhSBVIMSnq|Wh1u?$$gQPG?{mja3|&liS+jeC z@@B$smaTAlztP#~yT0zcaaVLLA`5-G#=RHTM~NGB&hzKaX{2sxN;DnX z9-~Uu*NmfZWHC7Uv1xO}+Tbxa!62yl6JEph8J~ku$%k*Gy2w>3T=cZMW$aGU<%2zXw-Hs<>i!}N)m$vJ0$Yz^I>4=^R z+g{?a6Y3`?;NVJqUGMYnDp*^)dA<>(>V-knF6sVmRzG0#84*=0!I^#9@*vHcjqtX{ z+}RpnRx;%_*gULnym5s8qW+-GSredgqPe^*{9alDgk~+u)8Rh4`Gbb)l5U;L-_!&>yJ7-^PMa_A+{o&0T95xqC7{ zv8M>rr}{uz*{|KOB9W_}tg=eEJfn(SWm}W0ZXVpsbm&$DbMlsYY!9t|Xde*5a_ek< z0=>X9z>iD(;LR^4i`JVrSdq;|j3-A|K*>&9`Zk)qwunv%{c<=?qCsq91FdCy1o7$n zdkU3PQU{Z6@i6Sh+zjn7WVz0wD}G{VzI4g2gFf8`W=LT-%NyK#8ai+(s?T?!IZ$d< z*0iuriZOP_@=e&*4M}N2gM$ht@IJEW5|;; zUU+i96^pxRj;{Ld(U9ID8xlTH_5$rJ-zrGTYGyNaX^o@kDl3OQ+H+xL`&RW@i|hGT zqrp61AIuEp@?00#m<6LQzaynXCWmT;BTf()W+b224978$x3vj8k!4wdeSyogUZ?W~ zfmO2c*j~UOC=ggO)2%tzlS_h~<12NwZ;cIJbOsqm7`fFYGc$d&T8Hwa*oF&M%RLu( zS0L~qvU^x3uEh0fqGUJ!3%vZrm^D1)7d_N^ zgO23aR~6QrFl%t2qb^3g=V@lc5HE*_ZlM5F5U+U@;EVaWN_ZD#QTCOCZCOsJU>C42 z!zOhb$hBj}SE`v>plH^}xQ4DX;BSJAiP#-pxRI>&Hn@>^&LgB76+R|Vyq|w@^~*Mf z6HADGAS27J#1}F7g$Az0B_o+PK0x5zJI!j&faf15p?K_DXK=1xp@lIQ27-G`g9?09 z>0ag=J4Oeu~^6`ZrMpZ z%C=94h=DiCK|XH#czwpctDvr#!45v2SPzw~)Nm|x!?)%6`{Hefl!1WH?3RyT1=>Z0 zng?H!5q~r;dpQKX<&l)9n-Yor1g-~n=f%DsZ?_FOWCu9$eB#EafK7(>cx+!-;}9+9 zh4t=%dMvjP!y@RiA9Ot6_r!&QmyNr-E#Cza_zL?X@et@BUg_11>U#ODfdx52oQd`W zlUkbzIc^eD(sU(9xN^qfmSm*Vzo4_EGr3$6=cP@3%r<|}5e$PVNeRbDV|K#5drR%j zSlcIKx$^@$p&Xt8W8mrgE=M?TISEGf1Bu?WH;x*dw{aLxfE4%lZ23<9?5rBsXBqX{ zugC^mkm^WB#h22FI`$p5K`BB8uU-IrgsKY4uPipmod6ea(^*K~|L}Bona*}MeP&W= z=lWg|(Z_hzL{{A`pR31g!8)8CPqkjPjgVS z*Y-@+s^Jt{t8~*@%mdAYKBs+LLSDOS0xj|TCX&@U_;l^o{=1cM7yKD33>KL;lu{lH zY=fRy$b`L*joHhee(=gX!tBIk>6b%f3E-KAQ>;nVKo^!KZI36dIHZCcfCN|8HrFVS z$31M|!Q@u8K0&Gvcv6Ud+o38CAB7|W4R;k4J>hLRRvc2aD3;;P;CL#Bkuioz#mP?Y zDoW0_m#Phcs2WLy5Mpbn?B)uGdH0^@LQm=aVI@7Z#hueDQdvceAB+U}3%||2z9AZr zlPF$W0F=aVHs4rrmWU#2*$D`BC%ECU7iJ7Jy*?(2;8$@$TBG7qpkh?XvGU)7cn|5V zjIIgcAJo}KH{xf$2^68tVg_G96JTFkwtT=zT3Wg0bA#qj>|>8xX9QyHP+^z#F+QoE zRvFVwA0U1WgXYfiy4>r=r93nFAuf%391(bHa+NbTPhmAHXpG~Hq$w5HSaW*T9Y!}# zlQWFn+a`3ER|VFgK77B|2A=G@N%O>vh9MNw3Hol=q7#;8gaIacI75O?R}f|=zxf0d z=ljBZ!v0?OX(Byx3GQ2dlMCI+cHx+5D*;f__!44^6Ztuj?Fn#A+rt~L$* zAe&_l#1-%RT&L#?1uza*jshWKrQTvVw)qXzGcdN=ND#mlJ{!*^KuvwofxW0@89Gn@ zmR*>X-%{GjL3k4PRG+rfD`HNmxY{?jW4cwknQ{QR3Na(tu5wsgOlltF-w~_l1GCcF z<+H7>Kn6cP!6W_zTD;qS`7PoyN96*gVJNwM_IinN3x75Vs}gP6SXVn%twhvPowZ$; z6+5yxttE~g&iEu4j9X;3xFuJ7CX&8zL*sq|;3gt?6615*L`D-Aohd~{=E`DzgHB$_ zWQ3>oRm0t|_Y~)Dc8@TGmKOr1t(w@^7+*kgxX|CWyQm6^;)N}BPgX!Jfh-A|j2fS1BIn6BLzAaps17Eq(*l-L(ip{nXY6-?^h_V9>RVhpb-T>Nm zf5LY(;yUgau58{pGqo~Fk2W`9zOHrQ!4JWD_?Supjj79?&aA7GN>H7~X8doU_j1>) z*aD)`S%TCs))yc7G8j-W7h-ju++k4sK#g3RtQAEQ$A#X~>=A?-SDEXq)9|S)Nm09| z5czP@+HW`=GAH9l3|Z>p1Vlv|pQB1s1+{p_XG~Qd5v)p_JhFw5NKRbn-ChyQ@jQaP z&_IQ6A7|8-o1__!%_)))Xg{T{@VJx8kxtwU6D_oxEyblpZ3u+0SbnNg!qK!`GQ1nH zKd-5#W+0FL^ltI#4%zgFXr;|uq_-SJV%qEm$%E`@^|5tY!;Qpys*zP}(QS@AF~+ve z<@O+>X<}`clevjqvCz*dYXPZgo!`g5ZVgtThQfb}_=+kQva)VpPLDg|F&ihTPptw@ zq0Qz0So472MaMy}wGxq-(LE;vF`Qcw7w$P|E3sH=T=1yio!+YrWyr<-u86|QXeYM& zJ$|?2*)h`Iv9A?pSNqG1a3uKm$m~$8f}&V~K;F>z2rzWT88+m4wsPM`nQT*i=aKsc zN3qNA4TN%bJB%IJtWRSzI+}bXtLjCcYc%?>vll&ab%?k3hOf18VJ^Kin3H=g=WaCe zS-93=QEeQ53tzDpt^Fm$?MP!3OIX0MZrW!i>&p?wScfi3gDA<<-f=m ze?G5?dv}gW8A6W<7(%0Bb}3~Ypcxx_!n=-$We7MavE)$_cB*mP zee}IvJ4fGAP$=F1#?67(kkK^mys3~HyLusL>zM2;Iy%Toyuib&{gD|?BcQSYBiVR`cRVVd)+=gn)j(N-*;}lV-S#a z;gcxE(YN4ZxAm$b>M6N?myBM+zj?_+E*>5HSk-LTt>JaB=T%0_1}Yz*C{%qPa9SpF zZk*YLxo3SOv0@Sa4MBVRCAQKwkylhYJMTfJl>>ObQ&)K?^A%<8c99~^3E!7!@qJ48 z;CF*%H%RU?B~RYCN&n?Q%D4If$ibgcv~n~puPLS#*1v&_rR^`y5NYBF8d2s$V1kbj z*G)_$rPaJ-Mnp97yxsd}7A z%M+XGKe>`68W9D4>|KbOra>%OcbMt48Y~g-0Kz`|N^PPgP$#B@(91y+@1aG*nr)je z@`bJYUB%~X<%9`^f!DncQLgs^-mxDji1M9(>?k`BIn=}^{OYR*^?pozg*2Fl3aDlDMtk1?Sp;xG#$-8;5&CQ2oeelAQ z={TGG1_A78mc-^y>&0uk2%+@!+Vmo*y&owCrah3-vBLQ7_vGI%1?-n9$D9R~mXg3` zt4eIDa$%xUN|Ai^C?j-Wf2t|Cg(14l6agQ`k}@s(sHtzvzf+_TAD*{RSKJF9>cOrY z#~a#E%oF6uN*cc5ic~9!zkT?shJ%Q< z>G&w_+C|(cyYdY!>wJtjY~Z+)oy3EOD8VNd=r72^UY|=W()yyC5rw!1q2(UX13bjT zLQ9JKQao{H!{qN2)3W;UWA|NiM3!-F5D{iy&N;y$sxbN*25hcOH8xE$M85s9H+gs0 znL*pz8*Q__!mI>Rv$s9zAS(B$!<5#cYoAYQZn3cfs8Q75#gqA68`zkUcgmpsLi3}D z*RvB7A5q80+`AMPW07818myH;z{zYckevc&H<+3fF=+gjLm=^l3$5{**g&4>MNmNnT0t*U6MzipZ`%ko^0^^q z00J)v!@8_pFnnny*uui7YDW{u2@dAkdI2lMg5iBWLR;eBBiJ>s!V_jE zb!+rtd~QA2RVS5D(B9Ztrb|k`Q7N|8X zcUByLz%7<;8EbnHR>(Vx@$9dC)O5z&?=-eI90%XpGz4mCOp_yB9aW@!S#pJAqm@KF zANtaeph^b2Bclp>Wzl(^Cyv2UD1Ch*W&`Fy6xq-Szh+70o0OcLlpl(BsLAGkFo*wR zY@^0GXN*F~%(bzmH}^{QDNo93u1>nlucF#KM_$}`aRr2*E9;etp)BZN^MZQ<{byu>;WU~y4b)C1C(ZVez5tMCmTq8hAPx-zTlxxsV2;oj<2PC*N;#hSFnGS+|AD~D z`*9NXaZg%b9i39+G6ARH<6W`9C7PwsvBqvlqb{=uO0iU0>N!r&5^6z zg8;i7npC>Zf7H7g8>kqlLHQ($-R@jbDd1l?@A0pNGx>e0^Pp@9{_Ejw!ilrFtj%C$4lS7S`2UMd^koqe)Yd?t^JO{ zZ1`>xx;jy@$#vV6hl!+{dRIc!&Mm<(%*>Um=5Mh>EW(}JE|NrZ*)i?KnGaG-DQ6f`VkAJN#ugGDPY)1NKWs>lv>tvFF~$w+a5>yq@qF65EYo8 z5}ty%CHSFX_r!T|6m96xg)WdJ%BoUX3J&uv0dwfCRz{HMW{J4d2H#{dkJ;9PvsYbmd}6O|LQ#NOz>F5gSh+qP`3R|**n=QF!35}@rSX` zdXm7~ru?oQd^Nqk$K04>k$%gY&N$p|VgM7$%=Ny*?n9UB@JGqU6CT?OKI$d$euWfC zR)S{xujKy73n0kIZ3s=;cV5DBvmC8+s@-O^nhPwnkb4(G2A=JXf4TUGEretf2D4W+@&=fJ>}tHd%)#{y0Gh^E?Fs3PMfsQDpDxBC$2N9Zu5Syj`e`;e^U$Mw z>l0SOZgo#mcm4+sYph@5qkyyTRCElT5q)CH6s!FLr9|GkjeW$;Glw2G z&!AHd&MQzl-GaV7YYNL$!~__QTsbpw{U@C5ccqw3fOxJj*89~1Du{*LPnw#C+klVu?iKH6l5dfv zoiT}H?EQ$MiGg<+md^V5bO`}36sB~x#AN-AseXwbPoj*s0=ihxDj)QYfxknv!42F^)V zfp)PF?$%*J{E+=@d}!)yU(a|vu0Q|)0{{R9g$@ng+X`%PcXdFH(Y_x$IvZ3>0Rvx? zLg>ctc*yh*p#>j9y;bl3J7mR+DT=&bvep|4 ztH(R8D7#Kt^wxJ6$qJoYb-g>k1g?x4Ck(MVCh|=g(kNWE2?*^xmMK$9AmxwWVR)g? zH9jji-6u(@M0FDEH#JYZfa{+FT%(U*!!1mV?DObYmT2~wqp$u@Zy9)wc&CMm@qhI3 zYHH1xF4p?I;2^T}k?l*N*jkBOYsvagdXxYE%7T=RdJv88nwd(Kf0Vd)MJ4wmFIVX7 z;t|XiC!&)c91zf_#lxJx?K1`!dYVji;PQl*PttlfNRt2?+p{S@V>ORHSqF{gg!{>( zWU(5)A80c7EprUiFtPnYqowX@21peycrnT~*$BJRH?S5l8Ie+u8=6w%T&ronyC&&x zOa8ox)@upC$LLg}O#<3(yfw(vi-45w+LJoPg=(kH>1L3Hc1RICRL0uMzu+!dIo2YD zMh@TnDHE3Kjo0e>A<8iTPrbEJ#_{V(iGgsYZ-3-|N<=hf%2uCTq@h@aC~&1MjTs+pgAS#;bO%umfLr^* zL!ES2DiRw4n5RxvK$L+9cL4^!Gn7EUg#6{QZ)+zpd(vJ#gJ3l(dON6D&LCrg)+rij z$m`m~ccAWa5ODwXk~HkwHU-sz*@NUS#4?LKfZfwVir(q6$Uf2D@UM*W*It(pVTZLm z;}Gz-97<@uD0?Yu1|MOUt5geg!U+E`M{@Xs-$qPz^k!jW+FywYk(-I>Nc9X2=#wG}PF49fL&`O0jlnkFZ80y1kS~t7u2#48CHib}EbaqkTn&AE zwh$Ge&sKt5(M$q{Wt%Torau#9V5zb`RWTd8e!I^GWm8#Iz;zJ3L=qCJUC>QVpgR^W zJuKjt%A#IX0Qhvzc@xdF6@>3LqJnJ{eMr&uaW(_4jsP=VHtl<4g85>YH`2pm#Tt@v z;h(z8qfg!69B%%@T4r+l28oTl`uug+G34lZ;w7pRm3i;ap%i9W?=FSgh)z>=Cu~K} z-|IREic-$@&<82ofund4Lw1w}^6J@d{NU*d%yY`p#`JUp$Q{-Q;Ayq$g$jqn)ezX{1qmnfJR()!2jE{{waK;@qIQ>_Si|ADdjH1v*t< zLEC|IAs_bt{Ihl8RUvti zGcRWcC7X^C(j7)HhKd_(<2x|6Qf`*{XTct;vrs7J@8c>liw^>4ru{!kOmue<$aa>< z|FmrWl2p}fD#{C(+CNp`c6w7>$d!)laO6{oWGe(sZc4wwbG1mOzs`10QVRy4fwDuH z8!p4;$(!V`GYH+hIi>#uw>c$5`xFCl&wY-^5VshCRtpdTg`1o_GV2Jn@jGgzH{j+K zY+G!3gX>%?gw@CQF6Cec_%=7OOD0IYfywTA8-=I`lVL~z^TgbuI+oqBG}LM}l*R@C z>0ID$R2SBce`BHfLDoJw1hfRSckJG-u{EbqjZ!&-(@>;;f))!AS zXoVO3L@Rswoo4%Y#nFjzoC~kd^VJ(Eules7ih|(W|02xlX#T|3J@nu9iL^cz{sSPt zMFAs`AYU=~zrn8u!9g^Seip=h&-jbz)z0g*H{NE8Xdc*c>hM#KP8QYu~4-CM`&3Sn*}!}BUIR_h>4_??|`xb>0FykQ>U ziYcB%wPIE^H34Y6KF*AqW#vks12X5#xL&;AW&h>*sIXj_p%Sv_;3QWEBmg#CSRmu8xBGZ%c16kyUiBZf;Q8xc)3*9iRO zHzu$-wlzZbF2rzX1oTp_T-)Y97QD;lc10_C0H-lTA-SQNfL>x%DV^CCsU@CIOMq_0 zv05GQm$kmO`S>Gm;uU!e-+pcz8)P4V2>OH-qQDUoz5c6@@3%DU!L_~_((f%n#11>M zJd%L-2LU>BNohCRB8gsuDAWz~E!v>!q!p_qg`NL6#Z@{ody1e<*J75J^@WUoIqy9{ zg?~4efOYKb-Ct(%G0>Cpn#&hr*$CeC-m|+B-?uv~iMuHaT}6cWOL?j&|DnmU=5~;I zXLNS^BSyc41346r2*~}KnQNGbr2=4z0~jlk@G%EI?KZFMMsi1-cIxgHEd;j-g&iey zWWVW?o{=21QA>w>dR+30dx&6uBj){*hXT!XFxc)@a2#!ZXpm*uyV@i~u}pd>zhUN+ zLu30PC&!BUP^bsK+N)kN6`8Yhp1)|?XoGiipH*FUC8wDwaG48HpIj@81=nTR0H#}^ z!S|ala=d@PMw1A|-StZ(O$5hn75wyThDmj=W?*%qpa+TUM$rIj`9m1p#=t^-JhG(K zxtBj#y$b{nhUpMgyLGW60+A0(E9h@q0SA^yDIAFv>iL)R?3Q}g33TfFTL+Pv=ieP4 zr=yVfsK3L0z}m_CUnlQz;NLigM@ng5`l*S3`xWbtR?Pxts&D=S3I5y(Jlvj3+pNRT zHZJC%uOSR`^Ew6?N!eiw3c2&0xb)b>#?C;6*lA0mx3}xJ!X*tk5eO1#ZT?7nNTIf- zE+Xf~v7?VaBu6^vK@cm!XO`fi{M~0WBacKivV1^}ZsPru9JRBy_nDVj=btn~vEN9I z+sZ#-*{Ac@6>|Q^)>1XlP?2hY4roU$xF9NO>^AdiKaF$WqZ2q0$HM+bawg*J3WSX< zC6UOeA`)xlQ0X@}XogUbRkburS7Nuh>O8>*;aFwO8l!&k%yGKJOm>((1TkcDe8lz4wn92Ps{pkMJKmVd0u6Cf$e!@J`d^ zo2tTaJvO7Ac^8F;cg+yj%;gswiM zHVjO^TD*v!=w+_YcwvhZxJXunZSnjpeNEx&gCqsqHF^n>_`w6h1#r~yoySS&(iih1 zf#HU0N1^E(?vN2bA%}v*U@ElCW)UP(thaUaT-#~=!qz+2O-sFU&blr;jJ0MUQx5;X zUzUnHEXdD`WAZ{HVQ!ETJc6d7dNT3`>|+%w<(1^{-V~Mo1%I5+rf_;)UDPxNsQ)rd zzl5(&jbn8J><2QjK{fAP>N{Sb2S9c_dY@Cl32*QJ8t!oB_d7}7S(7WR+C(@9o(xkY zVp-8_1f=s2XV4Nwxs6M~LR} z15O)FQoex*Nz{fIcNN(`;^wKW6pFu&H^#PXzTQl~xweZ9=$+k=X#VpOaF)xgCW5ON^|LoKyp~?p6u0-It7F6$IG*5H^FkX1PS)p_*)($mE}xw2 z)v!f;?VT52fNoQWvnc=x^VQ>(@d9?_KnkBS_8y>3yG(nK9UcqQBOhp3%xGgA7_d2p zK{qQM*h}P6qyIA?DdJ9u;dADc5PmMBvoxCEU_=(EqJiag41%!w*I;{pzMRt{4Zeu$pPdRsDS5KF1UJHCxLu{b3VEOh+!=%3_0 zr*wKQuwxusmr8?jIU)mCcz5!Hg;wa6k#?z}AInfdf`uHqC(mXpDG8No*_#0-RUTytnRf@vGJ5T;)`O1SBGx@!xUuk$7N>!O*W_Re< zj2Xqxa4)}NTFc~U5qZIo-jSZ!A-JW?t!cedmXg2=ZX7UcXxZW>2^%K_xypWD7FuoZ znD12FUHT3BDf}Q7p^^>3gKt-ISzP}bnz#QlF^fEVjAb$+PC}TB53>*jAlT&&tr>AK zMG(Wror4E8b>T|(Tc$t^K8iv(u>A`ult|J^b`;!dN0nZ$NgRDK?aPv!>ZdD38M+U$ zJ(Hhuax4}~Hr<|_gieeVw;5(c&qRo2U)1t`a>`}I zBM89gW*(ubG#hTLwe05FYQ=Gql6taC6Ez~~YRT8QTFHq6SFH*<$1s-X)c8$f#;l|! z!|Ityyfu#-GhMl6(-vzw`xDgK^XWoq>v&`5@>%1)P$1acWS^=WfMLilUFzWu1ZwTY z@Pyioyny%rePyyqSf%v#U(u1EahZMrk?SJrU&?^~(?ZI>vt?83m8 zRiE^P(!KwH8F#XCmjDCkn&Xtu)C8VuA`dc%FkQ?j5Y(CvlE9c$ZT>{nSEx}Fp#ar1 z<=67a01J1|$i}5`1ul^s=9^atk#@^(rRo)#Y3E6j{m~C_T!ufhO0p(-8S#VJJb>g!Ol5dw@{}Y% zwR7)jL%A1i+mc?Liz^Mr4|wP)+PVgv;CU5M$HoDxmm}80Qk=VcR7{v*#3Jr&y$Xap zfuj*Y@tD#~tgHUl72Aa%gvG-}=yz4#A<;pH5s&LGXCg(m2%Ek^<{lIVQexK$^g^{> zFBilFZKF0$_HpRslnlLT7M6k`@Qrsq`{ob-og*(P=tqaYiP+M>@dM}$om&9g|d-?gf@P<55V7CgWwuy{|Lo&nU!+vRtHsmX2Y?n#a@a0j}}RI zY#X<^b8_da96qkDyqVU%vYTIcR19&-jwR{D*qU}78M9hlvI3|Lu7F?n%_7kcM(tw3 z(6BH61nV2raOGAt!0y8PJtWqfDIe zXHr7JUIJqacCdZ)Vx}mFKeuJ|odKn$!7bxTqN)(+2`|iMn*pI7PJo4ceF=pL_UbH4 zRj<>dt3$Tfm-IAB41`eL6=kqDm&w}Xrj23#y*jp(>7WP^}~QT z!+lCKtQ?aboN?IM_D+;y_45GpcYW#xtKfzVuOcPmSdvZcXd0A*OAsqByG@~mS& zb}FWf-@M&Vwy%y1qH55t`mc^Y3!k}7Skv|neqsT8(g?j?FKjtq9saMPA zC9`F#z}_(K5D-9WiS-I3M0-KZcSzKmSYJ+SLnJWzHr*AW} zVJUK{-bRttYZ$YmX~Fzj(sygAfXP1l{N*$^D(!$7(!eJSh|6GW6A|Dd8XLevcnq>O zeQCnrHbr5Usm^=%5>Uqb@lry9u}13{DC)ptP>go~mRt@dH>vqqBgIqJ?Y~`d2kN^Q zay2yk7lqw6&`+S)vO-T#QdkZMQdmEhs1 zh0l&cX6bzE|9Ag=<==-sKJA9Yi6~uI+hN#er7mExd>?p;8wCi&^4)km5*#7|I)WeG z76*IG6tX#{M%`iYI4+;Wf*WMN75y?QCZk1~!PDx^&@jY8nGu9MUpCpuZN7RD6i8g%?4RZSD~LeuqSWD3=K+og zgjC0Pr;gkPxstL8hs{ev)UyCW(8h&)W>G-1I&7f|3I{E^6fE$+iTK3Q7T!J0mDF4K z+t4GPpee)bfhf6Z54#-yDy3Uk|M7A{)HtK(opW8H!J0SG>W_tYF+pMOvV)u4qR~7< zjD5S}p4!s%fm|dFpBYc_1t$LVAkc~}WxG#x=L}Zo(vQ~Zd7S8mSw<$$4@WW7n|jRAt*}RSy!7r9*e6JXKmiFbdvzah6G6P z&@~r6oOfi(BG-F`YLsP@rs7qzg%O3nIBlpg?ZV8qtPncl_!mbS`_S~F=HYw#=EV3+ zh+RdjfpavWg*EMRB0sRPcv*f~NRmzX%NS@Nng@d^sOGNO|>-{^o_sirGmgcf8AhbP7~ZpSVMHcI9c| zeBU+XRc*1a@G_g_AzOaMId;~eLM{Edy;4-kiBvfe5KQ9$Y!T9okg@mT^AeJMM?iiB zde4dJhizZ~v(MQys+l|;ph2OngUB%?ibQC#N6MpkYr9~5#9Nc*i(3VL1jn|i(H5i! zFwu{`nbIceNK#gNE#HB69f?Vf44G!dnq8Q<=aB-=~s{EeU?ln#akm15#qzqua= zWuqe3k1t(IuqW~|SX&Ij!$xJP=Nv}O8W2_X;1d8w8azeaZ~1~tabYO>_&Jg5MSf-{8yTzN zYGXAvI96W4wVgkPZbQ+eN0#0h)>NNQ5<)|RDqSFpYLIlAK<2%Mx)hxuq#%i_AgUqD zPGmKhll_#s!h#U6B!CIX%U8;LBbms6fSGAC_*ceDtwt`T zDX4|!(2&p{3vZd-}<>l7Yv@9MfTePi+OKu9b6L$jw-P!oR;j}|}50w;RlrO;- z|JTANBgH{qV|7%|niX(@W-_OkQ2?J3XC}Pcp=lf&i2yi%#pn zs;>-z7~GX7_9rS=g##^aLZi6j;&FkFA%|-HQ(_&wiVQUAi6EQ%`tt&A2Tkmg8SHAN zZ4T>;c0l0Mfy&)6Jhm6Dt)I*9C65QbfLJ95?B{V}s4GuYjtpJ96{6J{jVzVSw>d#H zBAtO>D=Uz#1|_QseGhfpEROlX>!Vd89y|Q$1pI)JFO}H)96ShxcS>VTTAWM#K|I#h zk+Rm?l6%42E&BfEBT}BsGr<^Jw_1m1s_0RE@irzcF2GUxFK?vdB zoHoh3opn6TIE4~~diLT2FR`!h4mzo1Mz>t?q14$ey&d((yGpQL1rC)8KT2o|w^u?6 z&Xn-PFh|qCU0QZ{tSgWLG@!8!AeqzhKi5|L#SG!Wj$ zD(Ve$U39!RAgBu=SYOz{4(HkQjd@Ui)@p@oJ`<`Rz<86N*AgX}Q~iJUb1zym5~_X< zkPWrv)p*#33tAiwNMUdxv5+X9Fk1C(rA3iCoXD@g_3#kPTl}Hc{(53X2(pi1@Ut7{ z+pasw?I}w18~-0%dec)dRbW*_Ysv*b>NaZ((dIY^OSo*X5mm~fZt8PqcMvf+oeE0c zu$RqKns!8_v>X!IpF28Gf28;ddf}&#eh}MaC6LUYMdk3hzKdzmeDWT+T+}%dJRw5c z(?|xAhHl0KaGhtY^+u!=S#vx3`Q>`fn|pq#`t3iSm7fYxmYqHQKArRVp>RJi=1C4( zJ2J;ky9^mUWumiwQu@5n$20A_*$;h);*d&e)B&$fiIq>qc+56mpR)B*g(YZ3Biy&V zI|?bSkGpIJE3lvsg@O0p%LZ$f?z?pbS``c?y(7~VzCll!B-m!FpA`CFixktSh*J)} zMrZ%!)rg2VLqr=t-R9F4#RVv3L&eVQ+&_eGx6pfn`W#D$06@Adb2RjDLO-PQnTALAXMT`MyP8sWRjT{z4s^0n>+Gy5y8bGc z^+d#`OKXvKYZd)SViN?@BfDHh|7L$xT2JN+yvuv53$^~A$Re|U_+qFIk)$YwOtX39@$WT{I`~8 zDvo-j4B8!3Ui~+Kcm_45IDUXi&^xgH5efqkKEA8+D=9!;2)!p&v7DK={O3% zM|HOC5np%tj96jX?qyBm3hAvAtDi@$3+d7J6HRrJIsRN9Fh5EGLkJ zSi2t|H5B(D0-#|(p5kC<7X}aBM(}G=61_e0HY(YlDFKH%o{Bc9}E?!5O3ffvu*S48;?T^!@xtz9db^^N_2*%fH;9+(wM?6EgO361(%kxas2gg#dL zeP^ZCo(9g6+~16-IppPdR~N@{YEMz-{`UT3d$zOsL}6ZyME8pJTNdjm6~Q3Bx#7nw zhhY!ZAITJ3+Zw@5_g*_p_Qq?Ek_y#NqOpmYr8%2u*~9XQqvKe0^s-p&h^o<(92a7R zaf+rlw}>d7qaoIWEU|Fzz>Oy-Tj5OX0HmC^T%SP~Y2csf%Gpua=EBd8zPVDYq<4lt za?E?L7S7vbC~$NZmjd_XplZp704;k3T@H5(0t?)mifvMY6I`|7(`Y@W8;OMB7*+;D zAn71cs6#{LAGwm32rW%2!LK8a>!ViI4XvnR;45JRqX98&(K(OD7&~=DK9Q3$rVo-5 z$*R9F4V3b}fVpq#@F`0KS$zx(LIoHh@?$)Wy}ROP z(1yD#puIs%+p?YyDiAB`sjaHT8J7H4xc`9l|GceW?p-xdra!B419{Ip{nm*7yA2`| zR(`Z6(FhHomiWM_#9bdI#ey2YFT%>=FU?T)jABsC*4 z3jXMPhW1ANpCn;qb;}6c>x0=7}pUdP2Im zwjTLMXL8vo4j@i>JT05RyKVMm&F(U6=s(cWbWZ?zuCb77Q;TtlI*dI#+8NZD7(dcu zkUf>}!DSo2tsLimdioo3FqY`qaCzKG*Guf*4~d(!hA&mUIGhSu=7&lhJ{Y>4n$WNJ zqs#f158}rwZ>Z_xb3pW_pAs-bb_c{%#+^!{%cflx@O14>2ue<1jZfGm zDIU7fXWhauA90e-)^H^Eg*{--f~&DKH%g-BwT&2ubSB0?rpX6~^jz4@j%+`R3qf*I zvhIUFiNXVfrgtLpdP8CjyXget-?O&7GN_W+eWXQl{$_l~=bPY+kA$gA;I%?IUsK=Bx)Mo@}H-Z&lg zKR|}|%vEa%jgZJf))w!cThyjL78cxpe!6|Y$=0;*jw7t11%iIJdFyfQb-#Y7`iKVx z>5$b}dzHZ(0!AZ$_O8|X|4{{vGhnVms&9|SiaL)siQT?1VEpAGPno$bDJ0l(gBoUN zX4Ib#fBdmgmr8h^F(|1lJya=g7K)dmXW6h0M~BhXf_?`c}&C zaIw=|-$VHB*1X+~ixhxRijY~B2{s5KCYhX#~-&~D) ztT~cU;0?5MMk$FH(8wQ8m92bHh04i(UvD;TCl7B{EP8rCdd!7}Rl*}BwvQ`yMV>?! zhsGAC?p^WVxqpT^N3v-mp`!mJRF*qCz_6kld|~{D|Mae|O}$hmc~!0Rz7yV3uMFl> zH1_==y%D2klB@iN?O3A*gRX-Idw^;>jgcEjoW;S)KCEJ;<9e;9Zo?o0#~)@v_x#ko zO=h{zTBdmx+Uzfb7%%-MKtGPO_@WD#Co_C(q!VBNGK*YI zKdFjj8?09*&OzE%g2Qf#wf0MZvho`rG(f-)S7`*R40VEDgm(R#3g>uv9|_2H0FKIPy_axCfw~DQMAbh_34Ku^c&N z#C(OzoyHMSn2FHwdj+|;AUp7vyOuA9dKr|Uolp-ilAd8RNFSFSmckCpNpE?Xj6CHl z9Y~l~MI(}db!-prqaqPXT%Yr`2(N%p}Vc;l8+gc-}Y=~5!<(w zvwyq-FrgU+;iwt$)<4sVdx1Tlkw2J7os}$gVcLVW*9GJ%-ME#?9Be`4P-H6uf{sjV z^alqP1d3k!$b|Q^mC^!R61^TG_qqR@xv}~>3K}_CsEI*mG zpa0EhL&_atM{Qb9!qpw-4xH}IVA~BHX~AZ8k7chwm}v1v2yf>F=Vy`Eg2$o#GwKNk zq-t@KtR1Y==Rm%3W~|}2kHkZAKjYq(IQtSfA7T+ZfJ6P7v5dh@@?pxMN;6n*FGk&z zZ|{XK#Gd_1L04TSrfXSL>Lw=DSsyb$Uxoje?O&Y-Rh+e=ft%1EJ=&vd2Pc7u^%>pJq$GgYo5R}mcGIkX+kgFSxq8kV zD=KG7He9Mg2B?3JR6YYv3R%Evh+@@jy_&BHV{OyMzn1KboKuFeg}Es%AE;5|)n$3N z7ynlx0RP;7Tk5o>!Q+?sQ<5XS#dlhg>B4J9I`{ardEiE@IL#a!B!!iHNGi?>^CPPI z2j^w{aLxX;9tbsz$p1_PJ{cZ?hIh@WUkWc?u%uG^+fB#ODd*;|7GQAhnJgn60ke@7>SF;^$ z?{P>yT_L#n=p){{gu3ZadSW(Nui2^o1w0-)I6~pxz`BJoW~S^bW^E5mBG?sc@0P=* zVU|=5Q(UI2mhKY%`jOZk6M?m1)cN?0N3Z*yxC;C~ku_a{A%Hp8|NsC0_w+$+7Yy}} z|1>R@pV6ZY#=T>6zj?vQ6}7=oRay}82X~I*8*QEz#|B-1LH~5Miy(f}M9UfPtaZks z`D?8(shY#=FG084`Mh@)XJh5X&|gD%`w(X*sgxo=xA*t5VT`^p12XI+sd{~PT=jHV z)jb=xXlB3eR}FH?{WMyfe}^p42{i* zKNv5EZ*z9D5BXwfZyQJsLTO;ms^fm;eAn3nmpO86C-?plnXF;|IJnk5HXd=`RR*!u z914^C^Dk3CH}Au)MyyKLR23SeKy_?TGhk^KBilsduY>`^d{{zI`P}uiJ%-fblH42S z?9Pu2SWPG$KVL%Omnp=rsP@t}ms{q{V|yxmC34wrB~PJ71cRFbt!&mjvA^|w0FGy) zlj0}izh?daeIuG0yUAxtoJr{bM-Izqj9j5qEoQ0mnCgbkoC}IdZyA11ir*}rDMIkL zoILAvNxa?t`0@my(E{S$pc(tp@UInk2aLE<&7l?avuj_9i)=nAY3%52tag5F0{F!P z>$UfUY)~MQMGYpRzLxim!u=`M&TcVa+f<$Y&X3N{2 z!ohmc%fvzG|zXLtKyWhRE^Tg}E1qQ~o>fxV_;j&qAb6Bdie_P+|pIJs16 z25x$=L1)%UHleoCSZ~^0>e`Q#5{hXl7T^ucWv~C@sgFaBQ~$3B_t*px6=xzcvJe~D z{*Th0LUIS~2GY)wOrg>jP@QkENSN4T$z642D_{W3YG@kL1(lfTMZaCE>aHHyC2fR3 zxt$Xzuwf>QN_&Lk&u3X1q-u|X1!_|EUx2wfX}8jgh+FL;NJK?_JJ%3v2)FYRoUi8W zSnX*Qo2&NPy0)InaNqZY>*z1pi80RATn$Q~(8RE_{6+8Emi+}zZ}5NAZx7mX3oqEb z@Xf1+N{*wiD0v<2tB1tyFA6ViU=lv}66!FvFds=$8HERa`QPhmC4#*2(xHhz_IiXl zNFM1iky?kUzMG;f%hKKKV_{1IBKhh+Z_@(LS|uEDjV4j)zV1qP@;lp~409RS32{#z zzZa<^(t!u8Fg9I3#;}b9kd$f0kvmMUQ?%jHsHBLi_Va*ZeKNXxWq+hhIl^4}RBXXN z$e%ZEm(*o3uDwrUTXEi3>Vy)_oMfvuMa!EIhYLLXvzrNtmN~twkt5u04 z9Ge>Z!U($n_r^Ze1;#dC>uZrjm>~!c%!GWz?g@3h> zz4ghadzK79*Dik)qDpWEbvqxVj_&Fa!6Tg4FV&H}LADPfOb|^sp-~txwCr>H&mpqH z{;05N&mCyafDuze%WX0idr=%qPX*yVmpqm+_$6YobEMPmg>n*fj%SZP;0{P34m$1P zqmXIe&&EtB4`i`^g+_0FRnNRFGfXw}+Z(=k?+DzLfxU1{QOXlMLt1gCmv*ZQGI#&6 z+m~}8*{pReyqC*rf_!a!N%a&Bi*6crhH)j|f^}+cbDF!1K{}shtsxk%T~EfLVS3pt^{3XbrU&#Ot?Gz3hzpK!_>#n>_%NtRcZp zHrF@%y++7;z|cQq0Vos2mt$D(#o!u{P5?z#bv327Z_S5>zjB4BFV(LM+K6B_`|v>` zox6%ZkuUB>dl$B>=DFe%@n0MnlW+y;_$H(13uz8lq}O)j0Xj-^+1CIy2@bcIKg2c4 zjhgzt`x_a8{lVG@LvH`psovGhqHkp;CH~|&wZU`y+V~omzd~ySMf&xoKmT5ZmR+AmaP;&1vrY)vKN8Sm|DiZ8Dz7P^00@@_JFn`4}Pc?pe-4@d;QsTzGicj{n!AU5W@qq-!T|6z=^C?P_SNK59j(N z_h6N?hU#{B%vFYJiyB9mOxKS}@EwtR5lFE)WSyLl6r(nYa-=zS5llLq5yk&k zI^w={>V~}i&+x$wJ9qQkGmoy76JJ`1nPN06ynyBjSbu7uy5USL7rs)OjEFEfs)A;l zaFGvW47&6sHQJ@ILk4Xf=T~-Lm{|;EMc#D@70LRyJDZB_CBMGDLk7l07Q&<9j933i zkPEMQ^j4^!aUWij9VZH&qgEQiHO5q%$`W*SJq9HYZomraz@&Y7EFt~aB&;Q{UAZDG zQ6e8NSOR){6<*0*n@-#51?RxC7137zWWd5y?KO^d=dd?@aiL@!2fgMta>SO-n_I!N= zd~#3H9#-{wczQBvmKm z_ZuJn37mB$uNgls_k3O41l+A&vlcx*R7?%*XVSFY7)f+| z#o2bBjH&J3X{6KiXr!3Vi7E77^YGm92Ytyap$)v_>17L>8d(c7ej5o}pjMy*DtBD9 zkCP#Ln+~B_kB<5icP+R~fgrOdu-j$i1*na)yruw%ulfg zycY5#zc|Vn1CvPtB!z!IAc-B-f;cb+u3||iwiIa!jPm3qY&2Y$l5St63mArvuxqGK z-IgK*nV=K7G;vW!5fQGY7M|6``xRW!gDguId2tfV4Pp)#J}shCXQ92geqCu}atJ^i z*8_$UPt~vt2ndUgqPEktH@}^M858;X zvmqTcO*PKJujrIH@GSU#PQ82idre;H!h52K7IZlj?ma*jTnM<1=-hMjVw zEX>UAi_uWqG5Y$0%dGWidreVAh15X*)@(G;+9fAwBRuQW$M@52m!V+m4o$B%f<@4+ zc}wU^eWb(!VuRMEILKWL!>3{+Sp8(3Szn=wGOcl({04Z->5B#Rfpco-Xw3NC@t;+- zf5C2Jtd7y0Uvh8;>a~$k%sOL(utwkcDO~m_XrY6S3oc=V(wks-&45Fib#_zza+vGn z_6K5D9B9!LaOn3`N^x;0zC@rxXhT`HgA6JF{DMR5F`*J4Wew}1vrSIA*@ZwYJSmPi z?(zIrc%)dlKRrG24z)D)N8Y@7>G7SiS=)OT9gcGI{KIz#-2eQCb5{rVOK<=g(zWV! z7pMzleR2F$?A0{AISSd>Ex}xPxZL#a)a|59#$dtf-fo&+f%n+X{i^*Zcs^vBL}i~{8`MARk0k4+g&D#c0$J4d%_3A0^EV2Nh(`x;}K$?PQ7qt`S4&@ zA&YDdtofOCjg`TIiT*~gS#W?EYAryOKPXalPG>vibBYD_3h-Dsa`QtbIwUzo!_ zqHftOjG+d=~ zq7WdL?!n%*UKS7yYdR>Bc3q4!H-BO)6rga(TSJy^_a;q!KD-ZxMEkqcZJ4EqlE7}{ zaH!tE)*V?68YIXsVKz`C)+}-j07pQ$zhZ3^Hv&thv2Y!A@S0-j|H84p6v3!7G>$Jg zz!gna!Be{>dta=Ix2+8t@eur1zg9te9*?RrMc|2(0qQv929KWv+W-wfKn0=rS>z(5 z?6SN&?G&jT6F^Q9w{%?*nK(MwAJf;TwNuq{0q#fX+V<(g!zP-^vcMWiZB8b#i3=+$ zwhBYuL&JhtDbRw(;M>SKUvwH2{tk&M_atoo$rV>ac)mGqzkhYmJNJY!r*Ax301G~l z9pAw#{p@^D8oFUfHO)+X4r^QoGXX_ALi?y9hNB?l>mFi{>_oAbnOMWbR zB}6L@^o^toihsbmN8vlu`nSy=Oey7g%2bx^0p;j7Bn^#xq<_!>WQ|^dJPl%Kz&@YB z!}S4usEl{-i+zCpT|pF|@3B)N9@<_xs5e#m-bVWQKsWynxsX4h!jMkN%uZi8zGTQ| zq)w|N5DI{_TzV_D6esCO@jUMLLoch2=C-JqQ$Do7aej*l^KHBQ+`OOEAT)U4L15oZ z|CQCuV7K3e;r>W-Y%H9SjWmAA-6f02wMFs`qzRU`m;3@;-D``R@_yw7nxC~nze@Ni z$(}EeJeF3oCQ(M7i#d!!;3MN)LxyxZ5vedQmA%yl>|BFM9fKs){f@}V3&3b%HOr9{ zox73V4L-Q_ZWZ_b*XSJT%`$y(x0Mwl@iAe2$~Oj{7GDP~u7RP=rc3J$@o(<&qHMVQ zg_N7rZ9(#t)sogF)fHc2*ZHal;%lRR?}hZVL5GeQ#PH{?AUQZhJUvY0ym{j1c@tM9 zlX%q&1WWojz)CG7a9aEb^bpyK)vI%+2cYZm_U5!lz9(gSN}Dll6VKL$arfvPYXKaU z^f#MP@LtO3vpA5h5+pNwVkEY3b>Sh^Rb-h!l;s7609F8LAPE!`Y7#MzsLeu(wSejv z%cIQU2(D^KER9HaDOz7zt3~+hTm%O$e9~!Xd-x(Dc^DUQ0hSvrpTU5BTsaWaZvt~&1$Lx=%U;<*UXC%<2UOcJ z$~gzmJY)2Iwrxfg&L*6?p`y25a8RYCQ-yD+|6S!zG}aU?J|U|pbSLqzx^(&0Kp{29 z>Rbg^e^Rmg?yNs#ng2(;{fdh@z#90st%jO3O^IeJL=n$@3R&9LBCrxlphR#RYX

XBbh;7PY z^{SOFSHH2MX9m!oBUs}qF9Z=&iFosek%1xP!Cr5rha1N>M)nx~-wRb+d6VLnc-cn~ znZO3dMGH)4YK0EMBacvK4b%e86N^X0 z4!wWRA~2#_0pLutWmK6a_3NRbpu0#!2eX_q-0yT7Ux+=geN4Qv6Q-9LSgi54;4c#^ zDAe!?v;(w?1}x-2Dj?2uCM46zXuB3utwGe!&9F`#vD3fUO*_>qGNslT)H7Lf7izSz zD-t5KxMf^Vx}RLl=l)|Ibje$C)L;>!+iFS~?4F{e(i~3X<5ETF@#07)WFoy8T9$IM zBHn1|H~*yzGN-1!dVGz-+MQqgRo~-B)5u>_;kETk`PcU^wfaDbYMHeCOL?HIZAdY{*4$2}wS4 zk^kO`I8So3rbuHOtwKvxGpPZNK}xFSNdU}yiJRhhik(fpW-cyOxAEWhVT+kBF6d3^ z%X_dj|MVx=Z0>*V^S>zlrG=k6@t|AV(s9+QPiw1*KvD7x79HEVpEdJnAjUsy#c(?+ z0&U_XkyL(B*>cBG0pc~8q%lhol9$IhqTP=;r+sy;q?*g6;c(4xoxq3gTX^wQGR$bn zcT4}WrLhwQ0m{`K!L3nn0T$$kudqGH6%t8#G7R|Sdz&}@w6dg^gjmKz`0(Wf23wJpNV|p9~X*SW#>_dEwmZD<6MjbKAFkEG(n;=OZ(pir9wpp zEsBVk6H3Y3!qI#AjTza%X;^$kj*gy0q4U9%~-mNGMr{002*2d;>CNNFxAV}52}?x2U&nT$1q z^CjduR{0BTabiMV%@jYL#^(q4Iz(Ul9P57yDuSMO`^YLJE zugw3~CC}x7%KElqi!)*bz{W;Knkjz!o2nGrjl;dww71yC<{w zr!tlMPOUlxfN50szb7fIlHFe}#k2kfOVWQ10o5}5_`>J;aJ8AGNeL4x^2jC>t%1F0 z$o7_u;ht|`>FPyF*T5o==3mcI7`coAtCMFzn9i?Sx~Ph|57@{Iwu&CC?B(ZnAwfutb4Yi4Sj&ZF4LeYY5om;zTjE; z5pQhOP~4uRCR|M53?)Y)jGVf-kYUcatg9n7& zJbko}*dUw~k6Rw;dxUS>>B@0PuRXboUr7oH$PGL=buFalx!G%ik&XqiS^@4K6l2RU z6rNLOF7+-Dx)_(kjRw4c6X5nMnM*QP<6E|NrHs!yi7+B=GSW zLA9-_x1(Gu$9FpS3=qTkXi&hv_pz(Qp?!7P!6}#e|6`xP)7?Sc1)v^@Pyf8(Sq(Qb zFq-Pe@Et>CE8kN6mC)3c3w0RBE$fONJz#BEmSHd5J4Zu9G@L#b``XQ2&;8gDj{P_#Z%bvQ3Y#75em33tD)P(| zRHviX}a@0|Gw`@NkGh?t`mKO@wm32-}enrS37hs zB259)`VOQzk8Ug$EY&Lp^m3qvW%$6%OWdQ?#|An-_DZ>L1qJ-k{eW)(}np>xdQ)^*S&%s8Q zP*82D-mm3Ge3ay-?Upz+ORhP%ZyKW`$7#*0i2}=0Dyyg4oT+PqH^>1$W|w`P2NPb2 zCxq#WDxnA*6;|xBb?Tp^VMMSQHi*~u@^GhjZE_fZyEcS~Y+fgJjG!JF+XGKqQe^0S4;~iaasv_O#7Z1OuaUW+Im3AjvMS)eE1t&i0DQn7#tIamg z|MD8~skZNJh3Q*yg#m^wy?(<-A;}n{LS7=V$=Jy?LJk<`!rSQR3#rY4h9CD%0%olV=%)c zHS_c%lMYyO4uyGb42EC4|7w{_Lb_8UiG9&aa!;c14i1o7w35&ox}mB z8HeT+GYwU_VoSBKU@t&sEjra^Y@M~Sq+`^`#~V$^@DV- zR@$l0*!*p8h!QT{89qwj52UD(K@Qr+^WG|DXv8Zjc1IIZwacnCh6Bh{Ho)lQv^i3y zdFai0hWk{K{WgPXp^dm=+wfg1t@_QDk=l zgeekn7vV{@Fb5RNFJI9VK^2P{RV0!kM1>>ZHn>rT4A}3<9AOY}ym}PBkCCtdq)17P z-X#639B&n#I<{a|<5A|3))Yg9FMpfllpU|WYS_zo(Waj78Y62YGvWnpFQ=+0&`2z;qtl+Ck|ZNQT3DX(Hg3b%eOP? zxp`twfrAphSBT{`xF=LOU##YA09p%iNtsu*!49XWl7Q+3$DrIvnYDd{IKE9)r&uBF zjlhW=GbTWCkt8?4(o-L$A_RqdrwKRF7FLpcn_!;1t0$f<9B5xOD%T#goY~;zs16AL z*Rz;Ts?(DalT*}XN_`CIqhmj09eD95GNQ?(HWcV&S*kyZ0(rHqH)R!ioeZAFpZ5z5 z-~SY|)Hci01*{xguyXIf2ZSsch@9RGbR+MRZ0Z7CJqSxWzrsM9<^2D^rRXZF0^Sko%0yB|Z%XO|kg_;yga`QcE02_>XIypHN7J;b!bD`ax3;ea~V`iAe2asuas-c?g` zJt0;bYoQ*M2+_-w@~pEbrmyGcz)QtnT>+XLxfoYIF&wiCd*o}|OPl}kQ+mLfhxCF- z5e>k*e3*$8%5JRct4x(g)lBA}Cm=_&r4Oms#yPAof;Idz=zOzf%e^mJisUd~^X_M7 zwBM&TuH+2$ZyR%yFTy)&KM1bq8A;sd#L9Nx01hPW92`=}dXC|1EguD}OwTuoT>L#Y zVDJeHwOQv7?}Wdb2AJJ7>MsNvNxRtT@==CupW=c)rLdLcNb*9pj zp8Uvn18YZSuLNUx*poZs3EZ|?IqhxYq*gJ(e{!>_0I#i2qJvw` zQ_th3NUDph)>_DdhOex&5Pjq!Z+0Gf*lfl{_qy7a9NB(5yk_l~{t+vm3Vpa(ce<(e zYxuDX7K!%h9SlvO(Y>H$A89oQcrLkycwsl+kRaRxOgzTk6PbU{Lj7S1Mo>Th^6Cem zDbk9bH|)3Ah5xG&Q3P+oKUM!oF75fdEeI3S2@>lSNdXUM=#>s=y9!P|J_C-A{zpvTOK<(w}6 z6J*huO07iQ*I(Yeea7*n;DJ=$Na~&IrB_fV&QSEK3OO`yYOC@0+eqiSY(7hF0Z3y@ zjhz{OF+$0QA9q(3Q;#gx3y=La#gUCDH+Ko8H@H>@GyysyYIKuW^SNVf2Z}Fk?}4vm zd@($+#GMhgJ}`US$S&u0#A^c27B?B(zca{;Y5_ouL=7 zU;qOXRY$XM<9_YwRrir2JMA_yiX}e#4&2SJUC<@?jEMWI@kIM);)!yV(2=;a z8b2a~dLq5Oo86Xuo)2$RIrV`cHu+yt zV8YS*!D<3oxQ@V7y@|bHq=YLLZ(9HsqSU~R z;iA)#?|~F6lo=)Nc5B5K-Kk!JJ#2AMwyKH4)VOQ7fQ;n>_oc@PoRYZrMAGSDKRm`e z_ZDF7=A_A8qCz7`u!JfN`X<*H*xZ+UD^QY3G;FY(jj5DeMuN9~k6`6-eDQeI1C@oQ zZ5eF40yc$B?pv_>W6aYJv`rD4xIWe3wGh{h14W}Gs{I^ZvE&tvyi0ksIj zvQrUhr_iI!K3PgFoPP7^(Dr#GpN>Y<4J3_gs5?3*GUwAIb9C0$7xr9?L)zWgcF8@} zC)IMu)lc*gE>T&t0jCQ{>w3Wb&3UeRNXzO%wR0b0_2OBYDqkbC1Hfgp1Dqb>br04S zCglzf({Su90_%B+t(w6m*=~dH3G5*&B|Kge@;gJpFMaMk4cFdNs3RfCJ`zOzhQ?MH zJ+LP72L^Pe16J2hYRM=zQXCN1khoQ~ArKl^jU4@gn)^|s3dn{46#YTYQ~q&!6)fbG z3k<)I5S&e+XQA7!Jb8?Ii@~*$l$8S0Wwr2jaC!O3et13_)O3Jsp)H~EQ-$3DYD4Yjz=V$#`lBq#znp@bn! zFe_W&nP@@hh#cCKYUX$U&ndIaUx!E(IpwEldyzl0?f84K5D;ZIYZ@0q20^cr44+^p zW%me>`G!4ihGe7Ng5)nhD$wuY3dMgugGHO-6Y38iw#7)NdvFU}g|LsKDZ5dgM#Hzi zk*uQA%5M+UF2T>`H%Tl+A)9V~oyFe#hU1;2&f);&|LXFX@s^Ou-60E66f4u|WW7^$ zWZCyhxvr&P<|G0CecMB{j2&lCV922Gid60tvoo7xV#rd0HDcuOr#jttpi5WRcI2(J zjmBs<23B7Et$q8twz&qsyZ`_L08$VE@J`AE`Kh(>mzF_~z1;r);1q-h2glUli9=du zXaC-cj0)cedUa&|h4h|3y@xXk%d_yD3XYaT0k@TOu(tq}ec%bqS&&;W4I$&Fd3}mzJCRdi8 z;RpZYiza+kJ;gAI5ur}BX-J_7yk;LpRY>ek zmY?fba5@yV1bIh~c{FepQQ4A64ZK*qWPZ>8V;J$EXR@30BB`L|C-Mrwt^k7X))!*> zG`JgBjRh*moL-Op!Nlo^N#2b^{Ghkp=`HN+1{%iNK{`yosZK$JPw6c|K4Zkg;6OpVaxy|Lo%z`w6>Yep$8@T z6rleRj86Rltb?3hQQGjkv9?b(y^?9NO}uTB@X&%5rwQ>Mr)72>8uacN*k3~gyBWZC z5~e5O#kv?H>_$vw)VWUgH(I*f1ii}IXEw1#D~f6aWdoR@5Z2q|pA7Z4@!X{t)j8D~ zrmLLs`?33R?bfG!lpR8cS94~s*qwwJvwUUsl?F7o_616IU8+wK?}jwp7DfF2MiiWt%mJJcCpj})FQe!( zOuh(!FBufTjEdeN5e&BKH`7-xeT1cre5<1*u;Gz@_Z0v@^HUVf2nY}46?@fR2Ng3j zTGil@gkvXPb#rAIsDbU=iC)93UZvmWZ)sT?1pJ+u%WTC5s}X zJ|49vxQtHjFN5tYr?(irIjrT)&<$azCJTgOT^~kkg6orRoTqg)BQ7i3XQ;^HaKzFZ zJbw#B*Rfuwgu}VapF1^rFVm%k*LwaT`*)P-79?iPqlRR`-x3|M8r!|0Do9|%X{?Av z+TZN_Q>QS~sc#`!%L$M|Ne&y^9_pwmeo%QBk0?d4aiK zM$(hmt2d!{ZNxQJ_QkWLW_-S5?;Dx-4z-4E$M(HW2CPz2$<}6IMLQlZFjj#UbnKk4 zXgMGDpX-gk?k&?c=3>t!ymfD2a8fjF5=^htH9Mo*i`ttAco(F=-mfB6x!frOIh*xU zi$4{P%ZAkn25W{+M=fNz;PEwDJV7hK>aw=&#?_?0-nm=K1PxNlWUdEN2L;@B%!_-U zJp+U^-6j_7-;7xcm)arfI?GBV7g$q(Y}J?5$~v;uYxi1~#aeuwHZ!`fkIegiT2~XSh&hN{l z?h95U$j<-!5`D89Z~Y#E4I68T7S3>qC9!cr8{a~PQXhhNt&;yG(j)SEsxo)vIqU0K z{IALRWe(p6u~9FQ?BtT581M~DYd0DKkg9?SYkB#n1cBN?l)pq=H!4V;^AIf7q{2wL zz0ABCHLjzkC&7j~7M#@u!f!xYJfViBMI_|>KG$5%diQc;QH!*8#55J3J z8?nOnR;;oR`oRPi1=Q{3Ew3>-k{J#Kg;KMHJKF!#wjVZ>T1W0iAZZvuwP(SOU6bQr zK8786`2}-K4qNWj%z7)!&yKapq{gE_38X5BwQ1^g4Hgb z9s6BbkdHJ+6TFN}MYGL1Kl=p$2_Y-h>=p*kEVFT0Y56TgDDMTu9`EvOuGL9lh!$`p zW-9MQ+*YBpUl*uO2<5y(nAykcV~LSGTE8|QMLVFi%5YLNVD7&y#Gsl6BsAh#71h9V z7SN>R39ZrBx59%MtD@Nn+NR|7@foZDz2pQ%%McXpB#IIS8G^wRF7ww=W$x9QAd%tvf&j*!25*2Or;@y>uQ z^ylbS!aU4mE(l&SD1aPXA$3N`KiMK3+g?g>$n|C~sp&wyG_3%)ez4oUdsujS`=GWr z!_**}>8T52tU1tP)>VVGt#P3A78pPQg00g}7>*qGSdYVcr-85-l8-()EJ-~x+RjCf zKsNcP@}hsRjhOvMr^Eb{P7LcZyhA5ozA!jgbH-A4%9naR&byE=>T7~rZ!*~XBd*gB zlDp7FnG+9}xQ)zq+Qs*Cwcw2#8IkX|7TAvr`lBC?0!!=mpsNS8vX!&x+gh%w?z8JL z&?qfA=?)82JFJ)s82Ox*#Tun4!-I!?r;-K zfB&}vA`sXmo%;qH)N3$)e(YZ!yQsfwse-xP_vXV2F8{b)C`LNnoFg&Rj=G=9;kNU# z>$QQk?{^bnVl!@&eM%`MuY6nMNwHMpTMnRFeE1K6XvhoRwd&UW-K9URK<|ZJWTwT? z?(i`JV^a-=H0YF4i_`!n!m2*OnG~;RRNqF9>q#dg3&a{5TOO`0mg^o zF}Fe?t5AiT1`csa$3csI0se$dt*|SOq>JJZ{}qLKsICSwMoE_(@u4#AF68mNBCi>h zlN%1AC3J@m!daMSv=Q*^((!!9h^ElZy`dsRruMpb$>w;B;zZ^7+`pF2B(^*CHoA+g zecaA4(6f>}y?e5!g-JJ_1jWU;0@$IQc57g#F5EIz;QjozMxQf~&$kycoe8+avehx0 z48XJ5#aM7mHT1wMNFW2&d#`U+Pcu(5Z49>a>8yL*k-{BU`x$~rv~!KCJ1f6Yw&gAV z|NgEI8)BQu-I^2&%xbNpBU!WP*kubo#9}XY6dz5c>7#tDcE(VXpABcw_`ZiE!~Vq~wLz9lXKou` zQqEGLJbGDZ`7{i}mX~PPls`*@b??ynYSxaZU3$jLZaVJkHpXu`#Ap z5fZiTlIiiRJV0C6PrPx1VUd=jWp;C*Qg8u&fOVNyJgI6W&(F4sSGArw_hlX{EU&na ztODO0*vlqCERwK;Sb^hosOjZdQZP0~zM&OUwQcXDjZ>GE6r^M~;Wg+@eOH}S$yo}>u;BnmLR+AEYM9G7cp@=8v4(0O!1nHh zj>zXOV0fr!0Qpyjbdn$Cp5Nq{Jf_x{j1KfNxRr=E(rDnx`WFWC_sHNUGkXW-3rM|& zNg5*A2?i&&uv-=R1uzOELqNu9%4Frzwe^6Gb?Xo^yQ(<$NBxzGb;YgGzls^yX|4OQD+qVY&*n81y+VfoW=7^fR@<$(*2yVyPe{wtpk? zP0hIvQBM0VZU_P(=Hz-z;+T|+Df@^B!%pMaep4p>((nK`(e{rSU!{8J`uIqx@C?^S zUSb%E0Sm`ow8*2=0dN2iK};Uz1T+8+L+kVtT;t=x0!(!G`%neH-dcpHf&>K6>zF#w z@>Hvai;=KPGxrj7!IjmFy!G~x2F%lW-caG~--#opbKDq303a4}@`L^y4k?zgGwzuL z`>AZjhvY#GE?2g8=QX%XNdJWwtpbX6Xf%h93Kt^Wp(v+7GdNl?ztr6AtapU+j8~lO zA`L_zir?RT)Ov1L+?cnOemDzR_KVLL%SQ8CzT~dprwAWdr#H_WK5-22!#1A0Xsr)4 zamUx5F!VM(LA}Z-pFJw&W`>Q7oFTH1J>vkb<}9&kb|)wNy~q8Jq@G(P@}76?d4Q|! zu6&b${&KBG)GVj${Mf`zB7WD|jhroXi9KRLuQO=HWy|*O!fD@jOot zzHz1wk`5W^`(4H|rBNG4f*Fh~&&69okykTF2X8SccdAF+-V&x|k|ezPPDx%R=3_1$ys(B=z~Y!SSnAEjz~!Z;nF9Q} z-d88VISih>5s^~WA0ME6?^yeJXiq3b|o@Ul{`6Aw2T~w zN?9g~*gvEwcvFT|CaB?MF2?imq3`0}PI0)#rkZkx1oC3hjJav?Wg)nM5aTz0mTrvX zNqHk5G1(fwL`x5Gwej?avtcU8S@WfC3irN=~}H- zPU|G}usv*>dB9>WN|pZ%4j={@waN1+WgLa>9_n+>dw4TL?NNZ4+7gGLfQyd~tcm4D z7iMbM#-~%z8=)xzF`WJMGLpOPn!$InZ#u4Af|cfHb|-?}6)OWxfPAj;s}m5x`#H7* z!qdfYmeiEZ9ZqbN+6!)XwxbEgOCERzJm{x|9heop?@{b7=?@mHNo8%6yA{;gz%@p7 z%~3^_Va1>g;@V1JyA=Gb;$=?BnV|DJZ-i$=V}rna|id+nJvy=kB$7HQXB#-lZ* zLH=mH{B-QFbt{R-(yD~w#3**hAgU=agr#f^!&<^sjPfr%J?TUYCWU&IoT%PLK^g3y zYoD&hiy}$s0eee&Qwq#*=bCh+`6Y+7jv6;{05Z_dB~s%Hf?vPoD30z=xtW9mWRO*i zxow;$`@4j}QH();Ri^hG2=!o%LV>GkL1Pe4m}2~Vvdu5eZ)hkylg!u2sJzfbYY%(h0x+J-cVJY;F536H1-4c$ z)QO8h55K}77tr06IMuG5&8VP7MD~KQ>sB?tb-E)i4Qaw+l7mMPmrYApORIR#Q2?he zbGRwc++SqrB`ZJw@w*S=FMIX91Zl}d(q_CzOei)Gw}XzF7Zl6e}pk27QVELS*zclwFN_| zR^)o+^R;*3Qmf^87Bmb8f4RLXOCSWmx(QPw_4a>Gw-E4{V;o)iB@)=@e72HZc&YVf zC#|~krYKnrbW_-}5J<2{9R2loKbh(I$Z^ZfsO&Y7%Az~vN-eNsQ^I#T`4}m;NQE&X zDjo=M9)-RRPQU2Rlw3;#9yRK7U#y9C5sP{>`#ZZ3{8#sc?vHqlz8hkgmC>W(*c~xF zJZkgoZaaKz3d(rjcs|#k+tCviMI!P;%CM%M!5=fAU8WX@sh(Z+ua|CDGXOMmrp+K4n+d<@LiiD2TQ=Yj)v9+~@0jPZweNqh{X;z# zl-}OfQ>|Hss}KQoX7<>bUTX_9q#EAHSN#@H)N9WjFY{ceybfZ+h_+4Wc+nhCuKn$p z-rv@}pUe1gCTd5ZS;fiHlmwh#!{G?sJm_M|_f1b!OVcXOB8>oixb#y#X_Rj^UbqnU z{#aIABYXY|yn=EY84JvFQW~`{wSNDvYhruZS^2V-E@n}aK8at&`1mU^1S5sFc4~IQR7sh(2D>FN>p&S8Ky*Hk4 z-T%4=2#qE&x&#Cr4=?%3TCEN^P!$)MeIImAqanJ}P1MtiOl4la^ea)F;WJ?&b`8Hf zkMWx>;eHi{MUZrc_sa3qeh4sRQG!b}h~5~+MtPL|4+>5uCEPAjADhqrq8OUjKDySU z!BXhHoNn__{g;2+oO;VhnU?IJX>A$vxPpRxj?ZHTDltr%$hVLt*dQsJ!4c}|Q6(%0 z)1V)}WyGU}d2j4E#+;8jT*K7=#T4W>&0}0aR1Z$TQ!l1|F<~VVgR=(E>$T zhyOVz4H;$_Y9S9q2gi;p`D0vhk&mtW>T&JA7{aMhvX~C-a`2C$Kg9aNP5!`A8!5H1 z&h}k6KrwWJ9|LVDg%ibFLV9kM@k}nxEoa%_(EmAIPKDolJIhk8N&Bk|#Y5o4qx#W9 z@UtNg!*WQn(}OcM_4C1{x=O;a4c5&O#FXGRd z0R81y6V@UUo@DNPAtR|z|NnB#qj(cVoZb0fagVxn5HR?=NyxBYjDx!r_HSX@1SloaU&(ELkCGf>^u4j7tx$pRMOovp!&|W^FW_SgSb%JD zNVV*bNl@vFq7b23EclQ!5f%LVZv56g^Xhr0F#0_ldgjyP=5OYUo*SCP_L)PFReOBw z@(L+OpH$w@!~{V;YBz@im_wMNa1{8-M5xmnr7Px7W~XTpBBo#g<^iRaqe&=+1mn*i zm04zveCTi_z%0^1b2Z4;E7jQjq<(kvDHZ_UDV0CtxN~Xl*HDWSUjN}6?JCMAi|MBvw|!}u}W7Sy3~uXiy9r)fh( ze>dg;VHXCD42inO?m9JgEVJQaeN^ol!mAp_s7wo{nvy49kU=k}iJhGiS4wPnomiX| zJ%5oXY6@r79FS$~sFikwMey6}aX-$P94&zvaW|01IT%z{_t`1jH+sx`*}6624MMFA zV{3wYC_oaaE9)Q!obCHn_sGN{!?uq(nG1+GpTnZ@`00b5t|Nspzw`0ZYfdbn1Q-64 zd{>!Tkdg^}xO#RiNMcT@k0dqUzV_Ufr4`uK3()rgc$=FU@_@Kf6;s-4z)dbUes8Xw z#jEj2*CdU8>7em@;-p19L`Yqv;Bbo+)Uv;th_AO%9~HN!I|yPAHO!hFE-=|Z#S}>- z)7ra~eW4{n4;eND5cqa%b=}$K#ORygN$%$P zXI{##9fTT))&o&^S=9!GXrEaO9?u9yITR-`Y)=0$NWpuYD4ywJ6#rw$pzOiv1)9B8kA@>$ z+&NeYcjdmobm5qfh`|c2fzehMj39%cyUqWl7e~)P-0>kuLflYeRBpVTl%zhyWz_%- zy-dV*t5GJLxdI>(>J1M~dS3NW551x<`V&P(5;oCu$q5YwY1U(`=1_hR+W|V6{r?qb zNf#|(%~C{yEvUpf6gvT)oUe4n8WNl+q(Utg2ob0s^QnaYLI=S{zKP;VrL5CRqz-~w zP-HiR5$LcYvhau7CZ^9gYP*4QGyqMSbIrW^rrn2bYqssL>|_O>Xl2NR2*4RGH_jyB zAd2rKpGt&0A{TlY&>499Mdk8%pD2I-zQ4ScbGeXvdZ~+TT^j+EHQK2$%#c(HO!wNs zq3Cy)#1C7=h~5S9zPv$ibCvfhh@|r?^DP&dNfA)zInkOoq_|2~4Zx$z^H9F}!C=FL_7iEZ_k!?*~^7M|D>B61DJ(R$x+NzPtkg*pH8c@AJPk#!LfK%YY5dvaHfz z%Ft&$m>^+D&1At8PJ#v0o<+Bn6{d7SB604nE!6TzE%pKFr7L!)-H_)bf~Nd5Rhxac@~d5ut7Jx2s}8 zv_V7Zuo<&zi9!N)go+eTfN=huMJQ;3`J%9sY+Bg&lQ=D)^2D$S*Zz1<3f`Ztj=ona zN1E}h;5_nRv?-%}zs_u48cGjw|H6bd)=+>?mPFMo=O_P!;I1}FctT(Oit9AEQ-A@| z_lq70brkRIB(M;gGTy77V#pY;gA#b7*ufP2NMZA{`(R<#9=|S5R4g7KW{TORUgpG< zcgfzXQHau8qkK_ENX0~Ge7e+fHij)N4DDwC&SlstD$iN>3ytfMAie$Rh^lxsGCy-f zH2``->=898`O~3!A~M!!NVA#aPEsC3a9>L7PfM;OsL%Hk@+bmSnByzS+=u0s6vX`g z-uALzBKY-eO__rMPjU=__?DHO3Zg~f33lA>wdSa+Zr`RC)G0-VXXEw6g|ed}@JBm8 za|U{vS*7n7OvxJz;(g$@^s5%gJQ2;rHsntLttTp@XQwBHP_nQ~6%w`BjbvALE;3IG5D z045zTK2B-qDm2c(%G>M$mejXpf+Jy0;Q-+d-Iq7rTk)9 zQA&WqC=dc@QE9&_A?XJXSzeztJomGs&?XTuAFSP-TZB=}Z8u;at-Eep{;=VEX3BUJ zm22xOx$#qKce++wr?$;I_ddpL3kxqbFuvlv_(sPW_33q&9kGs3)UB>2#CF@$)m(D4 zvA!fXHDHt=Q5)N$0b20d)TWMjr;B>0AoAp9PyW2-FpWjhIma*kh1Gzk%AvbRxWLo- zT8QW~fYu1wRQqlj#zF!Sr5Cl7$tSLT7R&nl_ot3t)+Z zEVu(FGgX1VeY=doE{Z@J9QY0^mR77GW82>LAGnMF&x+iAdR2p-_86TV^&;K8d<9{v ze$k(6{i{hYD0932)bA`iD^Qv2oo0T#Wafgn7XOL&^j6%dF0wz2#r89Z=oQpV2nkY6 z^(1XVTtc7nHlksFcJFQabBk9oa@M*hHqPrB^)J86l!Tr=cy7JO zZ0o`p|1U!F=^NT~A`;RlND|P*?s=~{oiJbV4L-g@m(eObZ()u?i9Jr@4AI z0uO*;?UnZzTRG=!9__Tc!UNaY>M4|3$QLwCIFpb_6I9z9zT|$8)MFWm>ePBMSdf7V zBLTvQ0WhhYDU_DM#m%WPk!lkiiar-^7~?KRUU;t^2*>3x4H&*E|1Go&7?$h1xUYYN z7xX$^W#k(~?iM7e8HMs9DBBXld%Uv!Cci<8mswKg3C z+81hom-k{6D3z{7^YWoD>)-6N5I(eX0YY7zdV!rda-(9_?vG&h1xR|D1dnkk{`&c^ zkT==DogUa;53BL;DZ2Ykt;a<9|3F@q+GmD=xBvQG_r*kKPRFf)Zn8+duv4s0?rcl7A zb84n9K|j?4?Oo6J+XBnqk+ndDVDjYM@PwtXYX{9hh8dTS z5c4V~+5n`FVG-b)TOJXgN<)!iJvKHuZ<~RH35V%o@^b(w(pio*+t2X_r(>d@2?g;& zB0)u;d3b{P8-{U9nnu{9Q7?23-$aDpsXVIEegyN0WUbr&6u z2D6D;wi5P_+4HkKmva@tr5Dg29pU%Fn5&vqAn+4GMN}Z}T6DI)_O-E#lzHx?hX1xm z2Dy5E=0Gcskb&4b70sjGq-iVL2*LJiQA4=9UpyyRfdwIUwYA4hu}-5%S&l`7$)-Ny z#e#qTvqrQ4cpjrHPPyKGNh@q&QKLS1nof(Tay^Ak6-+9xJMt)SE>Jkn02`MCvIJ*9 z_&g~zzezeIEPE6`#}W1E(wqf4%dT<%8H-4%J;8sE$gIIthEiAH5QwFV9tJ!v8X|<= z<%S7|=h|)ZI`HX7ZILG-&;t@MHlSN<0)-$n5WLWk+X9GDrj-2OegFW|-k)-&#JLmR z4m}9e2Qda)n?t@Fl2r9qT56vROP3U93ZF77eGl;HMz>g69Vmi_-$w{f_@AO^s>Tr&+&Qv-ZQZ8pgCC3a!)cIODE? zEn)4vUachlU5?hCFcv6IV!EfW-HdmDNQeo=T!2=cSZVoxzdx3!wS*;%$d4;PG>nR^ zd6Aq>Cjn!t%FP-OBkDBk*TjC-m3NjpX5c*z^x~%lT+Kj8m#_H|km~yTco0kK2Js|A z**dd%pYt-;+%LWPg?%03rx~#!{|PMy++8&A8j#^vOFXyT(KY-U-I${~ppQ+z@xWbd zcmMeUmAhjh$169HZ{Z(`omU>XGSc1-}hg9hy-3P;W!NOs^4 z`^5}KR_VVk)DYjxbKQnn8Y)^lK(FOa1naZe;CY$k(p?9d?X@@g?`dW6+Q8pz+_NLK zSLhOB$XC>;&?*lo>XNV5js$HoS=3^y3%1djWTVoD7~_ARAOJ4)tL%Wt598LiW3`QNI7Npe6 zjRn92x)x~Xw=RaV{H(_UFdK{rVk*u7l>lZVU@9eieX;Hvc?bJe2c0l#LaS}^d8aSC z_Rvw~kCLP03ZB&XzPti65`&T#r;*Ar%rWTd?omtk-sj5E7#HU(DkMgs=1)3$gR&1D zwz%fC3+D%;RU>;)gZ1x}n1yo|WwP~3Q0t>u>IJ@z^x0^_19yMP3>G$!&Q1 z#odirr~TS&7xQ=Rb~Es4ItnK_wZ~k`!C0eiFHff*MP71JoD1`kF&El84x9TgP8?vT za@)J_Iq?rMC2bHPZ#2~aNt@wvvHr_0moAaJ4#IRzVaVPKQKj2z*V)f zI>rwww`&9u*QUkU;0uj0eA5xxV#xUAQ~geIHfLd*h$z8=rj}4g%Ww*_;lfGTjYUy8 zX9q`)-pfGVChG5iLkHTX*Gw^3Lpx7AS>m&kPIWblnYdK756%oAfB)_I+aCl1j(IbK5zDS9ZvY0?afX<5I9D4DD4lN0TeAsO^s~Tt`5*Oa^gT zhoek*U77M^rwH<#(#~hWv19=ILu+(+7F7esBLw)2YUQOq7AM_tl?JNZ^(xKvWf(-8$0BpwfJQyJ5Hu;k=eK&&9_ z&DPEEFr!>7~Mo?lwZcR9k0hz(J z*1Gn@Dxdg}pX(O~=Lt)DkM8uQab#k~%wC9iC1;>p(OFDvtOI^r~4sjL8?(QHp-g z`35=u_5XcZN%IPG)3~Wu)q#HM+f4zV$4~AmOm}Fr6-!%4xQXX_P8A1~q;Hl5cF4oW z0V7AeM|W4Z`{EA1ekc7FJkvzl!w+$`DMOUUzXGBD!RJU%njvpiJ{5#?H}>8V)s~bl zI9T*;dvfNg#-mI9f+iU->>Y6r&_I(CD?inrS`EKDO6e){Pfe|lzU~nObL3miX#A2D zz%2K+9@QLEY~Ij=G^NsJ(9}vI8*&B&+57BBB9TJOeBIiKm>o>G2tH8)Q0}9X4_w>I zi(s}_2k*!l5dRN~sKv_J<*f@iUt;l7oXSjBCss5xA&CtxzLz<>$W=wIL9jI(hRCj?H4@yoyMwN;1eu&$w`9 z3hBt52Z&_m+sLg>)ASxE#i?`Dp_$MA7}1?kXI3v1&yDtXdg!5ulS{y)T5puQ%+)S04`@Sp0et!TtlV0R7&$ZA+&Aad*uY5BkY^E{pu_7PvA>W3cp)iW)B;9fZ(>VM@eIVF4mYKw0%Kt0LmiuL-I$o{Ar z)YDYk_~bfGRE zp|Dvdns_V0_&9>w7`rSP9nSX4*Z?n){3K%=x9g$8&-^LiU|Y;-2>pH@(^VF=3XcB& z6iOyAtOK66tGuJTxc)+xRA$djc*N!y26q4g&=*sjbJoyV}Uq>vCk z<-j^_<`wFE4jt7m$%gWJ1+QC5GHVay3~duKMXBD-Ju+co8i$+v&%yeEQy972fOZK6 zxH3raF}tYk{*9I!C$+X@Wr>4lt7{Nt*!liDS0wUDp_&q}$aUx&8}(QHL6! z_r<|A$(H(_(8~_U0BzE2`fgx&&+%`HQ*Q~Uj_G5w8OC%D-Gc}l603yStEJT!Q;dec zgGL`0uJ#I!C{-k|ry!^j!RP`<%w-YkpPg^ZLjd`x}>p z@bv%>5))qX9@())HsS-W6IrgR60>Po5QcXI;U*gc?U>E|xa)__z3F0P@AQ-RhBn=O zYQ#n>J6+ZP3EsqT2q2GBA>aVo9+k@&7j&&a?QuL7YED?hHBV+c4MH zpta4Hz2hXbR@L-EUqaU{nOMD0Nlm&!zV~m0BHu`pKhoOn^BY!D{y65Jwl?!f?A5y+ zC+7b>%XwC9-cDge%YQbUZjG>?icMp}oe0rzEHQ%9YLHjs8QlC{g{$C{I4v0CM{N$D zUO(6}RqN#Mvn%V37hSY*cu;;A%ln5^7)YC8BMa{f1Llvd_0~ko1&??8xYdI!)o22I$Y3w{dp#=T()^=u+#@**QPwQa1%Cn2*6x1o?50u1m-1e&*`h8)TS$ z#I?cVIi^oeEW(T;gRQfPcHwkg^+bz}?tB&EXmjH<@&;Eya6sqv)xMor_%lAW?>qZ^ zL877v80bWpy@=H#z2b~?7^??VSSoz$87DZ;&i_YRP^0B$1Ts9<%U3Aw7RwUX4L&Li;h&Q%N9L;s8gnidfRp^O%Qd$p7=$ z-L8~WacS4gN`vPStl26{e9LBz*WIi?`Pl^7#`sA(8S?RiZv>k~o}%&!u?|W)`9}G8 zVD0Tlhf~*2%%z5jko0d7i+K=M4J2}~s(XuI>gm+9o{`%^969Au3L-l(N`CQV+b6I8 z{A!c?gpp{!G(JgSwq~LAae0*Qu%tIMA%yAMg=hDt<}-l;0$=G6+ z*F&lmgZ{M|LEqpCo{=ua?k%>!0F$zI7qS1*weirpG?I}?41z?=U2vc=2&2ZBgsK-& zyP$ubbo$rD?9Tyf}oQMTQoYEgk?i5SIk)`^+Z!5l$BsOpoel zc^RFo+_HoHtVJ6jRA(^HNs}9_Tt-spqOZ9nd$HODHttq*)?kV^7)1}riE{RZpNzA zRp%C6I_;I6m2WxkI;ACMPw}N0#W}!xCe5$~6A1tc-~q`*T`oSY&A{{79SOKG0vK;s zeYT1?LEP$IqW)@dL_tN&lk^<2kaspw5DSy(!#P%G` z`e}}@|MEM$d$DNa{B)7CV(qlMmNLq>wP5b%2tOTu$>KX6oeC7^fp`Oj>K=W$Ss}X~ zTbgA)Do=c7@Plu22>qqKE9+eU+9c*O^X1b0aK6?5obM+2cgKQ4xH%1+BG>a_n=Pmh z0UR{&tK!oS8C#G~1kjzzzUKQWJAAC=pqsdNM9dwG^nLv%^Z-uqt9mo#O3QGV9q$HI zT9iquU@hQYNKu(Ei`AXtP)%cSz)*0yTCW7fpHPLhrO7Fr4Rm7>tM7>a$(Pt3x}9G-YVGR+D%wzn^arIxR&0r*-Gywsd3-J05`oNELB^3{ zjnV^WoD6s?O&(1x=ZXRuv88u178UFM^#R5nV1Kghr&K&1(%AdWcHf%?<1RVN=L*Wd zyC=Q#b=@maH~=>fU*OTivil=rTuirZqB}c<_K1e5f%OZk8p5v8 zW5)Jl>(H&7@vzMs5(BWd!HT>_Mq6n1nFnRqTsvJRp<6DzDR^uoNW4kY(oUYL2L{YT zfoa1?(4cGU5Lf_;#Ts|Lclw_>4QwwW62ROs4CKO=WGW@J&QnTUU9tU^uIb9nFzmVs zWf^~%7{M(^C*xqT7H3qd;3!Ib`8y)oVH{34Vi(MR8b_XEiv`al1h z_k$L%?j20do2%Z3Bf%@^N*i=oe=?`{qE%;&4yyY}yE2=QS%}}a*mPb4qR|QQ>_Q~C zSKgh82)nNUGjFKFL(QM)$;@<3DRqEhAJgl(Z*6jTV2_ZntKUdAnSPdTxqH-qIat?X z(`4uknYW~J2?f8$D;BgHAHa4K_$5~aYK4WEGN4!kKV{WeQd6FZNJNAKNO?S^azoH5 zyuJa2to>{mLD7vYyT!H3K`#N$L@NA&1}Pn7U}=%-^nMsNA(P*ZCY+mPHy~54w~0-u z^imK1_NmhgIlQ_Q)qt<}FTr3x^)K280D~^7)FyzdCEv~zLInndB(y-)IqWh0hX%U0 zss2H*I1APq(NE&9r|>r`C028`(anPNSA8q^)qmn*pw1y2DXE7`ho>pik;sHf#pn*t z$`U8op5fP-ERj1PMy9Snkx=^q`NI%3FCG=#Gs8@$QI)H||M6z~#%98Xj)zZsE)v^c zDKgPSE&3W8=y^yx9IJjds7?cK1-B6P`RB>p0Q((8#D6NL77Y`MAmgA#mw(TaPr`ON zHgCI^`vl>Ds4F%ImoGDz8gFvGZIlr&$M1`uU-z{kLennYj+r(ZPV;~Sg#nw#B4j>4 zw=t!|xt;({YPm@R|J*IQ{?z62S=Ttb88D-v_K9%n<63dA;v=G3X*^~+5WiK)8AJ7q zLh=^MTY&wtjexl344^{Bi~V$h0_*eTziWV1_+WOV3Uovb{5Lo z#2z(pv;04Qd@#B@6PmWQ{_)#b6Td(hgVpmWJ8fluv~}by0-;zc`O+6TZGC(ON>Z6I zI1CGe=utrbTuYBS)$E3ZP3*aaZxPFiq_(sUqrDi;Fx0ReG4=T(3077`>^s!20j;*l z0|OeNIJ-&o=y-P^(k?kfPkM5_b)$Zse;jJJ)Yy*{M z_dv!|+-r(}bh}EYP7ydlO5Ld2(pZ$wS@BDqGVT-vB&Nf+1!DdA2I2|3b%ceYT)u{8 z!>?OLU1alm*C&#W&CmHFNFG`|u!dg>$=HRhv=3PE7H533~!Tf7IMzxMCb3K|5sXsM#+a#9i7@Oo25b(ha z&GWP@s4LeA6+xxXd{$Q;CJAmcxKq)JiK%i>S_DQy^!4`oapbZKp1sp03ZMd;j~l)S2NA zu4hmEmZQ++qF)ihAc0s#G^D5IX|;~xmni7%Onshi^zJ$3uB*#5x8HP%{T>agEQWqm zJ^D@w$Omp`c{QrtD(-XofT6YBW5OPsQG+-ysa3SJ-XwZ)muaW=>-5$xRxb7HVlLQ^ zR)oL$$xBh5Zh+;0Yr}>0VjuXqc95Z5A))B}1zXz?TS43(0)CbA_wPa-ik&0N<=g4V zGReehYitlYkNi-miCUaG7v4EAf!Mpzw(Z5l_&;mzjO%B+B@nK&uP&>%jfF^<6#7?H zSpfS&3s2s#y&#kL)K$+DCu(ARbp(Jxe@R5Qx_N!|l6|+Uvc=l*TWiM6V+CGrrx<5k zq!Gj1RYU?Xy#VO9j;M@00Wjm{x`(eL1ja0~)pewFrF(^8U4W|~Wxe0V^?}3S0JP|5k3mimK1gfhPD4tIq2qu)*(0Mk;vnv5*y(rN|`vSyR7m* z1xZo04EThuWNaG2p*SLcxZ`?30VGNzs4+IhFOnw{qd^gVJc$c{9HqI9_K1XubKT)n z*m4?h_3jSlSa9FdT7V_HdLOg&rHbcNyp)_`o|)Tbf;%0!P`VPPvTo;!9bqACpV7I794q3FLD*Rk#C^*gs&rHUBp(070AKqn4Vhv2#Zy?VAhGvS5F8;R8 z`ZDyl%99M1c?4&Q+LTSE2eW=dgchlIT;0)+i+jMDEP{C(`&s3*pfbJ>DqS}eRj${Q zXG)wzx7h>I<}+M(Gp#CKspI;|!M=ma<}lhPU)$lG5U$Ipw>et`=TaOIk7w=KDjBF( zeM18sSt7wGEhrCubP-&cdq3SGwsXM{74rQ+Ojoe_mgW)Z4EDMc6Y^5&Guen#Q5OMt zd8>^FfN_FN)Hay$KPotBr{g!*bpw#eqjnCg9~X`)Wo*vDoTA|X36TT45MZl6|NoBo zy*LVjj!61e)LA%t6Zo3gtdII&qou}EQD!+@^MYA{LG#GQuZD!3+v#t8i!dS-E&ar2 z8vO`8T`7^0{Fvjrq%+{$RS76qA54cQkhsqCY5}MEs*J376L+;W%(4j;ro{JFJ*wQk zp*D*_<_Z&nt{=Mk++O_`&moXX4p?Pz+DE-PCtZcxy#Q~g!9hxV{s>a0?EE(~TQ8~r z!p>-B&{d|rv5fd>Lbf_nXyKW4 z5*vqLtA9tRK>48x89bsVlx}6C_tv(&DjpJ%3v~CF6A8pNm-`Xi@*@j;IXJ!nq==nK z>fG^P|NsC0|NIIMVFFJLtsrJ$9eCYTtqe?pCP z$0hTC4m`#tj<_yvvfzr0;Qb2m=6P{`Vts7OKUwPwYe@g~6a)2ITqGeM)siTGLmuNx zJ^z9-RQ`Gc*=Wv{U-F`0O>5zRqkA3H_d*tmA&;VtV~9tMr7>cBV<3VkNc)A{Uq-OR z>4SmWhzk7JMuF$BQ|Q^PDhMykhg`L$%xU?h!uGu&5-RXUpm=msgv##=7E!?e;UI7F z^Z$+nrYF>&%%xlp3)~^%LpNxKO;(VXGgu#i9uY{vCMwK7E^s@;cWaPCIZkP)ldT;` z!k}^31U;&h*L7+i`Ufn!yPVf~8s=0aXdB(k@S4Xbu1z@tV9<3mextIfVB8t`QvbPs zmPL>6gpBUaAX0f$KK0MV^Z^niT3thJ6g3|I@#pPammq^2t$A|ChcJC)v923jkH0pb zO{szliB9N9v`Tzsn{I_T7NeCuU$~%t5es0rsFc6-Lt^~xrOse*wvk&?W5hg7^O2}S z4cj2kOhM4&%MVhta+(PP-jFEJHl3%V(VYNMfkjjNV(*Zqb!pdXG~?AXb6|#cX2rbL z%i&oRsKjx)Q^(1mB?ffSb-r|swo&j`?5R*-qO@Xuk}Xw#bLAVN<`lHf$;ebAe@n@R zEkFnEKh8`r`}CQ}4ce&>Y^z-a;qv)44)p=S_V)${s~&Igt|C*cTv1tVi*+Al`n~Q! zWJ3Iva4j)Ulz!wKJe7=f$9g@U(oo2LB~&P^WST}TR#Fbcuigf$ZO<|NsC0|Ns8=Off8O)Z%_KuH*`OouCZjz5FhhT8y>%^OwO z{tI9Fwg`OekjISQDk0GqJ+@o7DAEUe+kfyz%1qErv)cr~Ux0nMR8R8!N7=-@5@pO4 zZgywVeNC{#-eAPSV49c;I=iWwA?({jmOI46sC1nTqIuW)wTRz?HZ4ndX2j`QiShj0nwGSUPG;-3C&Chu|DY+#uZsP~^fUce%gPs9$4^b_cj*`B89 zh{#|6|NsB=zdUrDSsq)j`gUR?nqB=mOBoR&ZG-88hyp;qvb5BM0)R#_z^%n< zy3JQ%!V{$Db$QW5R}!IL3NxaRWKui>XClvE-oQgvzQBcLSR!LnYH73fg1J7y45w4$ zgiPZ3iGFb4xy^&&=hD{XQ_)`TzOP zHQA#PpJyawt!#;o!e5DzmU5nr*PWC%z*xl z=ID6V=q{0|7m;+R%eS>)WRy2cwSt*2h(kvn)c3G@VM$3xhKp=KD)!@%lf(Hw){QWo z^9$1GK>-@`3|5f$?+^3vA+hGGW6LlGmx4ofARis}*@(4n7mk_G{7z~u9hB!Is?dM<6lBiLz><5tesD%+tGIUDp!d_;(Lp8QZO=s^f=63ubJ6&XQ^6Hq zf(VUmps#6g-4sZ}>aQU)ZuroZ|1BCy*&QSZC2Aat+aTg!C9G?pllwu+rA z6a1gK(JOm&95$hPf)M56ZAJM2H~)0gGy(}2Yy

-H@uFdq*sqpbtNtA-cX3!Eohr6lxF- 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 rND1jI9SF)(O!vspr)@@@gUBtQW>|*LAF} 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

OtqN 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

O0Su5Y3v3 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

p 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%0DC54@tncb@mch(JS=xO)&vN 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%0Dd#@yZ`1<*s5G;AHX=YsdnEAQ z8Ai8eMBdqh`PZX9^ueF3ieOOUq4H2`J?nqV!|?~*6yvYQ{XaVp`@s8*iahgg z6hfc@^#MZ!KNm#8=l`BwaS7vI8HSy2cDg30CCj@G+}Tu*-dRlvQ)69(ts}cbuM7 zd|uM;W1-p=xr?2~M^HU3C?_^76FZ0cHQnUh#2j^D3F|x9(|0@u=v57j%Nr}MZ0oX9 z;YOVazIs?C_y&?M0$j)GZwBQCRA?)H_8(+#q@#;u#^#TjDnt#SODun_frQ@wbG^ZO z8#>2F@w4zheuMD*5c{5U*FbUvkY|G;1fEBHch?^c8#dn2 zH^YpcEaT%cxw0ZaGPfAHfpC;uG9px9(c0Mc9^7OG10>#jL#8qYZHM}hj?X(gbB-xm zy9>&_KW6Q(?m3QpF)9gHQFeWw&fY@IB%r$Uj-GvF)Xm8J?oP5fu#+Sp;Nn2nAIY3f zC+MOlrdlz>zk^>&n(e~z+jJZ~l}-9CHJt*uCNuzuEk?ToAfM z5f2cMyA#$jHYxM|z-xrOMON+`v;`~K`zK}-9Yh}EYKg%l5zFtznmB4WaGc6tUhOwz%|Ir{A7cxg5kFTL!fTK|_WrhL69c#p z085&mBNio4elMkC&EgyozMJd8W^lUzR!g=+3o`lq)$RAE z4JPvq}ZQ3dpF+ zg~;}gbyn!SQrZn=3G4V?ad~6yKRTkSk(?4KL^2$Z*Ie}jNBnbp|H}`aOrW}dD|Ljn z`dz#m4CKeQ1a#}?Qb%~`KNsU?^ng(VMSvFsKjY_T{`5}^{|I((JPVoeM^fEIU&J3d z)@~C~gZQ>Sb!Jf;=k*@|Vv*nSi*}+U+kWD_JWUEYE$Bcq%WS4eKAN)DLagsIx0d9Q zzghII^R%UV9SxJG<@$p7$`#e_Da?T9Zh&cFWUy?N3xm5sCKV>GU9!EFu=J2Sg&t#< z=Ey{p%itEeB3w#xewxg){SVmsF&mBkioc<)gwNXU;ltPf;s?!A_|kC3+?Z!vUuqp1KibQ^ zEHT*v5pvP6wC1JNg-cxl2c!6v>jq{uI(8ws?XWoZGBeb zes~`}yKx#0UN!;R{~$y-tS(nbXa!x#&VV6jtMGxpyKc9|TgHBo{<=>*O)CD@HN9N* zH%R0M(gNbTUx{p?j-eG^&w5-v>kJ4mrw<_VE0Bh>Z+zc0)&5=`fV@z4J^1~TlDZ#r z7V(hG^UD|#@V|hA@(Z?pX8e9yURIt(*0`UK1Ug=8x zJ-xw~1d*^+Gf##^++bs`tz~?ev-u1otD0lSMU$P8lvLOn0(Lwp@WZox3ug}O6o0Ky++uQT1YAurPP-MI95Sn^))9ccP)*zE4NzUOm2!q(0 z^MO=(42|H&F!@8jkTJpY(AvMl+JAN|`j1l;kU8S#YeP7yJ5hkNin{-5Frfn^zL_r3 zvo=2grGam^{CtN9M_o$|peGj3I_ZjP@H14AqJHFEdA5N+D0RJ_#qT)h(P-zblK@AP zH?hsT)H1pLLkynWa37bD7V!N~6

;;7@A4g;2zLd4nT|3Wd_A1H!Ipx`nzjWQ@@7 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ⅅCo7oc~U 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

C3ON5~gmLPjg*a-r&uH0&pj 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%0DWE<=!=9r#dvD~#GXmIld@>R^Bb<>NLH^2@A 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

eRIMlQoLyght9J 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 QYYI973ZkVecHR})!F>1JXUa5kT9MWw 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 z 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≶b(d6FIAMRSc$ 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%0AlTC4Fyfc09>LKJ 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 z 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

    tbypZssQ2GI|I3%!1%-@^jkgcX88eTt$i7v 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

    d9i)HKDgydiUM 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 z%0DAyaAP51KOi%bf@uhzWtZdIcQn>B60G=nvUmq=q3|OM1e3TLh?`!Z^?QCGCXX@l zs*)wS4o?lZD+Uz0KoW_v$YW~hL^xiZ9_RTco0+jnQ%*Dw*uP^cosm5j4lubjxZbLI zXeTzBJspWAxxNGD+<*Bl=UCel z-rY?}80$gs);F?dT zj>X6ek^F3Yv0=F2{&jx;E)Z~?=-FyBAxCy(RJbm|$~-v^_i$JCkUfoxYd9czbC7%m z&38Zjks(37nI@DqB^L33WV9a_dJ%>=}+A?afHSjLLRWn+xRhVUW09xoS2i*+(K{#4)qr9!hIm)by?c*TSO)(cY z`)kRan?v9JS&R>zPA$ecM57V~L3Icct2s6;5<4VtX%aHP!4GZCgi}PczQKg6c>|hM z)!Q)=y-1?i^@Sn0_|x0XwNLxLcQ)Lo;r%H(<_ThgVO=ZMAFv!9&wh;krzI@~X(?4L zP_6>`Q3=1QXNqA-bE_50d3=x?1a7`NF@VLzxRuqM#fxtI0f|k_NFz&j^)SXTDm!6c zX}i>{*G04gV3RG44|~ba)L(}#?Azc|gTIJ#QZ*_riMoSfk7FC3OLBbMYd>hDW`-<~ zjX|Pv>vvXQ*Egov4dLV%7glq?1wI8}N8+_}8?h2~(Z4mUsTD25<%+Q>EUFwJ<~BtS zD5PX$6>#Jg<@z)-g=flLUG);{xE6Utn&~79>gg+Ltoaf2lJnLOH&s_hj|7IqZnHIT zgjBByWBl}>utkioqaUuRh0^haaFft{CagbP+!MU%)6m|L?W4B2`a;Cuu?}M>&5N5m zfaFzU$Th)*Xf1&aqe(Ddv%2t+o&B5OImbK^e&8#ZiK+awWQ1!pH;=YTFDPfj+)3P> z7~JD`8mQ5FL!2`TeC0`}X9QM4sgRY~=5rNj(SCHf56pNLj!9KVmwVySUtAP^V?eAd z!*ku@l!^67*!_#72f2ay6;2itI9ibz_t6T80bUN+hq~Zwj^!4WpRkEB+yCc-Z@MY$QN)PRHRmv`YTB| z*Y>PJWcg-wdRJs*lDe$1>OMVzo8o<=tf&gPhC5GC_I3b-4Hg%2*u?PykDjcZ~( zBu3Xf@8qn0=I~6vw;U9)P1d{h;`m$~VhXw+ zD&>nxqHIbPaC2KqXt2K0DMP3?><8H^u9xMPq%jgF3D4D}MgJ3wqR*}4W_2_Pwz$Lq za`~dm5et{tL@Rdw#gLn-m@RJO!Grjh@Qb+=#e@_=moau)4w%EqnZ zOI6{in~vLv@W8pz(+_f{UHBl+c1gI*!K93^DUM+%MM>prdLo@OmRU}gZ>WamZ@;t~ zt#uA~Ql9E-*Eqs@lav6OFewap`9D%G69Xi!uQ3I)K%@bU)=Szb8e!ZNUy^w02cirw z%c)sa6qc7wyTmtP(mu?)t2s}e)Pp@#g*}n^F`&{9P4+q9UyzR4`jJfmFqzKzZ(;nI zLZ!CA&(~a0CnZ^ztyG68+|@&tCwTF(6atwgcyV^1SYa`oF1%mC3KU}`9e&2o6l)$y zg~j4?7%$R6ERos=sEOtj3!s~hYg@fv55lxba5WSjxd{;XC>L*z#1DDviQxXG?bAFV zLKl zgtH*zn`o$28<~BtHk|KDISog13CThUApFl1mHx^>SbHnZI(#fvtGk?xyzka=ev}7P z^`Ho?_n6$M3OpI6;BoH4tZ)Z82-y)vOL*b(|q{ivCxyOf~p!m{%{OnO1~S=lJK- zC0B2eDBqt6=&oNrN~N3y>|;FLtJvJq(U7AExTTLkpoA-S zF=ZfXO=0zxX#kb!ucnyt0Vq-;*?BP0h8+lG%f5{-Dv|iNWqj?%>LmA8uX;`;#zb_# zP-?mc_QhVl0~kuATTDBA2%RbvsEr&2_W$@JPZf6M)!~hgO5_a_%D}C3w1J!NKUz{i z_geO^S~u{k>x7;qSC^7;kBz_5BQ zfaOQdjFP8rBRa^ghTaNLu2O&SIh;TZ2@59o)tc$qLN5w}cN#B9Iudj^J&+Q(0A|!b zh6==}iXMHC&UkK0)a~VTa})-_N*qaBExTHDA^#xW6V8&e8j;|+LmsH2yT53Ijl!>+ zwA2g77rY>~1xbC)=<7R&n@N^71a3aT6i$?8yWMipkgZ*-q^!!%Exx}VPX_&-tUa(h zt)=-HC5X<&q#~i9g2b;jX15j0Q(Pd_(asYkOu;G|VTx(1jysey++<_1%7J_y)Pf4> zJlKa0Ii=`oY^tN`!~Uw#xC?t&*0E!(4C?%~ea<$D%(PAiGK!NZ5>0UN;WlN9jt>$R zWV27gE92aJMq+kYwBidzhxGbcK0nP;9ROgGVxFy#Z@Rz6hy_DzgX{if77T`<2kAOC zj8Bo#3B6oRt^ZvYSAV;wBYf>}KLiVFr>KIo(O4ocG=<)tS;T!6p7Fy@7T$X4k}XJW zQ02R}B?M&M0m5rz|M2}-wVQ-A#s@!`O`CM~9^CV3ml-NggRpnbyYCyy(d<{TP268=`U=a0wd>;9pg;hw+O z!f`_}3KK-F9;;0Yt>POWH0<_G9?o&BMI*V^j{YWmIzsot*l*$M>oWp{Y;qsHZH%2- z^U>zH*sqAivKfCV`4*5e&>#Ao5^b;iRTrq1qz+S3QgpHYiRx17(vI~Hb@Uej)A#Zi zU;&_!+QXc4MSuG8Xv{U%!|sMWui?8DKoVxhZo|7NN?B0VKx}cPITdTMj_;*;*i^p( zU!o)Fjenx%@M}1hI_PGuK%o#0d=nL4MWmknq~iFxBXwmm$erqQ28uR~jI)Rpud}>L zIdv~9HG{>U09nm&TUw2%1q#% zyBdfBrXOo)#`b!aSo_qGB0ckFHtN32cw|qQK2OZT?Gy#8x(Stbxrg#-M@{eZu`V9m z4=_Y&e@(;SxRf{eSUmLH6pis7GZ@|Z6LyF*fO-|6Y@?&;%p+mXrZ)29ST6CrBY_Tz zw{<7G|EB8{3LTcUDQk=%IGCmZ99DIS8G8d?F~1>}n^iy+7uzqrxdxtiW@JI__|-yg*{Rln99&`dwKTVJsHb~XoYhQ%?ST4v-I@U}oa zku=hWM@$_4t~co}E%az6O}9V6REsWzoBDC!=cEtT2qFO6K*+DW7rT`oDzo6e=PF57 zQ9Ivx!D^Ic{nUb&$QBxe!*%~CzdYy8N#23>p38QyJ>YUsjIKCCMi3iHORq_JnW^S1 zv?^Dq9iE6aJ1Sj4-+68wm&H|q0Oh3>k<9ysO))jw6!$B1L4RYy5@qEDB%iy<_7l*6Q z{M5q2rhkocU7m}RP*LWJ(%*emVe%_GNeSEf_X_wvAjWW{Qidr<`1*@BD*Mf0MGuX{ z6=S97H4wNz9_O>gW29!>kybDjU~A6oksJyeC$?m>)_J?qE^hiTy`|mcx8TR>JK64T znXihrqJc>C9QhzccsSjg(HT|WW%9#o`mpGw1-MGXjb$Y(E!NiA=3;wH_(HTWC>i7A z33H3UGj=No$9SvRv@_B%tb93wZ&P_bTA&opMPjb`=9S!zbKxaX)dLHf#WF7GQc1vpB8&;)!PqbFypb_y=Pjtd2C~(hu2?+J z)cAMjAA4E^?EG2uK#a3q3J>(;S1 z7G%DmN;pByn-sw+q2X~_T|r0SyPY9@Y)2%0__v?^IJa-U??&0+3f>ziw*JnX16I_H z5m2hXdVmeu<|VrbHtNbVQT_5I!=OL66`a+(&9%bMPe9lBdZQR7M1A0QPMOaORjMzc z>z2!DkO7qWDcIxO`hB%VsZbqXx_Gqg1tfB8YB9%r`|XbK??fQcj+!w;kkwH(+Oiut z;pc*(t~7GgeRTK|z{)5lm$OM0hP)utp3{xKwmzgWM2tP-7H&3|$2$B}EJWL$jQ}$T zfCz$YTJl|o<@TNH=i~_NUXu}8n}FT)RA{ z2`pgZi_4W62jVfU9GD50G^??j$$DzXL`fRqI3vPrU~vzwwzcjFuBUPm~R zqzeFGnzOsxjxL)+%`G!h`3B3xn{Xl!0SVmYZ!|;r;_eH6*0K4^5#mtfRz$>q1c;Gd zAapY$2f8hFrxsp@vC7q|Orl>W}}9LFkE5|vFehor%}L@P(UxyD=f zu=Xu9I`BT~R^7yUu?*lls}&W}`U>kvsh_ToVnEH{I+g|bt!63XrDuFj@Y_nqcjev} z{6u?Z+ze^4y_n7?d`FRV}#si7z3{l{(~*7BlcX2YwR3aoOM& zvAp!^o%a#Dj=|Gz?8Jr}n^2yF`qUYYTJuY+BshuTPN6}vlqO60)H?f88C zl35HkcJnyoIQrMbZuGqS zj=|7;9%O4pJ;gMs@I=QML6?3}Y#FPZSjk%@8uD+cZPAO;S`VaMGMG11Kk;x|$1OH~ zkCrCCNNosMgi-aCj)8JdfCo#Ac|tICS^zGqlk}x| z>b^abIqJqd_N{Evi1dq6gZ@o#uSlZtM@g!`hv1pqVwQ4LWyR(#w+bcoJ$mNUq8AMU7-G-G@mL;|rsh zl9-y^IOgN}D_+^h*Y|3nyFl16W=}4ih=O+8d0&VwHL9cnt$OIb`VwF3M|0Z($D}L= zr=nhVYJU^dbxAVO5(1H>;i&^}2%<57LIMFZC(^-eGv>tWlLYEMyWOJte&@kD8Fa>r z)%)canf6mDJ|sF2Li}LeNomxeKIok|2TF+ZAaQCw$qvFIc!Z_P+ENF#Apa7UKxzn> zBj}7hpErYrDlSwk(x!fB40$`GHXbxP2l_AkG8p9AoY?tEVSGMB8_u#uw(fgzI3|8~ zQ?w2>LPNgUU9Zp2WrbggG<2-1L{>53%McRoo!J}CT+0}^xVkeM9Zpsu%`4O<77ZOr zlO(HNsP;jdsH4v#?b};j5zKN^BmV?2_jb16V)2nOORfBKSB3hJ)SVM+Y_j6 z4beJP<5!Qf)y$YMS5>B_2VAVxmLS)pS~a6YD98H^-V^&Fgr<$dhA>*Rr%yru(R=3X ze<;=SMfP^<-_)(xnFQ+K@*%T&6opJd-X7x~^OQIx(W+3OX6mc~<*wQb@4fWp0zu{? z@(GsS7p=URhTWpu(EW~DwkPLupt;Q+-gQL!7TUm+`d=&+tClyVD6G2%XsCj|#*bZ6 zy)02o-95z}W*s%Qk`C^Iu}6nndJ=uJIVw$EIFE2aqq=F0>YWnok@mywuPenzIL{ab zEBh&(zVuK~3t7Yd8%zr+*}XR{&GhF|y~oNDNjc>gp1}N+#h+EgKkwlhNo|@~ggh97V z)K$r}itX|HjGHc{EPMAa^wk<$)1@1a@`Y(qFacNTIn?4WDHGk=>Lci99wzQAEO?J&_TDJ5 z*e6$Qi_tDLf{Bs}%R=eiIu;xXF3)4!tb4NTv+u2!9_d>{DSDF_Y8)@;hj!fAE@Q7= z?N7vyrETXToJE>YtU!${$HKJ2(+-DCW9Wqf3}G4@yWQc4<23sTW8ttznH()S2RV9&UaiI!+>v?^_TXK_vLm z{f)y0AFsxnWooCd@qvV5N_kd1+N4=>96UovK!^3*Mhkoyq68yW_8e}{Ab=uj!@Y_( z+_MKLfJkRlJ@B=6X8aoiijhjUEd!TX_mGj;g)`IR#!AO&j65=jG8(SDyf_S z1a04$mGMtrW@sOIJPLNARKd6=h**4R)i`!jBmsNn-qxyt zPqYo|nd%Ut$HlJ3GhRy*L9*SK3ty_~ePmiz%P2_88a?HBS=?g*6nf-W>v_6!3#+L{ z=5g;ZOg@*hC#~R&(OQ6IQG|mhTw7Sfi==GNni=+d7-3BKg4Ic3Z^3!Dcb)~WRGrnwUH#NM-%^HXGdFb&}e)v%PCyjxa zugM}Q>nYtcB`Ix9w`n&QnUyvYF*$gSreGDGa^iZCb!^wU(4@uzvVT+_x@^HMP;!W) z?-+-51H3)k&DND-wW=t8tIto6ap&!op1q~H-2Z{m3^r}pX0n`keCD3WF4=W>F@_QB zBFglO=+2DTDn)z({npL#%|nC`IaY&!5aJDQtxlcd2beCU+|^3Wv)*-!u_fXzY`Gk5 zu$@DrPBl6q&+`o{DLjFo=MWk)HTT!2m2oAEo^X|Ud~nAnSB;+HO|kE;^$9Z8cb9PX zn}!ZMP;dFoO%LdNm?aQeHOZ54^}nB32@(e(60wPc8(+$xFS zd!x8bZoB)A@6vazc|YNq=I}n;<&N?xgYjnXFSK1g6-~`P1`1HWdUmc6Cp=t-TTVLw zpb;Z19wLt8?*l=$1KUoWf8S|DL*4kYpD9YiI>waP<2y4;DAMR-K;8@8Y$~KACUNETysZeF;eVwJJo^Gijy|qtMXsKX)mk1 zh2xJu$IqvV#XcT#Tt>J{QB?3qdkDN0}&?A>3 zNMN^I-oj!ME3yo;I89Bx1>kozMRR-hC)gF^E{*$%1KXU+B6)s|(Tg(6~08lK5%fiXvoEK544{%k4c5yKEsCK1~lSb*;%1*c7QZ^pdKzvEn zg=eBKtXi;K16>x^y7+H-HDRio6G2$3vaS=7038%I=P3wVez3fNuye2)&du+AU%6mH z%OOJ)TD__mx>gQLrlhInceYdB4VtIwSCG7wkOY5q6g>@hVZRM7*O>+qC}pVDW=JM1 znM^sd^-%U4SQ#qArTA86P-hRUBQN1zvpACYgEFTBPv<&^IvfybbZ)w-WskzX^DiH< zZ0Uq9w0jhvj+pI1f2|&=@`}^AhFh&MWIr_1QItzCN-R@Xz$E=r*}&KL$DYhKtr#a&bZXTyX#{L(AXaSkTU-XHC9BtI%7cSk3sN7)Rph)*mGP7XMBHn&E z7`VWoa+OZb=4@!xN-5gI)=XbXab&tsVhK~3#}L8f?rV~`S}Cx*k7>TcGRo%jkEi`` zb7*Fl-5c9gze4rGQ!}pNMiy85mEW^nLeyMBtTHt_MDy#(sIcui>#CY%7sEB(m3>f+ zYTyc$9umo`^Xo4Gh`Xx_u-4z5g*&SJEXTLy5#A`0Wm>tesh?9`klzB?QZ+-OKg1leZg{oihuOUxd$>BfFeODmLL4(TPM24tE z17Ls0>rapQ9Q12t$cQSJZQPqQ z?#*?zCT=5|?O~2!FSUl6+P0tS2inU9)s^WZhS>;oet2V>#%d%|Un01NO1Qaj({EIL zcU}>snoUMliFtw&3<{Q;mwxR23WDP7>+B!jsj@rex_97%IfAa9Bn#%i&K=pBII+J? z7q5VPD(sG4e1;QJm7m_hYPOOq(V?s%7O-`vD>bYC>j4H`jKFDEePxoBU_QLTKiC31LJr9_t8=o=oDv`vkf($pCDY{&{fH=lINynvaV~=3y~gpxxU`(>9hKK z&_8$Ht%F=wTO0M3u~>;^wXzbRJ5yiQ0fpyzLG(+&B6TEhMxWQjs3_Fp+p$~C{-la$ zLu|_>VkOPqJK8J5PHwaZ0zrtuybtXf!~LbXlnrTMl96#~$YQ~^t&oBGc#QnReRnA2 z5%G*gStiNzz3@%nAxh)I-5M%{vM$3cu6T5U_YzD*DtodVwp*he5;_|SzvpJG8(hk= zHF0^@t}I_*8@`(*v$_>q7C`rLnWNimIk}zC{%*d@k^klnjpj}Np|*A8RVq9Z#p(n} zaX+Ze|MTb`DxJs*|0Rx`-6s>1dQur$ZK}n?3c7hZ9htE&e^JLryd~##?u!FxKRc+s zZN|!cQD*6uvFnR7H}n`#YoMST2GO*m{IDtPt+({NN#}RVPW{!E7~vE;60FaNi>!O? zivvV%3He#pDH;z`nGqrR$uHv5r0?9Rw24vyJCzUj+1rVR2M|UCbIb@|_Hc&hhchFT zUo=sDN>${Knsh9`WC}6b9M5XmE!Iu75ST6q9Mr-MO7QNSuP&n>;sZSW1YvAPlvlYJ zbSV5w8e~sMKsJqMSzC|1!<{MutzrnVA11|5=~j$^<5G=96;J$AQ=VlLX5Q8u3~|da zNU^Kss-W%t>IL~IG&&@fGh45#zURp90pYR}UgT#CD^>ma=J$v^p}?b- zb^ssak}V#G{97g+3T>ucE&|@-18tJd1#Zu%6vEYUKop_@&B+eF)Mv(l+Z^$HHGec} z3f_vWMAGrq6F332Ocepb8upx7Jw_=p2;p{k=B4uKSkr5s8L7lA?iexuEVc75!sZ4- z1k?ijN;!{ts~{^)J~5)^**B{`0ZE^wbPi5YunwBzEAU2w!F?U&ax!)tun`h#9fqjRC`{SZ>Us-HX>P z>YQF$*~2TnUSsWI=9Z{>^Qa8wemF7jAq@Jpqf9k>^&2vs_mCJ+d*<91>&{jBV=x&& zW@If$?ect3!ArD&@7r(nV|Kwy;e|ovWA#JS@>~Ej49IiP*U-n1U<>hD^0fFyyey$V zQR}?GlggRo_+kPN>b=XZiE^itW0?#EV;Kz+&jTVL&fL4p9>D$h?h)?~?L+ErXbO8)|uN zwjoY4Aw<1E&y!swIqDzsd5rs<4Sc+ZzI+|A0%eM zGeH96C);NWDmlj1o3V-)j9p}i75Vs_`*If8T3+8G)(r9K+YXs15b%m@PXa;_^9p{& z)(Tm3%)o0Sm^h#qAc0-Mde2>$&4<3kYOzj9shhvib&~+;PON6!AA0-P*0PtKbUt_i15&3Xe`WnpDlxkfU?{{Pm?Gv4h=32(h94(bmf*Z(~pUU*$&1A~* zVpZF)2H*Kg1L|ou*R6?Ka!Ldku}Zj=zVKT1*P~Q$Gwj^r zm+%avGMFgMw5XQiETbX?m1#z#H7L3cctMHgCvS9%erIa4KR0-PJ`NqMj2+f}JFi_x zGyb(vUvc5BV+H4=!h^#UpzRTKVELk*Rg95Lh2Iz8Kv^&AVc8Itex<=(^$g{ha80lE zvr;cz_B+BGA`?fIcD*kju#3i64;L4H_7zpO%8@Kd05dPYBsRxbME1#TI_SAKZse+y zm5hwFb-Gn;^zg=FZ|lBqX->nSb5AMv47G5a=67OIUXhAlSHD><>j#%D`K(J0^7&Iq zP5CtJ6Nml1F)l~lr5|_pbqXsl_)0VqaZ6E=WGhK`22Nw84`v;e z@FL2Z0$7A3WLPLn+C*D)L{5MyMvrn&Hda!R#bX>opdW2T)}0JRm`uve672nb|*?U*%Ti?ma?6C0bdW=0RVfK^%U(_tvxfk z?pK8i6#~V_IsP=KKjB|9;;~gkd?0iQU&mYS2ZkKzPw`WMX7-?kFB3nbgd=xIKBn&a zLx4z0Y2`~fS4zTC+AYi;2b`qO)!{}sU_M5*V#SW~YgITqTUtJW-_BGKrrZXSYCG-D zf(dggecuQNdaBOCS=KkzmApf z(!!ulucV0oyupBBChEV;h<}S(!`GF@+}lE zF^qE!#02v|>p12vVd(}VcYo*uu>ySoW+%oYrzlmPOdDvA7?dDd8FI@N%38`Y1Wt`A zc!?zs3;vcDry)VC#uo=P1%|6*0^?z&Mwb(^Fa)cISE{;oVJp7fgp=nSzb#J>!@VvZ{WUP;=8ZZn0eV0ORw1hn}CQNozIF&7y$x`>r`zus_uIqxEj3S^(>W&=`w z9gib~NZNZgmAtts3-Qo*e0*8KTokC1?Ra5fiAaf5!N2vh{AXbD6ExxwI$O6#yA9QmLwGc-#1Hg5fra>u9xD zMXYbafx)nM;s?QZemoXRA*A_pbisgsBK%y5G0FcD`%f|in72s3L@O*hJAVy?e?O~c zuO+&9W%oO@w>@VDB+i=l?e?2>KSwHL-3KbffTTDA?v`6nr1-@UyjpKt5ErG-+FV-g zb!=Bkt_;lgxmcR|lxs2~8nh;urFX5FRIxv8<%Ra&I2)p~q`Yz_#5%9Sv&^q36Mrxg z#TeBgITUu-WPcQ04o#+N5c$WwmCMZm%zZy=F8LbJrtjU=D$c3?@m?2N50)OiG2dWJ zt^@`W&(3YrG<@f~F`@nqAOmmp*h%~uw_dEj9XQdKFo`Q&hz>nU#MS7b-4kN zQ-60OySB3BV&+PvGAA0|8b}WTx&{O`ugO1C1g^WJEP3{dG^75A7Hvd$ya=g&4sb1B z1or)bbNSk-p!+R^TS}LKbKHJ?uZZQUj=X_wpwtdqR6yk_hS6#IU}nK#p-*q2#6r+z z;jG#=?uwe2mD2OUH+IiNBLH*wjnE$eYJzvwrzh)8vU1{U#!%hvU1y8qU|=*7N)bGg zc$P}=BP`mC5$;^B*64Vm+2v<)1XG*Q2pnwJ@P3!Gh_U5vpgTnXr{~XvR#1eChZU6- z>JbT|F9BHb4o_vmB57r1*(w?FNBbpTAcBHe{&X$$^dxfz@+1Z4*_1{3>?*bEO9?; z#O=e~O||lrno-m6rq zlNBwQ+-oph?#jTf5yiY}Q|Hg$+KJb4h|2~@JzyH8Jtkb{@%za?DxC@J3Wb-$kznBeMu{}yYznxm@JEoOgqRnVr(cw%~5R!U*?3Zm_5SE7@&IhYA147fAi zZ6XE$w#L!`fNr+=PIRoi{-GM*zQf;Q`$ct7Qe;kH37qJp?x9p8(O++;!niDT^Cw;| z>m83Pq>^FD`6eg*-?@?}siSbK>g@N#UuMwLwXhIhV#(G-dkAbg51=7Hi?YfKUb?{Z z`}wxoU_=Z```HYByVvmktitmUP(t7}CH?4j`f&l&_37l2F05MnLp=gpxndGIvuDG( z%JP_c_*J$yI(U8LgNwxetA{p>I?V8+auKc3nO&=n zZu{O#oI_(v$u2q?8{X!gA;I_hUNP@e-q3a z1?^py(LU7(dkdRiQUx+sb{oP|A^22*(Bb+D`Qnw zM|S3r5rS@7cHz>w?mWKdOsmX`=|zrsxY7>SR4@2<5iP5&N_j%D-y;oGqy;8vn*ud` zPZQ0peQQ~L}|+-YJrd0un-lkw2;arCy9hL8rL#DY0gqcDHR3CJ1Y#xN3iJu zFMlj58>c7Okr*TY)Lz>{y^w&_ZDHd)f(c#+aN*P5I{vG$ReCQCfr-42BxXBpU;p_JsRZq z0HSLIJWV9D+r-b}fe($_Fx@Ut&p0Wyrzic~EhVvfRDv1@BB}3~E@A%iL6FR9zvG92 z0+gi}>x5&=#mU|OMcF$5=hkfPqHnljuGqG1+g?dlY}>YN+jg>I+gh=0J30CGzW+V{ zIdyK`v#Vy!w=ufMczVpYYgYH{XQ1JIscVjoLH7Xg-CV`9-H7taSPEVm*vQ6p`W(L2 zsAn@z2Og8a5pTvJiyTi|w=$@wMUK)n)egmMZ`Zu%@Y(^Tue8W5=3Tt%Te#)P!3CbKxA1N|*e4@I<$NH8^VNU$y6Fe~< zJw5AiUzi98pI|rZ2<}i_g?JAev8jNcpW)`LWhEq-X%m>aKKcZ-!jHIOjlvHi_Py)5-Ey9kfW>mSe}KqgixX7I&rwF(lY14K zpTp-b*3!UwO1z`odU7Ewo07q9v*sgImg=kRfx~>l>9_>4nJS$nNZ}lcf_aKp`oraN zypH4MintlTJGc6Q^t^55I^27yc`xoQW9N{HA;mpIXWhCt42EQL%b)Du(Ck_6y9#Qj zwdQQ+xtWAH>N~`EU-AVYKW8C7-|gWc=oWyOhG$~ufSlZK13E|1-Z?_=!+>DXa!|YJl_#1BgzH_cSbm?_=t4&{yrF4IS9xm#xzZ`v*oEZHe`pSJ z4&w&|Yzv}M5i0iMO`uegX94@FOxbw^+y>TRG*=jlPAK3<74)=Y zE2bUp4)Pqr&hW6G&6otz{?XLagx=bTRz;OXq;xEek^f#f{O7`E890P_=01_Bo!^V2 z;fPOwDKJXdRs%!T*$4luKKa6P;Ra-33O->4xz}lk)P~htmgiNRcxCZC91)K4jtkS- zh8`Uty5um0{7!4OLTfhuwZFjD*Wvu=G12H5p0p%oK_!e7ABPs^1B6OD#(8yt#RR*b zrU_w-iPZ#AVLTny(>@X8Hn}KDpvaGmr(22{RGL%gP7<#BAcHNE9H0?y4Yj%CSxLX0hJL{wul99eX;BZfI32;GpSV z$=VJ^E+QNSIH0Y2pUF-jWq)d#Kq{8E@ig$u7G2fxWwR3V#l?oSJoZpy@AuqNHKn9r zEj^>MYU|D@Z@I&OGH%W!y}zm};mF{UERnD=Gciv`m&o6{hk3~b@t2dDLSI>0)Y?F9 zu*-XG%sxoQlP;^+S31=K#2@iq8*Ya^2~8TUDlMY9qu7B$DCSno0tr7Mqfooz?0l0w z=?IZ~*-0cw5W&V^rs@;TmW{M*@c1fomQf(H*Y4Dlj>8G+V~GBs=0oS6cZvQO=Ue}# zPhHi$fWceqck(5MNTE0(QHw$C`sBdI_HKhb7cPlZjkbOA`qzl@Xd2K3x>mpQ*@V{P zEqPzI9@aa)H_Q1NZvEXng&CnT=hzX>M|O6b5!oX%a*&EHx42=9}^o($E5%0frJQGs(i+>*2)_p;Qn5IXxRlJv$^h z?I=&GgEdVY09$M8M=wvfc`|=4mpc{913iO-ZS_PmprDJbcCjikcR39)6Bl!Y*X0}ZPMusAf5Tx zN_5IWeo7MG0>JGYDGZ1wxS%!^y%h+2%7t-QlvP$0^pA<41^@{fNd;TXRSfQy&&ES$ zqV#7p+22%Ca#OoF8-%H8FmSgYH>}8qnLF@$vP5JIF4}s1MfK}nE|l*ZSnc4op@-P1 zpH#60p0XO00|GrWCX}8T$ES9gnNY4jGcmP?+fubHlUwT#(80Tm`$&7olvN@P^G@W3 z&L4Du1ALOYoImK@7wG`>BXhYb-w(ys)Ib<%FvBs%2Lda($tXL-W1pPWpQ&Zls_nbtlucnMAvEVpuHn6R z!p7zuZY~#N`3DKt>?9;{ScF#lUOl|TR4=cuCEBTY6Dtj#2Z*W}6%vi9$dOxIz&E1ZSiOWJ z5Rzx$Xs_&hq(8`Xi|Lkh5>_>26Qevtp&M9^q@L%j=%?SUnKyoQkRMTE-(UOShO&>r zW!h?wh?~h+Z@C&|8(jv4=-c+Q;oHi4{5DLZvu}jU3rnk3({=F*pcya*^0U8609Lf7n1abodJ%)Vp z(!sH+c%Kpb1LDDIFa%8g6ET;mTm{swy=9qe26RBHeS8|f{=;B71MfBgnoj1vXr|W7 zr(|f%>V~3$po^YWcxpbwC+B^=>S@eW;G^rlzx|a4q$?c!-bWJ6#x$YA?olVZw5lR~ zdFzOH`loWGyk?7UE#4~xRQnWk^lpc9vxP~~nLbts)SUgK6i}CSB8j3iNaOG<9*S#h z1>Yk2FXu;;$}2JVfH;1s2()`t+=N%}#p2ju1>DTt?HKcA&MB$pe7DX}OTG0D$!Gckz8+0GT-eh{qQI1?vltZv_B{0|3>Moh&=qjw=}z8ZX(r zb(2-xqk^T3MDMKmf`74ulleL>`Q8iy5RGMg|Mg-8j?_HeH;KYos+H{vP}D!|r1r`Q zlpH}`+uiI(-o9I2#SNA^WBn7J-)ptgBsSa|DXI*2U%($ikOWu5{89g{+U zU`CcV3}5ie=8O$Cz+((AyneoUF-H(f{mn^rJ_ifw2du#*Vr}@}5Ejz%;0k|*vxmSO zL-bl`>;)Yor3$3c7({~!U|T1J^V*2Syi?}~*4r`{!a`1_Ec@9Fs@c~nuAfxasV$_b zl=#$+3$G#R?59SLz0Cz3g7RWd@#{8CEq$9$>(xeS%*xCX4W)jousg^Gd02^ZT`K|$ z>9UvuAm&I6@03Ms<)Fsic$=m8p05M9-{+t^F`cmIJ`L1nf6_+H*p5{xr)y8xGp#EI zRt;X^~?_w?4n^nxAtq^fk|Q!3xgQ?3{gBmxX2`m~5@a4^N=~)@!EC9EDKhoDVx9sx^IE*@psqCY2CL|l>E%ZNFczT*gSs6{Q>@YHIY+V zS1B2JFha%j8x8?3Z>-@6iaGj?D;u9C{G`74M%+9lt3XvFuyv|zE6+~N^_pZ|esXWL z^_1T9fdf`P3|~Wv3K#c;iZeeh!rPomNnS&_LZ`d4BvPkAG+#gpW_DDLF@$r*Onj1o z@u%t%H7f{EAm!V_A6-8PxZ0I~2r*VN{b6_wpZ6aO*nB~r{BD^S`rKuW^6SDN{3*1a z-_qxgo-wV+Ck5dxnHWxd%$N&1&1Ge2kwkgUzX0u`Xlr<^&8)TEun~Wm19J7t29gsX zTl!4cu0R*`@`~~Acj&mt##Ys%>}lSj{kid{N95bAd6eV3ttTKMOgt##4=a%j@@ zNS&@{zS8(y`IvX2HFW{G|M5F|tvsrI`DtMCUgs%X;_Wbdop~YrDaSg~Q;U8u?`E%w zu9tTdzyS&!FS2PCfEf{TY;^7XnLu@O9jOA*+2`@hv(gklf9US13RRkqOSXZkMQ+lZ-9BAsxCj5iFdy7Sy#52!Xag0mnk+i994QNgvg~% zDaXk&&O2b>cbi*fR$>AP5da>YvEc&N9 zG?P0HFWGt6vlXq^S7A2&#N*#e?}#B50nNx4F7y1~EtHh78}iB+wLJDsTInw*?9U9# z+Kun9;qSR15)$-p(}ScXco&1Io`y^q;4qZpO&XUt8^u2)L6|4EG_rfY{%|TmoGwIz zU(@+H%(-qt$h!n4ISm|z{ps+`2!zw14vnR|+f%=s`!f$Ng}yvb4I32kBO?oPsQESH z6I;QTbq{s4PH1cSu~^Dy|4eyr3Z+G#at$^#SMEe|3NzLJbBn4VA!7BB-nyl$)EN+u zSq3dCb$=$47U&}l_;O(rkF=^~c!h#{{h_fJcLl@?*nYft}X?P=-A z!sZqvQ%mNhxxB@N+B(LABmRoLJu^R2z8eK2K{$VE`s&2vR^UEK>q{cHB(FJ&VL+i` zEjfpsn{B-zRw}L26Ro>+BzslZvG4NrASFkNjG;qP)lnjgjzl+*J{5sX8eng`huHVH52Mx=Xic4m)@P;h6NtzIu-t;wMS%ch%~d z2Tpv|yxZ?Z!CXfMU8h;5Fil(-m)rXWcdV-l^4fc|q9Kh#m@roU$*;1pJ+?xiZ?)!L zjyk7TRKV?wOjwsc_Fx!4UQWq3G@L*M&&6D4`CwrDgl%&GIltEtrH4?pF+gyg?!>>j zwVC-W$({U_i3mYA6`UUv6TsKu!V1|@ zrFO?iZpzMWDtq4o-CDs`Z!b%ZVGa_i!Q93@lF9EMOuCv2O{W;-le`&y!F6?Z5-|(= zxGiNitG0`lT9|HwgqI+>W$n%h-Xs{w>IDisRCKs}E>Bb(9Niwml8YLN z5V=_82S%E(iIfg!en{AhFDjSM3VYTpU@p^!#=Jcqm<9U7!ujz_FHPDEfwUIkhgQ~% zj|Y!2N4ngYbFa!M^;5H=>Io|{ESYl3TQRpRiu5ZbS@uR_W-{G?e@UNkyE)>19%{>Y zp%|y+*S4T{GtioyPf#16BVwBOaBq%V>*yU_1;*yi zI`!H_@cG=RrQPB;{8WU8frQ_HCTY{_$ChOY?fEJ;#FdrIJ_~lARB+f_jldir=&YDQu6%_HKa^$85@F9Kqb4;%mC6(La_BQAb$U zBv^revLdm=h8lMbuU!m?I(+af71jV9KhUpHZ3Hkxz81h!qS_7Q4r>6Vpmg#TL;I(F zA7%Ohuep!?H!Kiq5}WFz9@ts_O?%fb9O7O5uOYsMG<(DI!w`fcPqv%P_x74H*V+z> z+JrEvX@sEQx`ntDw@BvZxi1RkLFsr+2RDgkmgVPYg0V%#2H zp>j6K3uxUHD%7Sbb$ijWP}k-V%Pdxl+a`@R>-d8+m*7W+(902gWn@QkR&`mszZq93 z{fFN0p+(1uY&SS6;TD_`+BnN~jYwulymp5gb0c3GRXG}mJ=ce1a)oEh+7)~1PVJf`l?-#(qrQG*UxmsYJHH7YD} zXsEk+jrG=A5%6SeXfol<=rv`Q@2a~lmbq$vHGiGG7T)RF)k!GFs}2e>5GP6+&dAN< z1bBvMgrl!oIgpf~ooaff=4_ONRe06u6vjflN%?GR7`W;*WjSPO#bpfMSVNjRAXLEB_ccxWW{is?f}Is{msAsU%iE z+GPu~2OLLp0t4ZJ9XiD+B15TkI?g-joSwcJ_{lW0p}K;Zw|bUZBje;jjTLOj)%^Sw z9J#Yq;$d)4_{w)dJ@Sq+F}z>cTPIp4$r8MPiE{lX{n0wRI`vXy8!zHzN-Sr5oIlx& z&eRtn!%VA#n@Pg&_vJY4kvUfg>B4y=|F5m60SSUOKO85bwqjavMAVb1*dbuk&fawJ zh+DADG9w&)!CndnhKBgtkeCplYn9}Dqlc1EBB=4MLW+?*Hm*d?RX0n!U3sv~dnym!Kj$<>`}LlJ-qLoRUqLDV}Fby3ZT+t{a*5x z?!jqJlHP^+Zjr}$BVnSrBt`hDO7&j1PzjRBo(pN=xaxT#wcPfd&U!6)`fPeCA1Fnh zuIyE3l@bc&em4ork|vp_DI9vB)c-CU4$CSH<1BXtsW>4DtzitP815Q@epG=*gr(bf zkb?e;L{{D~a7T*Kh$Ak(>7sO5`1CCCDFhj)^lEx4O0r*aR+e>of&V0;*qjXmwF!oG zZiy2|KLw60aL)!OGiy^mTy&x^sRZuM3QBqu|5L8R8AGkWV#4p1n$VjBzc0qQt1W}~ zeOQGTNEF(+JGR}3L+CiHm#*%zOZW4-F-k4sm22nP>E?dknaRqDCrH^&;0wIoI=-{V zSwhao6l&xy4J6BCk@dN8ic?f6A7#qi2xb%V4nyLv%(7Y`C=bNI<_GDD!DvPs5weHu zgS-b6mM9U?8Oz{mN2&kB@}->~iTm9jzR5dkW;@V%MUcv@{vzgvOFR%U)3-Klc#_%( z>&W`41+FZgvrk+x5<>b;URKR03=@-?q;^%Yu>jg4v-e)fW@ip3pWQ<{#`mwpuu#wz zvmXIC)R#NZb5}sk#|Be)_YskN%ylga4`#-60QY5Z2pxD9`@N8mH`Oq{FZ^HrjHy=Y z9hwKq9+P@DBrF-sgas+U@$!l*nwoo)LB70LveA>!uj%>|cdWAOqSO0RE83MW%E~?) zf!>@(RPXtcELP5LtB9BsirpLkNOH6$cE)+juXJsE*))A3?0wBc zYpNuegqJ;nE6unq;~#11?YP6u{2R*+Xij(PYMCp1hhUAY7@9@}6W&JGtxl6ZvRla< zbH4^qw0?F+oZ{Ygmd+q}cpp{*{6=^8cht+2kC%E4z%mUvkq{ktiir4M3qlKSNG@Yi zPfC8WPa3q~P{H5#M)gDr`N1#CF!cHLbE`IRP%BfB7oTxlstg-+0ze-06%oWhw-V@- zxrGT!-E{y|3xt04Z7(RHX2=10lKGB7oingM4kb$(%RE+z!dpp@ze)UCZ@cUis*hn> ztYqYD<>ENUSAx%p3dL0 zYg_v&Mv>Xlq^sR$wWas8gcheNK~BD|V|Mky7^44)DKONa3}S1g?<;Y;bKSB5O$p=u z`|_rX`*#wp_ph+VgivFUuSAD8$DEhrcJPBb^#+<)pYcQ2{!YylgMo!753>^qWA~+u z57Jz*uC|y)R)q(}8fiBaVue0?4`GH61!^_(g2D_a(+>v-ZJD1U;3c1JMlF@qbWz9W zQ+eh2xP83R<>NMX8d$6@Cv`PIl)qf@sk{{RI>(M+P0CEw&a7K-WAf<`g0`sMqfTVn z4HhLovVVyRDYmUJ>0rB!@}o9~2;$E6>~PIJDDX{`renW{loh_#ZKz3vU(KN^WQ-G- zgXS^s=|Qu!6V+3BjYe5qc3b??tD!K&bApe(l*ZEoXJ3chZDl1!S>89I6e}IEfK<(@ zI4g?({`7%oew^ng#KN+5X}hHw_`4c^FcR3fDwcP;MSpdE`$dI>TRps_M2O^h?oBX#SdFp)I)}7YB4jFT z;dBSi8d^#I0=6FbUv2=ph%T)PL^~RXj55L4VU_z)<6>fzTEi2f8WJ9T*c(Sn_~yQz zRB=8?7u-PKA^z_z&KlxN{7MNzmmGeR&Ja6q2mGyniVS0J6(Qpo4CiP9H< zvvk7$!~dz@uFiOy1a`&dO4asXi$MR4yY_qK_kUh6#i)KIZuM};OEo@-llQdMw$21X z?&+1iIp#D}M7GRBTtD@=zID(DWDB|m`TVz*|Gk(0HT_?F`Fj7S5Z?c*=)Vp5FTQ+( z|A_ean_$@Ve~;V!KY{(9^tktYBl#v=4;DeBruzDiuoV5LSW5mQEbId5mETxkzW(jR z<)%cCuNjl=|34EGeE$t->_3l;dGenEI{S|ReLLs+8xZu@=l>SJIh;BZKb>AsbsaOCw`Pd`5bDCK^V1MwahFQ%6TzPC7al7Z+M*GeaXAOFe5^8+#MF zf3(n=I$BwN%h=dDn%P)8aN-;2>FXKrFyPx88S^mW8ye|b+89{yFmTdy(&Ot{>sh)v z81c}%GI7$oGB7aVTN&|~8oA;-IO%_5<{Pg^s+kYhf-GQC0j*YRggOMW-4I{pzsr`2g2OcJTOB)*t zJ=5=u&VQ9L;5%5F8GPIFUj_8|*7pC>VPIyZ=lG8uX4Z~I_Lh3zLf_^3mQMD1ZaM}w zRPG3jQP|x-s6#6>) zW_k|)C^54)`WG%2BQq0INB!?Q8(Sl59TOYd@7jMC{sYRw$nCpt9!3`W|0k(qWoG@I z#dk0;vNkesa^zvA|Hn*wy?=((-pIl9yScrA&i@OShv}a@kAb~0zLoy>xc&p{JHx}k zPD_t(_YW8zdRo@+r0qW)|La%Jm4}t%yTHNG$d-p0-^}*gN#75|w-3K{>Dhhz{~vGu zL&^^Lzh-NH>@W%q1opgz>#}2VIYWw;yRn=iwf@Eb)}+BFkj*jqX_|speuE$JaO)c)J1ymj8I$aB<`z ziAq=TeK0|qHk_VT9e!@kezmg5)w;vUQSYG%QfL7F(-XE;1Svch6^j^z(@~>7 zh8cbAy`(9a*{eWC!mLLhzy*77@Sd*`HjELf?VUe2Kc!LZa)vSdwOL%)Afv^Gj}GH2 zgV4Uk_>RV`K!rM}0}p#@`CoH7^3+i}Xm0=->5c!ep9@y^0rlITdbQ1tKT9Ij5UBL- z=r#!?nxd+|N2ZMasyN>KIMK=1L?duj289Xk+jE*~Gu?UwMInjVXm@V3IkqQ=lv#H4*vT^#(Qe_`8oG$B@-! z?o`8-oUh`bSCIR~lL}n5=FRrnruG7jPV0q>^&c5BAxQX=H4(dJRoCW!!YSi4pOw;& zX0zl5B0fqFEPo~w{mg*?Mqw6z@fKAxkc|pRYuWYnlFZlQo0Xi{We`gd9+ufwlC!OE z=VSGIFKhQ6gPfAZ4;D^9_6#QH3y8N!agwBjr6GE|c`T386Fg(v!4;9XEb4&}bjU(6 zllH=d{uwGZCXP?|`*MDDl@KpmrS*#|2$uAd+BCGE47k96=o%HnWq@!hN$A~mZ)+3J ze$6M^0x#O(y3`bPv>L{&lP01WX@#x_rZ-Dp7tmg)PQCc?f=T~VEQKVU&IYfvqCG=W zC=d3vO%|k&aDwo6vvo0RbmI@|&5onR5ZQ@6hYlQ>;%Of*JH zC2~_7JbI=qm{HrsnJY2qARzS-%yTcl6h#d}k4$A}qHLel7ba2=L5$}#>+mCCh#|W} z$o^aa_F=7sD=$>?Q5N7UW{vNTl}tlJ@T;EsaX8ArfJAn~C^oGBl3KJ)n5Th^JxD)1 zbzhJi3%4ob?98+#IvRKx_<8J9Cqy!#OWm^NZA4GIJE+c>+(t(&@R2<1c0iQ7mqt9o32tqk3o9I(hn!HN(`7bH7k>~xV$+I)ck`h`9tTNZ_#`RK4cBO~W z#uja_YrQXtd|O})^Wr3vRYXrhZu|2LGoYgE=tlgsA-2d1=1~a#Ued)vy9u7!=cw3O zzw3Ujt^vaDwfxZ?4Tkcnp{lP)L?E`0XJ>t~sAxOO>^f|9KN-WrVFQ>09h~N**L}0i zlj0sme%nOSycQHrWdj1M^p=zib|B^XX&T)NyMtaI3SwvP1!aLI;=D#Z0>JOO*+_BTjn=?0*hA zhWY~J>XtVnbGcG4?qy272V)~e96`p@siEG{uBHN1VDbX`b#mny@7_qU*o?OL2CTWA1 zkK%hPeeT5uY`hs=1#EZVrLdYbj2w9W*Gt9IwK~S$mrP$CCK(@sq=E=vQB&VroK2XB zPueUJ(6XB}l+ziEcmbnEaf$P^MZH-mc zkOt&nRHa99NlHoH-l0EL;SeX`wKyi{6 z*XDe7KZkNe`7gI<8IMU}BS>Vox)H%&peZM<%lN(qlr32|d(z`X2OZ7i_uWu>GNb9F zdseFj7mCy+hNmsld6F z$>~rZS*!9S9n8s1ihf8~l_1CGkt%_*8VrZVTaHSxS|1GS(P+1PMCHDivN_f!TW=qj z+mid^pAM#xHFycc-*Xp-C~5skZWNB?)VVf{QKd|Q0G1`IYFIL3Ahg##Mm~!1S8J>) zDUiF=&{5Tbm`#5R&Mo&;Wlcu!qJ)8+ktKzE>csXBjW6|x?K~1L7IAB zKi&ii7(*I0&VDTneZyt<%f7Uby%=js6q*Ep*{*jwmt&HH6689GwGX|YZd|F1hBX1f z4WtFFo^bG{%{G86p=>J>8+=`vV*SSRNUrqci167dz)PZ=yxm{({LACokGdGwK6EcE zA(L(q{D9dt%9kzs<^jEw_dA1$Yu!!CnFCQ!-8F6238``s@jDo*S@?QP*fw)1D8X=T-NuXa2#= zeqnh}x#RQf3>$7N(37S=XkxLaOgBJxRm52Q6cqDfiGe>(C@aM`GX@IpR7bR?etPL0 z1erVV-Sml_ooN|u5)ejvgH%rooC!6pKu;&FX0-p&R_boQN;{j%6zM4b=ky&ES*Jcc-jJP4SyZ<@C!Dw9 z=H~SYa?tOnI(w7MGjQ}<=$I!hb~@KA_Rb_`g)!1e3EM|hmny=k@$JEuLVf%=l;O>3 z?9JNGIFJdnom95C4myhRXK;P4J2NgEU7Lut}(R} z1etp)sVw(tJZ$7l_~Xckdo<>k7_gS~X`LEf=k6fPGVofKl8Mn){kG~5-XGVPpyYM* zKLK<7d*kP9{Xj@T>Q*`P4pMY>%=$=LiV5ZQ)29xaj01`KG=3klyW!cativ608Pbq? zngtW|#a4n+sUe17S*W}GS#H6ZA%|XCXo*IOOtG(I>#QJ`+-s5pD9Yi1I&ms33OnC% zok&Aq(LbT;ae@j#W`{n`-IG&(*Cg-bm7+_!vviAGyMyHOrXYRh&K>b4HnngvJ|c>* zPgNx3tu@U=1BVh&J`Cv4EqelSBY>s$k3dI0#0z3pmWxZx2iHPGw3zb_fAZ$3Pf72W zqSgB|YFg?-q<`@E$SV0;I@@_onY?gupVI$NFS*uKsDC?J2i29zl_U`GAAd%li{C8J zukdq8;$0~L2h0?yQdzpGqjR}(j;A2I6FcjlvE)C&PLN`rX(8|&t#3T|?toj8rsgqn z0X2|p(0Dq@WVE(;!c32#Q$Qq-nhZ%JX+TocfY zq6M%zVYWb0XI%RA?3?us@yPq@4QCG1E882hqzEIIA}Y9FCA7^?@grK4SXnIbPM6QS zWTBW^+K+Ag)O!X5!W|~{R_%o55-N!9XEGxb~sGHW2uNwKP5qzl4XqQy`KuX z;zSt=oO`VCz9vDPkm3n_G}1ECLq1>*s|^e?Zed`K$6!IS^!*dg2Dq_e@l_c(i9=7~ zw(z~@Ohe)7u+Sl7r^*x`a4+A1p(EWnPAd}E^+?Wbm=}>oHQ&Q#v#T86{rO_317!Hf4IxKgl~KR!RkemDrICouWpCDm{G`r7~pj-sG+N{EIl#W^_ovGVPX1 zE^03;PC$pmdW)JHh6J|zne!EUH$N(zrXcO+)3#nq;7oKQzv!WypHu((%_PiH|u#cd9wFT?V*wq_F7%k_%8IL{OFvlf4i4Wt$yq44tOj|~A z(*2~$;aofe?frl|HP(iy-0B^@meapJ=2*8Hy0wYvbH$|FY6Ss%vYqREx`ly3zrcmX zUeqCdElqE|`LRo+=U`IjN@(1)W_{)Pgi(x1U99WoJR;2YF16=r4R!}87<8Aw=wghv zRw^YftL*rK5bh^rd(8M{AVYe$FGTJE5){}#i$N_I8CodFcd?{Trx2opF`)xuTf?t# zRfErC6MM0SN_E!c^lPZV`A8A+tQNyAqOAc_*BQE_*9LEjvlGpMiHi6E=xq({!8>hNNDqZC;jtLM?GW@;M zU@(2j0pPW7s0EiksL-4y2Y2mTvaEb!lE2yp+{8D4s9ao|VJ8BwmDx(u2SU(JAHW#S zj=7X=UtMazqCb{5G!F2o!QdXY65agkTmCc~@j>jM>e9Q0jXxqc8SxA9FwVQZHl%c% zqRPFbNykPXYmHi@fnr5@8j}UKHIcRFWg0 z&IQr=dO_^Yc$N2m+ZysR!~4Ar06-#+IXGS3=8k@mrIP1h!?~SWk;GNTUK{FK#X&ZAVoxeuVba6C5PnTI}xPj^Vl$vooxWHQF|`JRtsr3f+a*F~^0Y zVJ;h2aU0}XSt{w1U(#eou)gjQlW<0Q*oVxlrR2=6ATuc zcwp9=V13{nDNc(D5!q*H{Z3ZHJ^ezOZsZ)+FV}LCqbSie**6)e6xV*dA~{oRZTGWh z`Td`BIIZsd{)FaP*-^mV28yZ0ndQ`d%IvxA4-zx9;X4ksqPdoO5T@ zrLE%#hrnBfovBiKL(k^R(Z%O68C;j9$mW=s9rwRoY#L4!vFT*MvPbRT&UPE!Zdu7d z_-G?TP6t=?A0@X?vw|3*5 zFUKMn?v4XO=tU_ml=FwEZkXHML|z|&dZQ0MsKZxD(Z*cTv{Rv!S}UlYiIoj*&IsW9 z<6q#@UaW`c6Gm&~@rW8Rc{X}=YZ$OrjKmM83GDbH9`AP{?c(gCy<~%Fqg6Z|kC?IL z7Q{9V!FCQ)i~i~Xt)qzLeyo1lMqDF?mwbKVmE~*6$RxyrWQl~wkZH5QCRuT#J1D}7 za%`=Pul$u9$8QlAy!F`mEftl1E=afpL6=xF-bzTkvBXyQr+L*>vw*@RO9xJ#=oqvM zZ-P7)fORo8)T_qNQJ%yz{&<^JO_&otywDmU?u3?2>9 z4>MB|1stXKUW)i0r)TU^gQrn`4Mq!W^fme)L#Kf-@^Ol41% zEa=pJ{j1B8JoB}(XTrn@l=1oUXWMluHGO#FBSphS1!!(PBQVr1f8_J6(3!R$P_)Xn zBAO7^na{GatSRa2_DuwIrI(RC6RE3aBH^MBT3FvYbj~sah)9LLnRK{&+~q;yTfV5KoCIPxJf`g5RM^$G9`s7I#*s4T9wbCYH1sRE3G{&Cj7` zKC8q?&*_j-Tu?aH!OsBOy0yOi%?%da`A1Npwxkj}7Pryi%;yiOm_Ja30P-u9jSz2M zZ3fVbi#b9z@SwH#4CC+cq1#6)J!~E!!lg3%q22S}74L-*SG;l)9Eljt6tL3PVglBj zZq0t{-Cyt96x*G(l8%K=riXE@1l&fDrxA# z5O^!KmRn^&VNDb=FkJPjR$&6+c_k+vKAPm67CZP;z)ceh3nJ@b=YoHDr*tIW8h{~3 zTfJ;Kdn#XyHd#%!4CxyB>T#b{>*_aFzSSE?YW$|>n?X3m_AbJ}Me3aildI~~@V0#v zYF^oq){A%^506WkAqLi0qf)LawCteYKtCKQIgP*3@$`9TBiye# z=msZN4oRd$!!VYka2AoF~kg zZ2LRaCql_xDVP}X3M0Yl*p+?L+*rzLpoR$?8gdOW)l|gCJhDq)=GG;yJmw+j;0qucKN_XOW(JBk&zRfl-LOQBRd%v0a?npAL>I+1j3%;zf| z*V(bFaIH%E1nLz-GuZEi8nDdO8`-XCw5#p4BE=ulBpdJ1*5`%Z>BD1XGj~Da^z=ym zjR6AiJBWEsl86=@6AxDbaj2YlMM$4UWMLJ2B2EM8rF?6w3nk2iG38J;J2xX0eNWc}#W% zj#LG#iw^n>rhCN=L<1wUcp1OQfc9U2RZ5^EocH;??zNCik@&b3I0tvuetL;t-aLm%o%?XylduO4~y^+3=I?`wY1+uwS=zsGIhEY zCB=^PWoN3bn#Rw;b@R-+R390k>b57o)Hi& za?J4*JLCzl0{FI6B%he##!i&x)^3xf)`binT{4j2AQ#5J+^(f>8HDsJ4cA!oZ-qDj z5Rcl`q-iGh6$nI7$^ki`EOD*aP|~-ug$DBj3ccc4Kpi~+W2qFhd(uX3_q*1 zPaBi;+D76IZ>sRk9VS)zJ(jZ}TaM%_`DSCkh*uCJcnD41@NR$chOyN`ENW{Dc-)5F zltGKpJkfSy`Hw##9)=Z4PWvG`lAY(z(gYE8oQ&DQ85Y3vcyJP;4rHDU=jS6!JU;jZ z;u|SV>)`NgUT+-Sj7hIa>7|jXHr0dG{%Lvo8jrYudW{cKQ6jk};ZYf128#bIB%f40 zhJSmA6*#Q8yoj@Vl3jzf?QNwPQrN~EHgqBEP=XZeU<%_6fSO%&e@Uw-hq3!TGw*w5 zoqR~|d$JEi90z9cmFzE}+}IU<;y=`E3^$@81YP;LY^`c9rocKKq54-qvq0&>{QfMI ze8m91E#jh3+6bM`zo05nR1scmksWpw4Lek;aH7wWyU#gcatD%FJ$rA9QmEzon|@AX z|MpraI#)X{K+FMeG@93$XCsLjQL1zZZHvPHWIw+Z4JT6a3)4?b897ZlI`zg>R|jn6 zUb(V0Ks+)}+MERZnfW&Tl3uK~TE=6KyOpa?kLmhy7h(ZIVXmbB00RNay2DN6al98$ zIw_=b3{{RnHiN3E>M6tiRg?L{xybko*P_l3*%M?uAE4!>knAz0!7Hi$<^+uWK@N;K zt=>NWBLy9;{6rfgY)@iKoev&@*7to@;5e4E^}NZ!!0AHxP_j6BP%78nTAZp?FFXJ> ztM0s9YJ!H+MAK_n-rayYg4>N6zds7~?mB#grL#?P)Y*12kY3ZJrSpj=r3~q46d37r zbhcuy(D4m{b$&Wzp!~pQuTHfW7^-?G`wD09c(mg;^e8Dn7oz*ycCxMcZ~hr7lnB-` zQWp4C+jDL{eP|5wC^5^=lbHdD18nZZy4n!}X9Is={wJsx(@%;e!A<4GO^avy(SZ!n zgz0Yk8#=ZUBES{MtV*>N!LJ+W#p7~@IzDDKk3fAU%6IF4_{vX-{Sqi8pd!SGo?vO2~!igk4VFS z%3;V?Q<`&kX2Aa!qQ!2<%ZUs8%LR!4{0SpmoFX7vJ?rISGtgsSYIz)eE$~Cy;9@8< zKsSY3a$+Arj{-YU?ycK;vj1Hj4U|w)>9Otg|L|#Fbpa7iA#^6+SMrbk#C#q+%X`!x zWzNg}EC2IS{bfe***ZFGnZyE5Y?HQZt@7-=7jC{HOU7umIIsC%J(4SbRJ){|v_;dN z$aQ&;-SsB;UVmW_5zD7ehq)N_VjPaaC8k)@Gv8$aWkM&IFDgCNI{U8REf8k=5)Zao zGSpE*#E#{%in#C0qqJgz;sw6c?Rg<>bEUSt#ktH7ylC`l9cjYV5yG0)MiTV8YH~R7 z$%*1B|266?vLaof0+m?e0$!q3@k96Kx3$LB%|6QyZoPQ*y6yH77bVAXsW;yYAsf=5 zzj(g_yZqJ^W6&;C9`pX|Id0Yk7is*HOj&g3Oc&p8BC2H|3-iIVbdi=)Q}*L^o+c{w zoB;1sBsL70x#JkG-y8hI_eZn(PcQKlqXkDm{&n5XF3|SlBL@=`#iad1x zuN$M}#~e}*M_q%L0X3&_=*&84ks(Y9NbCKN3A2^j`a+krCCw9H>%_$dWyU zwdriYx%M3PJukvZ{QeqeEZccwMEYF3gfXCaic!f;^*ZrDG8pc3po_`iA_m^nu)Qje zKKG-a(WHWNR1)I~Rht+nd87@i#LkpWw3hjBaW7(efe<~Xhzfl$Ae z{{Pi>3q9{Nc5?6l07-UVA`Cz~IrfIEGKGgKQPM!$+h7=7M8QI0SGYrRMpwEc&LDrn z16WK}W)gCO%HHw*&KTR@SA4g%2X4J<3>> zYArMQ383>J2(_*~9%Hb5^cdU%eHGR5O5U9r@-y-%U(-O({ej#Ba|tpC;21?OHv|-< z?(Qlk#Egl|0qe#SK=lmTPFL}#K(Fu%9gmd6Wq<$n3*-~!ZQoOUezt3z@tjLVviFeE z@}6ki_#u`yxw?Jo=pug+NBmXo!Z=Y9#t8SEH%k4Q>fzx+CkC&>=8b0aHz%O@{zS*j zdXrNe=lyv~?w$ZCYii#+>=3#KfzeYagj>O}?vwb@c+a!_U0ONfG7V97MtvVjQp=UU zTao0=OyO%-6k@n<%Q3&Az2jA4*Ja#-zVQ{t>+-k^+eg4^&5!ef&GMf_M3KOX#=gzp zvXMwMoI^@Cc2AAarWz@SSxURNVQx1adbJX;Wy570@OVqzJoqE?~Q(tn5O1 zN8!i1*1P6D081mqC4#A*F|>pfGY6mnsJ*Hk69&erFe*sAg1^&6VJBZ8o&AU!n)W52 z;UfU2OCftkRaSyBBo%Jnz3_V)gD`zJf69h8bh< z-hZ&3L_h!l2HlGB8S(G#v0KS3&e0#h!;?}gL=w3l-@+Gilg0!)Y6FyT3=f(EqL3eA90Hg8XB3jNU_u^+ z;t83`?WrVV{6;*THv>S^;K|Pjq>jV#o|XVcW*XXU+R!M;@uTFf385bL4&i#nL1TrE zEP4_hYj2(*lWv))Pyg~z@`nDO?^d($i(Xfnx0c3d|h9 znsJPi@+n%vrWjxTV$~Px=8@hMT{cwat|+0;9|`m_4v3a*YfL7g@)kH9B7(Jp$U57? zFlC`?6d=p8X2RQetLG<)eXSZ6y}{tB{93%!x}e&3w0^(ASTz@{YP+ zr8$TCp-P-*oO68>uMdB`5*+te ziYyQfW8OnXcYzp5^{=VUCd!>C6*l%!VJv^0Q=6Iw`$$7p801Vpaf_b~Ut;?n(&y!Y0|`^VLv5)eU9EZKftJ-xS%3(GIjK4Vy+9ymeX+8Tk^*50)L0Fw`(XXSa*c zcdOt+yryvi%N!2Ae`YHKNX&Rr;*kNLqP_Z5C!YbvD7ed6?zYa9Kx3U`?IHYv3oC`ZazSnvml%t+*tlcyw86j zdmgMLZsSUQm7IR8p!KMce^H|M*nK(ldicA#Nwn!@6x&e2oN6u@ zl)fN&kjz%O{DMUV;TL2qKTZC-_4la~l)tN7?fd*!vB=e=%ibcUf!EnojC!7fZlj(m zs+*S*8EX`po}DKeM6EPX1FRM9_o=T~C7+dJSwd|>a@%20dy;7x?PuXU+z1hk=OiqV z01Nsw7E~TIk^%cboxP;ejA70aL*&zKh2 z3sc_D5VQ&L`jY;cZ59|6hWe6ZZBEJL&Kr5ni-FWW$Yrg+cVkUO@NX?OX`hEbh_0~7 z<;Nqkw{ZT70TL_M=EdmaNaS~LtA-``rm@^cS@3%@4IvWN_$@fF>h4Mg>3S$@ehSj1 zq{@#on)NHQ1QAwzcyxr_VO50>81*)@VEA9hgyM8+nu!5cyGnkF>aHdS^wZd?Lvz0M zs6HuFD$+RqIOrO^;{18fik~02zOqG?1qn4ZBCQ|>II-}ha$%zVV=_E#DF;@6ShaC~ z^xR@)qzk{etO16s=TUEQwENul_>&Scm|3&T0Xvv-j<&{gRuj`Qe@ur&yk9U}@W2~F zvvR0s3i~nu6u7*V0XD_`WtU&He`$2M9yA}@TeCe*Qt5lk^q-ShNzK1_SXY7Y?eX0Cit5&9ARSi9hRo{W+=4#U4>WtKHUF^=tqE1AcG*>RRwCQgHv}1pxlWfVR#9MJ3BXY^_T-e0@}JcDL4b&={>QGJbrF3*rAD>pG$dV*=v&_d3;6Q8tHh z01nxgb$|XDy{bXnzxt(74cw@SfHNQO=)=0%dxw+{n~ZmS$(|DJy3f3jj!;rIstoE$ zs*siE)L=O*{cx$7 zNa;rWLeID2Wt_<>znn;Vv@pC(ZU2aBz02loy0KJUiLD31fBjF0pPP9YUx6x z1e!|Y1w+_1x|S^n0YaeRezkzk0JOPFqxRXqN2=IhE@k=Mnc|!Nx1kx=tFK{;{d&Ex z(k94A&!N^1J+?9kHz;AaXy*j6xzJil8?(>5{-8S!V$$58&|w16zwuob-;#e79YQUr zy_X@!0}Zx;ZNA-N(1EgAJosH;h4aUX9)D;cO{Ph8MwJ5&gk8hzjtKg_#NKxl!(Gvd zD;Gopk3|8ZODT&H6KvU~G+2M9e=kcY8kw^1^FYnU&Q-PU(*G-7D|JZBMZsGkAKrtxi7S-@9x=jMJBjXNoIp$bbYWt z7`%V2bkpGcR-a^hhAUtl98C)S{w*k)53G^c?L3$eS+5jp zII6lZ@}Y@ZF1A&SbYH~&$*+1t#Z-9(sP!vogJeQ8 zQd~n!tJ6h^G#QHmz8AHbe9|YBMO$-F8GrvQ$3pXN`P$A9dplDK=UjebzS;sbU0+|; z5EqdzsG6~1)S&M(V&S=beWioBv@q#`N|5biZqtJ6N3$w4^Y62%AtxQjePG*S;zHpn z**$1c#@YtDTr^rOj$p4~QrQS!V3BQGnCK2b9y4$4G5pNY8Q~^|26%orLqnVKn9sZY zBXpT2+@J{63qka(0pU<7jxP@q{-6)8otIMXOBhow*W4x4i03Dw910WI zO)*p7HRR@W9HwCj_UN`3n8w6rAp%r6;;*piUVT6I#wt8OK z?5bcQ^r7V%O?e%MdoN07t5d4bu)k3<-(RXY`@p?{+CTtr^zjY3=W3Gs-#*;V|Dmg7 zm`_L4S$fU9q~U_{mtIMGj~+k!IIm1Vhx7m@MzU#vQ^cp;H;wG+BXha{G5@2c_~&SN zNA20sc{Y(`SjoahV+1EXP@Xlyhv@f5Zt9g*a(#rqb+Z^03<2n$rlfYJ*Mn)*CjJ9o zl|ndyLiI&F@O4JF81Hnm_EL1mn^`E%B)-M_yG+GqC?31{1`6ADJCw69;#FF#1+Ngq2J)}ZRkq{v+0F}f7WD%H3(vA zOUQd(aNE#{q1fNL{KgSf0*6sUU`UJ`>I=bu0#{jp3t0${8Ef=^jBc#_Z2)85i!oqa z7a`r2D-nNdu)tY1td#D#|BPIAp_+`e<0_xJAdbSJz5ic**S^OSS(ZJwt1ltou=HWd z>lbHTMP8|wD)?ta_PvRUAD}nNw>#JYVUAj0T<$1wqmYN+aM980`-xU6I!}y@xE7c` z`!7#rq`3@^wcOW2XJStVSSs%+j4fa@m9rNQRoZ}S{AD-a`@5V}!T*EV$Ef*{(0?`3 z2Z!ZRGkwF}K0HqZsBaWT)?Kr-q$;`9OC>GG|6KeSG0C66#D%qNTx9UUWda+7-H~on zKEvwAm~5(b6xAeK*QL(BfTK z!VW?si8_KBJ>yt61@x3^anYAL`IHm#RbaVV5>RUx^9%j2v2SYai{ornYJ?5`_VG>q zsc%j?7l77dVrpD%r2eZYKk^)ZBTOZQFQ>9@C)0FfuxVd6Ys8iQa~<0vK+nKhE0(L; zGclz6(T1}}mh3+i>2omM2d;k3so0zHAyAT*Klwk=7hOgj~Z@1Vs{@$dOpNS_L&VTgnn)y#If^9V6 zoS}+>y_7Fv%RQ=|R5~|9aNx1@2`>ZP)I5 zIvhm>-dTG@_C$*RrNT7amV!YzR6~x9{63-IS&jmEE|bXE8p)%O4+oW%LvJ7gBJ>FN zAxP9Y_87w8Uq504l8GLRO*T#DBu%$)IQ&aE4|q_*9R`11(I2fo6rw^{iog>)5tBgOV@K>RQ39`b2MJ`ZUEJ|^}3?)|@K6kMM z9H*YYAKMEkxDEFoHo{(8ura{aIP32vv`Sd=HyM#&Q%X4A;N7UZ-&%_Zx;Xq;mCBYS z;Sw#zVoZTi7ACAFDvBm6XtHIuB<%5VmS#DAf#(J7j( zb4GF#*e7p_)9E;lhdUaRVBl3tVo`_vN;mnhm6+}Yhz|g?mw<9pvr*BX`q1a)DInM( zsD3h=qE$UxZs7ie?;*fg#a~+j5B@#Qb#0_=lv5NWJ{PX=6v$2fFYz5l`-5SQNp?2s zSRja6d5g{|d-3bpdb- z20=A652fEq)wm*$cosYna){ zr$yOj9s&EPKB?@ujJv%LF*c`J$!QbG?-hcWwtjU)rexZn#h=2lDhGVxipBZ0s#WK8 za&4%#S;N^(i#xDp)1L<8wp(P$YhKY=G)7EoMWWKGY%{MKX@SkpPVTK?6|SCul&Aj@ zm4EVHB3tj>8Sx^=^10IyBI1n6!@`4;1=BSaD(is(CkmX^q=-Vl+MPzN=(zaU|<%zGARSq)QmhYjqe%8rppiNfkW%*yW4>N zcFNmU?(TFu1RM({m0%aNaY&z9WNioHsbpP(+!A_#`(*hpC7?yQ-Y9D@aNPJt!_YdL z{fFYnAS%LCb<;kqQ)TyZ{jNaMyECFYYoAMV>7Sjk8C!ZU8Dazf9t5Y&b_wz!n|yQ% zgd}b(cIF-gv)RA(%@~!!gWczTeTn?F>Y5MX_xx>tot>+Um1ME2&8o`LyqzAY zBY!X&Si6eUl>gNGmmyM{S9HI;p-?w~eWa=G0&^JBU%C_cAtjGZ!@X%STQB7UzGp%m z2}xD3Sm=duShx6^UC6Vxk{I~p`dad!O2#bTR1R=9ooVp=+$_TPA_lKATy-OvTM53) z{gK5{6MxE1MKSmsf6S)GK+JN)F&Bg|Kt}mS@+8@GEk|(Zv6k|a&7RE4a(uNUnSyg= z+NWc8n5>3v=%IDp*yPVbNlZB&nQm;g?n9V+VY;Wcb01QkXdlKt`?qlk{bo#!s#yNf z7oE!i2PqH4qetK90#QpW%r8sf+bmx}C8F!*q2{$T;%ps~n%3r(RvKG=5J*v_88Gmm zm2N;XcZrR?55DqW5M+yvcU`Z9jz*t>%Va-&=Hm(`qt)&zo)f>#=pql8`l#14&8{05 zDPm$D6Rwg%UqoTa%Q;=3=mjf3_;vMrC;$Kh055ltt6~dd>J03mJ7ePqjB_xvQ~*6Z z!2B?uJa=xlxlzlY&f928wv%dmhBfNYeQxF6GR|3H=}^C&&|MxU*2ZT-Z68qHzs4{n ziljbPHLlHD9CQ%PTusFkykOBuYDPSzLf%dD5SqI^FY?vC0@t>U*|IO8yOgV$@utl| z=QZd_OT}G+&?I6G^xPt=W2hF^jd3}suB|K5Y3nisys*mSdZ;LV8SG%RScbsB zAVk?84>bwzdTDL%e;I@cB}$+75qi$s5D*VhYdf#XS?frZ4ZelOZ_hmh-*e=Q z`i)E}c<2QCtJQ{Cy``>~QPNK&TvGS&D0wuR;#_>y5UQ$roYQYN;xonfabXpy%|KoC z<@tUlb(=itByf3jVSLTN0hyF82Akp4I508=u&3HkUqo~sJWE0s8)j1T13ExkylY_~ z6)b?t>yg+igv}S43RvF!(A=}xmJ1vXKja7fk#&AaK!tx0HoN^V+uey&z+<(6x1~b! zzzQx6ST?^<*qUlPcR;l>@Bt-mALQ89#!rHgrnD;Z1|4&v?Cnp+lFM|sxC$A{|Y!4}u0-EVmrM5pbD zaLZ1HO$qTaKT*J1(&^?#h2SU=xTW9j(_Y zs{f`g4QZ3U;ncT$GIS`Gmz+8F;0sLBsGHZ~tYF2)+w5~`bS9wyc`>9z^zw@H>EXl7 zsU{u!-Kf=|$VO+;?5tBk%d3-qCdkD{@Mi7y$(bcwqi`e5Y7F0RwF-op^bUfIL513D z#*_V!vGk*t^m^!V%y>tBn=XV5lXQF`_5q%kXn7>C>xKcBP(g_#hh-CRU9J+lZ7FLG zf-;e)#K|}RmV42m3HN7g56~5{=30RUcUlooleBZEOvoV<_i^ZGf(me5z<)&=1c>-1 zcHqGLKJ!q}cPZ^tr8du9L)QR+SH~oWsyapbo=Og+pV=@KuV8t6ie&!R34)TTxWMz( z2Iz+=Y7FeglPuU|MCmPoRZCAtjepRxN@7kCK(AhMKKp7xv0NSRHZUL#yPD-vR!w3# zNE#Xcfo9(A6s7$;tPgXcC{`{Q&i8$udT+P6--Q>R^VA4x@mjAa;UU#+H2E35vxH8~ zB<3>$C7fB<9Fazj< zPX>)#OZO{xfDD)W8DwYV2i{3B0U7fO%N3(^#(!Y~qlsPq`Dd@^P#ug{b-%fxbk!yl zX6#rhMj;$^p+*{GqysadlV9iZz9hi)t1+%Ye3(?cA2Pf^-sg+(k#p33jVVMZmjLP8 zQJ?qma``fPD=bxdEhfNwmctieY;5*Ta!vU$X7B>*lL7NWpi8{FnJ85VC_Y&vrnI71 z{S>zbGhh0XN0}T4FIc@b7Rc*8%|Kme+f0#%sXqexbgOrdzFe_ZbZ9k*Dg~?W&o4%{ zv~l{Ga5UD`bq%ONmuhb$d9JeRQmf<7^ItNw1%y8FOp_c{N+s0kUbEu4@K;+*!Vdxx zW*QIknQq0(j1?poY2NyImL+f`lDOd$1ek;TgAm=OiMu!m&pe~s0;SYQk|pL}qOQAg zk*~GYAgVS5g`}IW^Uo?@+ABlo6YiH41SqY*wU$9}nkz!Sa?6_&&N3mmm{*;dQ*`b9 zUCkYxWBB`DY0%8|HL3BJ^eGGV-0X5ymDd{TT7+C)(Y{mINSXXuUvz?L3qncUItx-_ z*={T5;Klt+Mu>-9%MUP~4x+&88&kRe%7Zs5ZR&G=yTud2!?qihtbmp?7qb*l=zbgmp{+4$j775(F9~cPyp6?s2G#rP^1j< zA9?Gu@NwAtYx)7g{L;&L)=tACMQGEeHM&%vJQ@IL`p&g{#K^;Nt*{kh&-cgnZhLhFj6ujWTabaBhp+_p%Jai=~*lu^m(O^|c#?mW%Sa!^u9mjvnme3E{S3 zpRJCIfeyE{^J1)Ra?9J@P{kQ^$>504XQ(496asj#w|NQ}EB<0@RaCe(s#NTXCnZ%k zf1n+@qvl^N8}25hS!xK$wAwPWf13W##$4oHebFNBY;V_VMVZkoC0LSI)eny%6c|1_V!d1#YE>LM7@pNlwc`|Q;%24Xf? zzqgKQeXY&w`(dGOn4K!~b421@xCE~+Zjl0=q{1#-RV{!xBT^b)lDmT30rS3??Qu|^ z+#eN4c(09co8tLb5I$a@x!mXALQQt4*%HwjQ*oTW3gE0ta<4a#sGA&-gNp zz9{&N&F_2a>GiRexrTC+h*>Y;*%Q|lE}2>s6N@4hruo5SOROY-=i0gPlPN+GHL2TN z<&$PWPX9+jHG<_=+5h*X3+Nn6=Gpaw`Vs_oON%BOW}yk$um~2?sZw1iTW1$RYAm8g z34qljgAar@T(f6J2n~@?{@(9g;K#!Xpvu#1aXWeI1z)-qTZEY>h8$$P5t_4uus@Sg zZXIe!wu8^hJDRz+u%g4k!+&cM#o9nMDo2y)8s>;!b*0VIFdNLcP$TyOsR|%V zi0(_zFeQi+mJEdI9R=vRVH|KD(ij`*)eaX^QNsQwZf0?xi1VO5==&`RhGr`ha@B9v zn62LJ?PACt-6p%_36PIm4U2vD+!gceCNk_zl>q|reBUA&Qc1I6OF8e74g>AS00dCO zsAN->I?+spzM;x@Y7Ci1Q5!rimf_kP>sDToQLLK6p_i|Gah?mE%^1l(aDN&F5+sEP zBamsj#VO5Gl^-@Fi{geEpCF`3CyLzy^%}3 zw0q_Zov>{5;-hq+Fv67Lmsjt6y@}Smr_pWeEJR~=DKFQf@vzrUo9KLF**=^+Zl8f} zbHbOVRyyTRhVd~vR?~QBXhbop40C@z4Nw)zJme6@ORuprCK7+e#y?`Y!v5Jpni>Uq zEc4cVz!exOrXmR^@uKk~0ZJq(-jXuP;T_#($e8ql0q|vn<(k!O-;%G7)ZET+Mz0;6 zaB#EgX8%gHC_S~+ffzFSiyk#c3ZNK`6IFS>?yTM&OJJfgCb6_yaPKt;ADO^U4F&+j zvvm+#k)jNAyt;J$%m99$fP_UfqF^y^`476AU+AxTXXh0A5yyxQ1Q6mNH$XcK6!w4J z4X)aIpLGokCEHrIP!QnvC@sW!9PxSI z3{h~Hi0DR}n}sWuboR2x@;q-nIcW09IX|4EPjA0blIwahqMvQ0TDxL=QT)PUnhQWw zC$_D~oEvP_PDw>1AMkLY6&@;>*kE8h`Sy#B0jGtpu7Gh${c!sK_?z9i=g(a6&uQSh zikXb^m!2S5Z#|aPX|^@&NKVMDkE5bzQQqmVppjn6`49Yh+^D3Ham2s+>^<@mwb`Vm zL2|>|h=+~HcvOj@f}XEiOj2Kz4#NR>a7iSwUCZs$lD{ZCalYPpB%}-v|D@ z?0Gsw-jL3({Wr++>I$W+4~itiU#W3Fm0QeVT!apN4blz6eg3W=HXOf?GU)+bl18>4 zk$W5ix{$vj;N#HHzwNAj@JyjV`ABsc8;gGB$WY&FQM9#T46(<+uUV5>i`=wX|xKs9sja+x1@ zxXs!)HNPxYnhnB_6W8sGjr(`ug~A{qNbLo2A_Ni5y?`K# zFP1Ffnsfh+XWxYo1|64Q7xo#i-EgrZEZ~e7Mk>h3)5arH21`7R*s; zTDsMa^}lX&W44GPI*eDk)_{~AQxO3p1argp(sF*0BYFxS4}n0pFs@C;b-G5pR}pY-TvB%ZV+SW9zd{N;?p z-Tvu7nONF{%M;Vg+!HHk8O2j@)-uBMFWQw>H4<0g_J2rZ`&vA`uZzn5)I=I>S0h4WH_Jj+|XK2c4% z26__HBiaQ|z!(U-+bdp2)A#!EwFme0;ay-}@nqGUL*L1!iahJ8SHcH;B{z)92`Lim ztcd*sgW!(ncIyBD0{{U%5zk!8jssgq$>fO|ZA^_m?y(E0Bq}NQ-}_zUGwGqldlSdc z%V zfW#el!9BtDq|b0Gme(COA)pZ2#vvIxpyHmWg&D)2P?aD%KK5Q#3BEbEmeAn>e*^Gs zBaReoRI-UDQx?jeRdKQDt~qMJ4}JT0*K0PA?ATc6V7B5ASYZu~RY=jHmR?}}9qH}P zg$?4%jBF=7-F|&Aj6sT^9~9ZuxG^{>Fx%XWwv~(1${Jd78Vn%FEcUaa>;6eD(C7Hg z0c`C?|2Sz%ADj^2aRvF>ppu zwBe61p3GEn4-@YaRm#xJtF!Ghz&f9_Tm$nF^ET1jh>G#2&ZEqy2gq9rSG4FxRi5hYa%_f`_z2pe?oN5+Y|42)-lYa=weJBa0oW6$zoxex z-``(G42@3Tus3s5!NFs;d4SSSUt9HZegaLZilVj=!^?6kP zxIJ!hLqvBf-(NHJ3;4+zw_CeRwlvosgH`-Cq=KU!Tz|2vmG13VK9O2@p;C?MJDz^v zI>OHv0B3S7#bOkZ9+GXy?BX#v5pE}{i$@@55ZZx=6pg{?7i_br~V@h&x z)cMM;vq`v&ZykBH$jsCyX^VTxP8z>X%KwN)`tQ`6+bwbMk+>dI%vTY52K7D>aGKA} zRutIcZYNfq8rM9?u5ZcjdFVmQEWCZJEci^7xeD~dv93`xzPFd&0GyJqptiba@(V~3Yr5~U_kKb z^X9d$5H_JD?*N9;D&}}KPO_QW^5tuhW}=aG9Qz!|voZ+|ty2RjoGBlA3v7|8LU0z1%pA#!+uoy4sc!{fcnG48Hlan<}Jt zVGZkhDWgH+0^Qb1y?gU)Wj)0AEK>}MvJcHCaRL>^;n1o_DAdM(#8RW6wAk=g#d+g5wFJpq|xNocINsk*ly5bgYE@^QJ!pWRb&ZsL&_D8S^)v)d9>f~+=< zc)t|m(aOXZh8m~(e8ey0HVt*gjaEyOv&7CNnhI91wHwy0Z~SGqW}Ty`CtBd-#_C@- z#~Qbf`SbFrlGtDHE*8*tqnN-WivwMLU^d71N@ixVB_Wb^T!0G9TLjjMJecOOvACO+mMp- zc#Qqu<0>z&qt@u}GnuQ`?&yYe#K2BbOYjDBL{^?>wirSN40T5pQ7f(!0<%*QTgp=1 z7xh#;Qq0@3*cQ^5Op`FThitEq9$icJ21@Te?54G-BZa6E`LG2x1LrDmu=Hsq9Me`^ z%;b${MpVz;_gtMh@Zl%4fx(1FfK8_Mnnl*%RhT=A))lHjD2`-J`9`xDn{R43(h7w2 z&OYeu7Yty`mws(JmB?Z_z1lvyK%$hZNgmdQhYG(M){kLSd>Z1nKehNY2v&ToeM zt-0%|!3EpgYkqCMu%7$6Wobp5aASWA2=>61ju1S)UW-Y{6m?#8f-yc1NOZN>Hodi4|KO3O0F%{MPV_a zB(jmb=Z9=TppMSQk8G7{m1IMAMFo-Leut&Jh7nu%Tz+SVujrU&?oSgTI{X$}WCl5G z%G}=(o}SfYR%nokWoNN)ZrBvZ>JzU4>jJw{;J{l*q$QN@jSW`j(7~^EiuBl-w)I+$ zdAa<9Y^-fpDHo>6Ld-LJHuy%YqjvY@w2wWLD%sR-ez@ zho}k45DIA|ea{53FNO4rc*1EQF(9^jf@I{JY~ah zM9nS4b@Yp!ukry9O_e;h@kSZLZ7xN3%ISIF+4dFZ;(&U-$ z+00amwjDG0LCwc?)h3T#0%@*o9@dQ(Jc*A6>&q@5#9D_bMBH1#dX@7qX4Xk|cEn4= z9)GVUF5(wk3AlEL)Q5IcTyCzMq#gSI@_JOnw?*Wnc7b+`u+1Xk-7vV!RZ$a0f4IYx z-#E{tFXId2MzRvY=#pxEsfm+~IjaUhV)9cK*0f~VN{laI_OZfBuG?_qWtsMW2MSfB z{$7d6-AhMdXNHbScW)gN3&q=I8u5j0=zW`E+f|bo{BaiG-C?8|knw&~jz?8k7oBex zvrm?+5m#DjaUxfdLWE;&v^=J+=mz!es4~p=*~@)3@(=}$Nh-Sp;Hd!+QJdq=^6OwB z$DMjAme9XmvOHlW(*ica5l5wj5*?#vF?2X7z<0Ai&;wcOHa`}U#}ZXJ&_nCR-O>C# z1&-+`t(V%+W*7M~WHG`Z+`Ifha!775XH;k?Zpz}IDT%=mkf&`L_fSfs+_Kx7GJpgu zR(1sf=5A^&zSUFf17D6zqnWM{QFvCA>x?w%QkXQiLk}WRgEQ_?qQrt8x~N9=6w+X- znjXXt&CpPoP7RJ&)T*dK;j&;7ck?3O6Hu;;M(D9wsw?mze_cokVI>TOH9F!y6-Ih5 z{FXk0{#hp_rk(!ffTZQP0Po{cHXa|UYM(}}A>ZoCiplr#8KZ zNdf5R@CyVWYXSz|`qC}34&}PZAHKcZ59h^@WgZ7Fb@wRJvkR8q=nX$n!9+-5q?~Sp z0=lmez*pP2qt_p4{o@yXEioPN^h+ral7nQI_sqPl6aszw1r(3|_ESHIRF;*MLDjl( ze4kL({0=(SlJ=`kU!IYkEXy;uYpIa_nU%CKHqOv0rH!mpW6)Kjc=Voj@2#^aldDzk zN|hNnBK_l#vzW^1{+eO0VsceukqNExX*mvlXWTHzcdvKeQe`>;6UxK`s>1L!XX5pt zX)AnIc~?#smF*$z=>S5f#e)Igz4+F2k$0{MbPdCtf%Bw@^1&>)< z{D}GTC``jY4?Adsv2E~LH|;tUoEl=^LrCtJwL;%-pbgQngkAfLo6>qo{`Igf>l4WF zp8OeArUAmE(R+THDT3`-qPX!>wwNeZDG~P;93wF#e=++X2gf$=ze6T_2taUviW|ey z0RG|ofp6wBPD50?*P^uuv!CslA^QMB*KwZq1--Sdo;Z>Gu}8C|$|k#u1p^+Bwz_2i z;rg$9ul-FC&K2&8$1?y4kzRN|0e~UJcgfD$0|zdUsor*ra1C|5-td~Wya*lYjk8DF z_zIb&D>7X3`-_`w2ou1+#xWs&-(%W%+MUp~A?3(|8&ZzlEd!C-^*h)a=l;J?zynN~ z-4k$SodAze7r6G~!phl=l&vF4gxhadCsB-#usdmoZIW%v)A>kHeul>T(m5LFzwdqX zhrcep6J>PHNY=&S7N*uG_QbOprWvC@ZTo%D_GY0JYh)My58R<`l3+DA#6Vs?T53Ql z-!Y_H4O_uxTZErHaVxY+g;Ff z+G%lJ6Tr4gmgL3|D!&cf9ClLFcE0c7{d!f^ppzL(vJcg6n7fUJmGDa9=MtVQbzDyG z7Vpk0Z)wJ>cRD#e<7h%FYa4v4c3F_KYgQf?hE)HI2W(I(z~Vp`Ix{9LyfpsM{WLIs z=SYP!R;4D>KU&G=s1a5!KknirD88S&_`=Bn4A?#~uBbHn`@K(B8qhC_-`kh$g6r6* zZj>l~ayZaBhPfV(h#P9n!GZH)&$SgA3#R;YF{(`ylL;hQ!qRGa0~^3%=n@bn6sNsc z;G1KcYh#^MQ3z*Fs-*^XVs&icCoEFTCwa@uyFRJg(nO4+{Mm*<@GgPrHJnQ0$?ZP` zn3x;1NI$|_H2w3eI4fmd=mIjQCuM5>gO)k+C=r6THmc{(t0E)QVxI9hDsNLK`@n_= zUCVN6wx6oSNA#P<8T*{z)r3~O&TmgZ@w}P+0O6!-rhD>?tAcT)AK4f>N;az^#_+?) zZYO>xJb`1$lI!WI)vKu2=|2_x-?5_%+I6FKI+WtmK`G;{lhj{jBuMjHp-vm*9YLm$ zeANl1aJ=*+k=K^$(vc19b=V4pG2lx|O)gjm88X7<>7sL4Yw^ormPw}@1!cKq z4O5RZJBx#BG~BN8ThnUW)-$DE6-WPM>xrekhqa?j0!VPL z%wPkGgxb9S|Mr#t`LXG>%LSxd9&SNsWs$e2FXw8D7pBYD(DhFFb@4*uA47Q~i%Ru!-#u-aa#XzBl;<`F!37xKw&T6RI@`S?71I%OB`aVoPG#JQ0-qRMg1k!g1fD zCL$zZD1wVn*gbONhr!)BJzrBe!qI!xya->G+8utbOO0Aczpv z*08=q(sy-PIsi36E8zb820aCq&s;N(hWyJQXsrVQ5i}Kxf9Nj_n#{z|K996Q8SNhl zk~{QsR{~Q(CQ(Cc$lxG!ZGkB($2+!Ha!Na#*N)kysR#P7QhF2OBl4OJyj{@J^mD2! zRf>sEOR(1h0i)1dz1kG3(jCH;pc#liBLTrskh@ILni37wMp@*jj!TVUy;BJwbFYPY z0d)xuwW1ui3mqUe4|W3d5egVo57gKr8#w%IyGoz`icK?=SF23ybELeuFc^;hN&q7v zf{u{zyo*CVSLN2?#mSV2vb&b?B6D`X+j6s9jXc~5^<-a9P3yys7 zahT2@u>^ml!HElRwl{U4`)uhauc~ih*bJ-FUqs-$3a++W3Kr}pra1}0dd96%_7eDQ zc0dvTt^1xQe5ubj7$Kg}K&A$vBA>S3tgANYdkN|UcQDEQNT$OzDio98r3yw$x*|*KN6(7;qSLESe@9{qFH?=fhfvg6};~(TU}XUL`14@-TuGj zRNHPm@4=r#i9_a+ESK|a=|^3=aKOSeatyV)6a%UMG%9QuboRT!)vR^uoaaKLN(y7y zYaHGcLGn#SYHdv+@wF|-m!Yi{)EjqpypO|x`=91bF@96}9&sw_%j@EVRHT;tEsXWy zM*sS#jtL*<5$ZXKVc6XTJ{^1>?415Aq)J2y{N&1)^J%vjW7h|PtTWqE;0cvT9}UE?@=6aY{}ps|eOHY_6oqk0&v8xd1PHSGPZp>0aslB!p+o zWGiqOtMf7BPRS%qdaTj(mae2?99@B+NCz+IRE&(qvsH*fN420Y8Opfxq!72*by?7% zn2cj!^yFEw`kEnDtwdXDi)I$idgY~(i~X0+aU;cl@+#7dcLa9HwoBl^=L`-EeQ@@q zsVKbdv3Wfk?p^x9JDxRkP3du$WFwZnau}M?lV}R;0Z0KV43>^RDQy_P9D-HX3D1YEmx#ez(j^dg5-S7(5VR`_$sBUR%D0Ba!KH=2nQ z$b^Y$5w|8$L|@KD@w zlX_s}_ar^`nd2o`=Yi?p%k+0DMs_*G0~;;09&yr^&ugj>^r7-LytWIy%EIzrQOyzp z=~!L#PUa2s>sbJ1lCx)jZL7x(=0*DElW^@up~!RAVD}iKY<|8s_LO7WB!16L5tX2; z&ta6F($&P|CJCNkmi^>L(nu&{u_`_}VFb`DILoBbc3r0OG8!QQHRfF7Jr;alCjKf* zkINw(9+s!%VG_g?-J86#M)x`@b_{0BO&xV2tbytq!UO}83`4{R&WlDl_mE;T#7Qg- zqr%RtuKhs|uWKfyJ$*)Lc2Tb3DyQK)xaC-8H+ehKE?36kNdE=tu@Mcny{?>?STXIOUlE~7E86XT!J=+&?D3#BzQo9_d1S0Gli}C6$ zZch^wFKT}PL=cqch1tkq>6_n}|? z+GsUL_{hLqko??t8Y>ra-3seUVD~(^B4iwDsjDt^{6GKOa^b-p=@>(S9v?B%yLqL?a(JA`thrR}m zECX@F`Zo&`YHSHS!J&P2Z3u<{3saq~u^Ou~>hVhr7UXitJVM*R4A!DC4T-HSrMgJQS+9;60wL`$fP;+Axm;j`8dWJRP3GOaVw zuVpP6hc<-xxCPFOTmntd5r^+8Zl0Qo)M&<*K#s^{X}i^bNiTpPs$Z!kfHIo7F*Knd zc##2IElol`hZ1BGTL7gJiyqV~jB$$?bt@Ok*Lo43wyf0YVjFO}h*h-x2(1$(hYI&` z-Z&szJzVU`j}2qKg_LrVa?jUD1%$Q2F*_Iq(%MYGQQ3_c^@lVW%ubs$)<<2OH=lYq zo_LJ*?l~?1nV$0f6QzZfC`0#D9(u&+;0qp5tc+0f!AtXpIA3QAC3t0b$2~np zC>t4R7I*a+)0MFGz4Z^EUBhJPcx=tug+sn5;bo%TVo|p$P ztyCu7Bs1bL)zw90sVRjp@~t+Rt@|W2r{XhJ2r^m*{6W}m39;p^Sa>w3(3Y)R0nOzw zE8rYZBvVhI%xhs}lTm|R$m7hNI~sh-V?HSChrk;6+rr!e>c7=43M)eHE9^rjtGs@R zgpUs7`V1e=+aRT++%r4K^e*Rtuee+nl1sN`;m|(;Jd1j5CEg!n8&KTJ$xiRSvzR+q zOABJ~RR6PLVd=BPMR6$V;MvSzmU*xR5*Jdo%HDJ#i`j|RT`)}bJg42J41>k@^9Ezf z#6vR;;Dqnh;nuv@EM~ivFqR^N)yQjZ#w*a*g+0oI;AFIv0WDe?5FL_Iv>06C#17_; z>)wJZIJH-lmC#wVjK7r_Y+;z@Kkq%UN#_gPTwS-w_6t;<;twrvDj>()EOU8j7_Ob29PCprFymqyMKajMXx8ps zls|In&iVh9b1)7w^#&4tV*$%lh4J2kAVZ763F=G&jGUT8w&oXA$e}7z?SS&n6mP`Z zHexIdopyMK6P2l{u7&}+bhW#S%XB?HJKEKyo#>sFdtS=VUCl9>GtV0vcLg`F*6GJ{1nS(;5YtmskdbgW}R5Q?hh<%spKc9`bQ17#awpzUz9H2p<8(AhDX{`*nQPi{P0s*mx zm?(6mP#!GN?G@|EINzvV?CFm)uflWryPu&n>*aljUK(3$`yoQ(eeat@vu=a9f>E;D zaQ>s1)3ZJQl?@iVR*8$M>?ysyU7M{Inel1_baTc~=jkGFQMvg-~QE})~ zvgxYH;m7CS6>j@I3K0dfy{d53s_qeT7il&3W`PjpXph0J6C9FWm!lig0Q)9w+cSGM z@_f*!yo>}axg25~LaojbO$~&tR^!JL6!>UJ-lpe1;s4Bbryn~<671)RLg1B2@@cMD zkdiv{-0=F~v0&%POqirfdh;c}s$+oSWUIf;Si+mn5I&jrMr*q^t#{?*>eWL9-_X%y~X5&yMd({P3Fbr;IAq zC8(>*T|Hy2dcT>lOnIC5!|Y(kHzXY2f!sQJbE^WRHh~e6hM2Zm8;fDf*;KvHvu^Bw z2h*I8XYXi3XW3M@_K z^Q2v-G#s#c{un`DM0e5=hq5L>#_tK|L6oDl<0O@ziX>K`Mq72rHX2)fTQFL!?|{q( z^zkq=G>}t9p6O9K7h$u+jpUN49yI!avOc>t9+?tqE=q$kw27LMs?vAUk^Ek3(}k{i zrQPN`hi_2G8>T!##hIgIm(LahG;1$YP_CWE6_CA|5S9vOD(q2aic&UIiyk3PnlY{+ zEwL?Z0-_Q*Xhv9qPf4J*x2zU(l#E`QZK3{M&E)Cm#L~R7so;W}3QRIX+0Y1VfRMJu z04Uob*dN_x(T*HF8-)%iWevL9h?^jz__tN992iish1G8v$c+flbmUjIJ`tJ6M`H(B z4|mRaUlDy_W%7kfB4H=XeV)9OYwR_{qOs^vV9$1`ixIp7ZC42iTnI}WV-L0XQ!An| z1jaKH(1H#m0^5VcfF%<7DDDlDNC%kFfS%KQf5kETZ;gxUQi1N`m#QbAmc(uUvj`wI zlmO(z7bdBM79tkyn(=7H>SdQ=a%IhNF+e>K#d;k%T_{5v%2Ov~h{p$QLnl6JwBlh^ zOC?5f7||?w@H3ZJdcr%qV?m$rtNE+*qPS;!J3Z3~JS<5CAP_rqej_61R-(MfQ)xTt z@q6Jr6IFB?(^2}jiczo5v`SvS`XwkZ|(_UWweO!#I+js_^RA56=m=?WqW`$OfY%PmmM zQ#dAJBAqay9863I=n8iHf8G|XMlG=_whLyL$H*U*NCVTDgX%WJ(TKFVXYWDe_P`L2 z{lK?lq>reRCxkn#&lc$0@mRzLk-&@57lGRh!?ZU^gP8OU8)O%Q zLDrZ3Npd5^q%H}vKyd&wSt>d({a1r)D{|joeuvLWt$PiZOVTLEJ=30eWxlXFoFyK^&T<8q(VJ!>@sk7>A4!VmfsDNsgOpA&1D zO`LcQsb2Hv%I_H%7dBg+wU%;LeSmx_5ag7A_*7SVOrnTX;5Y-CKpX$ zM^tBdZk?3+4M>{P>TMEwlsQN~6l#&a5UXYhEIB=}Rb z#ywW>U96QqTpHusUK6P}eG0kbTeE&!CJ1ETj(pzq)3NudIAK)mS1a|@HobRemi4KH zjOhYCtili7e~sW?Pt(rS6_fZ49#yK{>{Z5xGOBgj)ygZrZMY{MI@CN^azLk@gWNqp zC_ugDVkX}|aB&{%i?>7Mgx$`^>6@#L#bR`XGX~aJS)0=WR26Ly&VqIJbe%pNqoC~$ z1Q-pjGsbvK>d7Dl#$#q^@P;xSnMioWcs zgmksffX7Dg>=&b6fxf*%=;~ZwPrQgSa%?R%%u5}wOdz8lIFS!m4G9u>#+$!hc=M+K z{q%3$4APW=Us@-Sxxe{m0UKv)5aUeI7xuw^$QU~GC6#$j$oKJDAb5}_jP9UWxM)9U z@p4q7>Nq%^w@|=1W%P|)j(o=8Xm+@<=M=w2?n42O&|N9Z0%8g`eR}QA;!hDW(hes$ zv_DoKK7K>4WjR-)B+MVb`_q%8)%JQfUQ5qkM27JkedC{6sFA2 z)h`C{ifKzYLES}`LB&y&wSrOu;Egy|h9~_k{D=+V^tRCU0<_8idX6?&TRbTXGaj}D zr^SH&n4e+TtkI(8QRNWVjDMr|-#v|+!toQZEFRk1k^4(i!g7LRfAzm%2B42#RSnNX zASYJXH>|~@Mc?tO{c8m&NPrr z#C20GvR1>Y5KRFHy=>{)K6{`xIdviOQ>JUxp#c*#uI{#TOYJjZdEY+l0W!UW8eQVs zmXsbN8!#0#g;cGwtUS1OC<@{w09`%a@o;3&MMQu_f?Rt>9xY|IwE$CAn*?}f<-q&Y zAN8^_>99o#)>qvFi=XE2Rs<~aU4X$;9xz=AT3Qi>=DPD{32$U+XbuvTX6O%DT3ejY0AS{q~g zMd)qK$u7-!wkd71q+Ung3fV$%Y4G+SF5Al&irafTQ4GR$OTxEFN*)k1{-lK7Wpk)u zp76v7g?hK{yJ1y@AInt&4nve&!Jq6X4Q{t!_a^uz05XS6dSW7OEakU3aAD7aQ!gO{pn`nY)NLa zhCTy&@+^NCTy!eDDV2H)GGy2qd=Oj;(?n)H=dQdTSsgDa?Vd%2e4f3oxvf;ejj}!7 z5RlB|v~2JeA#R|%W#yBaDRYsD522dyZ!C|9tZ%8+|r=fD(|6?`d) z9xzS~GAC;(B-gouE=^s!tQZRaBz7CHtong4g1VU4ML<}zE18dH-=U8aI9ana%ET}t~ zeeR>FPQbcEI@wACy7;u&XM7j<`IBK_hUkDq-dVn^+Ve^_3HcH#%i>&x7%dVkhrpQM z2Rllxuy&h~n17oN5?yNmpG=H><<>cufP8*95}%v#R-*i{JE6n{pOa77V`R#@zo7B` z_`x__5$^;2MSGe40$k%}4vIAi1RCJkhi}LXuQJisev&`fs7J1Z<-u;}08%lZ7E9#q zvV5tW_l;b1&~4MN8$F{~Q9tlD^V%)~K66^RFA8GN9Vp(9{sJ@Zxv??*#yJ`zz{_onyI4v1Jm*+F{h=`5HB7 z&U3_K^zG0TG)d_^7oL6O%%}jNL#}V@h^Jtsw5fz<>UM)tU8>1L`=WbQOwd#f=%ZV9 z!Ev>E*(kbAmhg1@JfA8|*ft}tl#p=uXC%MM2kN<`eV%b+Vwjkjo-<@u3W)tU=01RkN)M?tNsTqSd4>|7I$tHE_@+SYw!JI-PDOy zE{Z-n<=zj2%_Ti6P)G~fQQd_SqPhHA4cE!#@1>8)>)83e^xf8Tg}dtcogDdUK0`6T zbbuV`tG+gzR9{%6p6%5*BD^&cmpPLQN*L0L;9561N_p4Nk>QZz>`6c3;`cqdTIX+&E3;qHr@H>^rsH3o5G07!*S7OBcQ(Mea0 zWAT3VJv!LB_fhwHGBbDUfbpk1qT2+1stTjfX?UDjGXTBHESP9s8sY>SmQSdFEW$j6 z63i#D(6u%U8H$*E{SsBB&f~wP#M9i8W(mOd;h@X|~&$2r)oMYKV=&}sjn_Mtba`QQl-hoEW;v-0Mr(YDh;akoZ zr=&nRy^NAXcKgn_ip!UkH5SfTB%o4J_fC#s@qW)?$&@gk`?D@9!#6)fk%qQgY+tE6 zaRDQ}Z@=&oav$Eq)l{#cz5oCN001Ljv6Qz=5*EeZU+%igQX8E)o6ULPCV&39Y>Gq{ z`TkL+{k2>CB>^EkjUAd`_?XK{x$kTMIECFF?M9tEqD|sJBU^|;H!{3o_r+}SlcPgF z0Z7<+oWqH~VN#b3geW7lB7FvsqZkqMr@Zg@24rF52c5Z{_*nt6Wh7?T>YS2BYQ1DBl-jBml{0>j+8eA zKu55FX2^k1V0-hJFd5l(g=K)ioL%kf?o|$y6)7@wDNCQRR4We$9`e2Rt7sG`V=)5> z26!ugIV>LcS|N0{VKO4!Alhqa`8fl&%i8=rkCI*Hy-t1>GoV(90t*~sSxKjmzWx?> zGcW%Y{|*LbEXF?C5#3we>04W2v!>V|P!3OVojxB(y1kh}&=la{>Bbhm;0P_~?T}$> z(2LKD6G|^GpjS6^6sdQ6$r^js>Dp%NKJxvqfbn-%7H-JvOk6LGy-?wrO8L`|FE_|9 z%qP=hz*tH_*{vxr*OPVATXZNj6JKIs)LjoSkv6sGFha@)`_5-6I&*~II%S^;&E|(K z^^Q|#MHx@LMyD@!_&(j>1K4yovloUbep#&a8N0D?!w5h#W(I+LNkPN)B>&E?e_sb^ z6Ar>qDpX%L4W2lI+cV`_lsp>*|ImA}-n#|I`O`xbCHy7c8||VCDX7a8mA;eO z%xXpzu_%i(r9T}k{(rP5uHNv8r%nMCe9MqLPys8s<{(`Ia$&5)62h;t@}tAN4ycv1 z$D6^}euM;R?G`n1mKN(bi}w=?pyCy;xC8|18w|q6)eKt{aLXSv(%o?e%ky6(#m^;= zd;Fa`L5-5alVvRE_s_3FoEH((0?$NG zQ?y@RZ|?`nIhrX01?KV_v#4xea9`^>xC)-!X-!|7qykx{g}Q_oN@Np5@bma)A3oJI ze1F{ICo^0BVozk{dkkGZ*L_87PZJS|NV%{%;;QR%bas>gopbl*!y6&r%lH$uQ4Avv(hk0Ru&3_O%eP&& z)nLm!;%Wr^#hW!=YxmZWVzMLs!;;E;)aQguanKg2 zuw;Q>@^zMnhuzHNjTK^)L=95`G9HNoBSTZnjG6aw`KEZo{b~(~X|a1<&q!zjA+ff5 z$T04vp6VM3HbB02DhM_ zQe1};S$X(A^3=jgKd||g>4ayL@0v9$$#5&U6ezNGezdO`hdniy*x4@BZk4SK=QsRy zv#95W%Rb!ATtV!Dn;X0r6e91wL-m@1jeXloIa3*adJpaKuLC6GVv+Ujkr_Y7-|y6{ z=3DgkO!V$Ss2!(6D1crYi^l9^-l=yjcpYlHVhpfrj)&dw##01Y^v z$Zk0SF^&H6niP4QYOp3y$ArZ&s42d(_ENH8VK_Mj`q+4*T~q8u299UPjxx8CBUE9Y zE0)cKaTVy-g-#f^23aPt>oU_$#h2vBKIDi3kc<{29+)eMDLKx3>>V-4R}d3R#>O%(qFUB8y*e)QS z4B=hA?0jP3i)#FSy0HjzjkxML3h%B_K5}AX4uq*N#Sa5iD{Q(aBw)%unmPbmXIb3B zZRdeK1=@N^kia0tS`GABYd1l(Msbd;?Oh)D{#C}56GjxgL&BwosRVxP`_tpyX^Ig@m%EO}{1uZ$4iVnTVta zu>%ZY4}x?lu{iW3Z|(+Q0ILybqI|zk_mGNjVW0p2H5T~(-2PCS5t>O1@=?xzjhp4y z6`V%6k2xI^5c0dZ=>d^DgZ zkvH-wD*S(eY}+v#s^o?(5McF*t+`2A78>xGrPL)ML}efIZS@p%`9t2*QwMqO`|`lA z#RRRnJ*1q%7#c|InR+3PKt%jwa!g{j&&+{7#Wb*66$Zo%g)^~F4U#+UV6C;FMw{>! znZOCmUu7YP!0_eGALFyvK`Vtq-8WsVv82uesy&KT_TO*gY zn*>fMvrJx)&Q6X9HfxkU1s`>$@o1pQ!jcJ0CmZu|p5WeR%tq=}cKjr|ySx4q1=0My zLyz3AWv|{DqzYR-M7jDCU6WD}9d+c^S#S^YdJ-n*4-j+3QAyT#>1%Nu^wiBhge^H( z4$n-e9&ju+)@K^lH`5ZJjAOnb#fCOz?iHy`R#HGI_P&yv%3I9P#}~N0GanS-+IYTz z8!941=j<9-;ARE4&bjW$isH?>L2@9&-x^5=54{sBBZss}B|UO*cysimYt8Z~xv&3E zaFn(86NAa5KY4)Sf-Fs{`Boz)|6>euD)kBZxD)PNt^xC1Bp}Ld{*v+CPFGM+&cD{C zgmpU(c{r}2-L#e~U~+2*1}W6{|5I z&l#{AI3l$H;&-7%XY2j_MH)9j5lO1=i-FK*`(Y+YuOZxAm=`5T=0DWpcX?5O`gztz0@7kfmhVmAF$nx;_}=IwzfeY^i$&kkQR)}sxiTjnX?18 z$Hu#?&EmZ0MhXdLrNqML6#~w*Tr9OD-;8`RGYi{a@kj_Q2y?CKNxoxq7v3JK?=g7V zVlC(xWE7m`wEMEBN6zfrqja4=L(rVRoWQ`hcEuxlazx})&JF{nZx4=575(Ay^kZv? zS~DuH`cAD%rC~Gf`ZG5j*Lvd11KtC%ho@c2sqoXpS!AIGl3oWDkle)TA2kLY3hfjX zoRu}^^Nls&_y|8YH<50Jqd%2@mYk`K@B1rBhxsGibZj_N*IK0b9JgxgLqKmP;u_N} z(Qcr&T2{tG+Wh0dS}@y}YU0+%e}$l9nJfd-NP3wL6X@@KDw7J+SKQbJ=NsJPU>=)}Is7S{d*FszH}+`T6K;CmeY^k{Ax^c%quRjA{$%RxeL z`LX~TLOnjV0^4QAwW{2AO^P_tUx4H$`9e8F@X-L{%rcXZmQ3LaHbL2@SLs@sFI)Yd zqx!wzw01HloeVg0i_JF~StLqX)EKOw_ye3F!Gh>mQf*R=4|(}-xLBk|M8rG+ILMw7 znah#YntLBLlcAJGJI#P}6<7c*0-R<;_4Yj*@f|d8w4H^?CWNrkWimbpr2nEz#N*3+ zd}5*dJCO}aGiv5|dNMGIx=4Vx`~d&}9H)IhqJfB1vESiIR+vpQj8k2T#WPIRkIbzCaP>r;a@vxQFgqp;+DJ-WP;BGo!m{a*pRg2B!7m2V9)f zkBk-~&$>;O5zTT}}YTY6UH?4ks zT{fy+I84@G%8$hNqyP<1%+<{3m+=4W>$)H7M%h2jTuowf1$%s4{wSH9U4KVK6a^_f zJyubU8bvZWVRi>*s!=g+j|7ZIG&yxFPH6lwR-PA=VqZqAv%Yj@9}JP=0Uf|l4ivOw zCH%Hs_A{=+FU$6{Ae0C>`>xz(yJ>AUnddb37UZ>7_`>|(5IiSbMr3BxLUa9-a+EMT z2VhQu$0fm9MKwXH({XG|DPk$V4=PGiRVv*2b%}1zG<{eXM(6J2#2Ao8n^PW2nT)ba zaGt7t8X4)I?vckOF(og0E)Wul+nG8|@nuBare+F@osF-5S!8!hH?-i^HOvjaciEehpo@7GG~?7|O9Va>b05sUHt}Cfz7-Lh0loZ0B7x zbr(>bugKCRNjyT>lw*zn^V?cu$tIC?vjB{<<7;O;H8tabDGl4wF&I&^P)Z@37A$!K zbWXJ`#E zCMx{T{KE>Hg17}~(%qd7-rNLTFVf2s91)|fU)8NyoK^XC0 zpitH}sdiC?nt=X;a-sbU?{X95Z}mU8LQ%qfRFb{;HkmuyF5RNC zU^SMft2+RimqEfD|BN$YW0W6DHZ-6pzUHk)wuS7d)hR^fV;d5rtz0xd7>0gIy|U{J0wK$GPfiw!_sD`JoNUTT-!L#t@B4~CJ$-kp~AiR zBbTTVptNK8?i6p2<@6^4Ntwpyf3vkdwjJ1r#lI zDY5yPmNCgE}r5pzc1eIj)g;$yNPv+MAg8{%@B)%y=oIG-RB z`7p{D9kZ1P(pMDoeh8Zfx+)O^?K18vseJ;a(KQ^a_(rl3_oZx7rmN4x9g3t zuLdo@nU|E__V&7)SdJptZKOE9z_gs@eEP!VcCP<`83p>D2FXwdL!?CV^d!RL@jw+K zE3Zc-(Z2Irrvdda8&F2Q(!N8|=MT%=QP;W<3*684_L3priJWq*sh`M)(!}rA1GB7I zagVVM6RA%FpVM3j`g<0lY=E+~N@(GN^W^qng^I#EqHF$fVz0bv7`@)(H?Sl|I?A2>YM{Ol;Cf zuFj=$xMsqwDZAyck1bH|d1^YFm9p33+0NXO6PiaidO9zoehOvo^S|t9 zefEe&8YjT%5(fJKtyYNO9w9m<`jl4qeyp{YWhVBsW_Vza5!A$Fvugn~jy4GPs|9j} z_N`UT|9J}?@ePJx$i$-DosM~{b6>F z5-V^eVe`|P-zjFjSYH^k&~Vy{A4P|_^J&T)v?6~cF2DvzeLsn9wAe*l1~bkwD_rW%|*c6MZCijPG)p@J^t%I$Vz4=-vKkg<5dy7 zLwurm!!7Z}STx20jhi4?q2Xm!pgeI16Uvz4y!n|)Su{^q>Id}w(X{`a7YYcu|e;LMxEsa&V`PH21SA_wP} zM9u4`_Tp@sIUP9DXc3B{#}xdS#Qo+YL2}>s*~4X~2ke0DldDN56CEZ))mRQG*HNeM zqmGj7Ga5<;2$|+*@IfAJ{Wx)cL_|LWwZ9BfNpKqRCwFoi+y)hc+bEoAzM!HW%`qku zSc1PErH1-Z+;n@)lEPZI>wayzsrpe+bJqNj-hX6X^t%83##bliD6<@)9%+2lEL~@J z2z>?z*^!r?OLXd5_TI^z=(+n-f2Gq@$Zyc0J5FK{1~q976dlCT(p?X5fHd4&qY9xj&SrN&7dnroHwi%O6 zsNu3mH+cUkCTC-o3S`LuLw=+^wid~#6qw|Ff102kK7tj%#@V1RQZDyUfUep`2kg~s z>EkR9X4F=l(eFkQDac{8v$IW@uY`V*S0>^lrVn?qHtiCe{hfCZIC`8UxN|JtR^4Jh z{SEv~b6QgQ&mNzGutrrw(m3ds>;%#^jeO?T8Rb}vLQ`=R^d zYa)?^E9lysuhoK@6PI(3ZFz6^mku?Mq%}X>; zf2>wJtleI(#)tp{8^BrYW&{ZOk}Vm@njN($|NL?xJ!StvLPW*iP5S0vUm+0=I%{dwbKlyFoU7N(~=D+s|$i;Ses(4~{B4R91b>L?&+ z!9tqLWzriRk)L?FK0E&MTeF7YI1K;~pJ`wGkxrUkX;!9~vO#RLkSnWQD_U5`;ZF zTZn1gVxHNLr+L6#?hH&ldH*D!8B+ldLOFcgv8~eyehTU7e#Jm&6-sx*nwOk5YRW+G zv{sly6b`~2msVrt5pU)<_!*?b=Dtm8&QpbE1cyof8vKN(qmGER;Elsdx}t{%f23k! z%X{uJu(7GLl-tfH6Se;kW$2UQaaBMUqO`9sHs(OFDn$JNq_cRQ@>iK2;pY$l2)*ZQ z^DWXnsW@V2yM0e~1GBOjyhE_mFutd-0A{X8MX{-j6XF99(DdCBlW?UY0{dt!mD968+**KffYF zmyhV@{rerhs6S+voTsE! z6`*C6N2Q}ppyAHAbL2(#GyF#auO$7Yc@lZDC8V^SW6X@YvZ@)0Uie#Zl(2z!rPmvV z*c{vAA`Kf@4>fvfY0ZR|dfjdKh5V(FvUs#)Ih52o0LK8#=a%=0~#46_(u)0D<Mq?~#jc*gQgCo3Ab;^W@(%vM-1G!=(O^X=Suh~X`9Yq0KywyN#U3p)T23*8 zzQEBYX=MRv-P?I5MdoRd7~%)?8Ao{pbY*W1000@)frT8dEaB#4s+lKC^FER8;_uha zMP-6Bg1jDRGPOhfs*1zcuB10L1aK0_r0m0OEvwLGZHFP(#RBk4x@F5_jjaJgOt3{C z?+gGgHpEuI2_z{b@izR@C}4nDvz8Ac#Q%KhYGp2I3hit{51SD_m9>0lXkvlQF+(Ig z89_Nb&MAi{fC%HOaf7B13>Getfff%x5Qs{qM78((W)S}43{>3HXz>Qcx?RTsRfpVW zw@bnbbcWpjfQqbdbbM&@#@Z3_AsSgkk05&b=Fp-50CeX&SpC!3!4N)bNRkb$Xt5-x zT16W2Nc4j@*8Aur+g*X;5Wq|>mKEF&h8s9w7&(^iu6l=gf?Z8{>pJ$xK;iekpXr#B zo*Fx{_A>)j&ExS#mtR=PDP|+CgpW;d;c?>s^xOO?>yB=jSLDGwd5p)%PVUpd6w-78 zi-UOPcqM;1!*tmuxC%tR7SU8ya6BnGt9T$D@_&##DpZp8MS3^EqcD~3ZouFRSlh5v zx#(KJ2Ti+Q)1d7lV-(9{`xE{8x)APZaNhGX=8qjK?j9V`PvbF9taI(i0TBJeUT5-w zY}H%|MdW;=BCix-2?U_`mL;>BqvrgC3J`@#>!f8<3?WQDWKV0!a*l#}3ZO?a_wcOr zCG^7*;OV+Yy2b?yA3T$QC7 z6Vu&V3dLl-21^6O)+AkKHn-%eGc*IDdzLKRxKWn+Yq{fO)2eLmvq{v0kn{o5*A&PB zUteu&m-&fuA)_YF=`Bb3W8_`srrPF>=Gu zLx(kzKE+1D0s$d(Jw?sUs%Jg9aKFE@ASce1$ghYeU7yb8TP7IJa?NIx8%1Z%Ic>7U=t3n8w_ z{Ff-_P*qxT(oxMrR;y@Sgk(Ww#h=LMa#fD7zlR=-ft3l^%vjT)2~8oBXu}FcdJELg z&IZtb4kTo@!Q7wm><7sW|7_&_0Fmlmm#7YW*6Oa2u>Un7ttvg$7E<8Vh zf=W=hM`wL>j~`o7cdwXBe@M=1>RMZV&*+xW3W4 z^T=AoTX9d+!vHZr@sfzgiI?#stIgQ5fjcsa=umH&`1xc=^%JPs!ye(VXrM)Ei2NnT zI%l(|{68Hl7=*2GzC9>MGx_(b$3JS6*5Q$!=S5Ax&o_d8idMmuSOCIoif^Ht$PYf(xUA=i~VrjYd|hT`EvF0#^ZP{KXgalcHv{2Jq?WGBUGT|j4z@Io6yDq6#);7KrMqmujvGY@Yj#~ zxMMEczY->Q9+Y$m9u%r$IW_V`Bt+FLN@x`k4wf0P@25(Gk^G6`Zs2L(eIHJIFp%=G z3#b;2Xcd=svDoRsgjiq$ z>yTaqDr<}gjm~&{6}zb#{q}N!K2Cv@tTd`5dvUvTAdP-~`;yLBxD&s!1>- z@Vl;?D&f02M|AA1^i~8J2o-jINS8B-Ov;pQtzdINlt56*`Mz=~TX|~)1FTj(9a5@W zulY&nG}Z6lr17@4tw)3YInsZ#XSe_)o<8TAS{-+O`fR9n;5G3>4%Vd5uX=v48?~yI z`zcti_ZqQ03oAy6G)Mzj%4!@7P z)bngyZ%^!`vf8f%aSqd9`NrlveO?E$W~zFMwC2(VyvDttTn~X70kxgU0CSPiIyck7 z|Hg4pV2X{oxtA~}Uhd=Kg@hRF6lTcC@{&26zBVz+F;!$8>JldvXj`knez?l}A+9;h z`t$5htEt(xQwo3&`~;YWgWwjo0{s zsZ%8>2meMm^94KLBZO1VkYK1E`wV?qUC3-Iv2J>>rhn6VKle|z%cYWno%QbL&b)VQ ze7&MY*Y0Ry*oyyixP$oMr6oMw(_yFjfk!tg%I8YtE3gWSr*Jp#iX^B;r9bxp9kF@s zH;rjKS}S*D2h0#i#cQeB&h9pmAJPJKP(oYyI=Gxv&Z+D{M0@9Q0liG|DYvlXoa?Gi zq@$~pA>O~oU>s!|dM0Bh?+fupB3dye5&_Reqz;RFy_!~8sUv#fmQ{|I7d=Zr%ryT{ zpC2WN$!duDtJecZS?0?snXIF{t`0D&RTnR~F@$q_rv#7lsOx}1PPx%oP-iBDX)F)L zpd^LgVd{vWrrDtm6`@x#+$jMyP;`07HmZ_OkOZdheOip^%4^^)D(gyTQoah-heWtO}tU0H4 zB)FAI`*(k@SBcxSK(Tumhu)`6^SUI?LZ)mQ_M+I?qA#=z4BOdgx4ICiTSWy{5=WC% z!&WZnoC;qig?X}iBwXR;_98v`-?II6@?Pd}byC9UEV$?i=k+1gw144NDt`kZYHbw` z1QP4Zt=G_XyM7;QRlzw4jFDeFP1g)$1FN=bQ*xNWV~~oFvW_W} zqL5jbDqi-e>u-CH+!h?J3ckmDhmk8IC)Kj5<^`=#7uBR7l zKJ*JTO8Ca$Oz-u5f)@^9_1rtUJBA93_?h@XLZ^I+Na@PM`2Q) z(aXEYr0RVK|B6C|QJ+mh)UxysNse_W8!s|tF3{WfaF$X(e%1l1_U+?A-M95y{|O_> zh%@Crcb&D8`Lojz#P#JXMbX7XN}6`qD=RG?0$CwW_R^>S#OBJKg%aRlq211=5J0HWef^Pi7%g&Y#28|gDU=69-wu-#r_f@fo3ohMhwIQ z?hKMaah`t2PtyxQYy%*5M0aV|AY_Z1vNv}9dLYkH?x`yUQQBJr?{$a%Q6r~oe26X; znaLF0xl7Wf5D(87DkH9980u;|Yojmx|8jr*n?*mCzi#r^u%(0-MezM(=ol6|Ss!$b zz6o2MgX`nvCL2GqJ||j)pIlb32P$}aPn<##q6IX+yLI2Ogcq%JI{CR604DAXG&JhR zGQ6Lt#p{m5L~7EMvE-brl#dNP1xD%BSLkHTkgnTRPkuv`wczm5UJVX#t!oZFLxHC- zyXOTTje%w`lfyPfFGBzSJFf0;%BvV~WTEPl%~CTFRyINa0^LO6GOq27dZ96Mg+tZ( zFoV7Vs$<^VVkGhkhSqV#V!(P6`(lnr;sl;7klRd!BR4wR3lSmt(~R`!OfBUSpdz{B z9v7WF!xl6A-tTW}VSvzLJ_hpt_GWv7<6rKiAQl{|ZnIHpJ(r`>q;W;G*-< z=>lDj1DfLLBr>A@(~)^VCb_3wc7WVn(MgM_r_xU-yH2?3bu}x5b5uq34Y~IlawX4) z8W*i|hV`$Y5kd9$H2z^xnoQ~VHz?8k8m_>E8CPhNdu*XhW$|jzTGJ$lgmqGPO8cy^ z|KolTj9w^@l=`hby8Z1INWQ?|`403lTgf9N<=(@o6LNp0Odl$WuJ8q7L}ESB(_l=B z5dCX^?@Y=nF~aP=Ww+&gqlu#FBmT88-vn5h6$C+j{>S(2X+iD?=++GFm(`FJ)gAw) z%ovCZ&s|Hf;xvzVH--Fw0#}+-&UV7Wh=T$we{v1q^Gt5Sv|~jt6-d0&!97p$MYyXd zkq}rJs2va?uW+hW9IsHA;=nz*|M?Y5&#CpY?T!b}t=sxnDr-SJlFqp=g@G_J=1dNk z?B-cO+c|TIt{gZK4ovxq@PGA*_DiR0VC3P-2NsNCR`rNK_x@noRpr$9|cXc!%^p zHa|`QEMunAJW=|OoOJt9FL9f80EupK00Pf}Gg)p?FJ6C(rEa+ED$yp;HNA zdt3%4fi!$oYb^1I8&pNY4ywiF6*Vs3^IQ0tYK;(H66 z;|Y=^nNqvt2C~@|>0(=E?;pgh?Y4HrRw;_F^96cEe@@Q>)R=OU4Agm__1!+ruL}w8 zRw$+`@&NUcuU!7^ikckod}z~^=mxJtwIzAHGP1h1g`>Lq1wLkpFEt{mf8Bwu=}6gH z2xp!92xKXq*4zReI#WL4XK-JMV%f;Ae5h|fk3`Xdp+RQaI(jzouaL`nLp08-0uO(p zA;NGfc8?+n9Uo$YAc2xAms=&Q&I}wxglAB~;pxIes~Y)2mT7R7U6YibecIw`C4Xu# zjvXlP=-13Twb>}~l2O(oDoaVYC=PWDv>W7r(q(i%RkY2nZb(vR9lQIQ37d%^R7)@V z2ZD6%!d4{6q!8;ffCMm3)&5t)fj%I)(il*PPjw}0hqhk}$v3J$dTNJVg zd^<#+t5J_me@@53!*YX~%z$9aYK(lrmQB{+c!@qfQg1cA>GAUh5-TN4tmDpIX)jBx z-*IFw=G-!tt#wgN%p|Rn}$t3U8JldMrHq2F9 z%?Ajl@aE^m&w1~gy0#iX528xW{6(K2Prwgo$?v2N7d6;U$65cY97N2=JaXOu zAzzLwY^f|}V2Qfy*m#(_sE%QWMe62^3=plN==x!5hNS8t%y8y!cXzVqwlS40mD~{} zmYhI#8BmQpG3#4d7ouC7Y#I+s+dZ}yePmb}tIjwjZa5i!y_-BeqqTs`TK}f7>sd$L zWd)NFco^dKQ?1S9s_WFIi`;74l*5;njdeAX4>zLI$L&?9<$)a0M7d#JmeN(ae*Q_!bHD>a@F&+eqbNr_k_bxq`<>X{N50EZ% zdAZuxeXKfH*`do&;dPo+bCnpK>&#gpcIOX=SRIdzvAvAv!(Y&A<^mm(y{O!4*A-Zl z^vt}hkL(|Ahg*!7r75As*p4(qXjr*0)pT z8X~0|vvIDi{)1nZZZe*wEZNI=%$rAnpyIn53Nts{OFh%QX4zrUW@z;qVW>pmMBUk1 z!a9UqvMjmVzXiS3kzAO9yVD>b?>p~S;n!2-3LoGq=VtQ^9V47gRj^fMvC@JuGn&uuZ%z!O>f<|0n5bA%zbZp{>RsN zq!0as-}rZP2KOY~I`cGTHsC=7R?Y8m$gBFl{97~C#5c!Rta$~ZoZeAs5`vXzoeTSl zPT!W_@Hmzt_>nNvVf@1K@BCGN?2#nux(==7LH(W$dUkwkW(pMPaZOPw9PF;p@pcKt z%kUc9*4e_nkebpVZ$!@^BP=+6G59YiI035fZK-E5u7`75OE7S_{nfmTi{0kE~agCPaCn3o^HnBO`>NQ z>zSo8U7l$2BLb>d~@}dlX-aM>d%U^MVyN0UeL~0I`PyK0c8NVp1!ku_` z{YT4}E4NkLpSwL*_Tn_Z%_TGY85TL?yuVr&GxODGIWLK;% z2FFf4ab0iZN%Q><`fqKK`S@ej1U(Tu!)bZ^U6Ci(9{^NGDpca-d7CTiby=yR6zY&r8T^FP>QtXVZTJ$D|-tY|H%B}^&{d;WBC<#z{~6js1P18hvoHSsFs z-e1M-*=j}=v8A965$F*F^0LxhHk#}32q0SLF55Y>umIUHB3x6R_Mri|jlp1eInQw3 zLoGh6KVPWj?PtCCIRt)?j{ghv{mqk>?UdcvN3a9?oFlyftfbi{f634FmeRphKuLYl4O ztkL-H=`^Pk5S+-SO`K<|ZOAr)xEk}-}zNzj=bHARBKIw24mbnT!^1x=T{8h-`D1|2*In}|<&PFwnvCT28C_5YbiO(Z7B;bb?4pho=}Xno`KX7$^!Ss6@rw}4m)8UtrODVh&5j5kAR zoij8wnG3nk+5SB8(3Rp1^7Y6pEypDL@NRWWqjrF7eL`F3@e2%QC_WU5a=$u*vkY2~ z!4dllMtFi+?F1Ldsz#;DhZH_dfT&+(KEv>%vyDZ2ohh5=P9ghLQc^MZNUO|SI}+9y zMmhNn=HNW`gnlpesMVua`uR|J^{E6X=eGN~U^_TC2DEkM`})Qzpir{bH*>j+LrwS#%JmuyQ27tDnpHT~I^mS*HFrpi+DVWa;ck56dVayTuD6UBT%)w$p19Ft7c zgDFE*f&Q#Ad&tz8Icw2;p^_`daH4^nKln_+P{?{R)>u<2GUUXX-dka*S2r&w4vj-? zrr7qKBSQi;f|&91>_R=&Jt2IQ0(TwvbK4w2@HYJ4WBLi0?~|&pzF(UM@|Z-)!atKI z!`Ko`hi8zkRl=8Y*WR&gPl4qb!9gC1ywPp6 zm-OexqBr(GDH#uj(cRaSCI-C|`KvPjnvtysw4o83&QUMZ*t}AgWnXRXPTfv1Mt&;y zm`#o98Pi;S#8;cAkDI&iqB$eI_CO-#SEr6na64ssvRc6oY&S@q!C|Rw&|c@rSP0>r zF4^L2kyZ=mm7Kk&IDidtwud!ONLK{}N}D|ftCp@4>}==~&&KhB=GLXXLL5Ao!t+K8 zC$gz)3#C|@apC1nCbp!ny%_ZRU71GBUQ3!1?MS`>^O(K3Stk&qClRjOh^0;hTLl3j zIpR@6hi-AenGLvaypJ6saPbO_-9ETFK!)<>%dZ61SO+@w5epK!#=Z+NL z5JSPs`xgMdrrUa;F`(q5<2jE#R94Sf1bJv|UuPK6s-32mV=+ZhIlq()z^I{MLW2?~mpyCCKU*i8Lh z78?}5-OkIKK4;RdMW5@mEbhLMdAu^sO9V85xuPCvnn*LGJ=V@IjLO(y#ZwO&ZI>Ic z1QBy70sp;oZYa29tgGi6oapz_n5Sg~XR;hfrdUmnzQ>JO3pGYeHb{d5j)jci;8X$F4Nxd9;ixPy zz6VI@z0uJt{xUV(?NG8(uo)-5h6=NeY2SoVhj8Q(c3Dg30vX(x7)`_VlwvCHGMfy8 z+RYW=>3Xao6J$V^$>zeM-6t&-OO#oHs&1(4&LKQ){rOY@@!EkACcMu1jpCin#BXmo zR`3TwXLY}<<|hW5>Le*b?J`tc@Q}X`)OgzHh33+lq;Yqoa~@4k>o^vm&wdsCN&>(a z2vUJpIJNU+JIzqd7oIZXP%mFj^u{rYgtH=8ezD@^L32yjmVwH(>03GXLWmkBDLUc+LLumoZ{>V{Zn*u+c;gGD);4L zw(-(4Y>qw7vQY>VdEAWCIfl@a6PVWFsjL4{l;8_m>3o$JYG>Vij?2b(=L2(bv=>Sz zPRZ(wRF)noTV>cK+m4U?(7k>uV*%UVd==*eU$3~r%E1(l3g{%0_1b5h%R@`T3}6ik zDPUrvz?~zEQI&jj^q=odQ;h~KqHi3x`<6UxGes&nX*33IGV1szV=+Uk zC+OJ?*cWRQ4Xa>kQ2ClOefR)`-eyo_te3q$7AAuM&M8N1BUrLbUJ6<_XLNNi_1L** z#|W4#>%v;#RpUAL)tHxijF!{PE>hRPDH-(s9j~fYt{51}}JTJTZjmm@p24 zgF4nRY1%wXn$rf%5;SEv0WDI>p%os5ZI2=AfOoW20JEDjJZLIdANMxvY^L}w(}KyH z9uV$z20GgBP39hLR381LY`ssf*35#zSrQJ3bniIv`-ZQ1zTi*~1pCXhfJ0IQRYrd# zoDZ45Zn*c8*?VmmEWwGdl^!_C`_)m2t5~&0t87Zed4i+gk+4^P_qcah)wk!>O$}qV zHjz`(+jD?9Rs&x6gi;M)QWNq<+ZV?|#DM>Rcu%v0^=YoD`}ZWfkjm^Vac2HI1V4C( z@WPa%luPd8*8cG9SEjs<#_@a5N*sRB&=h}D3T)4 zz48IuKoJD%LliQnV-ZAm)_`-SXw2yO8-o0N8bU7M@AvU{D1}!Xi$B}I4X=}i^mhv5 z&gO-pZQ7pJ*#$a5oa1;AU{lC-vJ=z%!>W`Hv+cX35WvvKm_2n>%R-Z!=pD3nm=^Ro z6Q5Hu00MtW!3Mi^DgN8eu+6X-mZCS2`hU#jD(njU zuU%AaqG+8v6-my+YcDkH1;fy$<$q`~Mll|?6CJQY(0RWkKP~sQWO%p>EbEGuG`a=? zA$1*1_tRxJ3RQM5)O|Nz8x6p2OH4f@p?WFCo&=uOt*LY@LgCtXD`|C73R;-IY8oPD zHGO=4gR#~87@Pg*^!kPvf|{$`P912l!FWgW;_kg+zZy|F5(fJ}BZIn?zZ_`cq7>n| zC5BmaPBwjgK=iWIdp=}L@pUt=p{hR97bb)EyO~6|Vq9xL#3soQjA}f~IU^&}a-F9! zC>0LEJ!9e7nFfnm`u&zdO?@juQL$=KGQn4P&yu84TSDw4lpj5RBKCb3!D73ppNNVM zVn$DtHkp?@5T+zoA4-BVq`$&5Y;ZGSnV600BaIB6(5K>ztRV}qfb zdb3u_ED~mYv0JM^nie#m0N7!D;8Is}7FFls{9yUhaA180|D)yW z3U@S7tkZialAqMO?xM9B4={Iu^KN(ufB#T<*WHT>0v+otTC+mJ^n22|%W5Ycu@yPc z6QUr`TsWEVWW@dM^o*on>@!DXzpCGnPju6%y{$zf6L;_dmbRp^@|bZ9TbLQc`z2*i zxh)okKpY*x!MseiJKy#kej~C z^NhD9C&ucEB)%r@u6F!{xdnaM?9 zL>?J&GYXk&LDN;OdSX{0}ju4?rBHI3%%NX>?6$3QH}&zu06LYMo}Utq7CO$p_h zhFRWVK-D+}l7K`mqUsvuVe|x)SWZ#5Gvp92W|UG(x@U>>3E{e!ew(MR5cm|UHO*RD zuN28-7K&(pzuy3@twM?Zrz@{?$qLT3<)-`Y0g3Z;Q%vfyW6=-$5)rT~GUk+Clbd`f zR5W{+@une!1&(_DGX(~)%IMj*Q-3AWJB`?FUPj`D`N1Tsr_eH>+zLr!oXL(hk!TKM zgzJ@5FaIQ$X&9%&qUOtt)n`#heR!83&=M`7a&P=$!BBHW zL#<*T0o4$buJ7&D0bzQsa^h{UBS6;ba(zWj03p#uTUplzf z8Xj4jjV}R3L#hWe?X92;WYYivp4+wofRm>Af7s3xI*8Q;SGWbb2^tNAy+UPTtfOrU z!Y*zKnb>u29(Ly8#fd%`76bgnyI;=!nk34cv7r_ZUL<$1vFNfqO4*q-!C z6jK-{CGdoFJ>wC2?qJtS%ATjXpKdQta3M9WzsnnNWHcmrirzrdv1TPdjzYw+KajM& z!+;m@SQA50E4RJ?=r~XUlHOrj+;N={zV@1K7k?RY4=Y!8tH^E!M${LNS+5nlWnOO; z73}N;Dq;wCenbGHm6Jv)JOvXasg$8xkgnAd(v zJ?ffiXJR7a19zs8ABq@4Mt^br+=9L7FnBUZPTmOyGj1HTVJsODsCP;EM(nnJ9C{HR zx((Q57YyK`E^FK&4u()=WU`a?s}&!*#`{%RBBbZT(_uWq6^0EuVx3z@+XfnM{Rgbo z_rF(QT;FYBJ*mYW;}lpKS0%zeg;9H-N%mgTRHzQ{BYg1+rC& z6;iq@bdB4_bTp}CshX)4J!9#gjR{F?JUth3XNs=~$*&}Oo`C4CyYAn#5AbNUl{l{M z1^^*wK9RSjicj`14>U(o+<=(4|1}(sl|sSj91j_&eO0d6utZ_TLNKD3$|Wlo>AG_@ zkR^`L8CtfU;deW%DuyN#&14mX>XS=ig=iDD5EKB01w{z-3X8BT`xk5$RCloCUUc}U zY6Ij+{LTXorX>=MMl3~=*c~}ZtEeQ^#^^iUG==T<`3|lJ4$p$_G|muZUfq?DTJuAn z&B}3;I}X;g{d6^NDR^kpA>97jhl=o+D#`bjk;{22j#(Kcwr;*a0009300RTND)w+W zW%Vw@7yuR8N$|n{>qO|S9y?M6JsQ7O#R*0O*#=Vn_9KduE^Kf~;0)xpv^}jM;GnFu zUn%GXX;lNxL58@lYk5n#>H{Y7-fjLw3y1Wjgp^v|U3Un}ve?gyPoyU3!=V#!bl+^M z<;!;hCxxw1wD_|61k&-;2>)mDEFIu+bol|+dlw!3dR~XkgewITFG#AJu890&2C&e3 z;TXdOH9^2-^F%z_zQI$lM7(&l@+w}b6EC7$WEhC(9{zp6!5t071M|_HgxLG+{sWw` zGnOOGOxjs3P#>~#1>T#OIx1i_?rtoeX^(is6TNg-6T@+9s{m@N;1QqKxw|i~kr64f zB^6ano}yJgi{E-OTnYe&Adnei*T(U8R+|D%%TW$XQ@R=4Mnr4tRo^9?4QJ2b{IE2m z{HQCfuff?wXGywz+ngsJM*s6e|JH&slajw$0Yxk#gWllIY}vBo(tqXQ_@WxYrV1oT zH{gZkEMM4z&14orsi~g*=Wo@y!NHW~-XUMN{|`PAnoQ{aMZ_8u;J-a>j1c>Cd=8lb zK;RR{k&s4$^g+Nb-(uz?z8|^QB5v27x}09@K@yqt)$^SEDL1XFs+kPBfvMZeKCsu{ zS|p?UjO%zpjpJF+b1BZJScNGgfs|N>=`;Te(dT^eU3|fDgRfKVdG`U zRJ0@~MVDVNuz!Ds6Kml|>pyc2a>?YJC&p(;skzh`Khjk9<#2Bok@A8ch^WZQ^pVVZMmgc~xcERiU< zxz&U|4h6l*w!9irzwE@K1+UVXt;z10;w>1VfbtsEdtc{N#TFd4X`-ewdOR%iDm9r# zxH=1+Z+4`Z8|G^7`1#o@Xh-WzOWC;9^>1YL+SXcHVJl49gM-C^0a%rxZc_iH)FzO% zEkr+`L9imEefU;~ztMyGQNC)yRl0>JN~4=;hzT6QvODs(uI?aNMf5oe6C-psY(TcU z8SX+|ume|8DYpqk*j*k8Hvj8>-A9m%oilXBCea~7`=(sLJmYxF^Ktq1?n@xpFX2ILPS> zqOZSAk4%-@`92rkW$EZ^5rY@bJC$EJwyLTG6k_6<-kqb$U&z8{7NZKlOWmsxkCk z{@$g3^zv03R-;j$d->qWQgi~T)s;gqV zm+UQnM#A^phIX&F+gh^uJ=ZPpLMvs=CkGPe+dn0iNL-!jki$w@rRl#zGP1#hzYHI` z*$FibIIA!#F*TM)Q&&j%Hv+aJBW0?~d#BHkvdA)L01bpwWUjUo;}bspLOJK^I}Lv_ z@9Sg~r@0^};+^|ld81gkIUv*pQ&3^?5S#`T`LY(_$ULp zYs$+4_w+l0$hYRE^@eNb&cb|d@WX&^|6XvV@Jlw>OXb;((#gv35>FIl4I{9A7FI_-V>s|#Flg~ zC@g||Oh2iFKj8#jOW7ffo9B1dWDJJwmj&sVBAj0~tqQMBMJooK6dW&1d`jdOdCO>q z|L?A69$~Z}WzWD;tq$FPebP?q3FzVn+qWol2<9n9mf}4ZtsyK)ZaE7YYgmuXpO^fdamJ1oLN7FkU%P_R;cw!3! zkmzF4e#GyJn7#PE6$JLVlOv^_8QxCY{4uQ&O;vYxvUcPXM(WXbq% z2QspoD`mtDf3M!@NBKwyYXS7GeWl>Xq8F^qRSEPMwJQMjY-oNz{nwvbX*ST=R3+ta-|L}TFxqsn?c&hNE9~=p8clfoF;dWXf{HQcfz7>Zg6*# z)QK8#`R5j^!3{V5TH?TjjR_IBRljW&3-BAQu|HIDe4t7*t-&P4^~6R$;i4-$I{2phj(P6i{Zn6 zf#kA=BLx23mPepg{FQ)22Q{5qe&EzhC^P!)$u{i@y0a`CV+s6NXnbK}{zoE6b!~#3 zoGqR2e!c@y`n@n$(+ zW-I=_qmNSNV84b$lcATYHOJxs5-UL^x+SR5D~ZrLC@W%u(~7uOGE7J&n3tdqBj(4R zym~?$UZDxT#eq3kG|~WRGpW(CL;*QPip7)zvqYe22ZSbo+~U4K7hZvlh{IMkJZw|X zc&7xR^)TG0lQjOY!7NkGN<1ZP$=8?CTgi8zUET!AkSRoN8vV?<+a4mYsjUwDsh?V55C7XvtS2e~Hect+D1SCL zq2dL7_Lp%P`e~z$I9#Oe%O)&f<+ErVVT(2^pLzUQ85kvb>S!r2aeI#sv(Mf8R8osi z_W4tzf+aWm@kImv*H=WA?>B(|3yL;0t185^kap$lkuI*J zoN)?#3?@gs7Jt@A_9b3B8~}l?h+$*U-3mvh%cxPsU;mi>?RW!p(#&)3s0m4Bfi^zB zs01K+O!r|^`Q|-cpz()#_P785IkhEI-!)LiWzOj^sh!-;2V?rJ<}QUhICtEXl#-be-<+@L;p3s5GI~K!abF*}hO}OIwuC zvq1|cbdjDKCQOd_vP^6f>6if~XhC;e-zajdGKASh#H7W#OZ(3FJaA$^YEiV>910TzFppj5}(s2}lnJ z@B&L2KX)`of!ZO9z^M9BS{Gth1wsL+*e1!{2_)T;<$uQ^P8#o8TXtS{QPM8|*^Xhv zKE5}<QuESf@GLZvh;Rh^N0J6LPlv1*@+4|g ziYq!(TB^j5z?dbbSeESNlu!=sJJewJ;~wq#&xBQHS?r=Q&G}Q6lIlA@{>{!H2a7j* z^zipyJESMlCo6(MSU>~z+LrYrCV`@+ z=_%*@L!PuK1nk0xpffy&# ziDY>l+!ar8hn-I{!DZZve!(blYin8wCkrg#65mLHxSFC!Ya+o7#)_XBU>N(MU;qFQ z{OWpZ-2H2Dw7_F2Xwvenf?F3I6y|KpL1k|V`tQDE?C-nHqlbt?%J*dGnii{@Ovcb- z95*=XHw%3M@5WfD#RJ49SMp3daj(4tSI-g|MBF5yO`*-_fQxkn;I3d5(`;W`workK zeC{ULX`cO{_rf`axh6FmM-yR*Rje|(JmO?j86)47jV+sq1YeHrG>5flEZxz5EI~mO z9mY}~54)YCmjZ*#X6Zf)52>Q92SGsBOY|ALIxrxq3&3Ak9m8a-+B+5v#=O05~X$LmN1$p8BW76afA^u*70-nlEp zIi|cw5;f>3qF82$#fE+FEM>q8>7Nu_x-A)2glm0Ad zOln*i?;~CZy#q|jC8d-oz7k>&KcG~4Bx2ebmG&_M5B8@5J5$>DwOqste?oSp9PQTrJ*c0j{XToU3uKhx@?aHXzVNI>2UG;kq=zR< zt(~u)72DE1%d9z%b!z!`^A`?E1x=D=Zm%7MIM<4w2CtIiEl%j0Ux?g%^^PG^*7)F+ z>$4bC7%Hf$G*;9QQSC&0?~b^V`G|&I!0)z}Z{_<#bvOPLj*9t>#bYusRJ1E`X4M?7 zLF9+W3Ra2!Ty>6xQem%4zC~)Wo@#6@zq@31AWH#p=21h7V0Xg(7LEs=&F?cUdOvb6 zFfelCZA{W12t(u`=4sRmfID5&o8ps$m~yAXRRTa3^Iz|FEI^j!tQmXEhil_WsrdK+ z00RIx?nGuIHvj(93PIG+X+z;`yHkiv&H+L9^rWmAw5xJmdUX3?De+KEKkxm{kq*0) zvg@;JK52kj$830L&xpXOQu>phwu?}G2Te58SGEJ)HjD7Rq*B@!=8AZ6mv&U+gE-q* z{GcnSikxU9Kj;fwK@eW~J6)hL>Jax}gHb!R;=)kx7G6kAr=aJq0TY`fN^aJTi<kVe1o6RF;P#2 z7aoRp2Rs*MK)E~t_Xji6Gr+>_b{qSG|D|G@$}U-x0;f+0 zZWNK3oSJVRvsVh}5Z2jli4|mDqDfpyLwS`q^z#b@+2>wNhrb_Oaz3pX;Z4*xH$X4u zHNVYS^SQc@76Pd~_=DlQ^hv?tMz#gK2HkwY?NY&u%O&wV_Oye;*t%M{3?Aq`c}6~{ zjlDCeZ1JN}yz}sa@2`t!UX?gSWS^{@W8$K;SHk3|2+XrLF8|r8-bAt~f8oS|!gG^C zskE4(GSJlMDjDXWLBh8Z(IuRjY^5&kO9oK6*y^}a%Qwpc_g-q|Zh;5O;p3%?Q^RtgBzHI*DGi)v4VTi1G9K8e{m)U=*|QfW1}vdRLCpguQa-slanQp;ka{kr z=81Rd{_50|hq1ev6gH^ihI^NvJLV`nf}39PF@W@ehLxD+1!h}N9`4rg(8FS=J36yL zb>#!d;NBi~N!ma#xp}1P!l>XbfS(CJB{IrP2GL5Xn75Vea|mC|Do1B-6kT{W6GyBB z3+ik$i4n5n_Ont>$^J~WhfmzU>CUfqEoO2klKFUq3!PK4Ru8D_w>}+y?U3cV5h|Wp z@W|42H03}6xdW$49ZuVB#%*+6nK)#|DcL7Pr`Ub^q1DAG=3)GBq#vc!a5MpU$GTpO;%?kvk0{o76-63oaW_ye zr#EtIo)h5()iaoh^C!xW3Zopo&oYh#K!6lZ2zLwzX4x#!6lGN?Mq1KOHFRD-w-84f zKBOhPrHUiOBYH@+f;)d_o_XheW+vaizHhBwtfINQ>zsXdRUJ;<+tmzT$DKP- zJ9o=^w-bl!v+*gMRZ<9?5GK!w_?cSsQU9=VBY5cEMNFk@Pt(gXZ($ z*aO`aI##bS6lH8UW4T%>rZ6AXLl-NaL$5q+oz$#UPM`59r5Rswp~i6KiwW;LJKCdL#FLqJ^KIfx znNk`3g3+$&VoWzz|d6W)v zUc@YxLuuYm-hXDXTZ6kG%8;GHTp?IG#o(yBZD_w8!(@_EI3bD+EO(`=I#5EP;%_~j zU*jS`Sx=dkZXD4pJbz>(nI^XC_M$|al)+BgFnIf|o%k3&pV@EKnxNXsbI0Uk4doqR ze2Mgs_;L(dyj-#{^^UNcrKErKJ>huj$K2}WO1K*ooMX1difZYa7wzWNckRVLH=2lu zk`e7HNVllAOv;+S$~q^P)AOVrY7WXF#f;pqw#Jsl!3QEwT@3HYbLeQ|YMET~ZtQj1 zIBZ9|cc_OvI8 z*PRdSQ0rH~suq7`95DA`Qel?vAIY^wU>gY&$kzzat_!bzV2*u^KaXwIw~gfyDZFdZ zHO~B2))h(KvDl)2K-TI*TGwTV{mcNFOvx^ntZ*dT3lY3t1o-}TDB0F`q%)Y_LHL#M z5nzNh*PT_~%(^yMA=jr_9S=dq*l{;zvZRx@=dB!f_?qE{n25YeRi7X}g>r`#C>DxP z6Z!?ufc%XqTH>sPceo<*`+D#N;Q7nr4`+u!92bXTNfBRx0VI516Akn%fW{^swHxt$ z*22D(;+g5h6h=38PK({Sf?KJ+2fMe)(Qtik4Y87or!k<}XCj*iZ2sE!VQ*Le)65#XCOj*{d#mal@;9#Z1pgL5DLd-HCTph$yNG+`4O9EmzLRJMCMA#BN}hF8=5x|-F_XHmpwUec zn#Z1TLbhKb0o=hn0}>FN87Cpz7OcG}XLOW(FX^Zz6yrs!9`Ie|Suu_W{Cz)}u^8`~ z)PB90CU58On+QMYXbhVaRO%c{X)A*jY{?cknMPY%hslzP=64UZc}rTYbB)+jtAPqUu+Z$KAYvF3j(!&fXyo^N|O4#b7Kl_V+J z;=h-t87u=H&=#3y9)0^#*8c(?o;yZa7O39%`AhBG+vI(qP16HJ*qj7&YjE@ z2vAM&p5z_TBzTeOCv+`)gyp5|!U>f=>V6VSieyS;Lp2T&7JdQhHw}m5cS=nryo)+`Dq> z5eC?vvsuGX7vP1wou+^bT03oY-D53UbpyOopV~_0jTD^$HFpF#o^45ew)Dr3{B??n zcRJtlS#N1Mpoq%VZl#}A;9Ffi1_*CSXLb=~&{6fVR1QWJ)nh6qD6pM(=P7Srp!UC7 z*^^t}ON9JfxLzlCQ`S|H^E&Jy9I8N?gjEX_1e@V5pZs>&3qED(6V6kj=sT1CbP6tl z?a$lZgV;Sb_x`tK-HYDh*Hny=P|E?{;r6Sg^ZOzsg-ThSZB;zt z7i4yl(_1}E3fzZ7Cq5#4+9Ah;-d*B73d6$ENmlCd+s@aT6o_PEpqPqy``&<*H};!a z3{-hSJ|5|NL2UeXhzard#&TOHVG3s19sd4g>_1TM7>UV^iu zd7gmUJeD#V;Od?mUkR>nyHm_pk>lr$nC*jn9lO=q^BY0Lj%@)Ghp`^v@J&K=#;SLC zYrXy}pJa_5TpjyFYqT zDuWGkgD&#{Z>gUgEtk!y5wvPCKk~>DP|!skl<|tw9b6Swh}1dh(UuRFQKR7IiGdF& z3tTQmt|xkJ&7Q*4u`Y{1E;Iw3+M9h*@7a!5H5mvFv%5BOj41h1b1jIK=yboVhTcJ+ z;&Y7kQ&falX|aMlDi2n)3z+sEU}h9rhn`~#$kA2I3Shhs_$rkigK3}oLC~Zy!7qhF z?1y3X246BB`KH$fKU%y3JVG(KVO<;C>U>?x!^Faa{ySA{eiezD#MeEc2iM4b@429+ z7W2!;!IktjMY+Vh*Pb7v;dv(Qpl$0+73 zSQwpLJj8UJXnK9si;RCSu$y1#kvAWc(Y002NdM1%H(PG*s<=t`2|)LTD-{M3&fzzm8)I1E~m;;Mov6^ zC8915Aq&-exZRv1ET|-w40v$t(&W9YD4-R4ybO?MFiQdV)xPn~d;4Dhs!bEa+-z5) z2R)Jzc(f3%kCH&RFMXVT|NnNBoNX!5$*`mE(UoD#B%{43j7MSWeCWs>kLdg&v94L)6mj_xhg2hM zdOB?9YN`A3?p4_0b?OnH#_9)ntJMbw0=s2p!q+96$qSfOZE}^nmd9dbp(-mRibU)6 z9eLL?!aY0=J!o9TQB9y^K0Pj$L=OeUmq2D9oK}1aUe~c=Z5RQP{s=RAC4QaLvAQ)D z;@XTiG6RRs&+O|syGh)3F+{xr*CngCCL(8P&QIjJ+kVSGWuMKT#mK4n5Mnp=+b(!$p zh_&-0mN-hvOTxF`H^LJ@A&f4tsP(UfVMTxVwxoh9%w9AX6LRDxyP_ z6AwXgpsi;n^$>BGfudk^WLTReb4J=|JPjL|d@3ZHgRpNV&J%_%0e{drN0g}u=}fth z$;XA@(Vj|O8>r8aeiy}L`D9;f#E}+E81<=bEzLp!Eopm=hCk)WLXiW!WYjEbJoy8T z$0(k`VsHN9DPQ~}I%8r3oM8U0;$42AhBSJdj?p8!pWi#Vw|6Qz40RlCeBhI>*j~kY zZTW1{gncPVWcxIt1I;6lT@H3dHmA``tciEx*AmQAHh?m+qv+c`3Dq5fN}^Eo!@Xrq ziO^+pQ&~R0yLsG4IB$bkJ{romlnNc}ml1VwYZ+@vBUVy}uB$4PxF}+Jt;R1|r)L^Z zd_X0i`ZX`O%ePk|M-wl^$o=?Sn-mfR_^UyVQ<$g??gvywm}_lM(CU%isQC`8!_Th> zKZwjLLnVDP4CX~&2{QO97Sj+G#tV!CO6N_KQrTq1gD3$FCLNQMZ6 zW=X0JgqHH;{?VXzCDOp<;^cdwv*YZ#kmw-L!8Wc(wxn-@n&P++Vq~{W?71yrP|PK8 zMH+ZadODXqpG7K8a=fJBx+yUNk7QNqO;ENYCGJ#-&m*U6zHY|tBV)YgpXC6g#wN#5=0&TpRrXv9u$&T` zdb#Kfc8~7#QidR>l65>=A-v@B7bU{DSUR>nk2Sf5af$mDBzP&R&+(&+KK9X$&06QZ z2bVcU!0Wn<-8)!Ca*_KY&V^2S0FQaM(uSL_8$SZZ#Sk_g_MCA`eOHRE z&VFnni8e*gwhC#smhhGRL^)M@1h2dYnj;w zK{*yBaWgaqWYEL$)>|KIGCy+6B$D%U5|Un8zvmQ2Yjnadg=dPB*`O`lsmwIDW&sv9 zrhlC42h=r5cthJ_T+e#0rzdITP*8t-;k&)|*-Zu0D>y+AAVY>_)w`0mEw9pt2#_;G zYJd5vi&2!Kx4}b*{2Z3y2%fX@;;XH?*tk}w8gGq+xpU?s)?JLIqGr*0=M{bSBV5er zLFtYO&csYG9(VKLt?n3%(`oh62)sD$y9hxdisUJBOyk`HWunU5$ISKmOZ1+j8p8K# z`lsX@IfQ-OAyo7xW(1KICuHCa#0xRp&L+!v7%48$*+5Ha_yr`S9~)l&D8>ydBs+xrl<=3x{+hg0(4{s`%4ke`5R zh_>{pE^g&L#4m32^Z-KNm)s|fi}tb|-+mZsb|ZmPrH;2i3EZNc{NYHmzTKGEXh6fD z_@>^qy8QIZGHgT{e&{>`%NQbj1l5J!m90Snu3ba6hLI=a`3d>gk>*Ej5A>}~r}CTr zvSObj4=k^rF;{z`pDI`=i&S{ENkHE(;SPbhE5T>d~zl>LR3Y^ zfKPoj$ja*e()#u?fNI|+f~C%kU&-iAF1>HgDu8I|?67c0H9Y%hl_r#g`~`_y+8un9 ze|rSo)2Kt}GL=Glo-Ej~al`Tcf-G(IqWiwSUxjI;X6{Dc#MG(*t1%Tn*kgx*+V(E} z&=r6vNVFMIy*qpxpZS?uN+J3V(W~JyFtV&wG9VFxhOte;_e?e^_2(`*xRf&(t78#w zET4%EwWdakQhsMVX2+MAj{*m$k<_Q7ZBqsgO!`IP*z2aYsNRcTH`%2C-%q`2Lm*iy zuiQ1~jKRq@0Cn5cGA)7~S=dG2-wD=EYLs5<2Q<*PUw3lq+T2D>*nw(7OMD2|v$uj7 zZKqn+1ZH)5#Okk$HUxc7Z8_BbwUwu&I5x@o7X)@j2njhVDb0gsH;uu5NEKQrG^z5A3!R^Ds_djj3k~QK5q~oRMZ&chI9o##K-3hKxEBW^@-;^+%HF;f|bxwL0$J zXmWE80bYYD`tv?(gbu3+(G)~x^y#=nPdG1xRspMl9P|_Kq+s76#NEt)Zb21a6Ej~E zLQm9h*5D8&OSqH+YRQ$~M(2@v@S8D}F7h?)RIEUy zUQw;i`s^e+sltKcJyk+_yTG+lEOh*$doz-rICv-dV$}&(gD!qS)KtHjr6BGt5n)R@@Q@B>8$UkyKF( ziU$V)J^1%$HfbN#2UAVr?0Xm5&Abv)!#xQeihm!sbIIa4c44*J!hFJP2?_+(8EQ-^+|A{p*)iS0@k8o zqdI)U$Y9~)-xA34PKg7XVR@vB5BIf%=Ln!8N*F{%f_K7#Oaeu}q3%(kcb$4U@L?i$ z7Yk7#6QSf<(xqOf#zhBSH0rA32?CjzlQ$p@Z9eASy5c@PO1Fi=b0KiQ13kwa2Epx4 z2Nzx?gC{$M#6maIfW|sZghWuqDc$d(Hs1MUj{X(ga^qPv8XRW1$yVEo%j`^GMnSZv z10P$achmT6`z48SS$kO+5%E9>R^Jk{MnbvoX)9eAoBiY{*hCM^A*p`KIJ!;~jObo?>c@^Mj(3QoVYOx>5YWY&<4LR96Sn@I^}l4 zk@~DnGH_KXZzlg#{=FUpo;@1d5ark=&PFrFL@|63n;2o;zIDMILPAV6bMISlid;$h@}CkSjyV@%2^Y8P zpYVywh&Y@UvSC&-xsvKnCA!nWSUgLc-b82#RnQV0KBCz;rtd3h8dTy;NR+b% zQ=s*mI#$ICX%wl|@cn2h7&}|q#j9y2t~1hCAB#+$_Xwj6UmUmO?cUQ~m+RmPVWmc0 zU@>bBrF_4_GkQpOq;<%WRX<(Ri0i!(Z$hBV}jG2xin*+VB)|9Pg^7wDTf z*q!Xx!ntpDUP!r(m_c`H#;J2o=`(~+3@FDAj0ZSera^Aa3R;lHTAl(5=7>D=*R}Ap zei<6-&Ur6DB)a_-&KW#2thiDLVxgw6atA}DNkmlWHA@q#AFUFU>RtFD})C9A{L+-na~tgmhsb5dQJHZ_d5*i*%(~Iz^Z+VrwV{nex1-UMmc7a6Kp&$3n zA43`~LhZJ{viG9)5n^n4SP}*dt^jvlA+CkTzlhxrh#1ZID7TK*dLp3(wT~}}mCa8+ zzeZAFPt&@Lq9o&RNW&~#BX?+0;>(>`o_K~jpDz{(K_&5Gi#C`FAXxUp%&=6ym;Mb`+ z<vPR7*g!{?T8-AoO?-F&>G9B#ws@hT=;?*79 z1`5LU&8h3q$vP2P<>WuRc;;bOFO><2*yH=j0{{R4p)6sS00F@Ko7D=O0stTmMnXL1 z563yuDKTVRyPO~H8dEl$MH5QI5JgSS z^dpBTW8S|alIJAW`rx|HxEWX%R4&^CO%+bkGfYanV#*f1>y~sUS)vSZpqi!S7p-N| z_Gk=@J`<39Sd5-6O=%^!%kZFiL15^Gf5eQ63{UHB+C9jB=Pj()xKzGCmEE@a6-yQx z);~6gs6YIM&+}kz{nIS{T@&RSC{y-=?p% z0_o-6tF<7>mLDyvw3^m-J#<=2%@*Ig&+PyI-yve5ow+0<>ho9RhVo=esG!h?~Ya8aShOp7v z5$FPyQ6C2`7e^0;45vRRzZ~t^>3T!kmSN0;wZ~fRKp%&Jfo7+rua=5gEqw?W?r`($v`DZ~qWLay;wW8ZU)$rZ9g3ML+~w zKCw6Mqf9Z=)~QVU6Q4zwWoSLBY(Oq-NC9?`oEVNeut0JU})&5H=n!_@dC*au?Fn0y$!bR0?Md}L!NhOXlea(cY(uJe&m zh^&w8dd5;Uwk?#lhcTzc2@K~+>}~9nfXKbZj!QIOf)AO`GbnuGhg-aDNR@A6*v+{! z-8;%xzlS@LhCN+9;{doN-pkSo5}`nM5L=9Ilab8!X`MwRinVX*`8GO934KR$a)XEd z?iv0x?g>81q>w204#{()c7g3XJ9p2^dF^FZT84C}yB|1ys;%|vb%>(2!`s$vaGn4& zda~MP1BT;?eQmT}y2GLowYRvOHTZZ!}eqi~$w!YE!dinFZHU7ppf zQ&i$eEIaDpma*D?3z_5@WydS?rQvNz%duqhl2Wr9v7;U6o9oA;d}%3?qZ<@c&_*YuSZ$nt?$Jo`vl%#GzwEoB(x;wJd$n%m}LVn22*_f2X!l zKf%Wb01kD;Hhx9c^P>vHGNVw|h#1BnF{Sb?c8>i1cf>!ZK_C_g!vM@W_#>jsN^+NP zs{j8H01U?e1oP-O!Tj$S{?*p)0s(#qrJes7Ohiecb;K#*?@;AQT_|_95B*U3dKk{7 zWa}!j>D@Lh$Olq^YQ8;+kWrai3&qa?sJdY45rW(a|}`h zhIOn$b~0Dx=XF=Di7PZQfU*Fr&5ah|;D@Gx~n}E1fc_F z)BW#gB1jNx`Q4@e2^;jE0EYi%o)}*Kr5g8qIjU(N5+z8h zGR^*uis*OlK!NTQ2G9#-EB}owpI{J!bXmXmz?0!)nN52U%LA_xiwEkWT1_$7d>L(x9DI?+Fg z5oxQN1Xcl%WV=CzfRvQOVjf#|o}taaSXk_5l|4;Q+f+8avBBIBq=TU1`Hx6@ zxJ1Jz3gUwTGz9L6i`Z|L_DeujK?o_5Rjls{^7j-)g7a-HJ^)BMkS9z+Sp@%P3(6pa zPEHTx=|7hPz=+Qu?q~7+Kk-Em%o6w~U(ov;y|BOO0YIG#>cT)Mjrc!=0i7IpTo(5V zPH8I@Y80V{nLdfv^lWtGI`=T#kd9rR2#dnrK!bU`_MQ8Ev-AOrY#S?x`$1peZrbod zt&9><^1Cjom-2K$2?V%MniwA%6ezm~3CUta7a3q$JF*`Fz+V^3l7QZ1jv8bus;)z1 zcIpoyx@DTmA}D0~g2Ut8hPn=q6nuDj1?yg%2{pm78}Q``FlvU_{v}=Xb>kUjK0Ko9 zu`qklxnR%l>&YXLGMkf#C9Fk3TVElEPNUR%XtRt~*t)Xh5Syfd?qUDnD&dfDvZ^ns zR7t~g&$UBiFwPaxvToJ+qMfjDkP&h%%H!!*>DRr@rR}Y%;MEzj6Q;(LWNmMfOWn($ zyA!F6J)3tWM!Yi?+xx2|ftPkHE$+A(9|q3AnN`l z62xC~D=2C3`=>~t_X|Uiak_p38Sw={B7j)||C9-g8mn@PeHvff6U}nM%OgJnSO_PL ziYNtTPal!P1FPcn+`ju!Uj59(B?Kc5UU`uydO6TV&ev41S>lhkT5?Gen9n?E@-j*mvQ+7Q(cb z@R7q^Fj#4qktw8cOsRw{_Y>yHR9sQ4A#T>EAp>i3bJq^J8qt{?_3~)de0Q|k93TN9 zW5L@_=wWfD2|F)-lk3pkCpaHdc75roT$qZ|2EOy#UC4~n$OqI7Ypxgw8c+fnt2dLf z^b9}VOnhi+vL8`lNK;W@TbzRu_0AmA@Z7cgt+ zpDHs^3XSh9IQDIOntT}%&^>3Z5&DFkHB$WbErb*b6p`^)RTe72 zy1SPNZP;c53!deIY5l}5m3wyh-c*%L@rV@P(YE_@llozfM+EkyKlY?^^=s;xL<;EH z2a=U<=}7FS<0H=mxV*hwB^h3q$YSR%kN#XMpyNrt4c9`n#)bOCt0oXdY3RU85$ja3U0O51SgD~{5wf;LYnxF-Yh zVfzq1=rgOGj75Ag-W$A6GDN6bMC<5vc{S_Jn3rdL zz+tZRuCkT`yQkULV^@RirT>TTTP{xm{Rnn~qPe-Zf~0tOnXFKO7hlX`$sXZEcBDf1 zB=32#q=k%K+!ZLNHw}cQy-9V-XU_*XkiN1oo#lh@$V+Yzj;TWaNZ6jdn^<+(N|G^r<=6;)s6Z3^>*=XN1yG z{;uoH6hROz58BZ5Ox4V)EcV>jjP{vbb!_C63z#r?5dk`)vPG}G2Qo+-0xxxwlZy=o zdNUAjEa?UbGz@s2Ta}qVjPpC&5sA?BMyMQQ0R|BlgCOv;DKpRfY-U6};TF#D3Nlnf z6x{Y4UQ7{1w5&n~A^hLeIwlYcU-${mEjrg5OTkz-k z9?v=H9^UVkKlW2_@OzLm%|h7>|I{a0fTcPjn~|(r3lo{w7cD~E_jtKK*rPkg)StH~ z%@qrfiHb&7MILxA_v}U)eQE>j%YF*g`Ldom*T4B}rj}ixIkQ{&b-SoNlR>bup08QX z?UN8h&Sr~$oTDMiiu5A=i{nSq$5}Lv>dh2)i(=cM@ox+rjimC@^xnL?p|4V%*Yj*R zGC}|}eyn1(*)gPYI^AH$#YoW?U}X3=`zxbxSE+mW#E_@JjEWO>Q8XN~sCHdw`j9t0Q-Kjv*nNfQe%MGaeogU6LWx|qtE&WA#-U)^29`o zL4gQb-+ClNE{j?GkWRs){DZk^`b=udTbNdh_#w=)l*LOyAmNfiE1D+kw!6aIRdX6Y zp-4@7mmmQRoKjViAy~QI4KPfLF?=OHVdL5aw16iDm5nhK|IVg2po;u2btL>v9l$df zMg&w}kaGStuYumV{w2auq4d=MRtLa!%Ovr>n7hfB>zR*4p+ZO)DklzGX6aBCK)9A; z>4fQO5W(blLQ$5CV5i6yiJ#{f$ zjr#;M%t;W&9E?y+TDgbpa+1_OQ#^NC*$-Y!#j_av$v}gJIaTp@F2RLVUHiBl*e1KA z8NrP>Sv1~8{C;~>c3r=7h(aIaPNYzF(?2AF(!)*zu>*_u;64Cx6JyrhG)Z2!qwBf; z*%w_oeB~=CHAfa~?A72fy^(G(O zQdJJ5cNeC)Dh+L$WJe%Ok<~%TS-@nm;O`7Vt^pYo3e2AWn@+%x&VLYeI0&hHsbBF; zRrkKJhRTs5s4*zfN9yL#+oB|DV`r&Z;mGN>2I%hDGv|Ea&=p&lwzy>ZR4>#4DUsE* z>+8e)1+wgO*S`O(`|V)3E(?<4E)A`!&Zr#C3T>;TMb7Vx`C|Zq1hV)yfnWp<+qgo6 z>HiJ^4hZ%EIgllkzVfcC_Fac!J^5;rn*z8oH5xXBBsHY5o zN=Mo1V$7DZ_FRd&$M2U5UI}XnZ0oPZ%S;^B)l`6ex2)iU*Uz_`luxY&(eJi~Lfr=4 zKdV{(0enC)g}G;{5L>70o2=K#4kwT3i7ly~47Tdm-z92529SkGLfMc1hD$dpj$cyRx5t)D#ftBzUA(N37W52r-A-G zcbwlrmgNDnaQ_y3%z4s0NaxFbdc)V(r@l2AQOn{^ctIO7PBmX7h2V_A*qv}i^TLL> zPhjVv5RA)FB^)%bBQSl8Bgig(oJhtrWVPbQOzwAvKVIxTmlhUUtSS5{tj>N$Q%7Ww z9>Yyer&RD}lxeVE9r?rRx$yz@c*U?EH)tu8J^pZ zKEDTr|C%>ygwlZjlm*EHn*I7Kz+Ynrhp}0f%NLg~L7{iuYESry#>e+W>0Bg*_qlu~ zfRGzDr45Rz3Jp~XH6yZdze1xJ^;#f$rX~%*oHBs?Ib!;(GBJ{1mWeQDkhvARIDM=S zvhyZP+GJ+bX=KcdtnUnt&DTmKxEQ;^Piy=@R+LCix(-1)Cy(Uo>Z=!@?bGk<#{X5f z$`;BJ_=i%a(fsxG@s*x(7+$j%D4M(i8S|sB7bgkt-{$!aa`qARDa9?NgjBQD-KQP0 zf3#VR##MVSs%{RXUb%GdT|k(+pVDRlxvC)KCL(=4BuoXPDX-mw>1n%$*)`@;DS3N!YS zz#0b)#BcWOKA>Pmdz}la@P}Z!AUDD<(7YWpt~~i2VW44-@T=C%2+R`vn>rrcT^5_r zS%2>XK(h;k83h%6{vi&alRopi01p+ln~iaq%f`WsJU2szLIx$HxZ0Np%jk2Qs)21A z9hrnXVQUuYwg;5?7yA37jK>BT7`p^xFq3urQR1F51qENM57{OI0ghOZ z4hGF5s5jVDFsJ$H8i!rZ!kMDk2z1o`qh;UdVExCT-!NCH=PJT6ai$@Y4dH!n#bgtB zWRtYjPu#{n)_8n@Xp&_k`n@mI1m65uzmm-SU&WjM?C1Pv9fdZ)M^AAb#e03--X>iW ziNxfjwjy_)AD7I*6`f9-eN<0omWpKNNWRH@&kFr`A-;Q5lqWtnkA+jTVo=9X1lC>l z3ZbIH9}S!|>@Y7Bjs3V^L#BG4dBkQ%=E#OU-k?4G6~ zz(fhOlL3m$zh8*^AT#U!Sq*x3m-R9^la+OnsYH<^J$N{ka<=Us7ViseF}4b4;EH=L~LIS~T$XqGuGv z)*YWa6J2W}kpWYb#LN2wfjr?%_o4qDU%xg>D@FYK)Y{*S-a= z<=>e6%L$%bklCQ}!hct!VAT?wX~gyx{|}JwpvecC|)G;A4O zr>n31{rObeEL2Mm@fvLM9zXPciWO&Ha>QWCMhE8n*T=eZs`{m$bX{~h#+xYc=-6y~uvtRV$BkI+xqZ=FIE2YLxd^9$pPJcqK0HVIbqK z25yX<1orkT<=?sy0}@}%(V;@`2r7+*?WvAs935^*F+(_wltjw(;~jRojXS+W$KzwV z@@5^R4!JS33$T3ZAaY|d^l`^g=Z z`&@q{TxCSOX9Br6o-gtKL?q54Pq*dK1vPDa15pkKUc#uED3?ArC_UO!&%rwj&V2%$ zDX2~$#k;R1j6SefFs}3Fy;6?wVr)`IzNQqc3~Nu&$X>2lQYTM`cn9bto|7~mZS7<4 zSCN=v*v**6E zC+ATT)5cFEw8+c|lul-9zmk9FJ3tAm%zx3q##cLyND}$^c$f>dI7D#H>3lPtRZN?B zE86_xXM{;j<5Q;wrlw z$swN99Ocg;i>|DF0)IVqM@oEBBf5cTazOHJpgRAxyo#pHdU{bYMX=Sg^x48L1FLd^ z(T8x^VX;m5;qSIqS2q<(4?FiqF})wHGhm7K4+nDsKa7hV(CS%zeiPdW7s)i_N-asJ z3*9}pEg$5As;e10%Dxp*{dlv{mYXV+2Qfio1i>jpFk(D zrl$Tra60!+q_Wu{tC&W|b5$N3O?4WkVb|V75z>NODu#M|0e*Mrs~nYR#iNJX^OdcV zO>47E`Hf2TnE927lhu_ug?PYcH0gM{X#TQKQ2vWxP zp#@0>g-pAq*l@Vi`&7Q?B8{6ek0-n6&^FaUbF^4?nR?Lu&?0Uzb{WNyL*v zSY!G57SM}Ad)I{O<3$v=#!Dtr9#9zzEWB;(yhw$U#M`aD)9vybp!i{XX1FSrTWsY? z?kIn-AdpOgwJp+_h9GD?Kcz;UYJ-S>{AsJILehUec$|$kotq5Sc%oC#^x?z%@(u5h zck7?;ZI=cl+QLD%3z08LOqU|(Po=jQI&fm`6C5Bf3%6s9!ibuJ5kSVJ_lqe@1f7#^V5o9E|4OqS@FVF{f^SNQD=vc5u}p`42Xz*^@qfSb-2!VJ1H z9gO%L*L}v?k2PdANo7O#_PXRN_f<=e_R|5})L*kPg9E7Lx7|s;6KZydB|gJgOk4IC zxcGfn$AHH_U0pyQsGAA*ub1UFzAul(VJuC1-c;kB?!Kp&6s7K;jR+zlb$FjffEAnW zz!_Z+W{5bTyjLnc`!eVT>*5mO?^OzV)jV^q(~ZP~-NNwFH#lP&3cUnp#p&-~_w_lD zVnfSdYEB|y7dNfv$Z;`IuzU}^8!nX85bZDSx7P*nrTQI6n&m2V_k6$6xuT%2JHGxz z@T|&ue1}G|H};OSktvh`r=e?Q%C@IiepCC5rB&_J8na9)g+l&4UvFkt@>$2dhBZ1H zO3t&iFWXei!afYDKxc2bI{wl;^%s&rGKFj>%IAK6EQ}kfoJ$B!Q{f%231pF<)pQ2F zcsPQv%n7~)S!pf|#FfbDgWnK#G{dFIj73JVNrfAa`nC=&I{mUmHC=p`)F1&r;DshI zHIlV@XvU#@MM7hix$Phl7F4&2Zb6Tkcse}A;~XGi?(Pf=C_sbB-l%Q=u&hnmn15Cf z^MMJs$W~R{lN6L=y)^t;YBYN{uy-}erz0Xbf8YRSdE(CzNkc~81AZIoA+DrE5)#31 zMSK~|QU!*jH$%IBeoWVz+L(F7nVP$Bm)D3zhbt-}@Ka6i{c9+Z0tt!>=v3GK9GjG$ z9vRh9006FvO|C&@WkK-2*7rXWB{04_h{yBdF{vy7;sF2v==ik{^G7ZRlyA!oaZzAF z{x68Fe$X6q7ko3KckZlV>Jn{Sno|s#8Zt|?Z{yG`o~!pCA8(_!LPY!^J%^UPGlRYd z86@!56xO4uz5gt7u<9wOym4MNvNwTB6|opcW+A_RDeEi*h<45}0+38Tx-L zX7_1ktg%RK)0eU^yDK&QCP;4!9v#FE;c8n;9VrPL8okLj4$4=+0dUy#Gsw7bX+9W) z7=n<;O7O7qKL3Ya!NEoV0I28x+KhQaCWMHq@t&}imk^on$JES^%S1hx1{n1_|crKQ8wXThEC@_$xGZBw6REq-inIF!&x9Jp;rcVb|LpOwX96aD{g;NG~zW%2|`aCV%$dex`1{A zUIgUSwvurzm_S%q;Poejj9R=rK>nf}UsC4vN@hH{~@6A5*jocy&@$m-%W~ z@1fvxKgc|G)^sT$1(zti18ZJ9io#^WwW@h(GSw@A%#p-0ISxqOo_gQ4wxO0`k*+B?-hHuQT%+;1+yXztkf zcIZ1HY^jjtg=`i$9zndWW=tzt2dTUwjayMk{^Wku70%0~L10;VW9Jv>MgVr0_tRBT zg>9++49(y4x)siRx-(A$#eBSWEgyHrYr~;=U=F_A)VzIvchYfh^TkCuxK<@@=9T-x zwO7DOas6ty^`Q&YMD!h=#S|10o5*-7HryRWH7a3=tl5v z-nzzYQDpu~Fz}=29 z0p29RvlrmZN4V&7J$P5gQHU4>b$B4oz!z4&Lj{Q?slw@&GWj!)Hg)BKNpN+#c< zy?fs2maL_$k!*=k*|PImLeh$~pdu0zy+m);Xpx=Dnk6a>zdJK%7NkGk z_w)Pj-aGd>&v~BbJm-6!d%ov0-yet!Z%=xwH3RVSU$Ej5VKi2qlBg3o2z~diX`i_8 z!OyN`f4-cQkw2Do zqDe#7?S1f^wl*rEXAa2wAmizN!|a}kIB+cWp5qZHjRO!Coj{qlAJDoJa?<5zmmR;f zt@lXzQHzr@VbKqh1pL0uJu6Ix3#rhCw*9nmYma<1#&^oVtoR@8;B)4$JspSaQz)}4 z4cdcsE<7p8rVKF;2OZ>dBK7QzsxS_#OFc$X`eKYs<7|ftJk_leBRu!#TBNZZW{G3G zK0$IiD64c3_YH%@3dCog+Ti09_}Hn4Hv9@boOdmcw&)=2i0p2 z4)=(-I`JNaX74HPcb%Fh$6Y(E%qS7 zA(CF`fN))S-pikfdTwr8+o_87ocA^{*Fn8-q|5)H*E)OY>ii`sVf`y(%{18!5TvIC$@*g|v*i`C zCFISYAY1$xc-o4Ub(jDt8#8EzZ$ethuCJ~+h-j!~RCJqvO209mY;Bi4lV6OdW2r@h zb=CgQwUG@o6-8}MeTG?a$9Q`5n@9}YrGv8WOP>NlQpvsEzwl9HyhSJv&^=|D zeVwkV{4QOfpF_=%&Y=enT2$G|bsYOB-dK5~s?L_0AO19r7?l~|I{n( z8pv@;79;gJ69e%d*!p(6q+HHprSxm_LEDXJV1av``2I-`Lmp9l9FtxsMeVG{Y$KEU z{gh5N*X%jv42qPb?wkXIq?!C*`md>=gpNCtvO<|DNUnW+{GOJ>1pFHkn3GWEMgF;c zY)X?iEe0>k+nHy%-A65K)qdYCcl;oUiF=RXxqvN=k)f0qa>LUoYh`;|DOqw(U4F^@nMo5X<4GFvOj_wBPm8CT^>#kxR`i;3s0Va8)|M1S zF$G%BQnt((9`<$M=ej6JzUZtq+(dVzo^fec4o|sBg5K6X+qrM377Bsc<*3@*zvTd-SH}8c}-s^e$f#jq;v}A8c7=w|JUpc%BVXzgHx5pZ}E)FJw~l!nMCie zQzq~_S+j|7!44^uc3h`&#nm^t_brR(IVk7PPepf=vbAtX9JOvdc~P%WN#V$YV0MQR)zBYcc zSIa&fE?-%FZN4mI*Y3Z@PeO*>1BC-ijd|vtzPshc5M4kPRY6J>o&S)Y7KpuTt1XJ$ zftvUQBc#yhx9WGWzm~1B*JOFi6|HYM#TurVN3SW}(X4)O*r~H3Z`h_9M!BVd`|We8 zwi)GU!B)nW7t_(E(FLU0O$&KA4^uB)6mk6ruoceMZR(+Ijrj1HX@dZO%lBs;|g>7~uiCz3!LC11r2k#~7x4(M^ zq-eb%x#DB)kp1@W2=}(supBy0x8Qj*i)74vMZ89XPRYG_HQgnat0;q#vl_P4*IuHC zL+Fpv6%uDIZ>;*N{*yn*{b`;;)Ib@70Ox!p@G2*q*`IUYi6#y|-=fsmea{n_ z$D_)oqD`x++v9~@JxzqI`&9h#JvZF=CPVpPkIWhU|;E#amPqFplMskTF z;8M05xAtO%=R-{f>xq5OLHdyx4oySor!0v(E%X&fE%fuGF$?^1SW!LoV>!zEj%B*D zUo<0G-TrYuMf&*mu*>(O={AAc#>!d2}B6OZ!c9l9w!mln7E^X}I9m=E=uqSAj~P=9^vxqma;4~B@W zF}}W9yDOtFOB1BZMTH{UHMj5PZkzJICHc9JP9XM90IFW>Dy=$iC`{iYz{6UQU!hty zvo5fP@oJ3B<&vVBk}Rhu5U3+nm>7xdbu<`T}hm zAsc{L;p&qWo;v=1{p!!e7b^^Y{5^Hz_g0@^oRLPjp}uSz%6-csf;Hi}si<#hUw!+K z+9gTy5dAkpQImoV(jTu1CpmvQcaf$U+4<6Twrq@b!9VVYxqq1?_&?X#QisBxRk)Xl z#ISNBC0I-pVk&$ln-OD&CxRCZzDm=y@1`ocE}~e%XovFInuhPN(V5plBj`sY6j+Dh zZ>3XwV!M{43;J@c2vhz5MZhCv_b5;fow$*n;DEp)dNU#|ed4hBJw2BO{H4f?t~(g}8BHxO7J4FtQT8wr4& zhA0wlmHrwHL?&TludQ6pyMea`WH0PeIqj+^udzHOqxKzqftS zKhp9}x|TW#`%#fe5!ck1-cL-`kH$0I9g6}>;*Ost3OV(`)|*R+ad6WU9c+9mF2%<( zACo6UB3S3_LxLjUyo*b9r9y5wutVWD0t7@?d{^T-2or2YoK*_0Q_vGN?#sWfIm4p- zhkIBUF%}V%H`mvgsU`(#B0W&T@i}2`@kl!Zc_C1tfLNa?|E!r%Y_H0#v z8en7eFM}y)5kAH5_X*icVU~}8Be53!|3Rql1`ryoz?^4>(12@1$gmeIRgt+@cJ{|5 zm$D2A=U(CN^=_ASBA@b=q`huFT^XvJ8PIKp+NDdKX)Y$aJ0yfwYB=dFSN|YrIQ}SM zs;n#8k0~U;B?SROuA7A)^ly`sVj_%(kW_h1-r9bI8kQBJm;Pu*1U?~)pf@YGfT*gV zsUr!xFaco%pN{q07;|gTfO*I`f!4QqV4O%(K%WbTfTzvyX-X@7BCrb(1_mI5=;=#> zkVmwR1iFFcL?j>){WcM~C(*-J8{@*wBjYTXi1gSF{uwe75LfU=432exLTY6PFXnLa znf0*|gCV-!eHz_71w~QZDdu-FKOb4@?Gw85isyF2W6h46WjBL57Wl;sjtgkLS3@d` zgkMwPf(!Xie-}2FT_Er~=5|Yfn9xZ`4BGqPk#u}SU4LQ6weK<#!%qhzMs)56$E;P2 zfUL43i8I!NxTk)oDnINRSPuqv_J9Ja>q9EX0b`-u&Q%?F7gP3@tr~zZ*Z>hGt{Vh& z11rS~E+%d$fEkA%g8bW<$anW5eD@dN8OEZ`Vj@5tcN!`WitO5C84K*+JpgG!fD-=! zDDua=<(h}-Vsmk`6(+z0nzRGk!9N2<@GQlqDons~YVHz@7G3z-tq+Tf!3sO)4u9qf zWc9TaY8kI#`b@@O=ecOtw^~&3i^UNpIIH?0ypg$_9&U5FX;x71L>-uS z1QqD|dB-d6fhfk#lmwLVwUQ203z%!ilW>Ac#PMm}zpbdi1pz*#`?oWzU`)qIP!r?w z5(gguH_V`wn&Zz(L~!QW6ab=qzq}0nQ}`3Yj88Pd?+@S)5Q{qvpc$c?hCf#@<;t-^ z{nrb_9T<}|uqn6M!Vr)GO&SAD0)753!5_jUxEMyG28H9jSEigz6@ zx7a4fdL9dK*sH9@=eM8sV9%c5ycgl(2r7jCkZ+eU)3E2##OR1;mcq8Zvnnqw1BS=g z1s0#z)J>2C44-DOnM|<{Du%bkLq_e9s#R;Hq|tD`D}+208*Tz9TyF&j@VS&@L@ z-8u^3Guwe-Nq_>lNVs8&U_j;w771;pc_EOK%CqV5Ktllii@_QXnhYe`ob$}_rPU|v zliw>gP2WV4-IGY0Hri<(?{|XG)@^E)4e*Jq!^j}3>?<$`IT_Ys{K|2|{`^NMser8< zF&5+Whg4xi=kAPi*Be5^Aa*IO*T*23L*r|F?FD^A&Ff-z1>-H;36s3JdID3MfuOgk z(h-PvxJ@Dky6ulqQXX463J<`DI*(%^rgOm5r%!rQlDjB-e?Y%tLbO?oL^r(>qCdk( z(4I|UBw7PzRyD>VqJAh!1kaD@b({D=+HFv-9(VMZvJWdXOho=B4E#PKgxm?)R~8^zdD8SDCX8Eg8}fz z3jEneSvf2uGA!%#4y6>3d~vRz-%Y69!>T UNx%}T#2)X=%9^iYA09>i4@!evH~;_u literal 0 HcmV?d00001 diff --git a/public/llms-full.txt b/public/llms-full.txt index a3dfbc6..fb75df5 100644 --- a/public/llms-full.txt +++ b/public/llms-full.txt @@ -80,7 +80,8 @@ changes require a connection. 1. [Try TaskNotes with sample tasks](/app/demo/) or [open or install TaskNotes](/app/getting-started/). 2. [Learn how mdbase supports TaskNotes](/app/mdbase/). -3. [Choose where your collection lives](/app/collections/). +3. [Choose where your collection lives](/app/collections/), then follow the + [connection walkthrough](/app/connect-mdbase/) with video and written steps. 4. Create a task and open **Today**. 5. Turn on reminders only if the collection and platform support delivery. @@ -110,7 +111,8 @@ copy of your Markdown lives: hosted online or on your own computer. If mdbase is new to you, start with [mdbase and TaskNotes](/app/mdbase/) for a plain-language explanation of the format, Connect desktop app, and hosting -choices. +choices. For a video and written setup steps, follow +[Connect TaskNotes to mdbase](/app/connect-mdbase/). ## Hosted mdbase @@ -136,11 +138,160 @@ mdbase Connect background service whenever you use TaskNotes. See how to ## Change collections later -Open **More** and choose **Change collection**. Opening another collection does +Open **Settings** and choose **Change collection**. Opening another collection does not copy or move records from the collection you were using. --- +# Connect TaskNotes to mdbase + +Source: https://tasknotes.dev/app/connect-mdbase/ + +# Connect TaskNotes to mdbase + +

    +

    Your browser cannot play this video. Download the MP4 or read the written steps and transcript below.

    + +
    3 minutes 53 seconds · Silent walkthrough with on-screen instructions and visible cursors. Use the player’s fullscreen control for a closer view.
    +
    + +Download the video +· [Read the transcript](#transcript) + +These instructions are for the web, Android, and iOS app, not the +[Obsidian plugin](/obsidian/). + +The recording uses disposable demo data in the LAB test environment. Account +sign-in and OS-specific installer dialogs are omitted. The folder chooser and +Markdown editor shown are Linux examples; the connection steps apply across +platforms. TaskNotes is in beta, so some labels may change. + +## Choose where your collection lives + +- **Hosted by mdbase:** available online even when your computer is off. You + need an internet connection, but not the desktop Connector to use TaskNotes. +- **On your computer:** files stay in a local folder. Keep that computer + reachable and mdbase Connect running while other devices use the collection. + +Hosted collections can also be mirrored to your computer, so you can work +with local Markdown files. Mirror setup is outside this walkthrough. + +The same TaskNotes app works with either. Read [What is mdbase?](/app/mdbase/) +for more background or [Choose a collection](/app/collections/) for a fuller +comparison. + +## Connect a hosted collection + +1. Open [TaskNotes](https://app.tasknotes.dev/) or its Android or iOS app and + choose a collection. Sign in to mdbase if asked. +2. Select a collection labelled **Hosted by mdbase**, then choose **Review + access**. +3. Review the named application, collection, requested actions, and setup + changes. Approve only if you agree. For a collection needing TaskNotes + definitions, the button reads **Set up and allow access**. +4. Return to TaskNotes and add a task. It is saved in the hosted collection. + +If you do not have a hosted collection, expand **Add or connect another +collection → Create hosted collection** in mdbase. Creating a collection and +approving TaskNotes access are separate steps. + +## Connect an existing local folder + +1. Visit the [mdbase Connect download page](https://mdbase.dev/downloads/) and + choose the **desktop app** for your operating system and processor. Follow + the current platform installation and beta security guidance, then open + mdbase Connect. The standalone CLI download does not include the desktop + interface. +2. Name your computer and choose **Continue in browser**. Sign in if asked, + approve the computer, then return to the desktop app and wait for it to + connect. +3. Open **Collections → Add existing**. Select the collection root containing + `mdbase.yaml`, not just its `tasks` subfolder. Adding the folder validates it + in place; it does not move or upload its files. +4. Open the collection chooser in TaskNotes and select the collection listed + under your connected computer. If TaskNotes already has a collection open, + use **Settings → Change collection → Connect another collection**. +5. Review and approve the requested access and setup changes if you agree. + If TaskNotes subsequently asks, review **Apply reviewed setup** as well. +6. Add a task and inspect its Markdown file in the collection. Completing the + task updates that file’s status to `done`. You can use any Markdown editor; + the video uses VS Code. + +TaskNotes does not open the folder directly or maintain a durable offline copy. +Your computer remains the main copy and must be reachable for remote access. +See [Connection and availability](/app/connection/) if the collection cannot +be reached. + +## Switch an existing connection + +Open **Settings → Change collection** and select a collection you have already +approved. **Connect another collection** returns to mdbase to approve access +to another one. Switching collections does not copy or move their records. + +## Transcript + +
    +Read the full video transcript + +**00:00** — This video shows how to connect mdbase collections to the TaskNotes app. We’ll start with a hosted collection, then connect an existing folder on your computer. + +**00:08** — Hosted by mdbase: available online, even when your computer is off. No desktop Connector needed for TaskNotes. + +**00:14** — Hosted collections can also be mirrored to your computer, so you can work with local Markdown files. + +**00:21** — On your computer: files stay in an existing folder. Keep mdbase Connect running and the computer reachable. The same TaskNotes app works with either. + +**00:29** — Start with hosted: open app.tasknotes.dev and choose a collection. + +**00:37** — Select a collection labelled Hosted by mdbase, then review access. + +**00:50** — Review the permissions, then approve access if you agree. + +**01:00** — Add a task. It is saved in your hosted collection; no local computer is needed. + +**01:14** — Already have an mdbase collection on your computer? Connect that folder to TaskNotes without moving its files. + +**01:22** — For a local folder, first get the desktop app at mdbase.dev/downloads. + +**01:35** — Install and open mdbase Connect. + +**01:39** — Name this computer, then choose Continue in browser. + +**01:49** — Sign in if asked, then approve this computer. + +**02:00** — In Collections, choose Add existing and select your collection folder. + +**02:09** — Choose the folder containing mdbase.yaml. Its files stay where they are. + +**02:15** — Back in TaskNotes, open the mdbase collection chooser. + +**02:21** — Select the collection listed under your connected computer. + +**02:35** — Review the requested access and setup changes, then approve if you agree. + +**02:44** — Add a task to the local collection. + +**02:59** — Each task is a Markdown file. Changes you make in TaskNotes are saved back to the collection. + +**03:06** — The task is now a Markdown file in your existing folder. + +**03:11** — Keep mdbase Connect running while other devices use this folder. + +**03:15** — Once both are connected, switch collections in Settings → Change collection. + +**03:24** — Choose a collection you have already approved. + +**03:37** — In the local collection, complete the task. + +**03:46** — The same Markdown file now says status: done. + +
    + +--- + # Connection and availability Source: https://tasknotes.dev/app/connection/ @@ -220,11 +371,14 @@ The web and native applications use the same task interface. ## 2. Choose a collection -TaskNotes opens every collection through mdbase. Choose **Hosted mdbase** for a -collection available anywhere with a network connection, or **Connect to a -computer** to use a Markdown collection kept on your own computer through the -encrypted relay. Read [What is mdbase?](/app/mdbase/) if this is new to you, -then [Choose a collection](/app/collections/) to compare the two options. +TaskNotes opens every collection through mdbase. In the collection chooser, +select one labelled **Hosted by mdbase** or one listed under your connected +computer. Read [What is mdbase?](/app/mdbase/) if this is new to you, then +[Choose a collection](/app/collections/) to compare the two options. + +Follow [Connect TaskNotes to mdbase](/app/connect-mdbase/) for a short video, +written steps, and a transcript covering hosted collections first, then +existing local folders. ## 3. Create a task @@ -239,7 +393,7 @@ Navigation belongs to the current collection and can be reordered from Views. ## 5. Check collection status -Open **More** to see the collection location, connection state, last refresh, +Open **Settings** to see the collection location, connection state, last refresh, notification access, task model settings, and appearance preference. --- @@ -295,7 +449,8 @@ saving changes require a connection. | Connect to your computer | In a folder on your computer | Both devices must be online, and your computer must be running mdbase Connect | [Choose a collection](/app/collections/) compares the TaskNotes behavior of -these options in more detail. +these options in more detail. [Connect TaskNotes to mdbase](/app/connect-mdbase/) +shows both connection flows in a short video, with written steps and a transcript. ## Use a collection on your computer @@ -354,13 +509,13 @@ Source: https://tasknotes.dev/app/reference/manifest/ # App integration manifest -This page is generated from the integration manifest shipped by TaskNotes app 0.1.0. +This page is generated from the integration manifest shipped by TaskNotes app 1.0.3. | Field | Value | | --- | --- | | Application ID | `dev.tasknotes.app` | | Manifest version | `1` | -| Homepage | [https://app.tasknotes.dev/](https://app.tasknotes.dev/) | +| Homepage | [http://127.0.0.1:4173/](http://127.0.0.1:4173/) | | Collection access | `full_collection` | ## Required contracts @@ -781,7 +936,7 @@ This guide covers the TaskNotes plugin for Obsidian. It follows the "one note pe ## Requirements -TaskNotes 4.12.3 requires **Obsidian 1.12.2** or later and depends on the **Bases** core plugin. Before you begin, open Obsidian Settings and confirm Bases is enabled under Core Plugins. +TaskNotes 4.13.0 requires **Obsidian 1.12.2** or later and depends on the **Bases** core plugin. Before you begin, open Obsidian Settings and confirm Bases is enabled under Core Plugins. ## Getting Started @@ -2243,6 +2398,7 @@ Source: `src/settings/tabs/appearanceTab.ts` | Setting | Purpose | | --- | --- | | Default visible properties | Choose which properties appear on task cards by default. | +| Group complete and skip actions in a submenu | Nest the complete and skip actions under a submenu in the task context menu. Turn off to show them directly in the menu. | | Time format | Display time in 12-hour or 24-hour format throughout the plugin | | Default view | The calendar view shown when opening the calendar tab | | Custom view day count | Number of days to show in custom multi-day view | @@ -2373,7 +2529,7 @@ Source: `src/settings/tabs/integrationsTab.ts` | Export status: | See the setting in Obsidian for contextual details. | | Enable HTTP API | Start local HTTP server for API access | | API port | Port number for the HTTP API server | -| API authentication token | Token required for API authentication (leave empty for no auth) | +| API authentication token | Required for API authentication. If empty, a token is generated when the server starts. | | Enable MCP server | Expose TaskNotes tools via Model Context Protocol at /mcp endpoint. Requires HTTP API to be enabled. | | Add webhook | Register a new webhook endpoint | @@ -2648,6 +2804,7 @@ The following JSON is generated from `DEFAULT_SETTINGS`. Empty strings and disab "relationshipsPosition": "bottom", "showTaskCardInNote": true, "showCompletedTaskStrikethrough": true, + "completionMenuAsSubmenu": true, "showExpandableSubtasks": true, "expandSubtasksByDefault": false, "subtaskChevronPosition": "right", @@ -2753,6 +2910,9 @@ Welcome to the TaskNotes release notes. Here you can find detailed information a ### Version 4.x (Current) +- [4.13.0](releases/4.13.0.md) +- [4.12.5](releases/4.12.5.md) +- [4.12.4](releases/4.12.4.md) - [4.12.3](releases/4.12.3.md) - [4.12.2](releases/4.12.2.md) - [4.12.1](releases/4.12.1.md) diff --git a/public/llms.txt b/public/llms.txt index 632c670..6942964 100644 --- a/public/llms.txt +++ b/public/llms.txt @@ -6,6 +6,7 @@ - [TaskNotes documentation](https://tasknotes.dev/): Guides and reference material for the TaskNotes app, the Obsidian plugin, and the portable task format they share. - [TaskNotes app](https://tasknotes.dev/app/): Use TaskNotes on the web, Android, and iOS with portable Markdown through mdbase. - [Choose a collection](https://tasknotes.dev/app/collections/): Compare hosted mdbase with a collection connected from your own computer. +- [Connect TaskNotes to mdbase](https://tasknotes.dev/app/connect-mdbase/): Watch how to connect hosted mdbase collections and existing local folders to the TaskNotes app, with written steps and a transcript. - [Connection and availability](https://tasknotes.dev/app/connection/): Understand when TaskNotes can reach hosted and computer-connected mdbase collections. - [Interactive demo](https://tasknotes.dev/app/demo/): Explore the TaskNotes app with disposable sample tasks before connecting a collection. - [Get started with the TaskNotes app](https://tasknotes.dev/app/getting-started/): Open TaskNotes, connect an mdbase collection, create a task, and find your way around the app. diff --git a/public/search-index.json b/public/search-index.json index 530ad4b..85c4f8b 100644 --- a/public/search-index.json +++ b/public/search-index.json @@ -1 +1 @@ -[{"title":"TaskNotes documentation","url":"/","description":"Guides and reference material for the TaskNotes app, the Obsidian plugin, and the portable task format they share.","product":"shared","text":"TaskNotes keeps structured task information in portable Markdown records. Use the dedicated app on the web, Android, or iOS, or work inside Obsidian with the TaskNotes plugin. Beta · Web · Android · iOS TaskNotes app Manage portable TaskNotes v5 collections on the web, Android, and iOS through mdbase. Open the app guide → Obsidian TaskNotes plugin Task and note management inside an Obsidian vault using Bases and Markdown. Open the plugin guide → One portable task model# Both clients understand the same TaskNotes concepts: status, priority, dates, projects, contexts, recurrence, reminders, relationships, and custom fields. The interface and available integrations differ, but your task records are not locked to one screen or application. Start with portable task records if you want to understand what the products share. Read the formal specification when implementing or integrating with TaskNotes. Review the privacy overview before choosing a hosted or computer-connected collection."},{"title":"TaskNotes app","url":"/app/","description":"Use TaskNotes on the web, Android, and iOS with portable Markdown through mdbase.","product":"app","text":"The TaskNotes app is currently in beta. It is a web-first client packaged for Android and iOS, designed for quick capture, daily review, editing, and completion while keeping task records portable. The app is compatible with TaskNotes v5 collections, which use the mdbase 0.3.0 specification. The same collection can be used by other compatible TaskNotes and mdbase tools. Every TaskNotes session opens an mdbase collection. You can use a collection hosted online or connect to a Markdown collection on your computer through the encrypted mdbase relay. TaskNotes reads and writes that collection directly, so changes require a connection. The Today workspace in the desktop layout. Disposable sample collection Try TaskNotes before connecting your own collection. Explore Today, Scratchpad, search, and saved views with sample tasks. Your changes disappear when the demo resets. Open the interactive demo → Begin here# Try TaskNotes with sample tasks or open or install TaskNotes. Learn how mdbase supports TaskNotes. Choose where your collection lives. Create a task and open Today. Turn on reminders only if the collection and platform support delivery. What the app includes# Today, Upcoming, Projects, lists, boards, and calendars Capture, editing, completion, archive, and search Projects, contexts, tags, priorities, relationships, and custom fields Recurrence, materialized occurrence notes, reminders, and time tracking Hosted mdbase and end-to-end encrypted relay connections Browser, Android, and iOS packaging from the same application Plugin-only functionality such as inline Obsidian widgets, the command palette, external calendar integrations, HTTP APIs, and companion plugins is documented under the Obsidian plugin."},{"title":"Choose a collection","url":"/app/collections/","description":"Compare hosted mdbase with a collection connected from your own computer.","product":"app","text":"TaskNotes opens every collection through mdbase. The choice is where the main copy of your Markdown lives: hosted online or on your own computer. If mdbase is new to you, start with mdbase and TaskNotes for a plain-language explanation of the format, Connect desktop app, and hosting choices. Hosted mdbase# Hosted mdbase is the recommended choice for convenient access across the web, Android, and iOS. The provider keeps the main collection online, so it is available from any TaskNotes device with a network connection and can deliver reminders while TaskNotes is closed. TaskNotes reads and writes the hosted collection directly. It does not keep a separate offline copy, so you need a network connection to open the collection or make changes. Connect to a computer# mdbase Connect can make a Markdown collection on your computer available to TaskNotes. Requests and responses travel through an end-to-end encrypted relay; the relay cannot read your task contents and you do not need to open a port on your router. The computer holds the main copy, so it must be awake, online, and running the mdbase Connect background service whenever you use TaskNotes. See how to install mdbase Connect and use a computer collection. Change collections later# Open More and choose Change collection. Opening another collection does not copy or move records from the collection you were using."},{"title":"Connection and availability","url":"/app/connection/","description":"Understand when TaskNotes can reach hosted and computer-connected mdbase collections.","product":"app","text":"TaskNotes reads and writes the selected mdbase collection directly. It does not keep a separate offline collection or a queue of changes waiting to sync. What each status means# Status Meaning Connected TaskNotes can read and change the selected collection Connecting TaskNotes is checking the collection connection Collection unavailable The hosted service or connected computer cannot be reached Open More to see the current status and use Refresh now to read the latest collection state. Hosted collections# A hosted collection needs a network connection and an available hosted mdbase service. If either is unavailable, TaskNotes cannot open the collection or save changes. Reconnect the collection if its authorization has expired. Collections on your computer# A computer collection also needs the computer holding the Markdown to be awake, online, and running the mdbase Connect background service. TaskNotes reaches it through the end-to-end encrypted relay. If the computer becomes unavailable, access returns when the computer and connector return. During a connection problem# Tasks already visible in the current session may remain on screen during a short interruption, but TaskNotes cannot safely save new changes until mdbase is reachable. A failed action is not silently queued for later. If the problem continues, open More and choose Change collection to use another mdbase collection."},{"title":"Interactive demo","url":"/app/demo/","description":"Explore the TaskNotes app with disposable sample tasks before connecting a collection.","product":"app","text":"Explore the TaskNotes app using a disposable collection of sample tasks. You can complete and edit tasks, use Scratchpad, search, and move between views without signing in or connecting a collection. The demo keeps changes only for the current session. Reloading or resetting it starts again with the original sample data."},{"title":"Get started with the TaskNotes app","url":"/app/getting-started/","description":"Open TaskNotes, connect an mdbase collection, create a task, and find your way around the app.","product":"app","text":"TaskNotes app is currently in beta. Features, availability, and setup steps may change before the stable release. The app supports TaskNotes v5 collections based on the mdbase 0.3.0 specification. 1. Open TaskNotes# Use app.tasknotes.dev in a supported browser or install the Android or iOS application when it is available through its store. The web and native applications use the same task interface. 2. Choose a collection# TaskNotes opens every collection through mdbase. Choose Hosted mdbase for a collection available anywhere with a network connection, or Connect to a computer to use a Markdown collection kept on your own computer through the encrypted relay. Read What is mdbase? if this is new to you, then Choose a collection to compare the two options. 3. Create a task# Use Add task, enter a title, and save. Capture understands the collection's configured status, priority, project, context, and tag values. 4. Review the starter views# Open Today for current work, Upcoming for scheduled tasks, and Views for the complete collection of lists, boards, calendars, and project views. Navigation belongs to the current collection and can be reordered from Views. 5. Check collection status# Open More to see the collection location, connection state, last refresh, notification access, task model settings, and appearance preference."},{"title":"mdbase and TaskNotes","url":"/app/mdbase/","description":"Understand how TaskNotes uses hosted mdbase or the encrypted relay to reach a collection on your computer.","product":"app","text":"mdbase lets TaskNotes work with a portable Markdown collection instead of hiding your tasks in a TaskNotes-only database. Every TaskNotes session opens one mdbase collection: either a collection hosted online or one kept on your computer and reached through the encrypted relay. What is mdbase?# Two related names appear in TaskNotes: mdbase is the open collection format and specification. A collection is a folder of Markdown files plus a small description of what those files mean. mdbase Connect is the access service TaskNotes uses to ask for permission and connect to a hosted collection or a collection on your computer. Read the mdbase introduction for a visual explanation of the wider ecosystem. What it gives TaskNotes# TaskNotes understands what a task looks like inside an mdbase collection. That compatibility is defined by the TaskNotes v5 collection format and its mdbase 0.3.0 binding. That means TaskNotes can: use the same task fields, projects, tags, saved views, and settings on the web, Android, and iOS; ask for access to one collection without seeing your other folders; and keep reminders running while TaskNotes is closed when your collection supports them. Behind the scenes, mdbase checks that each change is valid and writes it to the main collection. You still own readable Markdown files rather than a database that only TaskNotes can open. How the connection works# The mdbase collection is the source of truth. TaskNotes reads and writes it directly and does not keep a separate offline collection, so opening tasks and saving changes require a connection. Choice Where the Markdown lives What must be available Hosted mdbase With the hosted provider Your device must have a network connection Connect to your computer In a folder on your computer Both devices must be online, and your computer must be running mdbase Connect Choose a collection compares the TaskNotes behavior of these options in more detail. Use a collection on your computer# Install the Electron-based mdbase Connect desktop app to make a folder on your computer available to TaskNotes. It runs a small background service that keeps TaskNotes connected to the Markdown folder. The download also includes command line tools. The mdbase editor is online and is not part of the desktop app. Open the mdbase Connect download page and choose the package for macOS, Windows, or Linux. Install and open mdbase Connect. Follow any platform-specific beta installation notes shown on the download page. Add an existing mdbase folder on the computer, or create a collection. In TaskNotes, choose Connect to a computer and select that collection. Review the requested actions and approve the connection. TaskNotes requests and responses travel through an end-to-end encrypted relay. The relay passes the encrypted data along but cannot read your task contents. You do not need to open an inbound port on your router. The background service on your computer checks that TaskNotes has permission, then reads or changes the Markdown files. It does not create another hosted or offline copy of the collection. Do I need to leave my computer on?# Yes. Your computer holds the main copy, so it is part of the connection: It must be awake, connected to the internet, and running the mdbase Connect background service whenever TaskNotes needs remote access. Sleep, shutdown, a network outage, or a stopped connector makes the collection unavailable until the computer returns. Reminder delivery also depends on the computer remaining available. You are responsible for the computer's security, disk health, and backups. This works well for an always-on desktop or home server. It is less convenient for a laptop that sleeps or travels regularly. Hosted mdbase removes the always-on-computer requirement, but it moves the main copy to a provider you must trust. Both choices require a network connection while you use TaskNotes. For more detail about how Connect protects and routes your data, read How mdbase Connect works. A practical recommendation# Choose Hosted mdbase if dependable access across several devices and reminder delivery matter most. Choose Connect to a computer if keeping the main Markdown folder on your own machine matters more and that machine can remain available."},{"title":"App integration manifest","url":"/app/reference/manifest/","description":"Generated reference for the TaskNotes app's mdbase integration requirements and capabilities.","product":"app","text":"This page is generated from the integration manifest shipped by TaskNotes app 0.1.0. Field Value Application ID dev.tasknotes.app Manifest version 1 Homepage https://app.tasknotes.dev/ Collection access full_collection Required contracts# tasknotes.task version 0.3.0-rc.3 File capabilities# list read add replace move delete Notification criteria# task.reminder listens for mdbase.runtime.timer.fired version 1.0.0."},{"title":"Reminders in the TaskNotes app","url":"/app/reminders/","description":"Understand reminder data, notification delivery, permissions, and collection requirements.","product":"app","text":"Task records can contain relative reminders anchored to scheduled or due dates, or absolute reminders fixed to a particular time. Saving reminder data does not by itself guarantee notification delivery. Delivery by collection# Collection Reminder data Notification delivery Hosted mdbase Saved in the collection Available after opt-in Computer through the relay Saved in the collection Available while the computer and connector remain available For mdbase collections, the authority schedules reminder events so delivery does not depend on one TaskNotes screen remaining open. Notification payloads are content-free; selecting one refreshes authorized collection state in the app. Turn on reminders# Open More, select Turn on reminders, and approve the browser or operating system permission. Some existing mdbase grants require Review notification access before the channel can be enabled. An unsupported or insecure browser reports that notification delivery is not available. The reminder definitions remain in the task record."},{"title":"Work with tasks","url":"/app/tasks/","description":"Capture, edit, organize, complete, archive, and search tasks in the TaskNotes app.","product":"app","text":"A task opens beside its source view on wider screens. Capture# Use Add task from navigation or from a saved view. When a view has safe creation defaults, TaskNotes applies them automatically so the new task remains in that view. Edit# A task can contain: Status and priority Scheduled and due dates Markdown notes Projects, contexts, and tags Dependencies and subtasks Collection-defined custom properties Time estimates and tracked sessions Recurrence and occurrence-note policies Relative and absolute reminder definitions Background saves remain ordered if you navigate away while a write is still in progress. Complete, archive, and delete# Complete a task from its row or detail screen. Archive retains the record and may move its Markdown file according to collection settings. Delete offers a short undo period before committing the removal. Search# Search runs across the current collection and matches titles, notes, projects, contexts, and tags. Use Refresh now under More if a change made by another tool does not appear yet."},{"title":"Troubleshoot the TaskNotes app","url":"/app/troubleshooting/","description":"Diagnose mdbase connection, authorization, refresh, and notification problems in the app.","product":"app","text":"Start by recording the app version, platform, collection type, collection status shown under More, and the smallest sequence that reproduces the problem. The collection is unavailable# For a hosted collection, confirm that the device is online and try Reconnect this collection. For a computer collection, also confirm that the computer holding the Markdown is awake, online, and running mdbase Connect. An authorization error appears# Use the reconnect action for the current collection and review the access that mdbase requests. If you no longer want to use that collection, open More and choose Change collection. A change did not save# TaskNotes writes directly to mdbase and does not queue failed changes for later. Restore the connection, then retry the action. Capture and editing screens keep recoverable input visible when they can do so safely. A change from another tool is missing# Open More and choose Refresh now. If the record still does not appear, confirm that the other tool wrote to the same mdbase collection and that the record uses a compatible TaskNotes task definition. Notifications do not arrive# Confirm that the current collection is an mdbase collection, reminders are enabled in More, the browser or operating system permission is granted, and the task contains a valid future reminder. For a computer collection, the computer and mdbase Connect must remain available."},{"title":"Views and navigation","url":"/app/views/","description":"Use and arrange lists, boards, calendars, projects, and saved views in the TaskNotes app.","product":"app","text":"Views are saved ways of selecting, sorting, grouping, and presenting records in a collection. They travel with the collection; the set pinned to navigation is a preference on each device. The Views manager controls navigation order and saved view definitions. Starter views# TaskNotes creates managed starter views such as Today, Upcoming, Calendar, and Projects. They use the same saved-view catalog as user-created views while providing focused presentations for common work. Presentations# Task list supports grouping, visible properties, section moves, and manual ordering. Kanban groups tasks into columns and can update the grouped property when a task moves. Calendar shows task dates in month, week, day, and list layouts. Mini calendar combines a month picker with tasks for the selected day. Projects finds project records referenced by active tasks. Navigation# Open Views to add or remove a view from navigation and to change its order. The first navigation item is the collection's home. Mobile displays the first three views directly and keeps the rest in the Views destination. Create and edit views# The view editor controls the name, presentation, query, grouping, sort order, visible properties, and safe defaults for tasks created from the view. View documents remain ordinary collection resources rather than being stored only inside the TaskNotes app."},{"title":"Portable task records","url":"/concepts/task-records/","description":"The Markdown records, collection configuration, and task concepts shared by TaskNotes clients.","product":"shared","text":"A TaskNotes task is an ordinary Markdown record with structured properties. Those properties describe the task; the Markdown body remains available for notes, checklists, links, and supporting detail. Collections# A collection is a group of records plus the configuration that explains how to interpret them. The configuration defines field names, statuses, priorities, custom properties, record locations, and saved views. The TaskNotes app uses collection throughout. The Obsidian plugin usually describes the containing folder as a vault and presents saved views through Obsidian Bases. Source of truth# Where the authoritative copy lives depends on the client and connection: Client and collection Source of truth Availability TaskNotes app · hosted mdbase Hosted collection Requires a network connection TaskNotes app · computer through relay Collection on that computer Requires the network, computer, and connector Obsidian vault Markdown files in the vault Controlled by Obsidian and your sync choice Portability and compatibility# Portable does not mean every client exposes every feature. Inline task widgets, Obsidian commands, external calendar integrations, and companion plugins belong to the Obsidian client. mdbase collection access and background reminder delivery belong to the TaskNotes app. Use the client-specific guide for interface instructions and the specification for normative data semantics."},{"title":"0. Overview","url":"/developers/specification/","description":"TaskNotes is an Obsidian plugin that stores tasks as individual markdown files with YAML frontmatter in a user's vault. Each task is a first-class file: readable and editabl...","product":"specification","text":"0.0 About tasknotes# TaskNotes is an Obsidian plugin that stores tasks as individual markdown files with YAML frontmatter in a user's vault. Each task is a first-class file: readable and editable with any text editor, version-controllable, and searchable without special tooling. A minimal task file looks like this: --- title: Buy groceries status: open priority: normal due: 2026-02-21 tags: [task] dateCreated: 2026-02-20T11:15:00Z dateModified: 2026-02-20T11:15:00Z --- Buy fruit and cleaning supplies. Tasks are identified within the vault by a configurable detection method — by default, by the presence of a specific tag (e.g. #task in body or frontmatter). The plugin stores its configuration in .obsidian/plugins/tasknotes/data.json within the vault root. This specification was derived from the behavior of the tasknotes plugin and is intended to serve as a stable, testable contract for: CLI tools and scripts that process task files outside Obsidian, any application that wants to interoperate with a tasknotes vault. The spec is deliberately language-agnostic. It does not require any particular runtime, and the executable conformance suite (in conformance/) can be driven by an adapter written in any language. The tasknotes plugin is the primary reference for how this spec was derived, but the specification is normative — where the spec and the plugin behavior differ, the spec defines the intended behavior. Known deviations are disclosed via conformance claims (§7.5). 0.1 Status and authority# This document is part of tasknotes-spec version 0.3.0-rc.3. This specification is normative for implementations that claim conformance. No single implementation is normative; implementations are expected to conform to the specification. 0.2 Motivation# TaskNotes-style systems store tasks as markdown files with YAML frontmatter. This model has practical advantages: Task records are plain files that can be inspected and edited without proprietary tooling. Data remains portable across environments. Files are suitable for version control and collaboration workflows. As soon as more than one tool reads and writes the same task files, implicit assumptions become an interoperability risk. In practice, these risks appear in three areas: Field semantics and naming drift. Date and timezone interpretation differences. Recurring-task state transitions that are handled differently by different clients. When these rules are not explicit, users can get inconsistent results from equivalent operations. A shared specification reduces that risk by making behavior testable and versioned. 0.3 Objectives# This specification defines a stable contract for: Representing task records in markdown frontmatter. Mapping storage keys to canonical semantic roles. Defining effective collection configuration via provider model (for example tasknotes.yaml and/or TaskNotes data.json). Interpreting date and datetime values consistently. Applying recurrence, per-instance completion/skip behavior, and optional materialized occurrence notes. Managing time tracking sessions and time_entries lifecycle behavior. Parsing and resolving links consistently across task fields. Defining dependency and reminder behavior. Optionally applying deterministic create-time templating behavior. Executing write operations with predictable side-effects. Validating task records and reporting issues. 0.4 Non-objectives# This specification does not standardize: UI layout, styling, command palettes, or interaction design. Internal caching architecture or rendering pipelines. Transport protocols (HTTP, IPC, etc.) except where they affect persisted task semantics. Rich template-language features beyond the portable create-time templating contract in §5/§7/§9. 0.5 Scope# This specification is standalone. It does not require conformance to any other specification. Implementations MAY internally reuse other libraries or specifications, but conformance claims under tasknotes-spec are evaluated only against this document. Templating is optional and profile-gated; implementations that do not claim the templating profile remain conformant without template support. References to TaskNotes plugin behavior, Obsidian behavior, or external specifications are informative context only unless this specification explicitly marks a requirement as normative. 0.6 Design principles# 0.6.1 File-first persistence# Task state is represented in user-visible files. Derived indexes and caches are non-canonical. 0.6.2 Deterministic semantics# Equivalent inputs MUST produce equivalent persisted outputs under the same configuration and active runtime timezone. 0.6.3 Explicit mapping# Semantic roles are canonical. Storage key names are configurable and therefore must be mapped explicitly. 0.6.4 Backward evolution# The specification supports migration from legacy keys and historical behaviors through explicit compatibility rules. 0.7 Conformance# Conformance is profile-based (see §7). A minimal implementation can conform to a narrow profile while remaining interoperable for core operations. 0.8 Normative language# The key words MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY are to be interpreted as described in RFC 2119. 0.9 Example collection# A default tasknotes vault looks like this: MyVault/ ├── TaskNotes/ │ ├── Tasks/ │ │ ├── buy-groceries.md ← task file (title-derived filename by default) │ │ └── weekly-review.md │ └── Archive/ ← archive folder (if moveArchivedTasks=true) ├── .obsidian/ │ └── plugins/ │ └── tasknotes/ │ └── data.json ← plugin settings (primary config provider) └── tasknotes.yaml ← optional spec-level config (secondary provider) Task files are identified by the #task tag by default (configurable). The full default collection state is described in §9.21. Configuration provider semantics and effective configuration rules are defined in §9. An implementation MAY use either provider, both, or additional providers, based on its documented precedence policy. A task file example (using default field mapping): --- title: Buy groceries status: open priority: normal due: 2026-02-21 tags: [task, errands] contexts: [\"town\"] dateCreated: 2026-02-20T11:15:00Z dateModified: 2026-02-20T11:15:00Z --- Buy fruit and cleaning supplies. 0.10 Versioning policy# This specification uses semantic versioning. A major version introduces breaking semantic changes. A minor version introduces additive behavior or optional features. A patch version clarifies wording or fixes non-breaking defects. Implementations MUST reject unsupported major versions when strict mode is enabled. 0.11 Change governance# Specification changes SHOULD be accompanied by: a motivation statement, precise normative edits, migration notes when behavior changes, updated examples."},{"title":"1. Terminology","url":"/developers/specification/01-terminology/","description":"This section defines terms used normatively in this specification.","product":"specification","text":"This section defines terms used normatively in this specification. 1.1 Collection# A collection is a filesystem scope within which task files are discovered and managed under a single TaskNotes configuration. 1.2 Task file# A task file is a markdown file identified as a task record by collection rules. 1.3 Frontmatter# Frontmatter is the YAML block at the start of a markdown file delimited by --- markers. 1.4 Task record# A task record is the semantic task object obtained from parsing a task file frontmatter (plus optional derived metadata). 1.5 Semantic role# A semantic role is a canonical meaning defined by this specification, independent of storage key names. Examples: title, status, date_created, complete_instances. 1.6 Storage key# A storage key is the YAML property name used in frontmatter. Examples: dateCreated, date_created, completedDate. 1.7 Field mapping# Field mapping is the configuration that maps semantic roles to storage keys for reads and writes. 1.8 Alias# An alias is a non-canonical storage key accepted for compatibility during reads. 1.9 Canonical write key# The canonical write key is the configured storage key that conforming writers use for persisted output. 1.10 Date value# A date value represents a calendar day with no time-of-day and no timezone. Canonical form: YYYY-MM-DD. 1.11 Datetime value# A datetime value represents an instant in time. Canonical form: ISO 8601 UTC with trailing Z. 1.12 Target date# A target date is the calendar date to which a recurrence instance operation applies (for example complete instance on 2026-02-20). 1.13 Recurrence rule# A recurrence rule is a tasknotes recurrence string stored in the recurrence semantic role. It uses RFC 5545 RRULE-style parameters inside a single semicolon-delimited field value and MAY include an explicit inline DTSTART prefix segment as defined in §4.3. 1.14 Recurrence anchor# Recurrence anchor defines how next-instance progression is computed. Allowed values: scheduled completion 1.15 Complete instances# Complete instances is the set/list of target dates marked completed for a recurring task. 1.16 Skipped instances# Skipped instances is the set/list of target dates marked skipped for a recurring task. 1.17 Materialized occurrence note# A materialized occurrence note is a task file created for one target date of a recurring parent task. It stores user-authored per-occurrence content and, when supported by the implementation, owns the authoritative task state for that occurrence date. 1.18 Recurrence parent# A recurrence parent is the recurring task record referenced by a materialized occurrence note. The reference is stored in semantic role recurrence_parent and resolved as a link according to §11. 1.19 Occurrence materialization# Occurrence materialization is the creation and reconciliation of materialized occurrence notes from a recurring parent task according to §4.18 and §5.20. 1.20 Effective status# Effective status is the status presented for a given date context after applying recurrence instance state. 1.21 Completed-status list# The completed-status list is the configured ordered list of status values treated as completed for non-recurring completion semantics. When a single value must be chosen deterministically, the first list entry is used unless explicit operation input overrides it. 1.22 Idempotent operation# An operation is idempotent if applying it multiple times with the same input produces the same persisted state as applying it once. 1.23 Unknown field# An unknown field is a frontmatter property not mapped to a semantic role in current configuration. 1.24 Validation issue# A validation issue is a structured report containing at least: machine-readable code, severity, optional path/field context, human-readable message. 1.25 Strict validation mode# Strict validation mode is a mode where invalid required semantics are treated as hard errors and write operations fail. 1.26 Legacy compatibility mode# Legacy compatibility mode is a mode where specific historical behaviors or aliases are accepted for migration but are not canonical for new writes. 1.27 Configuration provider# A configuration provider is an adapter that loads configuration from a source (for example tasknotes.yaml or .obsidian/plugins/tasknotes/data.json) and normalizes it to the schema in §9. 1.28 Effective configuration# The effective configuration is the final resolved configuration after applying provider precedence and fallback rules. 1.29 Template file# A template file is a markdown document used at create time to generate frontmatter and/or body content through variable expansion. When templating is enabled, template behavior is defined by §5.3.5 and §9.14. 1.30 Template expansion# Template expansion is deterministic replacement of template variables with create-time task data and runtime date/time values, followed by template merge rules. 1.31 Time entry# A time entry is a structured record in time_entries containing startTime, optional endTime, and optional description. 1.32 Active time entry# An active time entry is a time entry with startTime present and endTime absent. 1.33 Time tracking management# Time tracking management is the set of operations that start, stop, edit, and remove time_entries, including completion-triggered auto-stop behavior when configured."},{"title":"2. Model and Field Mapping","url":"/developers/specification/02-model-and-mapping/","description":"A task record consists of:","product":"specification","text":"2.1 Task record model# A task record consists of: frontmatter object (structured fields), markdown body (freeform text), file metadata (path, created/modified time) where available. Frontmatter is normative for task semantics. Body content is non-normative except where an implementation exposes body search or body-derived features. 2.2 Required semantic roles# Conforming implementations MUST support these semantic roles: Semantic role Type Required title string support required (value required via configured title source, see §2.2.2) status string/enum yes completed_date date support required (conditionally required, see §2.2.1) date_created datetime yes date_modified datetime yes If storage omits a role marked yes, validation MUST report an error (see §6). For operation-required roles, validation and operation rules in §5 and §6 apply. 2.2.1 Conditional requiredness (completed_date)# completed_date support is mandatory, but presence is conditional: For non-recurring tasks with status in configured status.completed_values, completed_date MUST be present. For non-recurring tasks with non-completed status, completed_date MAY be absent. For recurring tasks, completed_date is not required by recurrence completion semantics and MAY be absent. Validators MUST apply this conditional rule and MUST NOT treat completed_date as unconditionally required. 2.2.2 Conditional requiredness (title)# Semantic title is always required, with deterministic read resolution and storage-mode-dependent read/write behavior: Readers MUST resolve semantic title using storage-mode-aware precedence (§9.13): when title.storage=frontmatter: mapped title key when present and non-empty, then file basename fallback; when title.storage=filename: file basename first, then mapped title fallback when basename is unavailable. If mapped title and filename-derived title both exist and differ, the source authoritative for active title.storage MUST win and implementations SHOULD emit title_source_conflict. When title.storage=filename, implementations MAY keep mapped title as a synchronized compatibility mirror, but filename-derived title remains authoritative. Title storage mode controls canonical writes (§9.13): frontmatter favors mapped-key writes; filename favors filename-derived title with rename-on-title-change behavior. Validators MUST enforce semantic title presence using the active title-resolution policy (§9.13), not frontmatter key presence alone. 2.3 Common semantic roles# Implementations conforming beyond minimal scope SHOULD support: Semantic role Type Notes id string stable task identity token; see §2.6.5 priority string/enum configurable values due date or datetime see §3 scheduled date or datetime see §3 tags list free tags contexts list commonly prefixed with @ projects list project references, see §11 attachments list ordered file references owned by the task, see §2.6.7 and §11.8.3 time_estimate integer >= 0 minutes time_entries list see §2.6 recurrence string tasknotes recurrence string; see §4 recurrence_anchor enum scheduled or completion complete_instances list recurring completion state skipped_instances list recurring skip state recurrence_parent link-or-string parent recurring task reference for materialized occurrence notes; see §4.18 occurrence_date date target date represented by a materialized occurrence note occurrence_materialization enum parent task materialization mode: manual, on_completion, or rolling occurrence_next_trigger enum parent task next-note trigger: completion or completion_or_skip occurrence_template link-or-string optional template used when creating materialized occurrence notes occurrence_past_horizon duration optional rolling materialization lookbehind bound occurrence_future_horizon duration optional rolling materialization lookahead bound blocked_by list dependency records, see §10 and §11 reminders list reminder records, see §10 Optional extended roles are defined in §7 profiles. 2.4 Field mapping requirements# 2.4.1 Mapping presence# An implementation MUST have an effective mapping from each supported semantic role to a canonical write key. Mapping configuration is defined in §9. If semantic role id is supported, it MUST also have a canonical write key. 2.4.2 Read behavior# Readers MUST: Read the canonical mapped key if present. Support configured aliases where enabled. Resolve conflicts deterministically when canonical and alias keys coexist. When canonical and alias keys both exist for the same semantic role, canonical key value MUST win. When canonical key wins over alias, validator/loader SHOULD emit warning alias_conflict_ignored. 2.4.3 Write behavior# Writers MUST: write only canonical keys, avoid introducing alias keys in new writes, preserve unknown fields unless the operation explicitly opts into normalization. 2.5 Legacy alias compatibility# Implementations SHOULD accept these aliases on read for interoperability: Semantic role Canonical example Alias examples recurrence_anchor recurrence_anchor recurrenceAnchor complete_instances complete_instances completeInstances skipped_instances skipped_instances skippedInstances recurrence_parent recurrence_parent recurrenceParent occurrence_date occurrence_date occurrenceDate occurrence_materialization occurrence_materialization occurrenceMaterialization occurrence_next_trigger occurrence_next_trigger occurrenceNextTrigger occurrence_template occurrence_template occurrenceTemplate occurrence_past_horizon occurrence_past_horizon occurrencePastHorizon occurrence_future_horizon occurrence_future_horizon occurrenceFutureHorizon date_created dateCreated date_created date_modified dateModified date_modified completed_date completedDate completed_date time_entries timeEntries time_entries time_estimate timeEstimate time_estimate blocked_by blockedBy blocked_by attachments attachments — This table is compatibility guidance, not a requirement to choose camelCase or snake_case as canonical. 2.6 Structured role schemas# 2.6.1 time_entries# time_entries items MUST be objects with: startTime datetime (required) endTime datetime (optional) description string (optional) Additional constraints: a task MUST NOT contain more than one active time entry (entry with startTime and no endTime) at commit time. an entry with missing endTime is interpreted as an active/running session. an implementation MAY accept duration on read for backward compatibility, but canonical duration is derived from start/end and SHOULD NOT be persisted on canonical writes. Nested key names in time_entries are fixed by this specification and are not independently configurable in mapping. 2.6.2 projects# projects SHOULD be represented as links when link semantics are supported, but plain strings MAY be accepted. When interpreted as links, parsing and resolution MUST follow §11. 2.6.3 blocked_by# blocked_by items MUST be objects with: uid link-or-string task reference (required) reltype enum (required; default allowed by §10 when omitted) gap ISO 8601 duration string (optional) Detailed semantics are defined in §10. uid parsing and resolution MUST follow §11. 2.6.4 reminders# reminders items MUST be objects with: id string (required) type enum absolute|relative (required) relative-only fields: relatedTo, offset absolute-only fields: absoluteTime description string (optional) Detailed semantics are defined in §10. 2.6.5 id (stable task identity)# When semantic role id is present: value MUST be a non-empty string. value MUST be treated as stable identity metadata and MUST NOT be rewritten by rename, move, or title-change operations. readers and link resolution MAY use it as an identity lookup key (see §11.4 Step 3). implementations SHOULD keep id unique within a collection; duplicate IDs SHOULD produce a validation issue. 2.6.6 Materialized occurrence roles# The roles in this subsection are required only for implementations claiming profile materialized-occurrences (§7.3.4). Parent recurring task roles: occurrence_materialization: enum manual|on_completion|rolling; controls when occurrence notes are created (§4.18.5). occurrence_next_trigger: enum completion|completion_or_skip; controls whether skip/cancel transitions advance creation of the next occurrence note (§4.18.6). occurrence_template: link-or-string reference to a template file used when creating occurrence notes. Link parsing/resolution follows §11 when supported. occurrence_past_horizon and occurrence_future_horizon: ISO 8601 durations used by rolling materialization (§4.18.7). Materialized occurrence note roles: recurrence_parent: link-or-string reference to the parent recurring task. Wikilinks are the default interoperable representation in Obsidian-oriented collections. occurrence_date: date value identifying the target date this occurrence note represents. Implementations claiming materialized-occurrences MUST treat recurrence_parent and occurrence_date together as the occurrence identity key. Within a resolved parent task, at most one materialized occurrence note SHOULD exist for each occurrence_date; duplicate notes MUST be reported when detected (§6.4). Materialized occurrence notes MAY also use normal task roles such as status, completed_date, scheduled, due, time_entries, reminders, contexts, projects, and body content. For dates where a materialized occurrence note exists, its own task state is authoritative as defined in §4.18.3. 2.6.7 attachments# attachments is the authoritative task-membership list for files associated with a task. It MUST be represented as an ordered list of non-empty link-or-string values. Each value MUST identify one collection file and MUST follow the parsing, resolution, and canonical-write rules in §11.8.3. The list itself intentionally contains references only. MIME type, byte size, content digest, storage revision, timestamps, and other binary metadata belong to the collection's file descriptor or filesystem metadata and MUST NOT be duplicated into canonical task frontmatter. The Markdown body MAY embed or link an attached file for inline presentation, but body links and embeds do not add or remove task membership. A file is a task attachment if and only if it appears in the mapped attachments list. Readers MAY accept a single scalar reference as compatibility input and normalize it to a one-item list. Canonical writes MUST use a list, preserve its order, and MUST NOT contain empty or duplicate normalized targets. 2.7 Unknown fields# Unknown frontmatter keys MUST be preserved by default during updates, complete/uncomplete, skip/unskip, dependency mutations, reminder mutations, and archive operations. Unknown fields MAY be removed only when: explicit normalization/migration is requested, or strict schema replacement is explicitly requested. 2.8 Example mapping# Example effective mapping: mapping: id: id title: title status: status date_created: dateCreated date_modified: dateModified completed_date: completedDate recurrence: recurrence recurrence_anchor: recurrence_anchor complete_instances: complete_instances skipped_instances: skipped_instances recurrence_parent: recurrence_parent occurrence_date: occurrence_date occurrence_materialization: occurrence_materialization occurrence_next_trigger: occurrence_next_trigger occurrence_template: occurrence_template occurrence_past_horizon: occurrence_past_horizon occurrence_future_horizon: occurrence_future_horizon time_estimate: timeEstimate time_entries: timeEntries blocked_by: blockedBy reminders: reminders 2.9 Example task record# --- id: task-2026-01-10-weekly-review title: Weekly review status: open priority: high scheduled: 2026-02-20 recurrence: FREQ=WEEKLY;BYDAY=FR recurrence_anchor: scheduled complete_instances: [2026-02-13] skipped_instances: [] blockedBy: - uid: \"[[prepare-metrics]]\" reltype: FINISHTOSTART gap: P1D reminders: - id: rem_day_before type: relative relatedTo: due offset: -P1D - id: rem_start type: absolute absoluteTime: 2026-02-20T09:00:00Z dateCreated: 2026-01-10T09:30:00Z dateModified: 2026-02-20T08:02:11Z --- Review completed work and plan next week. 2.10 Deterministic load example# Given frontmatter: recurrence_anchor: scheduled recurrenceAnchor: completion If canonical key is recurrence_anchor, a conforming loader using canonical-precedence policy MUST resolve semantic recurrence_anchor as scheduled and SHOULD emit a compatibility warning."},{"title":"3. Temporal Semantics","url":"/developers/specification/03-temporal-semantics/","description":"This section defines how implementations MUST interpret, compare, and serialize task-related date and datetime values.","product":"specification","text":"3.1 Purpose# This section defines how implementations MUST interpret, compare, and serialize task-related date and datetime values. 3.2 Supported temporal value classes# Implementations MUST support: Date values: calendar day without time or timezone. Datetime values: instant in time. 3.3 Canonical serialization# 3.3.1 Date# Canonical date serialization is: YYYY-MM-DD 3.3.2 Datetime# Canonical datetime serialization is UTC ISO 8601 with Z, for example: 2026-02-20T13:45:00Z Canonical datetime writes MUST use second precision (YYYY-MM-DDTHH:MM:SSZ) and MUST NOT include fractional seconds. Implementations MAY accept alternative inbound datetime forms but MUST normalize outbound canonical writes. If an accepted inbound datetime includes fractional seconds, writers MUST normalize deterministically by truncating fractional precision to whole seconds. 3.4 Parsing requirements# 3.4.1 Date parsing# Date parsing MUST reject invalid calendar dates. valid: 2026-02-28 invalid: 2026-02-30 3.4.2 Datetime parsing# Datetime parsing MUST reject malformed values. In strict mode, datetime parsing MUST reject ambiguous local datetimes without offset (for example 2026-02-20T09:00:00 with no timezone offset). In permissive mode, implementations MAY accept such values only under an explicitly documented compatibility policy and SHOULD emit a warning. 3.4.3 Mixed input tolerance# Implementations MAY accept both date and datetime values for roles like due and scheduled if configured to do so. The accepted form MUST be documented. 3.4.4 Inbound acceptance matrix# To avoid ambiguity, conforming parsers MUST follow this matrix. Date forms: Form Example Strict Permissive Canonical date 2026-02-20 accept accept Basic date (no separators) 20260220 reject (invalid_date_value) MAY accept only under documented compatibility policy; SHOULD emit warning Datetime forms: Form Example Strict Permissive Canonical UTC 2026-02-20T09:00:00Z accept accept ISO with explicit offset 2026-02-20T09:00:00+10:00 accept accept ISO with fractional seconds 2026-02-20T09:00:00.250Z accept (normalize to second precision on write) accept (normalize to second precision on write) Offset-less local datetime 2026-02-20T09:00:00 reject (invalid_datetime_value) MAY accept only under documented compatibility policy; SHOULD emit warning Space-separated datetime 2026-02-20 09:00:00 reject (invalid_datetime_value) MAY accept only under documented compatibility policy; SHOULD emit warning Basic datetime (no separators) 20260220T090000Z reject (invalid_datetime_value) MAY accept only under documented compatibility policy; SHOULD emit warning When permissive-mode compatibility accepts a non-canonical form, canonical writes MUST still follow §3.3. 3.5 Day semantics vs instant semantics# 3.5.1 Date roles# Date roles represent days, not instants, and MUST NOT be timezone-shifted. 3.5.2 Datetime roles# Datetime roles represent instants and MUST preserve instant equality through normalization. Example: input 2026-02-20T08:00:00-05:00 canonical write 2026-02-20T13:00:00Z 3.5.3 Implementation guidance: UTC-anchor strategy (non-normative)# Because date-only fields are human-readable (YYYY-MM-DD) while implementations often compute using datetime objects, a common strategy is to use a UTC-midnight anchor for date-only internals. Recommended approach: Parse date-only values to a UTC-midnight anchor instant for internal computations. Format date-only values from UTC calendar components when writing YYYY-MM-DD. Keep date-only roles as date-only on write unless an explicit conversion operation is requested. Evaluate user-facing day semantics (today, overdue, day grouping) using local calendar-day boundaries per §3.6. Implementations MAY use different internal representations as long as all normative requirements in this section are preserved. 3.6 Local calendar-day evaluation# 3.6.1 Active runtime timezone# For day-level semantics, the active runtime timezone is: the caller-provided temporal execution context, when present the collection authority's configured timezone the process/system local timezone. The timezone is runtime context, not TaskNotes type-binding configuration. A remote caller SHOULD send its current IANA timezone for interactive operations; a headless authority SHOULD use its durable collection timezone. Every operation MUST resolve this precedence once and use one effective timezone for all day-level semantics in that operation. Implementations MUST make the effective timezone discoverable. 3.6.2 Local calendar-day rules# When calculating day-level concepts (for example overdue/day grouping/calendar day cells), implementations MUST evaluate against local calendar-day boundaries of the active runtime timezone. This requirement prevents off-by-one day drift in positive and negative UTC offsets. 3.7 Comparison rules# 3.7.1 Date-to-date# Compare by calendar day ordering. 3.7.2 Datetime-to-datetime# Compare by instant ordering. 3.7.3 Date-to-datetime# If compared, implementations MUST document coercion policy. Recommended policy: convert date to local start-of-day for day-level comparisons, avoid implicit coercion for instant-level comparisons. 3.8 due and scheduled semantics# due and scheduled MAY be either date or datetime by configuration. Implementations MUST: preserve stored granularity unless explicit conversion is requested, avoid silently converting date to datetime during unrelated writes, require documented explicit policy for date-to-datetime conversion operations, apply consistent coercion policy in filters and status calculations. 3.9 Completion date semantics# completed_date is a date role. For non-recurring completion, writers MUST set completed_date using §5 semantics: explicit completion-day input when provided, otherwise current local day in active runtime timezone. 3.10 Created/modified timestamps# date_created and date_modified are datetime roles. Writers MUST: set both on create, update date_modified on successful mutating operations that change persisted state, preserve date_created unless explicit migration/edit operation changes it. 3.11 time_entries semantics# 3.11.1 Timestamp format# time_entries.startTime and time_entries.endTime MUST be datetime instants in canonical form on write. 3.11.2 Range validity# If both times exist, endTime MUST be greater than or equal to startTime. 3.11.3 Duration handling# If duration is present, implementations SHOULD treat it as derived and MAY rewrite or remove stale duration values during normalization. 3.11.4 Active session semantics# An entry with startTime and no endTime represents an active/running session. Implementations that support time-tracking management operations (§5.19) MUST enforce at most one active session per task at commit time. 3.11.5 Derived time calculations# For interoperability, implementations SHOULD expose both derived views when reporting tracked time: closed_minutes: sum of entries where both startTime and endTime exist. live_minutes: closed_minutes plus elapsed minutes of active entries (if any). Implementations MUST document which derived view is used by each reporting surface (for example task cards, stats, APIs). 3.12 reminder temporal semantics# Reminder time fields are governed by §10.3 and MUST follow canonical datetime and duration formats from this section. Rules: reminders[].absoluteTime MUST be a canonical datetime on write. reminders[].offset MUST be a valid ISO 8601 duration string. relative reminder base conversion for date-only values MUST use reminders.date_only_anchor_time from §9, or 00:00 local time if unset. 3.13 Example: local-day overdue evaluation# Assume local timezone America/Los_Angeles and local date 2026-02-20. Task A: due: 2026-02-19 status: open Task A is overdue. Task B: due: 2026-02-20 status: open Task B is not overdue at start of day; it becomes overdue on 2026-02-21 local day. 3.14 Example: preserving granularity# Before update: due: 2026-02-20 priority: normal Operation: update priority only. After update (conforming): due: 2026-02-20 priority: high Non-conforming behavior would silently rewrite due to a datetime. 3.15 Example: canonical datetime write# Input: timeEntries: - startTime: 2026-02-20T09:30:00+01:00 endTime: 2026-02-20T10:00:00+01:00 Canonical write: timeEntries: - startTime: 2026-02-20T08:30:00Z endTime: 2026-02-20T09:00:00Z 3.16 Example: UTC-anchor roundtrip for date-only field# Input: due: 2026-02-20 Internal computation anchor: 2026-02-20T00:00:00Z After unrelated update, conforming write: due: 2026-02-20 Non-conforming behavior would rewrite due as a datetime or shift it to another day based on local offset."},{"title":"4. Recurrence","url":"/developers/specification/04-recurrence/","description":"This section defines recurrence semantics, including rule representation, anchor behavior, and per-instance completion/skip state.","product":"specification","text":"4.1 Purpose# This section defines recurrence semantics, including rule representation, anchor behavior, and per-instance completion/skip state. 4.2 Recurrence applicability# A task is recurring when semantic role recurrence contains a valid tasknotes recurrence string. If recurrence is absent or empty, the task is non-recurring. 4.3 Rule format# 4.3.1 Required format# recurrence MUST be a tasknotes recurrence string. This syntax is RRULE-derived but is not a full RFC 5545 content line or multi-line iCalendar fragment. The RRULE parameter portion MUST use RFC 5545 RRULE property syntax. It MAY include a leading inline DTSTART segment. If DTSTART is present, it MUST use one of: DTSTART:YYYYMMDD (date-only) DTSTART:YYYYMMDDTHHMMSSZ (UTC datetime) Canonical combined form is: DTSTART:...;FREQ=... Implementations MAY accept inbound RRULE: prefixes or multi-line iCalendar-like inputs for compatibility, but canonical writes SHOULD use the combined single-field form above. Examples: FREQ=DAILY FREQ=WEEKLY;BYDAY=MO,WE,FR FREQ=MONTHLY;BYMONTHDAY=1 DTSTART:20260220;FREQ=WEEKLY;BYDAY=FR 4.3.2 Invalid rule handling# Invalid recurrence rules MUST produce a validation error in strict mode and SHOULD produce at least a warning in permissive mode. 4.4 Recurrence anchor# recurrence_anchor controls progression semantics and MUST be one of: scheduled completion If missing, implementations SHOULD default to scheduled unless collection configuration defines another default. 4.4.1 Recurrence seed precedence# When recurrence generation requires a seed/start date, implementations MUST resolve it in this order: DTSTART embedded in recurrence, semantic scheduled, semantic date_created. If no seed can be resolved, recurrence materialization MUST fail deterministically and validation MUST report an error. 4.4.2 Anchor progression behavior# For recurrence_anchor=scheduled, progression is based on the scheduled chain and DTSTART MUST remain fixed after it is set. For recurrence_anchor=completion, complete-instance operations MUST advance progression by updating DTSTART to the completion target (date or datetime per §4.4.3). 4.4.3 DTSTART update semantics# When recurrence_anchor=completion and instance completion succeeds for resolved target day D: Instance-list state (complete_instances, skipped_instances) MUST always use day D. If the caller provided an explicit datetime target, DTSTART MUST be rewritten as DTSTART:YYYYMMDDTHHMMSSZ using that target instant normalized to UTC. Otherwise, DTSTART MUST be rewritten as DTSTART:YYYYMMDD for day D. RRULE components other than DTSTART MUST be preserved unless an explicit recurrence-edit operation changes them. If DTSTART is absent, completion-anchor progression MUST insert it before RRULE parameters. 4.4.4 Recalculation semantics for recurrence_anchor=completion# When calculating the next candidate occurrence for recurrence_anchor=completion: Implementations MUST treat DTSTART progression as the consumed-history mechanism. complete_instances MUST NOT be used as an exclusion set for future occurrence selection in this mode. skipped_instances MUST still exclude matching candidate dates. Candidate selection MUST choose the first RRULE occurrence strictly after the current DTSTART anchor (or resolved seed if DTSTART is absent). This matches the completion-anchor progression model where each completion advances the chain by rewriting DTSTART. This model is intentionally not fully reversible via ordinary uncomplete instance; progression history lives in DTSTART, not only in complete_instances. 4.4.5 DTSTART canonicalization on recurring writes# To ensure stable recurrence materialization across implementations, writers that persist recurring tasks MUST ensure DTSTART is present after create or successful recurring-instance completion. Rules: If persisted recurrence already contains DTSTART, keep it unless an explicit operation updates it per §4.4.3. If persisted recurrence omits DTSTART, writers MUST resolve a seed using §4.4.1 and insert DTSTART before RRULE parameters. For recurrence_anchor=scheduled, inserted DTSTART becomes the fixed progression baseline and MUST NOT be rewritten by later scheduled-anchor completions. If seed resolution fails, operation MUST fail deterministically and emit missing_recurrence_seed. 4.5 Instance state fields# Per-instance state is represented by: complete_instances: list of date values skipped_instances: list of date values These lists represent day-level instance outcomes. 4.6 Invariants# Implementations MUST enforce: Items in instance lists are valid date values. No date appears in both lists simultaneously. Duplicate dates are normalized (set semantics) or rejected deterministically. Validators MUST NOT reject an instance date solely because it is not an RRULE-generated occurrence. 4.7 Instance completion semantics# Operation: complete instance for target date D. Conforming behavior: Add D to complete_instances. Remove D from skipped_instances if present. Leave base task status unchanged unless explicit policy states otherwise. Update date_modified when state changes. Operation MUST be idempotent. 4.8 Instance uncompletion semantics# Operation: uncomplete instance for target date D. Conforming behavior: Remove D from complete_instances if present. Do not add D to skipped_instances implicitly. For recurrence_anchor=completion, uncomplete MUST NOT rewrite or roll back DTSTART; restoring prior progression requires an explicit recurrence edit or implementation-specific rewind operation. Update date_modified when state changes. Operation MUST be idempotent. 4.9 Instance skip semantics# Operation: skip instance for target date D. Conforming behavior: Add D to skipped_instances. Remove D from complete_instances if present. Update date_modified when state changes. Operation MUST be idempotent. 4.10 Instance unskip semantics# Operation: unskip instance for target date D. Conforming behavior: Remove D from skipped_instances if present. Do not add to complete_instances implicitly. Update date_modified when state changes. Operation MUST be idempotent. 4.11 Effective instance state# For target date D, effective state MUST be resolved in this order: If D in complete_instances: state is completed. Else if D in skipped_instances: state is skipped. Else: state is unresolved/default for that instance. Because overlap is invalid, this ordering is deterministic. 4.12 Interaction with base status# For recurring tasks: Base status is task-level metadata and MUST NOT be forcibly rewritten to a completed status on instance completion unless explicitly configured. Instance state determines completion for recurrence-aware views and operations. Dependency blocked/unblocked evaluation for v0.1 follows §10.2.5 and is not recurrence-instance-aware unless explicitly extended by implementation policy. For non-recurring tasks, completion uses base status semantics (§5). 4.13 Completed-status configuration# Implementations MUST define which status values are treated as complete for non-recurring tasks. The completed-status list MUST be configurable or schema-driven and MUST NOT rely on a hardcoded single literal. 4.14 Example: complete then skip same day# Initial: recurrence: FREQ=DAILY completeInstances: [2026-02-20] skippedInstances: [] Skip target date 2026-02-20: recurrence: FREQ=DAILY completeInstances: [] skippedInstances: [2026-02-20] 4.15 Example: idempotent complete# Initial: completeInstances: [2026-02-20] skippedInstances: [] Complete 2026-02-20 again: persisted instance lists remain unchanged, operation succeeds without duplicate entries. 4.16 Example: anchor semantics# Task: recurrence: FREQ=WEEKLY;BYDAY=FR recurrenceAnchor: completion If implementation supports next-occurrence materialization, it MUST compute next occurrence relative to completion progression when anchor is completion, not solely by scheduled chain. Implementations using DTSTART progression MUST update DTSTART to the completion date for this mode. Worked example (recurrence_anchor=completion): recurrence: DTSTART:20260220;FREQ=DAILY recurrence_anchor: completion complete_instances: [2026-02-20, 2026-02-21] skipped_instances: [2026-02-23] Conforming recalculation: does not exclude 2026-02-22 because it is absent from skipped_instances, does exclude 2026-02-23 because it is skipped, ignores complete_instances for future exclusion in this mode (§4.4.4). 4.17 Validation examples# Invalid overlap: completeInstances: [2026-02-20] skippedInstances: [2026-02-20] Result: validation error instance_state_overlap. Invalid date in list: completeInstances: [2026-02-30] Result: validation error invalid_date_value. 4.18 Recurrence materialization# This subsection is required only for implementations claiming profile materialized-occurrences (§7.3.4). Recurrence materialization creates ordinary task files for specific target dates of a recurring parent task. It is additive behavior: implementations that do not claim materialized-occurrences continue to use the instance-list model in §4.5-§4.12. Materialized occurrence notes MUST be task files according to the collection's task-detection rules (§9.7). 4.18.1 Parent and occurrence ownership# The parent recurring task owns series-level semantics: recurrence recurrence_anchor recurrence generation and DTSTART progression parent instance-list compatibility state (complete_instances, skipped_instances) materialization policy fields (occurrence_materialization, occurrence_next_trigger, occurrence_template, occurrence_past_horizon, occurrence_future_horizon) A materialized occurrence note owns per-date task semantics for its occurrence_date, including: status completed_date body content and checklists time_entries per-occurrence due, scheduled, reminders, contexts, projects, and unknown fields 4.18.2 Occurrence identity and parent reference# A materialized occurrence note MUST store: recurrence_parent: a link-or-string reference to the parent recurring task occurrence_date: the target date represented by the occurrence note The preferred Obsidian-compatible representation for recurrence_parent is a wikilink, for example: recurrence_parent: \"[[Weekly Review]]\" occurrence_date: 2026-02-27 Implementations claiming materialized-occurrences MUST resolve recurrence_parent using §11 link semantics for this role, even if they do not claim full extended. If the parent cannot be resolved, validation SHOULD report invalid_recurrence_parent. For one resolved parent, there SHOULD be at most one materialized occurrence note per occurrence_date. Duplicate detected occurrence notes SHOULD report duplicate_occurrence_note and MUST NOT be chosen nondeterministically for writes. 4.18.3 Effective state precedence# For target date D, recurrence-aware effective state MUST be resolved in this order: If a materialized occurrence note exists for (parent, D), derive state from that note's own task state: completed when its status is in status.completed_values; skipped when its status is in status.skipped_values; otherwise unresolved/default for that instance. Else if D is in parent complete_instances: state is completed. Else if D is in parent skipped_instances: state is skipped. Else: state is unresolved/default for that instance. If a materialized occurrence note disagrees with the parent instance lists, the materialized occurrence note wins for D. Validators SHOULD report occurrence_state_conflict, and repair/normalization operations MAY update parent lists to match occurrence notes. 4.18.4 Parent instance lists as compatibility state# When materialized occurrence notes are supported, parent complete_instances and skipped_instances remain part of canonical persisted state. They serve as interoperability state for unmaterialized occurrences and as a compatibility index for clients that do not read occurrence notes. Conforming writers SHOULD reconcile parent lists after materialized occurrence completion, skip, uncompletion, or unskip: completed child state: add D to complete_instances, remove D from skipped_instances; skipped child state: add D to skipped_instances, remove D from complete_instances; active/unresolved child state after uncompletion/unskip: remove D from the relevant parent list. Reconciliation failure MUST NOT silently change the occurrence note state. Implementations SHOULD surface a recoverable error or warning. 4.18.5 Materialization modes# occurrence_materialization controls when materialized occurrence notes are created. Allowed values: manual: occurrence notes are created only by explicit user or API action. on_completion: completing a materialized occurrence note creates the next occurrence note. rolling: the implementation maintains a bounded materialized window, such as today through the next 14 days. If absent, occurrence_materialization MUST default to manual. on_completion does not by itself create the first occurrence note in a series. The first materialized occurrence MUST be created by explicit materialization, rolling materialization, or a documented create-time option. Conforming implementations MUST NOT create occurrence notes merely as a side effect of read-only browsing. 4.18.6 Next-occurrence trigger# occurrence_next_trigger controls whether skip/cancel transitions also create the next occurrence note when occurrence_materialization=on_completion. Allowed values: completion: only completion creates the next occurrence note. completion_or_skip: completion and skip/cancel create the next occurrence note. If absent, occurrence_next_trigger MUST default to completion. The next occurrence MUST be computed from the parent recurring task after applying the triggering state transition and §4.4 anchor semantics. Materializing the next occurrence MUST be idempotent: if the next occurrence note already exists, the operation MUST return or reuse it rather than creating a duplicate. 4.18.7 Rolling materialization bounds# For occurrence_materialization=rolling, implementations MUST enforce finite bounds. Unbounded future materialization is non-conformant. Bounds SHOULD be expressed with ISO 8601 durations such as: occurrence_past_horizon: P0D occurrence_future_horizon: P14D If bounds are absent and rolling mode is enabled, implementations MUST use documented finite defaults. 4.18.8 Recurrence edits and historical notes# Materialized occurrence notes are durable task files. Editing the parent recurrence rule MUST NOT silently delete, rewrite, or move existing materialized occurrence notes. If an existing occurrence note's occurrence_date is no longer generated by the current parent recurrence rule, validators MAY report materialization_target_not_generated as a warning. This condition MUST NOT be treated as an error by default because recurrence edits can make historical notes intentionally non-generated."},{"title":"5. Operations","url":"/developers/specification/05-operations/","description":"This section defines normative behavior for task mutations and read-facing resolution concerns that affect persisted state.","product":"specification","text":"5.1 Purpose# This section defines normative behavior for task mutations and read-facing resolution concerns that affect persisted state. 5.2 General operation rules# For all mutating operations: Validation MUST run before commit in strict mode. Writes MUST be atomic at file level (all-or-nothing per file). date_modified MUST be updated on successful state change. Unknown fields MUST be preserved unless explicit normalization is requested. This applies to every operation in this section: create, update, complete, uncomplete, skip, unskip, dependency mutations, reminder mutations, archive, and time-tracking operations. Operations identified as idempotent MUST remain safe under repetition. 5.2.1 Target day/date resolution# Recurring instance operations act on a target day/date (complete instance, uncomplete instance, skip, unskip). Non-recurring complete uses completion-day semantics for completed_date. Resolution MUST be deterministic: If caller provides an explicit target date/datetime, that value is authoritative. If caller omits target for recurring instance operations, implementations MUST resolve in this order: task scheduled, if present and target-day-resolvable, else task due, if present and target-day-resolvable, else current local day in active runtime timezone (§3.6). Target-day resolution for fallback task fields (scheduled / due) MUST use this extraction policy: if stored value is canonical date (YYYY-MM-DD), use it as-is; if stored value is datetime, use the literal date token before T (YYYY-MM-DD) without timezone shifting; if stored value is non-canonical but accepted by compatibility policy, implementations MAY normalize to a date token and SHOULD emit a warning; if a candidate value is unusable, continue to the next fallback source. For non-recurring complete, if caller omits explicit completion-day input, implementations MUST use current local day in active runtime timezone. When an explicit target is datetime: operations that require day semantics MUST use its calendar date part in active runtime timezone, for recurring complete instance with recurrence_anchor=completion, the same explicit datetime target MUST also drive DTSTART rewrite semantics in §4.4.3. This explicit-target datetime rule is intentionally distinct from persisted-field fallback extraction above. 5.2.2 Idempotency and date_modified# For operations marked idempotent: first application MAY change state and date_modified, repeated application with semantically equivalent input MUST leave persisted state unchanged. When a repeated idempotent operation is a no-op, date_modified MUST remain unchanged. 5.3 Create# 5.3.1 Input requirements# Create MUST provide at minimum semantic roles required by §2, directly or via defaults. 5.3.2 Required behavior# Create MUST: apply default values, generate date_created and date_modified when absent, resolve semantic title and filename/path behavior according to §9.13, apply create-time templating when enabled and supported (§5.3.5, §9.14, §7), serialize canonical keys and canonical temporal formats, when recurrence is present, canonicalize DTSTART per §4.4.5, preserve caller-provided semantic id when present, fail with validation errors if required constraints are unmet, apply default reminders according to §10.3.9 when configured. 5.3.3 Title and filename resolution on create# Create MUST produce a deterministic initial filename/path. Rules: Generated filenames MUST use filename-safe sanitization and MUST avoid invalid/empty basenames. If title.storage=filename: basename MUST derive from semantic title, title changes after create are handled by update semantics (§5.4.4), implementations MAY also persist mapped title as a synchronized compatibility mirror, title.filename_format and title.custom_filename_template MUST be ignored. If title.storage=frontmatter, create-time basename MUST follow title.filename_format: title: sanitized semantic title, zettel: implementation-defined zettel pattern (MUST be documented), timestamp: implementation-defined timestamp pattern (MUST be documented), custom: title.custom_filename_template expansion. If generated path already exists, implementation MUST resolve collision deterministically (for example numeric suffixing). 5.3.4 Example# Input intent: title: \"Pay electricity bill\" Assume defaults: status default open priority default normal Persisted frontmatter (example): title: Pay electricity bill status: open priority: normal dateCreated: 2026-02-20T14:00:00Z dateModified: 2026-02-20T14:00:00Z 5.3.5 Optional create-time templating# This subsection is required only for implementations claiming profile templating (§7.3.3). Create-time templating pipeline MUST be deterministic: Compute base create payload from explicit input, defaults (§9.8), and generated/system values (date_created, date_modified, resolved title policy). Expand template variables using that base payload and active runtime date/time context. Merge template frontmatter into base frontmatter with base payload precedence (base keys MUST win on conflict). Resolve body output: if expanded template body is non-empty, use it; otherwise use caller-provided body/details (if any). Template parse rules: If template content begins with ---, implementations MUST treat the first --- ... --- block as template frontmatter and the remainder as template body. Frontmatter variable expansion MUST run before YAML parsing of template frontmatter. Portable variable support: Implementations claiming templating MUST support all variables in the Required column of the table below. Implementations MAY support any variable in the Extended column. Required task-data variables: Variable Value Format / separator {{title}} Semantic title string; YAML-quoted if needed {{status}} Task status value string {{priority}} Task priority value string {{dueDate}} Due date if set YYYY-MM-DD or empty {{scheduledDate}} Scheduled date if set YYYY-MM-DD or empty {{details}} Caller-provided body/description string {{contexts}} Contexts list comma-separated, e.g. \"work, home\" {{tags}} Tags list comma-separated, e.g. \"task, errands\" {{hashtags}} Tags list as hashtags space-separated, e.g. \"#task #errands\" {{timeEstimate}} Time estimate in minutes integer string or empty {{parentNote}} Parent note name/path string; YAML-quoted if needed Required date/time variables (expansion time): Variable Value Format {{date}} Current date yyyy-MM-dd {{time}} Current time (24h) HH:mm {{year}} Full year yyyy {{month}} Month number MM {{day}} Day of month dd Extended variables (optional): Variable Value Format {{dateTime}} Date + time yyyy-MM-dd-HHmm {{timestamp}} Full timestamp yyyy-MM-dd-HHmmss {{shortDate}} Short date yyMMdd {{shortYear}} Two-digit year yy {{monthName}} Month full name e.g. February {{monthNameShort}} Month short name e.g. Feb {{dayName}} Weekday full name e.g. Monday {{dayNameShort}} Weekday short name e.g. Mon {{week}} ISO week number ww {{quarter}} Quarter number 1–4 {{hour}} Hour (24h) HH {{minute}} Minute mm {{second}} Second ss {{time12}} Time with AM/PM hh:mm a {{time24}} Time (24h) HH:mm {{timezone}} UTC offset long e.g. +05:30 {{utcOffset}} UTC offset long e.g. +05:30 {{unix}} Unix timestamp (seconds) integer string {{unixMs}} Unix timestamp (ms) integer string {{zettel}} Zettelkasten ID date + seconds-since-midnight base-36 {{titleLower}} Title lowercase string {{titleUpper}} Title uppercase string {{titleSnake}} Title snake_case string {{titleKebab}} Title kebab-case string {{titleCamel}} Title camelCase string {{titlePascal}} Title PascalCase string {{priorityShort}} First letter of priority uppercase char {{statusShort}} First letter of status uppercase char Unknown variables (not in the above lists) MUST be handled per templating.unknown_variable_policy (§9.14): preserve: leave the {{...}} placeholder as-is. empty: replace with an empty string. Deterministic expansion context: date/time variable expansion MUST use the active runtime timezone from §3.6. locale-sensitive variables (monthName, monthNameShort, dayName, dayNameShort, time12) MUST use English locale outputs for portability (January, Jan, Monday, Mon, AM/PM). template-generated datetime-like outputs used in frontmatter MUST normalize to second precision when written as canonical datetime roles (§3.3.2). Failure behavior: templating.failure_mode=error: template read/parse failures MUST abort create. templating.failure_mode=warning_fallback: template read/parse failures MUST continue create using non-templated behavior (base frontmatter + caller body/details) and SHOULD emit warnings (template_missing or template_parse_failed). 5.3.6 Identity handling on create# If semantic id is provided on create, writers MUST preserve it. If implementation supports auto-generation of semantic id, generation policy MUST be documented and resulting id MUST remain stable after create. 5.4 Update# 5.4.1 Patch semantics# Update MUST be patch-by-default: only targeted semantic roles are changed. 5.4.2 Preservation rules# Update MUST preserve: unrelated known roles, unknown fields, original date/datetime granularity for untouched fields. 5.4.3 Example# Before: title: Weekly review scheduled: 2026-02-20 priority: normal customClient: ACME Operation: set priority to high. After: title: Weekly review scheduled: 2026-02-20 priority: high customClient: ACME 5.4.4 Title updates and filename updates# If an update changes semantic title, behavior MUST follow title.storage: title.storage=filename: implementation MUST rename file basename to match updated title (with sanitization and deterministic collision handling), preserving parent folder unless caller requested a move. title.storage=frontmatter: implementation MUST update mapped title field and MUST NOT rename file unless an explicit rename operation is requested. If implementation keeps frontmatter title for compatibility while title.storage=filename, it MUST keep stored title synchronized with effective filename-derived title. 5.5 Complete (non-recurring)# For non-recurring tasks, complete MUST: Set status to a configured completed value, unless already completed. If multiple completed values are configured, implementation MUST choose deterministically (default: first entry in status.completed_values). Set completed_date to completion day: explicit completion-day input when provided, otherwise current local day in active runtime timezone (§5.2.1). Apply overwrite policy deterministically (overwrite or preserve_if_present). Update date_modified on state change. Implementations MUST document completion-day input handling and completed_date overwrite policy. Operation MUST be idempotent. 5.6 Uncomplete (non-recurring)# For non-recurring tasks, uncomplete MUST: Set status to configured active/default status according to policy (default: status.default). Clear or retain completed_date according to policy. Update date_modified on state change. Policy MUST be documented and deterministic. Operation MUST be idempotent. 5.7 Complete instance (recurring)# For recurring tasks, complete with resolved target date D (§5.2.1) MUST follow §4.7. Writers MUST NOT convert recurring completion into a base status rewrite unless explicit configuration requires it. When recurrence_anchor=completion and caller supplies an explicit datetime target, implementations MUST apply §4.4.3 datetime DTSTART rewrite behavior. When recurrence_anchor=scheduled and DTSTART is absent, implementations MUST insert DTSTART deterministically per §4.4.5. Next-occurrence recalculation in this mode MUST follow §4.4.4. 5.8 Uncomplete instance (recurring)# For recurring tasks, uncomplete with resolved target date D (§5.2.1) MUST follow §4.8. For recurrence_anchor=completion, ordinary uncomplete is intentionally non-reversible and MUST NOT roll back DTSTART. 5.9 Skip and unskip instance# Skip/unskip for recurring tasks with resolved target date D (§5.2.1) MUST follow §4.9 and §4.10. 5.10 Dependency operations# Dependency operations MUST follow §10.2. 5.10.1 Add dependency# Add dependency MUST: validate dependency entry schema, parse and resolve uid per §11, enforce duplicate and self-reference rules, preserve existing non-target dependency entries, update date_modified on change. 5.10.2 Remove dependency# Remove dependency by uid MUST be idempotent. 5.10.3 Replace dependency list# Replace dependency list MUST be explicit (not default patch behavior). 5.11 Reminder operations# Reminder operations MUST follow §10.3. 5.11.1 Add reminder# Add reminder MUST: validate reminder schema, enforce unique id within task, update date_modified on change. 5.11.2 Update reminder# Update reminder MUST target a reminder by id and be patch-by-default. 5.11.3 Remove reminder# Remove reminder by id MUST be idempotent. 5.12 Archive# Implementations MAY support archive semantics through: archive tag, archive status, dedicated boolean/archive field. Archive behavior MUST be documented. Archive MUST NOT implicitly delete the task. 5.13 Delete# Delete MUST remove the task file. Delete MUST NOT implicitly delete files referenced by attachments. An implementation MAY offer a separate, explicit cleanup action subject to §5.21.4. Optional safety behavior: Implementations MAY perform backlink/dependency checks. If checks are enabled, implementation MUST provide a bypass option for explicit force delete. 5.14 Rename# Rename operation changes file path/filename while preserving semantic record identity. 5.14.1 Rename interaction with title storage mode# If title.storage=filename, basename changes from rename MUST update effective semantic title. If title.storage=frontmatter, rename MUST NOT implicitly rewrite mapped title unless explicitly requested. Implementations that persist frontmatter title in title.storage=filename mode MUST either update that field on rename or remove it to prevent divergence. If semantic id is present, rename/move MUST preserve its value unchanged. If implementation supports link/reference updating, it MUST: update resolvable references deterministically, report unresolved or ambiguous updates, update dependency uid and projects references consistently with normal links. If implementation does not support reference updates, this limitation MUST be disclosed in conformance claim. 5.15 Batch operations# Batch operations MAY be supported. If supported, implementation MUST report per-item outcomes and summary counts: total succeeded failed Partial success behavior MUST be documented. 5.16 Concurrency# Implementations SHOULD provide write-conflict detection (for example based on modified timestamp or file hash). When conflict is detected, operation MUST fail safely unless explicit overwrite is requested. 5.17 Dry run# If dry run mode is supported, operation MUST: execute validation and transformation logic, report intended changes, perform no file write. 5.18 Error model# Implementation-native operation failures MUST provide structured error information with: operation name, error code, message, optional field/path context. For conformance adapter envelopes (§5.23), failures MAY be represented as a compact error string for transport compatibility, but implementations SHOULD also expose the structured fields (for example via error_details). 5.19 Time tracking management# This subsection applies to implementations that support time_entries. 5.19.1 Start time tracking# Start on task T MUST: fail when T already has an active time entry, append a new entry with canonical startTime and no endTime, MAY set a default description, update date_modified, persist canonical time_entries shape (including removal of legacy/stale duration fields when normalizing). Recommended error code when already active: time_tracking_already_active. 5.19.2 Stop time tracking# Stop on task T MUST: fail when T has no active time entry, set endTime on the active entry to canonical current datetime, update date_modified, preserve non-target entries and unknown frontmatter fields. Recommended error code when no active"},{"title":"6. Validation","url":"/developers/specification/06-validation/","description":"Validation ensures persisted task records conform to this specification and collection configuration.","product":"specification","text":"6.1 Purpose# Validation ensures persisted task records conform to this specification and collection configuration. 6.2 Validation phases# Implementations SHOULD validate in these phases: Parse validation (YAML/frontmatter structure) Schema validation (types and role constraints) Semantic validation (cross-field invariants) 6.3 Validation modes# Conforming implementations MUST support: strict: errors block writes. Implementations MAY additionally support: permissive: writes may continue with warnings. Current mode MUST be discoverable. 6.4 Required checks# A conforming validator MUST implement checks required by the claimed profile(s): Check ID Requirement Required for 1 Unconditionally required semantic roles are present (status, date_created, date_modified). core-lite and above 1a completed_date conditional requiredness is enforced per §2.2.1. core-lite and above 1b title resolves via active title policy (§2.2.2 and §9.13): storage-mode-aware precedence and fallback. core-lite and above 2 Field values match role type requirements. core-lite and above 3 Temporal values conform to §3. core-lite and above 4 Recurrence values conform to §4 (including tasknotes recurrence-string syntax and anchor-seed resolution rules). recurrence and above 5 Per-instance lists contain valid dates with no overlap. recurrence and above 6 date_modified is not earlier than date_created when both exist. core-lite and above 7 time_estimate is non-negative when present. any profile that supports time_estimate 8 time_entries entries include required startTime, ranges are valid when endTime exists, and at most one active entry exists per task. any profile that supports time_entries 9 blocked_by entries conform to §10.2 (shape, enum, duplicates, self-reference). extended 10 reminders entries conform to §10.3 (shape, type-specific fields, unique ids). extended 11 relative reminders have resolvable base fields or produce configured error/warning behavior. extended 12 link-bearing fields (projects, blocked_by.uid, and supported attachments) conform to §11 parsing/resolution and traversal safety. extended, or any implementation supporting attachments 13 templating configuration is valid when provided (templating schema and enums). templating 14 create-time template failures obey configured failure mode (error vs fallback). templating 15 semantic id (when present) is a non-empty string; duplicate collection-level IDs SHOULD be reported when detectable. any profile that supports semantic id 16 materialized occurrence notes contain valid recurrence_parent and occurrence_date roles. materialized-occurrences 17 no duplicate materialized occurrence notes exist for the same resolved (recurrence_parent, occurrence_date) pair. materialized-occurrences 18 materialization policy values and rolling horizons conform to §4.18 and §9.17. materialized-occurrences 19 attachments is a list of non-empty, unique normalized file references with explicit extensions. any implementation supporting attachments 6.5 Unknown field policy# Unknown fields: MUST NOT fail validation by default unless collection is configured for strict schema closure. SHOULD generate informational warnings when strict schema closure is desired but not enabled. 6.6 Issue structure# Validation issues MUST include: code (machine-readable) severity (error, warning, or info) message (human-readable) Issues SHOULD include: field or path expected and actual details where useful 6.7 Recommended issue codes# Code Severity (default) Meaning missing_required error required role missing invalid_type error value type mismatch invalid_enum_value error value not in configured set invalid_date_value error malformed or impossible date invalid_datetime_value error malformed datetime invalid_recurrence_rule error recurrence not valid tasknotes recurrence syntax missing_recurrence_seed error recurrence has no resolvable seed/start date invalid_recurrence_anchor error anchor not allowed instance_state_overlap error same date in complete and skipped lists invalid_time_range error end before start in time entry missing_time_entry_start error time entry is missing required startTime multiple_active_time_entries error more than one active time entry exists in one task invalid_dependency_entry error dependency object missing required fields invalid_dependency_reltype error dependency reltype not allowed invalid_dependency_gap error dependency gap not valid ISO 8601 duration duplicate_dependency_uid error in strict mode when dependencies.enforce_unique_uid=true; warning otherwise by policy repeated dependency uid in task self_dependency error task depends on itself unresolved_dependency_target warning dependency target not resolvable invalid_reminder_entry error reminder object missing required fields duplicate_reminder_id error repeated reminder id in task invalid_reminder_type error reminder type not allowed invalid_reminder_offset error relative reminder offset not valid duration invalid_reminder_related_to error relatedTo must be due or scheduled invalid_reminder_absolute_time error absoluteTime invalid datetime unresolvable_reminder_base error relative reminder base field missing/unusable invalid_link_format error link value cannot be parsed as supported format ambiguous_link warning link resolves to multiple candidates path_traversal error resolved path escapes collection root unresolved_link_target warning link target cannot be resolved invalid_attachment_reference error attachment reference is empty, lacks an explicit extension, or targets a directory duplicate_attachment_reference error attachment list repeats the same normalized target invalid_task_id error semantic id is empty or invalid type duplicate_task_id warning duplicate semantic id detected in collection scope alias_conflict_ignored warning alias key ignored due to canonical conflict unresolvable_title error title cannot be resolved from title resolution policy title_source_conflict warning mapped title and filename title differ; active title-storage policy selected authoritative source template_missing warning configured template file cannot be read/found template_parse_failed warning template frontmatter/body parsing or expansion failed missing_recurrence_parent error materialized occurrence note omits recurrence_parent invalid_recurrence_parent warning occurrence note parent reference cannot be resolved or does not reference a recurring task missing_occurrence_date error materialized occurrence note omits occurrence_date duplicate_occurrence_note warning more than one materialized occurrence note exists for the same parent/date occurrence_state_conflict warning materialized occurrence state disagrees with parent instance lists materialization_target_not_generated warning occurrence date is not generated by current parent recurrence rule missing_skipped_status error skip of materialized occurrence requires configured skipped status next_occurrence_materialization_failed warning triggering operation succeeded but next occurrence note could not be created orphan_occurrence_note warning materialized occurrence note has no resolvable recurring parent or parent state references a deleted occurrence note unknown_field info unmapped field encountered Implementations MAY extend this code set but SHOULD preserve existing meanings. 6.8 Write-time validation behavior# In strict mode, mutating operations MUST fail if any error-severity issue is present after applying intended changes. Warnings SHOULD NOT block writes unless explicitly configured. Datetime/date acceptance and rejection in validation MUST follow the normative matrix in §3.4.4. 6.9 Validation examples# 6.9.1 Missing required role# Input: title: Plan workshop status: open dateCreated: 2026-02-20T09:00:00Z Issue: code: missing_required severity: error field: dateModified message: Required field 'dateModified' is missing. 6.9.2 Invalid recurrence anchor# Input: recurrence: FREQ=DAILY recurrenceAnchor: due Issue: code: invalid_recurrence_anchor severity: error field: recurrenceAnchor message: recurrence anchor must be 'scheduled' or 'completion'. 6.9.3 Overlap in instance state# Input: completeInstances: [2026-02-20] skippedInstances: [2026-02-20] Issue: code: instance_state_overlap severity: error message: same date exists in complete and skipped instance lists. 6.9.4 Invalid dependency reltype# Input: blockedBy: - uid: \"[[task-a]]\" reltype: BLOCKS Issue: code: invalid_dependency_reltype severity: error field: blockedBy[0].reltype message: reltype must be one of FINISHTOSTART, STARTTOSTART, FINISHTOFINISH, STARTTOFINISH. 6.9.5 Unresolvable reminder base# Input: reminders: - id: due_minus_1d type: relative relatedTo: due offset: -P1D Issue when due missing: code: unresolvable_reminder_base severity: error field: reminders[0] message: relative reminder references due but no due value exists. 6.9.6 Unknown field in permissive mode# Input: title: Plan workshop status: open vendorPriority: p1 Issue example: code: unknown_field severity: info field: vendorPriority message: field is not mapped to a known semantic role. 6.9.7 Multiple active time entries# Input: timeEntries: - startTime: 2026-02-20T10:00:00Z - startTime: 2026-02-20T11:00:00Z Issue: code: multiple_active_time_entries severity: error field: timeEntries message: task contains more than one active time entry."},{"title":"7. Conformance","url":"/developers/specification/07-conformance/","description":"This section defines conformance profiles and claim requirements for implementations.","product":"specification","text":"7.1 Purpose# This section defines conformance profiles and claim requirements for implementations. 7.2 Conformance principles# An implementation MUST NOT claim conformance to a profile unless all required capabilities of that profile are implemented. Implementations MAY implement additional behavior beyond a profile, but extra behavior MUST NOT violate profile requirements. 7.3 Profile model# Profiles are cumulative unless explicitly marked otherwise. 7.3.1 Profile: core-lite# Required capabilities: task identification and loading semantic-role mapping and canonical writes (§2) required role support (title, status, completed_date, date_created, date_modified) create, update, delete operations (§5) non-recurring complete/uncomplete (§5) temporal parsing/canonical serialization basics (§3) strict validation mode support (§6.3) validation core checks (§6.4 items 1,1a,1b,2,3,6) 7.3.2 Profile: recurrence# Additional required capabilities: tasknotes recurrence-string parsing/validation, including RRULE parameter syntax and inline DTSTART handling recurrence anchor semantics, including seed precedence and completion-anchor progression complete/uncomplete instance skip/unskip instance instance-list invariants and effective state resolution validation checks for recurrence and instance overlap 7.3.3 Profile: templating (non-cumulative extension)# This profile is not cumulative; it MAY be claimed alongside core-lite, recurrence, materialized-occurrences, and/or extended. templating MUST NOT be claimed alone. Required capabilities: create-time template processing semantics per §5.3.5 templating configuration support per §9.14 deterministic template/frontmatter/body merge behavior deterministic failure-mode behavior for template read/parse failures support for portable double-brace template variables defined in §5.3.5 7.3.4 Profile: materialized-occurrences (non-cumulative extension)# This profile is not cumulative; it MUST be claimed alongside recurrence. It MAY be claimed alongside extended and/or templating, but it does not require either. Required capabilities: materialized occurrence roles and identity semantics (§2.6.6) recurrence materialization semantics (§4.18) materialize/complete/skip/uncomplete/unskip materialized occurrence operations (§5.20) occurrences configuration defaults (§9.17) parent-reference link parsing/resolution for recurrence_parent (§11), without requiring full extended validation checks for materialized occurrence identity, duplicates, and state conflicts (§6.4 items 16-18) Claiming materialized-occurrences also has required capability-token implications: meta.claim.capabilities MUST include materialized-occurrences. meta.claim.profiles MUST also include recurrence. Omitting either token while claiming materialized-occurrences is a non-conformant claim. 7.3.5 Profile: extended# Additional required capabilities: dependency schema support (blocked_by) reminder schema support (reminders) link parsing/resolution semantics for link-bearing fields (§11) time-tracking management semantics for time_entries (§5.19), including per-task active-session constraints dependency operations and validation per §10.2 reminder operations and validation per §10.3 If extended is claimed, all of the above baseline capabilities MUST conform to documented semantics. Claiming extended also has required capability-token implications: meta.claim.capabilities MUST include dependencies, reminders, links, and time-tracking. Omitting any of these tokens while claiming extended is a non-conformant claim (even if capability-gated fixtures are skipped by a runner). Optional capability extensions within extended: rename capability: reference-aware rename behavior (including dependency UID references) archive capability: archive semantics (§5.12) batch capability: batch operations with per-item outcomes (§5.15) concurrency capability: write-conflict detection semantics (§5.16) dry-run capability: dry-run semantics (§5.17) When an optional capability token is claimed, corresponding behavior MUST conform to documented semantics. 7.4 Conformance claim format# A conformance claim MUST include: implementation name and version, tasknotes-spec version, claimed profile list, validation mode support (strict required; permissive optional), known deviations, compatibility mode status (if any), configuration provider status (active provider chain, precedence policy, and fallback state). Example: Implementation: example-task-cli v1.4.0 Spec: tasknotes-spec 0.3.0-rc.3 Profiles: core-lite, recurrence, templating Validation modes: strict, permissive Known deviations: none Compatibility mode: disabled Configuration providers: tasknotes_plugin_data_json > built_in_defaults Configuration fallback: none 7.5 Deviation disclosure# Any known deviation from normative text MUST be explicitly disclosed in conformance output/documentation. A deviation entry SHOULD include: affected section, deviation summary, impact, planned resolution version. 7.6 Feature detection# Implementations SHOULD expose machine-readable capability metadata, including: profiles effective runtime timezone active configuration providers and precedence chain enabled compatibility modes configurable status sets supported mapping aliases templating support flags and effective templating failure mode dependency and reminder support flags attachment membership, reference normalization, and host-provided binary operation flags (including whether physical deletion is available) time-tracking support flags, including active-session policy and auto-stop-on-complete behavior materialized occurrence support flags, including materialization mode, next trigger, and rolling bounds configured natural-language capture triggers when the optional nlp block is present 7.7 Strictness disclosure# Conformance requires strict validation mode support (§6.3). Conformance claims MUST indicate whether permissive mode is also supported. 7.8 Example profile matrix# Capability core-lite recurrence templating materialized-occurrences extended create/update/delete required required companion-profile required companion-profile required required non-recurring complete required required companion-profile required companion-profile required required recurring instance complete/skip - required optional required via companion recurrence claim required materialize occurrence notes (§4.18, §5.20) - - optional required optional recurrence parent link resolution - - optional required for recurrence_parent only required template expansion/merge (§5.3.5) - - required optional optional double-brace portable variable support - - required optional optional recurrence-string validation - required optional required via companion recurrence claim required link parsing/resolution (§11) - - optional required for recurrence_parent only required attachment membership and ops (§5.21) optional via attachments capability optional via attachments capability optional via attachments capability optional via attachments capability optional via attachments capability dependency schema and ops - - optional optional required reminder schema and ops - - optional optional required time tracking start/stop/edit semantics (§5.19) - - optional optional required rename updates dependency/project links - - optional optional optional via rename capability archive semantics (§5.12) - - optional optional optional via archive capability batch per-item outcomes (§5.15) - - optional optional optional via batch capability write-conflict detection (§5.16) - - optional optional optional via concurrency capability dry-run reporting (§5.17) - - optional optional optional via dry-run capability 7.9 Executable fixture suite# This specification includes an executable fixture suite in conformance/. language-neutral fixtures are stored in conformance/fixtures/*.json section/profile/operation coverage is tracked in conformance/manifest.json coverage guard tests MUST enforce both section representation and minimum-depth thresholds for key sections/operations. adapters execute fixture operations per conformance/docs/ADAPTER_CONTRACT.md runners MUST execute fixtures only when both conditions hold: fixture profile is satisfied by claimed adapter profiles under cumulative profile rules (§7.3), all fixture requires capability tokens are present. Fixture expectations MUST be profile-modular: they MUST NOT assume capability values or profile memberships beyond what the fixture's own profile/requires gating guarantees. Fixtures for optional extension capabilities (rename, archive, batch, concurrency, dry-run) MUST be capability-gated via requires and MUST NOT rely on extended profile membership alone. Conformance claims SHOULD report fixture pass/fail results against the claimed profiles. 7.10 Meta operations# The following operations are part of the conformance interface and MUST be supported by any adapter that participates in the conformance suite, regardless of claimed profile. These meta operations MUST be callable without requiring any capability token. meta.claim# Returns the adapter's self-reported metadata. Input: {} (empty object) Output: { \"ok\": true, \"result\": { \"implementation\": \"my-tool\", \"version\": \"1.0.0\", \"spec_version\": \"0.3.0-rc.3\", \"validation_modes\": [\"strict\"], \"profiles\": [\"core-lite\", \"recurrence\"], \"capabilities\": [\"dependencies\", \"links\"] } } Fields: Field Type Required Description implementation string yes Human-readable implementation name version string yes Implementation version string spec_version string yes tasknotes-spec version targeted by this adapter validation_modes string[] yes Supported validation modes; MUST include strict profiles string[] yes Claimed conformance profiles; valid values: core-lite, recurrence, extended, templating, materialized-occurrences capabilities string[] yes Optional capability tokens; known tokens listed in §7.11 profiles lists explicitly claimed profiles. Cumulative profile expansion is applied by runners for fixture selection (§7.3, §7.9), but does not change literal membership semantics of meta.has_profile. Profile-token consistency rules: If profiles contains extended, capabilities MUST include dependencies, reminders, links, and time-tracking. If profiles contains templating, capabilities MUST include templating. If profiles contains materialized-occurrences, profiles MUST also contain recurrence and capabilities MUST include materialized-occurrences. Runners and fixture suites SHOULD validate these claim-consistency rules directly from meta.claim, not only by capability-gating feature fixtures. meta.has_capability# Tests whether the adapter claims a specific capability. Input: { \"capability\": \"dependencies\" } Output: { \"ok\": true, \"result\": { \"value\": true } } result.value MUST be true if the capability is in the capabilities array returned by meta.claim, and false otherwise. meta.has_profile# Tests whether the adapter claims a specific conformance profile. Input: { \"profile\": \"recurrence\" } Output: { \"ok\": true, \"result\": { \"value\": true } } result.value MUST be true if the profile is in the profiles array returned by meta.claim, and false otherwise. 7.11 Known capability tokens# The following capability tokens are defined by this specification. Implementations MAY define additional tokens. Token Required by profile Meaning dependencies extended Supports blocked_by, dependency operations, and dependency validation reminders extended Supports reminders, reminder operations, and reminder validation attachments optional extension under any profile Treats the mapped attachments list as authoritative membership; validates and normalizes its collection-file references; and implements §5.21 attachment operations using host-owned binary storage. A claim MUST separately disclose which host file actions are available; it does not by itself promise physical deletion where the host cannot perform an authoritative reference check. links extended Supports link parsing and resolution (§11) time-tracking extended Supports time-tracking management operations (§5.19) materialized-occurrences materialized-occurrences Supports recurrence materialization and materialized occurrence operations (§4.18, §5.20) rename optional extension under extended Supports file rename with reference updates archive optional extension under extended Supports archive semantics (§5.12) batch optional extension under extended Supports batch operations with per-item outcomes (§5.15) concurrency optional extension under extended Supports write-conflict detection (§5.16) dry-run optional extension under extended Supports dry-run mode (§5.17) migration — Supports migration operations (§8) templating templating Supports create-time templating (§5.3.5)"},{"title":"8. Compatibility and Migrations","url":"/developers/specification/08-compatibility-and-migrations/","description":"This section defines how implementations transition from historical behavior to canonical specification behavior without silent data breakage.","product":"specification","text":"8.1 Purpose# This section defines how implementations transition from historical behavior to canonical specification behavior without silent data breakage. 8.2 Compatibility modes# Implementations MAY support compatibility modes for legacy behavior. If supported, compatibility modes MUST: be explicitly enabled or disabled, be discoverable through configuration or capability metadata, not be silently enabled by default in new collections. 8.3 Migration expectations# When canonical behavior differs from historical behavior, implementations SHOULD provide: deterministic migration rules, dry-run preview support, rollback-safe workflow guidance. 8.4 Alias normalization migration# For legacy key aliases, a migration SHOULD: read both canonical and alias keys, choose canonical value deterministically (recommended: canonical key precedence), rewrite persisted file using canonical keys, preserve unrelated unknown fields. 8.4.1 Example# Before: recurrenceAnchor: scheduled recurrence_anchor: completion After normalization: recurrenceAnchor: scheduled With warning: alias_conflict_ignored: alias value ignored because canonical key present. 8.5 Temporal normalization migration# If historical writes include mixed datetime styles, migration SHOULD normalize to canonical UTC ISO Z for datetime roles while preserving date-only roles as dates. Example: Before: dateCreated: 2026-02-20 10:00:00+00:00 After: dateCreated: 2026-02-20T10:00:00Z 8.6 Recurrence state migration# If historical data allows overlapping complete/skip dates, migration MUST resolve overlap deterministically. Recommended resolution policy: if overlap exists, prefer most recent user action where recoverable, otherwise prefer complete_instances and remove overlapping skip entries, emit migration report for affected dates. Policy choice MUST be documented. 8.7 Materialized occurrence migration# When introducing materialized occurrence notes into an existing collection, implementations SHOULD avoid automatic bulk creation. Recommended migration behavior: do not materialize historical or future occurrence notes unless explicitly requested; preserve existing parent complete_instances and skipped_instances; when importing existing per-occurrence task files, require deterministic parent/date matching before adding recurrence_parent and occurrence_date; when materialized occurrence state conflicts with parent instance lists, prefer the occurrence note for that date and report occurrence_state_conflict; provide a dry-run report before converting existing task files into materialized occurrence notes. Migration tooling MUST NOT silently delete occurrence notes or parent recurring tasks. 8.8 Dependency migration# When migrating legacy dependency data, implementations SHOULD: normalize dependency key names to mapped canonical key, ensure each entry has uid and canonical reltype, normalize legacy string/path references into configured canonical reference style, remove duplicate dependency entries by policy. If historical data omits reltype, migration MAY apply dependencies.default_reltype and SHOULD report count of inferred values. 8.9 Reminder migration# When migrating legacy reminder data, implementations SHOULD: normalize reminder key names, normalize type values to canonical enum (absolute or relative), normalize relatedTo values to canonical enum (due or scheduled), normalize absoluteTime to canonical UTC ISO Z, validate and normalize offsets to ISO 8601 duration syntax. If reminder id values are missing, migration MAY generate IDs and MUST report generated count. 8.10 Link migration# When migrating legacy link values, implementations SHOULD: normalize supported link syntaxes according to §11 parsing rules, preserve alias and anchor components where possible, normalize resolved targets into canonical write format by policy, detect and report ambiguous links instead of silently choosing non-deterministically. 8.11 Divergence register# Implementations SHOULD maintain a divergence register with columns: section current behavior target canonical behavior migration strategy deprecation timeline 8.12 Deprecation policy# For any behavior deprecated by the specification: announce deprecation in release notes, provide warning period, provide migration tooling where feasible, remove deprecated behavior only in a version aligned with compatibility commitments. 8.13 Data safety requirements# Migrations MUST NOT: silently drop unknown fields, silently convert valid date-only fields to datetime, silently rewrite recurrence semantics without explicit policy, silently materialize occurrence notes outside explicit user/configured materialization policy, silently delete materialized occurrence notes during recurrence edits, silently drop unresolved dependency entries, silently rewrite link targets to different destinations without explicit policy, silently delete reminders unless explicitly requested. 8.14 Suggested migration report format# spec_version_from: 0.1.0-draft spec_version_to: 0.3.0-rc.3 files_scanned: 214 files_changed: 67 warnings: alias_conflict_ignored: 3 instance_state_overlap_resolved: 2 occurrence_state_conflict: 1 unresolved_dependency_target: 4 changes: normalized_datetime_fields: 41 alias_keys_removed: 29 instance_overlaps_fixed: 2 occurrence_state_conflicts: 1 inferred_dependency_reltype: 5 generated_reminder_ids: 8 normalized_link_targets: 14 8.15 Compatibility statement example# Compatibility mode: legacy-aliases=true, legacy-timeentry-duration=true Planned removal: v2.0.0 Migration command: tasknotes migrate --normalize-frontmatter"},{"title":"9. Configuration","url":"/developers/specification/09-configuration/","description":"This section defines the normative configuration model for collections using tasknotes-spec.","product":"specification","text":"9.1 Purpose# This section defines the normative configuration model for collections using tasknotes-spec. 9.2 Configuration provider model# Implementations MUST derive an effective configuration from one or more configuration providers. A provider is a source adapter that returns a partial configuration normalized to this section's schema. Implementations MUST: support at least one provider, document supported providers, document provider precedence order, disclose active providers and fallback behavior in conformance output (§7). 9.2.1 Common provider types# Common providers include: yaml_file: a tasknotes.yaml document at collection root, tasknotes_plugin_data_json: .obsidian/plugins/tasknotes/data.json, built_in_defaults: implementation defaults, optional runtime/CLI/env overrides. This list is not exhaustive. 9.2.2 Deterministic precedence and merge# Provider precedence MUST be deterministic. Unless explicitly documented otherwise, implementations MUST resolve configuration per top-level key: for each key in §9.3/§9.4, the highest-precedence provider that supplies that key wins, winning object values replace lower-precedence object values as whole objects (no implicit deep merge), after top-level selection, implementations MUST apply documented schema defaults for missing nested keys before exposing effective configuration. If an implementation supports deep-merge behavior, it MUST be explicitly documented and deterministic. 9.2.3 Strict vs permissive provider behavior# In strict mode: failure to resolve required effective keys (spec_version, mapping) MUST be a configuration error. If permissive mode is implemented, then in permissive mode: implementations MAY continue with defaults when providers are missing/unreadable, implementations MUST emit configuration warnings, implementations MUST disclose that effective configuration is partial/default-derived. 9.2.4 TaskNotes plugin provider (data.json)# The TaskNotes plugin stores settings in .obsidian/plugins/tasknotes/data.json within the vault root. When using this file as a configuration provider, normalization MUST apply the field mapping in the table below. Key mapping table (data.json key → spec effective config): data.json key Spec key Notes fieldMapping mapping Normalize role names: dateCreated→date_created, completedDate→completed_date, recurrenceAnchor→recurrence_anchor, completeInstances→complete_instances, skippedInstances→skipped_instances, recurrenceParent→recurrence_parent, occurrenceDate→occurrence_date, occurrenceMaterialization→occurrence_materialization, occurrenceNextTrigger→occurrence_next_trigger, occurrenceTemplate→occurrence_template, occurrencePastHorizon→occurrence_past_horizon, occurrenceFutureHorizon→occurrence_future_horizon, blockedBy→blocked_by, timeEntries→time_entries, timeEstimate→time_estimate storeTitleInFilename title.storage true → \"filename\", false → \"frontmatter\" taskFilenameFormat title.filename_format Values: \"title\", \"zettel\", \"timestamp\", \"custom\"; used only when title.storage=frontmatter for canonical writes, but preserved as compatibility input when present customFilenameTemplate title.custom_filename_template Template string, e.g. \"{title}\"; used only when title.storage=frontmatter and filename_format=custom taskCreationDefaults.useBodyTemplate templating.enabled boolean taskCreationDefaults.bodyTemplate templating.template_path Path to template file customStatuses[*].value status.values Ordered array of status value strings defaultTaskStatus status.default Default status string customStatuses[isCompleted=true][*].value status.completed_values Statuses where isCompleted: true defaultTaskPriority defaults.priority Default priority string autoStopTimeTrackingOnComplete time_tracking.auto_stop_on_complete boolean autoStopTimeTrackingNotification time_tracking.auto_stop_notification boolean taskIdentificationMethod task_detection.method \"tag\" or \"property\" taskTag task_detection.tag Tag string used when method=\"tag\" taskPropertyName task_detection.property_name Frontmatter key used when method=\"property\" taskPropertyValue task_detection.property_value Expected value; empty means key must exist tasksFolder task_detection.default_folder Default folder for new tasks excludedFolders task_detection.excluded_folders Comma-separated folder paths to exclude moveArchivedTasks archive.move_on_archive boolean archiveFolder archive.folder Archive destination folder useFrontmatterMarkdownLinks links.use_markdown_format boolean; see §11 Key data.json fields with defaults (for cold-start reading of a vault with no tasknotes.yaml): Field Type Default Meaning tasksFolder string \"TaskNotes/Tasks\" Default folder for new task files taskIdentificationMethod \"tag\" | \"property\" \"tag\" How task files are identified taskTag string \"task\" Tag that identifies task files (when method=\"tag\") taskPropertyName string \"\" Frontmatter key for property-based identification taskPropertyValue string \"\" Expected value for property-based identification (empty = key presence) storeTitleInFilename boolean true Title storage mode taskFilenameFormat \"title\" | \"zettel\" | \"timestamp\" | \"custom\" \"title\" Filename generation format customFilenameTemplate string \"{title}\" Template for \"custom\" filename format defaultTaskStatus string \"open\" Default status on create defaultTaskPriority string \"normal\" Default priority on create customStatuses StatusConfig[] see object shape below Ordered status definitions autoStopTimeTrackingOnComplete boolean true Auto-stop active session on completion autoStopTimeTrackingNotification boolean false Show notification when auto-stopping useFrontmatterMarkdownLinks boolean false Use markdown links in frontmatter (requires obsidian-frontmatter-markdown-links plugin) moveArchivedTasks boolean false Move task file to archive folder on archive archiveFolder string \"TaskNotes/Archive\" Archive destination folder excludedFolders string \"\" Comma-separated folders to exclude from task indexing StatusConfig object shape: { \"id\": \"done\", \"value\": \"done\", \"label\": \"Done\", \"color\": \"#00aa00\", \"isCompleted\": true, \"order\": 3, \"autoArchive\": false, \"autoArchiveDelay\": 5 } spec_version is not present in data.json. Implementations MUST synthesize an effective spec_version as described in §9.5. Provider keys not listed above MAY be ignored by tasknotes-spec consumers. 9.3 Required top-level keys# Required keys apply to the effective configuration after provider resolution. Key Type Required Description spec_version string yes target spec version (provider-supplied or synthesized per §9.5) mapping object yes semantic role to storage key mapping 9.4 Recommended top-level keys# Key Type Description task_detection object task file identification rules defaults object role defaults used during create status object status set and completed-value semantics validation object validation behavior (strict required, permissive optional) links object link parsing/resolution behavior title object title source and filename behavior policy templating object optional create-time templating behavior policy dependencies object dependency behavior policy reminders object reminder behavior policy time_tracking object time-tracking management behavior policy occurrences object recurrence materialization defaults and bounds compatibility object legacy alias/behavior switches 9.5 spec_version behavior# spec_version MUST be a semantic version string. Pre-release identifiers are valid (for example 0.3.0-rc.3). Implementations in strict mode MUST reject unsupported major versions. If permissive mode is implemented, permissive mode MAY proceed with warning when major version differs. If a provider does not supply spec_version (for example TaskNotes data.json), implementations MUST synthesize an effective spec_version matching their target tasknotes-spec version and SHOULD disclose that it was synthesized. 9.6 mapping schema# mapping MUST map semantic roles (from §2) to string storage keys. Minimum required roles in mapping: title status completed_date date_created date_modified If semantic role id is supported (§2.6.5), mapping SHOULD include id. If profile materialized-occurrences is claimed, mapping MUST include recurrence_parent and occurrence_date, and SHOULD include parent policy roles (occurrence_materialization, occurrence_next_trigger, occurrence_template, occurrence_past_horizon, occurrence_future_horizon). Example: mapping: title: title status: status date_created: dateCreated date_modified: dateModified completed_date: completedDate recurrence: recurrence recurrence_anchor: recurrenceAnchor complete_instances: completeInstances skipped_instances: skippedInstances recurrence_parent: recurrence_parent occurrence_date: occurrence_date occurrence_materialization: occurrence_materialization occurrence_next_trigger: occurrence_next_trigger occurrence_template: occurrence_template occurrence_past_horizon: occurrence_past_horizon occurrence_future_horizon: occurrence_future_horizon time_entries: timeEntries blocked_by: blockedBy reminders: reminders attachments: attachments 9.7 task_detection schema# task_detection controls how task files are identified within the vault. Detection methods# The tasknotes plugin natively supports two identification methods, controlled by taskIdentificationMethod in data.json (mapped to task_detection.method): tag (default) — A markdown file is a task if it contains the configured tag (default #task) in its frontmatter tags array or inline in the body. Configured by task_detection.tag. property — A markdown file is a task if a specified frontmatter property has a specified value (or exists, if value is empty). Configured by task_detection.property_name and task_detection.property_value. Schema and selection rules: task_detection MAY specify either: method (single-method form), or methods (multi-method form; non-empty list). If both are present, methods MUST take precedence and implementations SHOULD emit a configuration warning. If neither is present, effective detection method MUST default to tag. method MUST be tag or property. methods entries MUST be unique and MUST be from: tag property field_presence field_match Method-specific required keys: when tag is enabled, effective task_detection.tag MUST be non-empty (default task when absent); when property is enabled, task_detection.property_name MUST be provided and non-empty; task_detection.property_value MAY be empty (empty means key-exists semantics). If methods has more than one entry, task_detection.combine controls combination semantics (§9.7.3). If omitted, it MUST default to or. 9.7.1 Tag matching semantics# When task_detection.method=tag, matching MUST follow these rules: Normalize configured task_detection.tag by stripping one leading # when present. Compare tag names case-insensitively after normalization. Frontmatter matching: tags MAY be a list of strings or a single string. each tag value is normalized by trimming surrounding whitespace and stripping one leading #. match requires exact normalized equality (for example task matches #task; task does not match tasking). Body matching: only markdown text outside fenced code blocks and inline code spans is considered, a match requires a hashtag token with exact normalized name (for example #task), partial-word matches MUST NOT count (for example #tasking does not match configured task). If either frontmatter or body matches, the file is identified as a task. 9.7.2 Property matching semantics# When property detection is enabled (method=property or methods includes property): task_detection.property_name MUST name the frontmatter key to inspect. If task_detection.property_value is non-empty, match requires semantic equality with the configured value. If task_detection.property_value is empty or absent, match requires key presence only. 9.7.3 Multi-method extension semantics# tasknotes.yaml-level providers MAY additionally support: field_presence (example: required key status) field_match (example: type == \"task\") Extension-key shape: field_presence: string or list of required frontmatter keys. field_match: object map of key -> expected scalar value for exact semantic equality checks. If multiple methods are configured in tasknotes.yaml, task_detection.combine MUST define combinator semantics: or (default): file is a task if any enabled method matches. and: file is a task only if all enabled methods match. If task_detection.combine is absent, implementations MUST default to or. Implementations MUST exclude folders listed in task_detection.excluded_folders from task indexing. Executable conformance: adapters participating in the fixture suite SHOULD expose config.detect_task_file to evaluate these detection semantics against fixture inputs. Example (tasknotes.yaml, equivalent to tag-based default): task_detection: method: tag tag: task default_folder: TaskNotes/Tasks Example (property-based): task_detection: method: property property_name: type property_value: task 9.8 defaults schema# defaults defines values used at create time when caller input omits a role. Defaults MUST NOT override explicit user input. Example: defaults: status: open priority: normal recurrence_anchor: scheduled reminders: - id: due_minus_1d type: relative relatedTo: due offset: -P1D defaults.reminders behavior is defined in §10.3.9. 9.9 status schema# status defines known status values and completion semantics. Example: status: values: [open, in-progress, done, cancelled] default: open completed_values: [done] skipped_values: [cancelled] default_skipped: cancelled Rules: default MUST be one of values. completed_values MUST be a non-empty list. Each completed_values entry MUST be in values. skipped_values, when present, MUST be a list whose entries are in values. default_skipped, when present, MUST be in skipped_values. For implementations claiming materialized-occurrences, skipped_values MUST NOT overlap completed_values. Implementations claiming materialized-occurrences MUST provide at least one skipped value or fail skip of materialized occurrence notes deterministically (§5.20.3). Non-recurring completion MUST use this list, not hardcoded literals. When a complete operation does not provide an explicit target status, writers MUST use the first entry of completed_values. When a materialized occurrence skip operation does not provide an explicit skipped status, writers MUST use default_skipped when present, otherwise the first entry of skipped_values. 9.10 validation schema# Example: validation: mode: strict reject_unknown_fields: false Rules: mode MUST be strict or permissive when present. If mode is absent, effective mode MUST default to strict. Conforming implementations MUST support strict. Implementations MAY support permissive. If mode=permissive is configured but not implemented, configuration MUST fail in strict mode and SHOULD emit warning/fallback in permissive mode. reject_unknown_fields=true enforces closed-schema behavior for mapped roles. 9.11 dependencies schema# Example: dependencies: default_reltype: FINISHTOSTART treat_missing_target_as_blocked: true enforce_unique_uid: true unresolved_target_severity: warning require_resolved_uid_on_write: false Rules: default_reltype MUST be one of the allowed reltype values in §10.2. treat_missing_target_as_blocked controls whether missing/unresolvable dependency targets contribute to blocked-state evaluation (§10.2.5). If treat_missing_target_as_blocked is absent, effective value MUST default to true. enforce_unique_uid=true enforces uniqueness at validation/write time. If enforce_unique_uid is absent, effective value MUST default to true. unresolved_target_severity MUST be warning or error. require_resolved_uid_on_write=true requires dependency UID resolution success for add/update operations. 9.12 links schema# Example: links: extensions: [\".md\"] unresolved_default_severity: warning update_references_on_rename: true Rules: extensions defines extension trial order for extensionless targets"},{"title":"10. Dependencies and Reminders","url":"/developers/specification/10-dependencies-and-reminders/","description":"This section defines canonical semantics for task dependencies (blocked_by) and task reminders (reminders).","product":"specification","text":"10.1 Purpose# This section defines canonical semantics for task dependencies (blocked_by) and task reminders (reminders). 10.2 Dependencies (blocked_by)# 10.2.1 Data shape# blocked_by MUST be a list of dependency entries. Each entry MUST be an object with: uid (required): reference to a blocking task (link or string) reltype (required): one of FINISHTOSTART STARTTOSTART FINISHTOFINISH STARTTOFINISH gap (optional): ISO 8601 duration string If reltype is omitted on read in compatibility mode, implementations MAY treat it as FINISHTOSTART and SHOULD emit a warning. 10.2.2 UID normalization# Implementations SHOULD normalize uid values to a canonical reference representation on write. If link formats are supported, both wikilink and markdown-link forms MAY be read. Canonical write form MUST be documented. Link parsing and resolution MUST follow §11. 10.2.3 Dependency uniqueness# Within a task, dependency entries are keyed by normalized uid. Policy is configuration-driven and MUST be deterministic: when dependencies.enforce_unique_uid=true (default), duplicate normalized uid values MUST NOT be accepted as canonical persisted state: strict mode: duplicates MUST fail validation/write with duplicate_dependency_uid; permissive mode: implementations MAY either fail or normalize to one entry, but MUST emit duplicate_dependency_uid. when dependencies.enforce_unique_uid=false, duplicates MAY be preserved as compatibility behavior. The active policy MUST be documented in conformance claims. 10.2.4 Self-dependency# A task MUST NOT depend on itself. Self-dependency is a validation error. 10.2.5 Blocking semantics (v0.1)# For v0.1, blocking evaluation MUST be status-presence based: A task is blocked if it has at least one unresolved dependency. A dependency on a resolvable task is unresolved when the referenced task is not in a completed status. Completed status MUST be determined from configured status.completed_values. For recurring referenced tasks in v0.1, unresolved/resolved evaluation MUST use base status only; complete_instances/skipped_instances are not consulted. When a referenced task is missing/unresolvable, whether that missing target contributes to blocked-state evaluation MUST follow dependencies.treat_missing_target_as_blocked (§9.11, default true). For v0.1, reltype and gap are preserved and validated but MUST NOT change the unresolved/resolved decision. 10.2.6 Missing referenced task# When uid cannot be resolved: implementations SHOULD emit unresolved_dependency_target. blocked-state contribution for this missing target MUST follow dependencies.treat_missing_target_as_blocked (§9.11). issue severity SHOULD follow dependencies.unresolved_target_severity (default: warning). for blocked_by.uid, this dependency-specific severity policy MUST take precedence over links.unresolved_default_severity. parse failures that produce invalid_link_format and containment violations that produce path_traversal remain error-severity conditions from §11. if dependencies.require_resolved_uid_on_write=true, add/update MUST fail with error. 10.2.7 Cycles# Implementations MUST reject direct self-cycles. Detection of multi-hop dependency cycles is RECOMMENDED but not required for core-lite or recurrence profiles. 10.2.8 Reverse relation field# Some implementations maintain reverse relationships (for example blocking). Such fields are derived and non-canonical in this spec unless explicitly mapped. If maintained, reverse updates SHOULD remain consistent with blocked_by edits. 10.2.9 Dependency operation semantics# Add dependency# Add dependency MUST: validate entry shape, handle duplicates by policy (preserve, normalize, or reject), preserve unrelated dependency entries, update date_modified on change. Remove dependency# Remove dependency MUST remove by normalized uid and be idempotent. Replace dependencies# Replace behavior MUST be explicit operation mode (not default for patch update). 10.2.10 Dependency examples# Example entry: blockedBy: - uid: \"[[prepare-metrics]]\" reltype: FINISHTOSTART gap: PT4H Example unresolved dependency (target missing): blockedBy: - uid: \"[[non-existent-task]]\" reltype: FINISHTOSTART 10.3 Reminders (reminders)# 10.3.1 Data shape# reminders MUST be a list of reminder entries. Each reminder MUST include: id (required): unique string within the task type (required): absolute or relative Optional field: description string Type-specific fields: absolute: requires absoluteTime datetime relative: requires relatedTo (due or scheduled) and offset (ISO 8601 duration) 10.3.2 Reminder uniqueness# Reminder id values MUST be unique within the task. If duplicates occur: strict mode: MUST raise duplicate_reminder_id. permissive mode: MAY normalize deterministically and emit warning. 10.3.3 Relative reminder base# relatedTo MUST reference semantic role due or scheduled. If the referenced role is absent, the reminder is unresolved. 10.3.4 Trigger instant computation# Trigger instant MUST be computed as follows: If type=absolute, trigger = absoluteTime instant. If type=relative, resolve base field from relatedTo, if base is datetime: use that instant, if base is date: convert to local datetime at configured reminders.date_only_anchor_time, trigger = base + offset. If reminders.date_only_anchor_time is not configured, implementations MUST use 00:00 local time. 10.3.5 Offset semantics# offset MUST be a valid ISO 8601 duration with optional sign. negative offset = before base positive offset = after base zero offset = at base instant 10.3.6 Invalid mixed fields# Entries with incompatible field combinations MUST fail validation in strict mode. Examples: type=absolute with relatedTo and no absoluteTime type=relative with absoluteTime and missing offset 10.3.7 Reminder ordering# When computing reminder schedules, implementations MUST sort by trigger instant ascending. For identical trigger instants, implementations MUST use stable tie-break ordering by id ascending. 10.3.8 Reminder operation semantics# Add reminder# Add reminder MUST validate shape and unique id, then update date_modified. If id is omitted by caller and implementation supports auto-ID generation, generated IDs MUST be unique within the task. Update reminder# Update reminder MUST address reminders by id and be patch-by-default. Remove reminder# Remove reminder by id MUST be idempotent. 10.3.9 Default reminders# If defaults.reminders is configured (see §9): create without explicit reminders MUST apply defaults. create with explicit reminders MUST follow reminders.apply_defaults_when_explicit (§9.15): false (default): explicit reminders replace defaults. true: explicit reminders are merged with defaults. Deterministic merge rules when apply_defaults_when_explicit=true: Start with explicit reminders in caller order. Append each default reminder whose id is not already present. If explicit and default reminders share an id, explicit reminder MUST win. 10.3.10 Reminder examples# Relative reminder: reminders: - id: due_minus_15m type: relative relatedTo: due offset: -PT15M Absolute reminder: reminders: - id: call_now type: absolute absoluteTime: 2026-02-20T09:00:00Z 10.3.11 Reminder resolution error handling# If relative reminder base is unavailable (relatedTo=due but no due field): strict mode: validation error unresolvable_reminder_base. permissive mode: warning and reminder excluded from trigger computation. 10.4 Interactions# 10.4.1 Rename interaction# If implementation supports rename/reference updates, dependency uid references SHOULD be updated consistently with other link references. 10.4.2 Completion interaction# Changing task completion state does not automatically remove dependencies or reminders unless explicitly configured. 10.4.3 Archive interaction# Archive operations MAY suppress reminder delivery in runtime systems, but archive MUST NOT silently delete reminder records from persisted frontmatter unless explicitly requested."},{"title":"11. Links","url":"/developers/specification/11-links/","description":"This section defines link syntax, parsing, resolution, and write-format semantics for link-bearing task fields — primarily projects, blocked_by.uid, and attachments. Alignment w...","product":"specification","text":"11.1 Purpose# This section defines link syntax, parsing, resolution, and write-format semantics for link-bearing task fields — primarily projects, blocked_by.uid, and attachments. Alignment with Obsidian and other ecosystems is informative context only; normative conformance is defined entirely by this section. Applicability: Implementations claiming profile extended (§7.3.5) MUST conform to this section for supported link-bearing roles. Implementations claiming profile materialized-occurrences (§7.3.4) MUST conform to this section for recurrence_parent links, but are not required to support unrelated extended link-bearing roles solely because of that profile. Implementations supporting the attachments role MUST conform to this section for attachment references regardless of profile. Implementations that claim neither extended nor materialized-occurrences MAY treat link-shaped strings as opaque data and are not required to implement §11 behavior. 11.2 Link formats# Implementations that conform to §11 (see §11.1 applicability) MUST support three link formats. 11.2.1 Wikilinks# [[target]] [[target|alias]] [[target#anchor]] [[target#anchor|alias]] [[folder/target]] [[./relative]] [[../parent/target]] Components: target: The file being linked to (without extension by default) alias: Display text; does not affect resolution anchor: A heading or block reference within the target path: May be absolute (from collection root) or relative (from current file) Examples in frontmatter: projects: - \"[[home-project]]\" - \"[[projects/alpha|Alpha Project]]\" blockedBy: - uid: \"[[prepare-metrics]]\" reltype: FINISHTOSTART 11.2.2 Markdown links# [text](path.md) [text](./relative.md) [text](../other/file.md) [text](path.md#anchor) The text portion is treated as an alias and does not affect resolution. Markdown links in frontmatter require the obsidian-frontmatter-markdown-links Obsidian plugin. Implementations MUST NOT write markdown-format links by default unless links.use_markdown_format=true is configured (§11.7). 11.2.3 Bare paths# ./sibling.md ../other/file.md folder/file.md Bare paths follow the same resolution rules as markdown links (relative to containing file's directory unless starting with /). 11.3 Link parsing# When a link value is read, implementations MUST parse it into a structured representation: Component Type Description raw string Original string value exactly as written target string File path or identifier (without anchor or alias) alias string? Display text if provided, otherwise null anchor string? Heading or block reference if provided, otherwise null format enum One of: wikilink, markdown, path is_relative boolean Whether target begins with ./ or ../ Parsing examples: Input target alias anchor format is_relative [[task-001]] task-001 null null wikilink false [[task-001|My Task]] task-001 My Task null wikilink false [[docs/api#auth]] docs/api null auth wikilink false [[./sibling]] ./sibling null null wikilink true [Link](file.md) file.md Link null markdown false ./other.md ./other.md null null path true 11.4 Resolution algorithm# Resolution transforms a parsed link into an absolute path (relative to collection root) pointing to the target file. Given a parsed link and the path of the source file containing it: Step 1: Parse the link into components (target, format, is_relative)# Step 2: Route by format# If format is markdown or path: If target starts with /, resolve from collection root (strip the leading /) Otherwise, resolve relative to the source file's directory (standard markdown behavior) Example: link [Docs](docs/api.md) in notes/meeting.md resolves to notes/docs/api.md If format is wikilink: If target starts with ./ or ../, resolve relative to the source file's directory If target starts with /, resolve from collection root (strip the leading /) If target contains / (and is not relative), resolve from collection root Example: [[docs/api]] resolves to docs/api If simple name (no /, no ./ or ../): proceed to Step 3 Step 3: Simple-name resolution (wikilinks only)# For simple wikilink names (no path separator): Define the search scope: For blocked_by.uid: scope to files matching task_detection (task files only) For projects: scope to all markdown files in the collection unless narrowed by explicit configuration For attachments: scope to all non-directory files in the collection ID match pass: search scoped files for semantic role id (§2.6.5) equal to the name. Implementations MAY treat literal frontmatter key id as compatibility input when semantic mapping for id is unavailable. Equality MUST be exact string equality. If exactly one match: resolve to that file If multiple matches: fail with ambiguous_link Filename match pass: if no ID match, search scoped markdown files by filename (without extension). Implementations MUST deduplicate normalized candidate paths before final selection. If exactly one filename candidate remains after normalization and extension handling, resolve to that file. If multiple filename candidates remain, resolve to null and emit ambiguous_link. Callers SHOULD use a path-qualified or relative target to disambiguate. Step 4: Extension handling# If the target has no extension, implementations SHOULD try configured extensions in order. Default extension order: [\".md\"]. Example: [[readme]] tries readme.md, readme.mdx, etc. Step 5: Path traversal check# After resolution and normalization, if the resolved path would escape the collection root, abort with path_traversal. See §11.5. Step 6: Return result# The normalized collection-relative path if found null if no matching file exists Resolution examples# Given collection structure: / ├── TaskNotes/ │ ├── Tasks/ │ │ ├── task-001.md │ │ └── subtasks/ │ │ └── task-002.md ├── notes/ │ └── meeting.md └── projects/ └── alpha.md Resolution from TaskNotes/Tasks/subtasks/task-002.md: Link value Resolved path Notes [[task-001]] TaskNotes/Tasks/task-001.md Simple-name search [[../task-001]] TaskNotes/Tasks/task-001.md Relative wikilink [[./task-003]] TaskNotes/Tasks/subtasks/task-003.md Relative (may not exist) [[notes/meeting]] notes/meeting.md Absolute from root [[alpha]] projects/alpha.md Simple-name search (projects scope) [link](../task-001.md) TaskNotes/Tasks/task-001.md Markdown, relative ../task-001.md TaskNotes/Tasks/task-001.md Bare path, relative 11.5 Path sandboxing# Link resolution MUST NOT produce paths outside the collection root. Rules: After resolving relative paths (applying ../ segments), the resulting path MUST be within the collection root directory If resolution would escape the collection root, the link MUST resolve to null and implementations MUST emit a path_traversal error This applies to all link formats: wikilinks, markdown links, and bare paths Implementations MUST normalize paths (resolve . and .. segments) before checking containment Examples (collection rooted at /home/user/MyVault/): Link From file Result [[../../../etc/passwd]] TaskNotes/Tasks/task.md null + path_traversal [[../../secrets/key]] deep/nested/file.md null + path_traversal [[../task-001]] TaskNotes/Tasks/subtasks/t.md Resolves normally 11.6 Canonical write format# When creating new link values or changing a link target, implementations MUST use a deterministic canonical form. Default (wikilink format)# By default (links.use_markdown_format=false), the canonical write format is a simple wikilink: blockedBy: - uid: \"[[task-001]]\" reltype: FINISHTOSTART projects: - \"[[projects/alpha]]\" Rules: Use the filename without extension as the target when the file can be identified by simple-name resolution within the appropriate scope. Use a path-qualified target (folder/name) when the simple name would be ambiguous. Do NOT include the alias component in dependency uid writes. Do NOT include the anchor component in dependency uid writes. Preserve the alias component in projects entries when the alias was provided by the user. For attachments, always write a path-qualified collection-relative target with its file extension, for example [[Attachments/01K1-photo.jpg]]. Attachment writes MUST NOT include an alias or anchor. Markdown link format (links.use_markdown_format=true)# When links.use_markdown_format=true is configured (requires the obsidian-frontmatter-markdown-links Obsidian plugin), the canonical write format for link-bearing fields is a markdown link using the collection-relative path: blockedBy: - uid: \"[task-001](TaskNotes/Tasks/task-001.md)\" reltype: FINISHTOSTART Round-trip preservation# When writing an existing link field and the resolved target is unchanged, implementations MUST preserve the original format when possible: If the user wrote [[task-001|My Task]], preserve alias for projects entries. If the user wrote a relative path, preserve relativity when possible. For blocked_by.uid, alias and anchor components MUST still be removed on canonical writes. If preservation is not possible (for example unresolved/ambiguous reconstruction), implementations MUST fall back to canonical write rules in this section. 11.7 Configuration# links configuration keys (see §9.12): links: extensions: [\".md\"] # Extension trial order for extensionless targets use_markdown_format: false # Write markdown links instead of wikilinks unresolved_default_severity: warning # \"warning\" or \"error\" update_references_on_rename: true # Update link targets when files are renamed Rules: extensions MUST be a non-empty list when present unresolved_default_severity MUST be \"warning\" or \"error\" update_references_on_rename=true enables rename-time link rewrite behavior (§11.9) use_markdown_format=true requires the obsidian-frontmatter-markdown-links plugin in Obsidian deployments 11.8 Role-specific rules# 11.8.1 projects# projects entries SHOULD be interpreted with this section's parsing/resolution rules. If a projects entry is a plain string (not a wikilink or markdown link), implementations SHOULD treat it as a bare filename or path and attempt resolution. If unresolved: links.unresolved_default_severity=error: validation error otherwise: SHOULD emit unresolved_link_target warning 11.8.2 blocked_by.uid# blocked_by.uid values MUST use this section's parsing/resolution rules. For dependency semantics, unresolved uid handling follows §10.2.6. For unresolved-target severity, dependencies.unresolved_target_severity controls and takes precedence over links.unresolved_default_severity. The canonical write form for uid values is specified in §11.6. 11.8.3 attachments# Attachment references MUST resolve to files, not directories. Canonical attachment targets MUST be collection-relative, path-qualified, and retain an explicit file extension. This avoids ambiguous simple-name lookup, makes the frontmatter portable without a media-specific extension search policy, and preserves the actual filename. Readers MUST accept wikilinks, Markdown links, and bare paths. They MAY accept simple-name or extensionless values as non-canonical compatibility input, but canonical writes MUST resolve and replace them with an explicit path and extension. Aliases and anchors are not part of attachment identity and MUST be removed on canonical writes. The normalized resolved collection path defines attachment identity for duplicate detection. Implementations MUST preserve list order and MUST reject duplicates after path normalization. Unresolved attachment targets use the configured unresolved_link_target severity; offline-capable clients SHOULD distinguish a known-but-not-locally-cached file from a genuinely unresolved target. 11.9 Rename and reference updates# If an implementation supports reference updates on rename (i.e. claims the rename capability): It MUST update resolvable references in blocked_by.uid, projects, and attachments link fields. It SHOULD update links in body content. It SHOULD preserve the original link format when possible. It MUST preserve alias and anchor components where valid for the target field. For blocked_by.uid, alias and anchor are non-canonical and MUST be removed on write (§11.6). It MUST report unresolved or ambiguous rewrite cases. If reference updates are not supported, this limitation MUST be disclosed in conformance claims. 11.10 Validation# Link validation issues: Code Severity Trigger invalid_link_format error Link value cannot be parsed as any supported format ambiguous_link warning Simple-name resolution found multiple candidates after normalization unresolved_link_target warning Link target cannot be resolved to an existing file path_traversal error Resolved path escapes collection root unresolved_link_target severity may be promoted to error via links.unresolved_default_severity=error. For blocked_by.uid, use unresolved_dependency_target severity policy from §10.2.6 instead of unresolved_link_target. 11.11 Examples# Dependency with wikilink (default)# --- title: Implement API status: open tags: [task] blockedBy: - uid: \"[[design-api]]\" reltype: FINISHTOSTART - uid: \"[[projects/infra/setup-server]]\" reltype: FINISHTOSTART gap: P1D projects: - \"[[projects/alpha]]\" dateCreated: 2026-02-20T10:00:00Z dateModified: 2026-02-20T10:00:00Z --- Dependency with markdown links (links.use_markdown_format=true)# --- title: Implement API status: open tags: [task] blockedBy: - uid: \"[design-api](TaskNotes/Tasks/design-api.md)\" reltype: FINISHTOSTART --- Relative links from nested task# # TaskNotes/Tasks/subtasks/task-002.md --- title: Sub-task status: open tags: [task] blockedBy: - uid: \"[[../task-001]]\" # resolves to TaskNotes/Tasks/task-001.md reltype: FINISHTOSTART projects: - \"[[projects/alpha]]\" # resolves from collection root ---"},{"title":"12. mdbase v0.3 Data-Contract Binding","url":"/developers/specification/12-mdbase-v0.3-binding/","description":"Status: Draft","product":"specification","text":"Status: Draft Record contract: tasknotes.task 0.3.0-rc.3 Event contract: tasknotes.task.completed 1.0.0 Target: mdbase 0.3.x 12.1 Purpose# This chapter defines how a TaskNotes task model is exposed through mdbase without coupling TaskNotes to one record type or one application's private extension. The binding has three deliberately separate parts: the tasknotes.task data contract defines the portable task view; an mdbase type's implements entry maps that view to its own frontmatter fields and supplies TaskNotes behavior; and the rest of the type file continues to define that type's storage, matching, defaults, lifecycle, links, and paths. The normative artifacts are: mdbase/tasknotes.task.md, the record contract; schemas/tasknotes-task.schema.json, the projected task-view schema; and schemas/tasknotes-task-binding.schema.json, the implementation binding schema. The optional event-interoperability artifacts are: mdbase/tasknotes.task.completed.md, the event contract; and schemas/tasknotes-task-completed.schema.json, its event-data schema. 12.2 The mental model# A contract is not another record type. It is a view that several record types can implement and several applications can consume. personal_task ─┐ work_task ─────┼─ implements tasknotes.task 0.3.0-rc.3 ── TaskNotes issue_task ────┘ ├─ automation └─ another task app Reading or listing through the contract uses the union of all implementing types. Creating a task is different: the caller MUST choose one exact target type because the contract does not choose storage, paths, or lifecycle policy. The contract version is an exact semantic version. For this draft it is also the tasknotes-spec version whose task semantics the contract exposes. There is no independent x-tasknotes.version or spec_version mirror. Record types use implements because they adapt persisted fields and semantic bindings to the tasknotes.task record contract. Event sources do not use a type file. A TaskNotes application instead registers an event-source declaration for tasknotes.task.completed with an active mdbase interoperability bridge. 12.3 Layering# An implementing type MUST keep these responsibilities in their canonical locations: Information mdbase v0.3 location Persisted frontmatter shape, required fields, enum values, formats schema Type identification match Display field, defaults, links, uniqueness, and path generation collection Managed create/update values lifecycle Contract identity and custom field names implements[].contract, version, and fields TaskNotes semantic behavior implements[].binding TaskNotes metadata MUST NOT be encoded as custom JSON Schema keywords. x-tasknotes MUST NOT be used for contract discovery, field mapping, conformance, or authorization. 12.4 Declaring an implementation# An mdbase TaskNotes type declares one implementation: implements: - contract: tasknotes.task version: 0.3.0-rc.3 fields: title: summary status: state priority: importance dateCreated: created_at binding: # TaskNotes behavior; abbreviated here profiles: [core-lite] capabilities: [] title: storage: frontmatter filename_format: title status: values: [todo, doing, done] default: todo completed_values: [done] definitions: [] priority: values: [normal] default: normal definitions: [] The contract file identified by the exact contract and version MUST exist in the collection contract registry. The binding MUST validate against that contract's binding_schema. Each type MUST declare at most one implementation of one exact contract identity. A type may implement several different contracts. 12.5 Portable fields# fields maps contract field paths to record field paths. Consumers access contract fields and MUST NOT assume that their names are also frontmatter property names. fields: title: summary status: state blockedBy: dependencies attachments: files Every unconditionally required contract field MUST be mapped. Every mapped contract field and record field MUST exist in its respective JSON Schema. The contract view contains only mapped fields. It does not expose unmapped frontmatter or the Markdown body. A consumer that requires either needs separate, explicit whole-record access. title is optional in the portable schema because TaskNotes permits filename title storage. When binding.title.storage is filename, consumers derive the effective title from the record identity/path rules in §9.13 instead of expecting a projected frontmatter value. The camel-case contract field names are stable portable identifiers. Their snake-case tasknotes-spec counterparts include: Contract field tasknotes-spec role timeEstimate time_estimate completedDate completed_date dateCreated date_created dateModified date_modified recurrenceAnchor recurrence_anchor completeInstances complete_instances skippedInstances skipped_instances recurrenceParent recurrence_parent occurrenceDate occurrence_date occurrenceMaterialization occurrence_materialization occurrenceNextTrigger occurrence_next_trigger occurrenceTemplate occurrence_template occurrencePastHorizon occurrence_past_horizon occurrenceFutureHorizon occurrence_future_horizon timeEntries time_entries blockedBy blocked_by attachments attachments 12.6 Semantic profiles and capabilities# binding.profiles and binding.capabilities describe semantics that records of this implementation may use: binding: profiles: [core-lite, recurrence, materialized-occurrences] capabilities: - dependencies - reminders - attachments - links - time-tracking - materialized-occurrences - archive These are properties of the implementation, not claims that every consuming application supports them. Before mutating a governed field, a consumer SHOULD verify its own corresponding capability. It may still perform unrelated operations when it preserves unsupported fields and invariants. 12.7 Status and priority semantics# The implementing type schema defines the legal persisted values of the mapped fields. The binding gives those values TaskNotes meaning: binding: status: values: [todo, doing, done, cancelled] default: todo completed_values: [done] skipped_values: [cancelled] default_skipped: cancelled definitions: [] priority: values: [low, normal, high] default: normal definitions: [] The following consistency rules apply: binding values MUST equal the mapped type-schema enum values; defaults MUST equal mapped collection.read_defaults values when present; completed and skipped values MUST be members of status.values; default_skipped MUST be a skipped value; completed and skipped values MUST NOT overlap for materialized occurrences; and definition semantics MUST agree with completed/skipped membership. Status and priority labels, colors, and icons are presentation hints. Status cycle, completion, skipping, auto-archive, and priority weight are semantic. 12.8 Title, recurrence, links, and operations# The remaining binding sections project the effective TaskNotes behavior defined elsewhere in this specification: title follows §9.13 and MUST agree with collection.display and collection.path; recurrence follows §4; occurrences follows §2.6.6, §4.18, §5.20, and §9.17; links follows §11; attachment membership is the portable attachments contract field; binary MIME type, digest, byte size, revision, and timestamps remain authoritative in mdbase file descriptors and are not projected into task frontmatter; archive follows §5.12; time_tracking follows §5.19 and §9.16; templating follows §5.3.5 and §9.14; and optional nlp triggers follow §9.18. Archive always operates on the portable tags contract field, so the binding does not repeat a record-specific tags_field. The implementation's fields map determines the actual frontmatter property. Application-local notification preferences and generator bookkeeping MUST NOT be placed in the binding. 12.9 Multiple implementations# A collection may contain any number of types implementing tasknotes.task 0.3.0-rc.3. TaskNotes-aware readers MUST: resolve the exact local contract; enumerate every implementation in canonical type-name order; read each matching record through that implementation's projected view; validate the projected view; and retain the concrete type identity for updates. Implementations MUST NOT merge type schemas into one synthetic schema. A record is validated by its concrete type and then by its projected contract view. When an approval, cache, or external protocol pins an implementation set, it MUST pin the exact contract digest and sorted implementation descriptors, including each implementation digest. A newly installed type is therefore not silently added to an existing approval. Creation MUST name one concrete implementing type. If no type is selected, creation fails as ambiguous. 12.10 Task-completed event# An event source that claims tasknotes.task.completed 1.0.0 MUST emit one CloudEvents structured event for each observed transition from a non-completed status to a completed status. Its data contains only: task_id, using the stable TaskNotes ID when present and otherwise the normalized path; task_path; the current title and completed status; and completed_at, the instant when TaskNotes observed the transition. The event source MUST use the mdbase event/action interoperability profile 0.1, pin the exact event-contract digest, and preserve any correlation and causation identifiers supplied by the mutation context. It MUST NOT include a complete task record merely because one is locally available. An authorized consumer can retrieve current state separately, avoiding stale snapshots and unnecessary disclosure. Contract compatibility and bridge authorization are independent. Installing TaskNotes or resolving this contract does not grant permission to publish or consume the event. 12.11 Precedence and consistency# The complete implementation is self-describing: the contract schema is authoritative for the portable projected view; the type schema is authoritative for persisted value shapes; collection is authoritative for generic mdbase behavior; lifecycle is authoritative for generic managed writes; and implements[].binding is authoritative for TaskNotes semantics. Where values intentionally mirror each other, producers MUST keep them equal. A TaskNotes-aware consumer MUST report a configuration error instead of silently choosing between contradictory values. 12.12 Safe writes# TaskNotes-aware consumers MUST preserve: unknown frontmatter properties unless explicit replacement or migration was requested; Markdown body content unless an operation explicitly replaces it; fields governed by unsupported capabilities; and unrelated type metadata and implementations. Generic mdbase operations are safe only when they preserve the same data. Completion, recurrence mutation, occurrence materialization, dependency updates, time tracking, archive, and other domain operations MUST follow the TaskNotes semantics referenced by the binding. 12.13 Complete custom-field example# --- kind: mdbase.type name: work_task version: 1 schema: dialect: json-schema-2020-12 value: type: object additionalProperties: true required: [summary, state, created_at] properties: summary: { type: string, minLength: 1 } state: { enum: [todo, doing, done, cancelled] } importance: { enum: [low, normal, high] } created_at: { type: string, format: date-time } tags: type: array items: { type: string } collection: display: name_field: summary read_defaults: state: todo importance: normal lifecycle: on_create: set: created_at: { now: true } implements: - contract: tasknotes.task version: 0.3.0-rc.3 fields: title: summary status: state priority: importance dateCreated: created_at tags: tags binding: profiles: [core-lite] capabilities: [archive] title: storage: frontmatter filename_format: title status: values: [todo, doing, done, cancelled] default: todo completed_values: [done] skipped_values: [cancelled] default_skipped: cancelled definitions: [] priority: values: [low, normal, high] default: normal definitions: [] recurrence: syntax: tasknotes maintain_due_date_offset: false reset_body_checkboxes: false occurrences: identity_roles: [recurrenceParent, occurrenceDate] default_materialization: manual default_next_trigger: completion links: accepted_formats: [wikilink, markdown] write_format: wikilink archive: archived_tag: archived move_on_archive: false time_tracking: auto_stop_on_complete: true templating: enabled: false occurrence_enabled: false ---"},{"title":"Changelog","url":"/developers/specification/CHANGELOG/","description":"Initial standalone draft of tasknotes-spec including:","product":"specification","text":"0.3.0-rc.3 - 2026-08-02# define manual ordering as an opaque string rank so clients can insert and reorder tasks without renumbering an entire view 0.3.0-rc.2 - 2026-08-02# add first-class attachments as an ordered frontmatter list of portable file links, with explicit membership, canonical-path, reference-safety, and materialized-occurrence semantics expose attachment references in the tasknotes.task mdbase contract while leaving binary metadata authoritative in the file store 0.3.0-rc.1 - 2026-07-28# adopt the discriminated first-class mdbase contract shape for tasknotes.task, including explicit contract_type: record add the tasknotes.task.completed 1.0.0 event contract and minimal privacy-preserving event-data schema for the mdbase interoperability profile separate type-file record implementation bindings from application-level event-source declarations 0.2.0-draft - 2026-05-31# add optional materialized-occurrences profile for recurrence occurrence notes, on-completion materialization, and occurrence-state reconciliation add optional NLP trigger configuration so TaskNotes clients can share capture suggestion vocabulary replace the private x-tasknotes discovery envelope with the first-class tasknotes.task 0.2.0 mdbase data contract, portable task-view schema, and implementation binding schema document the precedence and consistency rules between JSON Schema, collection, lifecycle, contract field mappings, and TaskNotes behavior 0.1.0-draft - 2026-02-20# Initial standalone draft of tasknotes-spec including: motivation, scope, and normative conventions terminology task model and field mapping temporal semantics recurrence semantics operation semantics validation model conformance profiles compatibility and migration policy collection configuration schema and provider model (tasknotes.yaml, TaskNotes data.json) full dependency (blocked_by) semantics full reminder (reminders) semantics explicit time-tracking management semantics (time_entries lifecycle, start/stop/edit/remove, and completion-triggered auto-stop configuration) explicit links chapter and link-resolution rules for projects/dependencies optional templating conformance profile with create-time template expansion/merge semantics"},{"title":"TaskNotes for Obsidian","url":"/obsidian/","description":"Install TaskNotes, create a first task, and open the default Obsidian Base views.","product":"obsidian","text":"This guide covers the TaskNotes plugin for Obsidian. It follows the \"one note per task\" principle: each task is a Markdown file with structured metadata in YAML frontmatter. Requirements# TaskNotes 4.12.3 requires Obsidian 1.12.2 or later and depends on the Bases core plugin. Before you begin, open Obsidian Settings and confirm Bases is enabled under Core Plugins. Getting Started# 1. Install and Enable# Install TaskNotes from Community Plugins in Obsidian settings, then enable it. If Bases is still disabled, enable it right away so TaskNotes views can open correctly. 2. Create Your First Task# Press Ctrl+P (or Cmd+P on macOS), run TaskNotes: Create new task, fill in the modal, and save. If you prefer inline workflows, start with a checkbox like - [ ] Buy groceries and convert it using the inline task command. 3. Open the Task List# Open your first view from the TaskNotes ribbon icon or by running TaskNotes: Open tasks view from the command palette. This opens the default Task List .base file inside TaskNotes/Views. 4. Explore# Use Core Concepts to understand the data model, Features for workflow capabilities, Views for interface behaviour, and Settings to tune TaskNotes for your vault. If you already have task-like notes, start with Adopt TaskNotes in an existing vault. Quick Links# GitHub Repository Source code, issues, releases, and contribution discussions Task Management Status, priority, dates, reminders, and recurring tasks Inline Tasks Widgets, natural language parsing, and checkbox conversion Calendar Integration Google Calendar, Outlook, and ICS subscriptions HTTP API REST API for automation and external integrations JavaScript API In-process API for companion plugins and in-vault scripts Companion Plugins Optional plugins such as Canvas Bases and TaskNotes Workflows that build on TaskNotes Migration Guide Upgrading from TaskNotes v3 to v4 Troubleshooting Common issues and how to resolve them Command Reference Every registered command, generated from the plugin source Backup & Recovery Protect task notes, Base files, settings, and integration data Specification The formal spec behind TaskNotes: data model, operations, recurrence, and conformance"},{"title":"Calendar Integration Setup","url":"/obsidian/calendar-setup/","description":"TaskNotes supports Google Calendar and Microsoft Calendar integration via OAuth 2.0.","product":"obsidian","text":"TaskNotes supports Google Calendar and Microsoft Calendar integration via OAuth 2.0. Setup (Your Own OAuth Credentials)# To connect calendars, create OAuth credentials with Google and/or Microsoft, then paste them into TaskNotes Integrations settings. The sections below walk through each provider. Google Calendar# Video by @antoneheyward In Google Cloud Console, create or select a project, enable the Google Calendar API, and create OAuth 2.0 credentials using the Desktop application type. Then copy the Client ID and Client Secret into TaskNotes (Settings -> TaskNotes -> Integrations) and click Connect Google Calendar. If your Google OAuth app is still in testing mode, add the Google account you will connect with under Google Auth Platform -> Audience -> Test users. Otherwise Google may block sign-in with a 403 access_denied error saying the app has not completed verification. Microsoft Calendar# In Azure Portal, create an App Registration for your Microsoft account type. TaskNotes currently uses Microsoft's common OAuth authority, so the app registration must allow the account type you plan to connect through that authority. Tenant-specific single-tenant authorities are not configurable yet. Under Authentication, add the Mobile and desktop applications platform and add this redirect URI: http://localhost Also turn on Allow public client flows. TaskNotes uses a local loopback callback with a dynamic port, which Microsoft matches against the registered loopback URI. If Azure does not accept the loopback redirect URI through the normal UI, configure loopback redirect support in the manifest by adding: { \"url\": \"http://127.0.0.1\", \"type\": \"Web\" } Next, add delegated Microsoft Graph API permissions (Calendars.Read, Calendars.ReadWrite, and offline_access) and grant consent when required by your organization. Copy the Application (client) ID into TaskNotes, then click Connect Microsoft Calendar. The client secret field can be left blank for public-client desktop setup. Security Notes# OAuth client IDs, client secrets, and account tokens are stored locally in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system. They are not written to TaskNotes' data.json. Tokens refresh automatically, calendar data syncs directly between your vault and provider, and you can disconnect at any time to revoke account access. Secret Storage is local to the Obsidian installation and vault. When setting up TaskNotes on another device, enter the OAuth app credentials and connect the calendar again. After disconnecting, use Forget saved credentials if you also want to remove the client ID and client secret. Troubleshooting# \"Failed to connect\" Verify credentials first, then confirm loopback redirect configuration. TaskNotes uses a local callback on 127.0.0.1 with a dynamically selected port. For Microsoft, ensure loopback redirect support is configured in the app registration. Also confirm required permissions/scopes are granted. For Google 403 access_denied errors during sign-in, confirm the account is listed as a test user in the Google Auth Platform audience settings while your OAuth app is in testing mode. \"Failed to fetch events\" Disconnect and reconnect to refresh OAuth tokens, then re-check provider-side calendar permissions. Connection lost after Obsidian restart Tokens should persist between sessions. If reconnection is required each restart, check whether Obsidian Secret Storage is available and retaining secrets for the vault."},{"title":"Companion Plugins","url":"/obsidian/companion-plugins/","description":"Companion plugins are optional Obsidian plugins that build on TaskNotes without adding every workflow to the core plugin. They run inside the same Obsidian app, use TaskNotes...","product":"obsidian","text":"Companion plugins are optional Obsidian plugins that build on TaskNotes without adding every workflow to the core plugin. They run inside the same Obsidian app, use TaskNotes' runtime API for live task reads and writes, and keep task data in ordinary Markdown files. Use companion plugins when you want a deeper product surface than a script or webhook, but you still want TaskNotes itself to stay focused on task storage, editing, views, time tracking, and calendar behavior. Available Companion Plugins# Plugin Purpose Documentation Canvas Bases TaskNotes canvas companion for Obsidian Bases views, with canvas-style boards, JSON Canvas snapshots, optional TaskNotes badges, actions, and relationship edges. Canvas Bases TaskNotes Workflows Markdown-defined automation for TaskNotes tasks, schedules, events, and manual command-palette workflows. TaskNotes Workflows More companion plugins may be documented here over time. How Companion Plugins Relate to TaskNotes# TaskNotes remains the source of truth for task behavior. Companion plugins should use the TaskNotes JavaScript Runtime API for live vault operations instead of rewriting TaskNotes frontmatter directly. This keeps task updates consistent with TaskNotes settings, task cache, events, calendar behavior, time tracking, and future data-model changes. Companion plugins can also publish their own runtime surface through api.extensions. Other plugins and scripts can discover those extension APIs from TaskNotes: const tasknotes = app.plugins.getPlugin(\"tasknotes\"); const workflows = tasknotes?.api?.extensions.get(\"tasknotes-workflows\"); The extension registry is useful when companion plugins need to expose commands, validation helpers, catalogs, or run APIs to other in-vault tools. Choosing an Integration Surface# Use case Prefer A user-facing Obsidian UI that works with TaskNotes tasks Companion plugin In-vault scripting with Templater, QuickAdd, MetaBind, or another plugin JavaScript Runtime API Local tools outside Obsidian HTTP API or TaskNotes Obsidian CLI Notifications to external services when tasks change Webhooks Direct file analysis without Obsidian running mdbase-tasknotes CLI Compatibility Expectations# Companion plugins should: Check api.apiVersion and api.hasCapability(...) before using runtime features. Use api.catalog and canonical runtime query DTOs from api.query instead of reaching into TaskNotes filter/view internals. Include a source value when mutating tasks so TaskNotes events are debuggable. Avoid reacting to their own mutations unless the behavior is explicit. Keep user data in the vault where possible, using readable Markdown or JSON files. Treat TaskNotes task notes and Bases files as user-owned documents. TaskNotes does not need every companion plugin installed. If a companion plugin is disabled, TaskNotes task notes remain normal Markdown files and TaskNotes core views continue to work."},{"title":"Canvas Bases","url":"/obsidian/companion-plugins/canvas-bases/","description":"Canvas Bases is the TaskNotes canvas companion plugin for Obsidian Bases and Canvas. It turns the current Bases result set into a canvas-style board, either as a live Bases layo...","product":"obsidian","text":"Canvas Bases is the TaskNotes canvas companion plugin for Obsidian Bases and Canvas. It turns the current Bases result set into a canvas-style board, either as a live Bases layout named Canvas Bases or as a generated JSON Canvas snapshot. Canvas Bases works with normal notes and with TaskNotes task notes. Bases remains the source for which notes appear: filters, sorting, grouping, formulas, and visible properties all come from the .base file. Canvas Bases handles spatial layout, cards, edges, zones, pinned notes, text cards, and linked canvas updates. Requirements# Obsidian 1.10.1 or newer. The Obsidian Bases core plugin. The Obsidian Canvas core plugin when opening or editing generated .canvas files. TaskNotes is optional, but must be installed and enabled for TaskNotes-specific badges, task menus, dependency edges, subtasks, time tracking, Pomodoro actions, and recurring-task zone actions. If TaskNotes is disabled, Canvas Bases still works as a Bases and Canvas plugin. TaskNotes-specific actions are skipped when TaskNotes is absent or does not expose the required runtime API capability. When to Use Canvas Bases# Use Canvas Bases when a task view benefits from spatial arrangement instead of a list, table, calendar, or Kanban column set. Common uses include: Planning project tasks on a visual board. Seeing dependencies or related notes as edges between cards. Embedding a board in a daily note, project note, or meeting note. Turning a filtered Base view into a reusable .canvas snapshot. Grouping notes with Bases, then manually arranging the result. Dropping cards into assignment zones to update a note property or run a supported TaskNotes action. If the question is only \"which tasks should appear?\", keep that in Bases filters, formulas, sorting, and grouping. Canvas Bases is for visualizing and arranging the current Bases result set. Canvas Bases Layout# After Canvas Bases is installed, open or create a .base file and add a view using the Canvas Bases layout. In the live layout: Each Base result row becomes a file card. Displayed Base properties appear on each card in the same order as the Base properties menu. Base groups become group frames. Cards and group frames can be dragged and resized. Ungrouped views place cards directly on the board. The initial card order follows the Base sort order. Inline note-body editing is available when Show body editor is enabled. Board controls support panning, zooming, fit view, reset view, and opening cards. Manual notes, manual groups, and text cards can be added without changing the Base query. Canvas Bases stores layout and board state in Canvas Bases-owned keys in the .base view config. It does not need to rewrite the core query just to remember card positions, sizes, colors, pinned notes, text cards, zones, or the linked canvas path. Materialize a Canvas# Canvas Bases can also create or update a JSON Canvas file from any active Bases view, including native and third-party Bases layouts. Run these commands from the command palette: Canvas Bases: Create canvas from current bases view Canvas Bases: Update linked canvas Canvas Bases: Open linked canvas The create command asks for the canvas path, layout, edge options, node size, and update behavior. Canvas Bases-owned node and edge IDs are stable, so updating a linked canvas can preserve existing Canvas Bases node positions and keep unrelated manual Canvas nodes and edges. The generated .canvas file is a snapshot, not a live query. Re-run Canvas Bases: Update linked canvas after changing the Base result set or board layout. TaskNotes Integration# Canvas Bases reads TaskNotes through the TaskNotes JavaScript Runtime API. It feature-detects API capabilities before using them, so the board can degrade cleanly when TaskNotes is unavailable or a capability is missing. When TaskNotes integration is enabled, Canvas Bases can: Show TaskNotes status, priority, planning, recurrence, blocked, blocking, subtask, time estimate, tracked time, and active tracking badges on task cards. Add TaskNotes task actions to card context menus through the TaskNotes task menu API. Draw dependency edges between visible tasks. Draw dependency and parent-subtask edges when the TaskNotes relationship mode is set to all. Add or remove dependency and subtask relationships by dragging from one card's link handle to another. Update mapped TaskNotes task properties when a card is dropped into a property zone. Run supported zone actions such as complete, uncomplete, archive, unarchive, start or stop time tracking, start or assign a Pomodoro, complete an occurrence, or skip an occurrence. TaskNotes remains responsible for task semantics. Canvas Bases asks TaskNotes to read and mutate tasks instead of editing task frontmatter directly. Edges and Relationships# Canvas Bases can draw edges when both endpoint notes are present on the board. Supported edge sources include: Source What it uses wikilinks Links found in the note body. properties Links stored in configured note properties. all Wikilinks and configured property links. TaskNotes dependencies Blocking relationships from TaskNotes. TaskNotes subtasks Parent-child task relationships from TaskNotes when enabled. For property edges, configure a comma-separated list of property names, such as: depends_on, related Edges can be opened from their context menu. Removable TaskNotes and property relationships can also be removed from that menu. Assignment Zones# Assignment zones are board regions that do something when a card is dropped into them. The default zone action updates a note property. A grouped Canvas Bases view can turn Bases groups into zones, so dragging a card into another status, priority, or custom-property group writes that property value back to the note. Custom zones can update another note property or run supported TaskNotes actions. This lets a board mix automatic Bases-derived groups with manual workflow areas such as review queues, time-tracking lanes, or Pomodoro focus zones. Files and Data# Canvas Bases keeps user data in normal vault files: Data Where it lives Task and note content Markdown files. Query, visible properties, sorting, and grouping .base files. Live board geometry and Canvas Bases options Canvas Bases-owned keys in the .base view config. Generated board snapshots .canvas files. Options for non-Canvas Bases active views Canvas Bases plugin data. Manual non-Canvas Bases nodes in a generated .canvas file are preserved when Canvas Bases updates that canvas. First Board# A practical first Canvas Bases setup is: Create or duplicate a TaskNotes .base view. Filter it to the tasks or notes you want on the board. Add a Canvas Bases layout view to that .base file. Choose which properties to show on cards. Enable TaskNotes badges, actions, or relationships if the board is task-focused. Arrange the cards and groups. Use the toolbar to create a linked .canvas snapshot when you want a Canvas file. Canvas Bases can also create starter files under Canvas Bases/ with a demo Base, sample notes, and a linked Canvas path. Run Canvas Bases: Create starter files from the command palette if you want a small example board to inspect before adapting your own TaskNotes views."},{"title":"TaskNotes Workflows","url":"/obsidian/companion-plugins/tasknotes-workflows/","description":"TaskNotes Workflows is a companion plugin for Markdown-defined automation. It lets you create workflow notes that respond to TaskNotes events, schedules, manual commands, and se...","product":"obsidian","text":"TaskNotes Workflows is a companion plugin for Markdown-defined automation. It lets you create workflow notes that respond to TaskNotes events, schedules, manual commands, and selected Obsidian events, then run typed actions against TaskNotes tasks. Install TaskNotes Workflows# Install from Obsidian Community Plugins Open the TaskNotes Workflows listing in the Obsidian plugin directory You can also install it from Obsidian: open Settings > Community plugins > Browse, then search for TaskNotes Workflows. The plugin is designed for workflows users often ask TaskNotes core to handle, such as: Start time tracking when a task becomes active. Stop time tracking when a task is completed. Move completed tasks into a review folder. Copy parent task context, tags, priority, dates, or dependencies to subtasks. Warn when a blocked task is moved to active. Run a daily review query. TaskNotes Workflows keeps this behavior outside TaskNotes core while still using the TaskNotes JavaScript Runtime API for safe task reads, writes, canonical queries, events, and relationship resolution. Requirements# TaskNotes must be installed and enabled. TaskNotes must expose the JavaScript runtime API. Obsidian must be open for workflows to run. Scheduled workflows run while Obsidian is running. They are not a background service when Obsidian is closed. The plugin runtime uses Obsidian APIs only. Node is used for development and build scripts, not for workflow execution, so Markdown workflow definitions can work on Obsidian mobile while the plugin is loaded. If TaskNotes is disabled or unavailable, the workflow Base can still validate and display workflow files, but TaskNotes read/write steps cannot run. Files Created by the Plugin# By default, TaskNotes Workflows uses: Path Purpose TaskNotes/Workflows/ Workflow Markdown files. TaskNotes/Views/workflows.base Generated Obsidian Base that renders workflow cards through the custom workflow view. Plugin config folder Run history and detail logs, unless a run-log folder is configured. Workflow notes are ordinary Markdown files. The YAML frontmatter is executable configuration, and the note body is for human explanation, testing notes, and maintenance guidance. First Run# On first load, the plugin can create a default workflow folder, a workflow Base, and a set of example workflow notes. The default workflow notes are disabled so they can be inspected, dry-run, edited, and enabled intentionally. The generated Base is the main workbench. It shows workflow cards with status, trigger and step summaries, recent run state, and buttons for editing, dry-running, running, and opening the source note. Workflow notes also show a compact workflow card in reading mode and live preview, so the note remains useful even when opened directly. Default Workflows# The plugin can write these starter workflows: Workflow What it demonstrates Auto-start time tracking Starts a timer when a task status changes to active. Stop time tracking on complete Stops the timer when a task is completed. Morning overdue review Runs a daily cron query and marks overdue open tasks high priority. Move completed tasks to review Moves completed task notes into a review folder. Inherit subtask contexts and tags Copies contexts and tags from the first parent task when a task becomes a subtask. Inherit subtask priority Copies priority from the first parent task when a task becomes a subtask. Inherit subtask planning dates Copies scheduled and due dates from the first parent task when a task becomes a subtask. Inherit subtask dependencies Adds the first parent task's blocking dependencies to new subtasks. Mirror parent priority to subtasks Updates existing subtasks when a parent task priority changes. Mirror parent planning dates to subtasks Updates existing subtasks when a parent scheduled or due date changes. Mirror parent dependencies to subtasks Replaces each subtask's dependencies with the parent task's current dependencies. Warn when starting a blocked task Shows a notice when a task becomes active while dependencies remain. Daily active task review Shows a daily count of tasks still marked active. Treat these as editable examples. Adjust folders, statuses, priorities, dates, and filters to match your vault before enabling mutating workflows. Workflow Shape# A workflow file looks like this: --- type: tasknotes-workflow schemaVersion: 1 id: auto-start-time-tracking name: Auto-start time tracking enabled: false description: Start a timer when a task status changes to active. triggers: - id: status-active type: tasknotes.event event: task.status.changed to: active conditions: - field: trigger.after.path operator: exists steps: - id: start-time type: time.start input: task: \"{{trigger.after.path}}\" options: description: \"Started by {{workflow.name}}\" run: mode: sequential noOverlap: true source: tasknotes-workflows maxTasks: 1 onError: stop --- # Auto-start time tracking Enable this workflow to start time tracking when a TaskNotes task moves to `active`. Required frontmatter fields: Field Type Notes type string Must be tasknotes-workflow. schemaVersion number Must be 1. id string Stable lowercase identifier. Use letters, numbers, dots, underscores, and dashes. name string Human-readable name shown in workflow cards and command-palette commands. enabled boolean Disabled workflows can be edited and dry-run but do not run automatically or from manual commands. triggers array One or more trigger definitions. conditions array Optional workflow-level guards. steps array Linear typed step pipeline. run object Run policy and safety limits. Triggers# Triggers decide when a workflow should run. TaskNotes Events# Use tasknotes.event to react to TaskNotes runtime events: triggers: - id: status-active type: tasknotes.event event: task.status.changed from: open to: active Common event names include: task.created task.updated task.deleted task.moved task.status.changed task.completed task.uncompleted task.archived task.unarchived task.scheduled.changed task.due.changed task.priority.changed task.tags.changed task.contexts.changed task.projects.changed task.reminders.changed task.dependencies.changed task.recurrence.changed time.started time.stopped pomodoro.started pomodoro.completed pomodoro.interrupted recurring.instance.completed recurring.instance.skipped The workflow editor loads available TaskNotes events dynamically from api.events.list(), so event pickers can follow the runtime API instead of relying on a hardcoded list. TaskNotes event triggers can use these filters: Field Purpose event Runtime event name. from Previous status or value for status-change workflows. to New status or value for status-change workflows. path.glob Optional path glob limiting which task files can trigger the workflow. allowSelfTrigger Allows this workflow to react to writes caused by tasknotes-workflows. Leave off unless you have a clear reason. TaskNotes event output fields include values such as trigger.after.path, trigger.after.status, trigger.before.status, trigger.changes, trigger.source, and trigger.correlationId. Cron# Cron triggers run on matching minutes while Obsidian is open: triggers: - id: weekday-review type: cron schedule: \"0 17 * * 1-5\" timezone: local The schedule uses five fields: minute, hour, day of month, month, day of week. Keep cron workflows bounded with run.maxTasks, especially if they query many tasks. Interval# Interval triggers run repeatedly while Obsidian is open: triggers: - id: half-hour-check type: interval every: 30m The plugin enforces a minimum interval to avoid excessive background work. Manual# Manual triggers let a workflow run from a card button, another plugin, or the Obsidian command palette: triggers: - id: manual type: manual Enabled workflows with a manual trigger are registered as Obsidian commands named Run: . You can launch them from the command palette or assign hotkeys in Obsidian settings. The generated command id is based on the workflow id. Changing a workflow id creates a different command, so any hotkey assigned to the old command id will need to be reassigned. Obsidian Events# Advanced Obsidian triggers are opt-in from the plugin settings. They can listen to selected vault, metadata, and workspace events: triggers: - id: project-note-opened type: obsidian.workspace event: file-open path: glob: \"Projects/**/*.md\" - id: task-note-modified type: obsidian.vault event: modify path: glob: \"Tasks/**/*.md\" - id: metadata-changed type: obsidian.metadata event: changed path: glob: \"Projects/**/*.md\" Keep path filters narrow for Obsidian triggers. Vault and metadata events can be frequent. Conditions# Conditions can appear at workflow level or on individual steps. conditions: - field: trigger.after.path operator: exists - field: trigger.after.status operator: is value: active Supported operators: Operator Meaning is / isNot Exact comparison after scalar normalization. in / notIn Check a value against an array. exists / missing Check whether a field has a value. contains Check whether a string contains text or an array contains a value. startsWith String prefix check. before / after Date comparison. onOrBefore / onOrAfter Inclusive date comparison. Step-level conditions use the same shape: steps: - id: warn type: notice.show if: - field: steps.dependencies.tasks[0].path operator: exists input: message: \"This task still has dependencies.\" References# References use constrained template expressions. Arbitrary JavaScript is not evaluated. {{workflow.id}} {{workflow.name}} {{trigger.after.path}} {{trigger.changes.status.after}} {{steps.query.tasks}} {{steps.parents.tasks[0].path}} {{item.path}} {{today}} {{now}} If a string is exactly one reference, the underlying value is preserved. If a reference is embedded in other text, the value is stringified. Use forEach when a step should run once per item: steps: - id: overdue type: task.query input: query: where: all: - field: task.due op: lt value: fn: today - field: task.status op: notIn value: - done - cancelled sort: - field: task.due direction: asc limit: 50 scope: includeArchived: false - id: mark-high type: task.patch forEach: \"{{steps.overdue.tasks}}\" input: task: \"{{item.path}}\" patch: priority: high When a step uses forEach, {{item}} refers to the current item and the step output becomes an array of per-item outputs. task.query uses the canonical TaskNotes runtime query DTO. Its output includes tasks, count, total, matched, returned, groups, groupPaths, query, and warnings. Runtime query conditions use canonical field IDs and operators: query: where: all: - field: task.status op: ne value: done - any: - field: task.due op: lte value: fn: today - field: task.priority op: eq value: high sort: - field: task.due direction: asc group: - field: task.status limit: 25 scope: includeArchived: false Common fields include task.status, task.priority, task.due, task.scheduled, task.projects, task.contexts, task.tags, task.isBlocked, and file.path. Operators include eq, ne, contains, notContains, in, notIn, exists, missing, lt, lte, gt, gte, isTrue, and isFalse. Use api.catalog.filterProperties() and api.catalog.filterOperators() for the complete runtime catalog. Steps# Steps are typed actions. The editor reads a step catalog so it can show expected inputs, output fields, examples, and TaskNotes option pickers. Task read steps: Step Output task.get One task. task.query Tasks matching a canonical TaskNotes runtime query. task.parents Parent tasks linked from the task's projects. task.subtasks Tasks that reference the current task as a project. task.dependencies Dependencies stored in blockedBy, with resolved task data when available. task.blocking Tasks blocked by the current task. task.relationships The task plus parents, subtasks, dependencies, and blocking tasks. Task write steps: Step Purpose task.create Create a new TaskNotes task. task.patch Update one or more fields. task.set Set one field. task.move Move the task note to a target folder. task.archive / task.unarchive Archive or unarchive a task. task.complete / task.uncomplete Complete or reopen a task. task.reschedule Update planning dates. task.setDue / task.clearDue Set or clear due date. task.setScheduled / task.clearScheduled Set or clear scheduled date. task.addTag / task.removeTag Mutate tags. task.addProject / task.removeProject Mutate project links. task.addContext / task.removeContext Mutate contexts. task.addDependency / task.removeDependency Mutate blocking dependencies. Time and utility steps: Step Purpose time.start Start time tracking for a task. time.stop Stop active time tracking for a task. time.appendEntry Append a time entry. notice.show Show an Obsidian notice. workflow.stop Stop a workflow early. Companion plugins and scripts can inspect the same catalog through the TaskNotes runtime extension: const tasknotes = app.plugins.getPlugin(\"tasknotes\")?.api; const workflows = tasknotes?.extensions.get(\"tasknotes-workflows\"); const steps = workflows?.listStepDefinitions(); Run Policy# Every workflow has a run policy: run: mode: sequential noOverlap: true source: tasknotes-workflows maxTasks: 25 onError: stop timeout: 30s Field Notes mode Currently sequential. Steps run in order. noOverlap Skips a new run if the same workflow is already running. source Mutation source passed to TaskNotes runtime API calls. maxTasks Safety limit for forEach batch steps. onError stop or continue. timeout Optional duration string. TaskNotes attaches source, correlation, and reason metadata to events caused by runtime API writes. Workflows use this to make runs debuggable and to avoid accidental self-trigger loops. Run Logs and Debugging# Workflow run logs are stored under the plugin's Obsidian config folder by default. You can configure a run-log folder and a log level in the plugin settings. Run records include: Workflow id, name, and source path. Trigger payload. Step statuses. Inputs and outputs, depending on the configured log level. Error text when a run fails. Use dry runs before enabling workflows that mutate tasks. Dry runs still execute the workflow path, but mutating steps should report what they would do instead of changing task files. Example: Manual Command Workflow# This workflow can be run from the command palette after it is enabled: --- type: tasknotes-workflow schemaVersion: 1 id: show-active-count name: Show active task count enabled: true description: Show a notice with the number of active tasks. triggers: - id: manual type: manual steps: - id: active type: task.query input: query: where: field: task.status op: eq value: active limit: 25 scope: includeArchived: false - id: notice type: notice.show input: message: \"Active tasks: {{steps.active.count}}\" run: mode: sequential noOverlap: true source: tasknotes-workflows maxTasks: 25 onError: stop --- # Show active task count Run this from the Obsidian command palette with `TaskNotes Workflows: Run: Show active task count`. Example: Inherit Parent Priority# This workflow copies priority from the first parent task when a task becomes a subtask: type: tasknotes-workflow schemaVersion: 1 id: inherit-subtask-priority name: Inherit subtask priority enabled: false triggers: - id: projects-changed type: tasknotes.event event: task.projects.changed - id: task-created type: tasknotes.event event: task.created conditions: - field: trigger.after.path operator: exists - field: trigger.after.projects operator: exists steps: - id: parents type: task.parents input: task: \"{{trigger.after.path}}\" - id: inherit-priority type: task.patch if: - field: steps.parents.tasks[0].priority operator: exists input: task: \"{{trigger.after.path}}\" patch: priority: \"{{steps.parents.tasks[0].priority}}\" run: mode: sequential noOverlap: true source: tasknotes-workflows maxTasks: 1 onError: stop This pattern uses task.parents rather than trying to parse project links manually. Authoring Guidelines# When writing workflow notes: Start with enabled: false fo"},{"title":"Core Concepts","url":"/obsidian/core-concepts/","description":"TaskNotes follows the \"one note per task\" principle, where each task lives as a separate Markdown note with structured metadata in YAML frontmatter.","product":"obsidian","text":"TaskNotes follows the \"one note per task\" principle, where each task lives as a separate Markdown note with structured metadata in YAML frontmatter. The Note-Per-Task Approach# Individual Markdown notes replace centralized databases or proprietary formats. Each task file can be read, edited, and backed up with any text editor or automation tool. Task Structure# A TaskNotes task is a standard Markdown file with YAML frontmatter: --- tags: - task title: Review quarterly report status: in-progress priority: high due: 2025-01-15 scheduled: 2025-01-14 contexts: - office projects: - \"[[Q1 Planning]]\" --- ## Notes Key points to review: - Revenue projections - Budget allocations ## Meeting Notes Discussion with finance team on 2025-01-10... The frontmatter contains structured, queryable properties. The note body holds freeform content—research findings, meeting notes, checklists, or links to related documents. Obsidian Integration# Since tasks are proper notes, they work with Obsidian's core features: Backlinks: See which notes reference a task Graph View: Visualize task relationships and project connections Tags: Use Obsidian's tag system for additional categorization Search: Find tasks using Obsidian's search Links: Reference tasks from daily notes, meeting notes, or project documents This approach creates many small files. TaskNotes stores tasks in a configurable folder (default: TaskNotes/Tasks/) to keep them organized. In practice, this lets TaskNotes fit into existing vault habits instead of replacing them. You keep using normal note workflows, and TaskNotes adds structure, filtering, and commands on top. YAML Frontmatter# Task properties are stored in YAML frontmatter, a standard format with broad tool support. Treat frontmatter as the machine-readable layer and the note body as the human-readable layer. TaskNotes automations and Bases filters rely on frontmatter; your project notes and context stay in the body. Property Types# TaskNotes uses several property types: Type Example Description Text title: Buy groceries Single text value List tags: [work, urgent] Multiple values Date due: 2025-01-15 ISO 8601 date format DateTime scheduled: 2025-01-15T09:00 Date with time Link projects: [\"[[Project A]]\"] Obsidian wikilinks Number timeEstimate: 60 Numeric values (minutes) Field Mapping# Property keys are configurable. If your vault uses deadline instead of due, you can map TaskNotes to use your existing field names without modifying your files. The exact rules for how fields map to semantic roles, how dates are interpreted, and how operations like completion and recurrence behave are defined in the TaskNotes Specification. The spec is the shared contract between the Obsidian plugin, the terminal UI, and any other tool that reads or writes TaskNotes data. Custom Fields# Add any frontmatter property to your tasks. User-defined fields work in filtering, sorting, and templates. Define custom fields in Settings -> TaskNotes -> Task Properties to include them in task modals and views. Bases Integration# TaskNotes v4 uses Obsidian's Bases core plugin for its main views. Bases provides: Filtering: Query tasks using AND/OR conditions Sorting: Order tasks by any property Grouping: Organize tasks by status, priority, project, or custom fields Views: Task List, Kanban, Calendar, and Agenda are all Bases views Views are stored as .base files in TaskNotes/Views/. These files contain YAML configuration that defines the view's query and display settings. You can duplicate, modify, or create new views by editing these files. This makes view behavior inspectable and predictable. If a task appears in the wrong place, you can open the .base file and see exactly which filter or grouping rule produced that result. Enabling Bases# Bases is a core plugin included with Obsidian 1.10.1+: Open Settings -> Core Plugins Enable \"Bases\" TaskNotes views will now function"},{"title":"Features","url":"/obsidian/features/","description":"TaskNotes includes task organization, time tracking, and calendar integration features.","product":"obsidian","text":"TaskNotes includes task organization, time tracking, and calendar integration features. Task Management# TaskNotes gives each task a structured set of properties, including status, priority, due and scheduled dates, tags, contexts, and optional estimates. Because these values live in frontmatter, they stay readable and portable while still powering advanced filtering and grouping in Bases. Reminders can be relative (for example, \"3 days before due\") or absolute, and completed tasks can be archived automatically to keep active work surfaces focused. Recurring tasks can stay virtual for lightweight checkoff workflows, or you can materialize individual occurrences into normal task notes when a specific instance needs its own checklist, comments, time tracking, or attachments. Occurrence notes inherit useful planning metadata from the parent while keeping their own completion state and time entries, and calendar views coalesce them with the matching virtual recurrence instance. See Task Management for details. For recurrence behavior, see Recurring Tasks. For reminder setup and data format, see Task Reminders. Filtering and Views# TaskNotes uses Obsidian's Bases engine for filtering, sorting, and grouping. Each view is a .base file, so you can inspect or edit its query logic directly instead of relying on hidden plugin state. This design also makes view customization practical: you can duplicate a default view, tweak grouping or formulas, and keep both versions side by side in your vault. For details on how Bases integration works, see Core Concepts. For Bases syntax documentation, see the official Obsidian Bases documentation. Inline Task Integration# Inline task features let you work from normal notes without context switching. Task links can display interactive cards, checkboxes can be converted into full task notes, and project notes can surface subtasks and dependency relationships in place. Natural language parsing supports date, priority, and context extraction across multiple languages, which helps keep fast capture while preserving structured data. See Inline Task Integration for details. Time Management# Time tracking records work sessions per task, and Pomodoro mode supports focused intervals with break handling. Over time, the statistics views help you compare estimated versus actual effort and spot trends in workload distribution. See Time Management for details. Calendar Integration# TaskNotes supports bidirectional OAuth sync with Google Calendar and Microsoft Outlook, plus read-only ICS subscriptions for external feeds. Calendar views include month, week, day, year, and list modes, and drag-and-drop scheduling can update tasks directly. For planning workflows, time-blocking and calendar-linked task updates connect backlog management with schedule execution in the same workspace. See Calendar Integration for details. User Fields# User fields let you extend the core model with vault-specific metadata like client, energy level, billing code, or review state. Once added, these fields become available in filters, sorting, templates, and formulas. See User Fields for details. Integrations# Beyond calendar sync, TaskNotes includes an HTTP API and webhook support for automation workflows, external dashboards, or custom tooling. See Integrations for details. Companion Plugins# TaskNotes can be extended by optional companion plugins that use the JavaScript runtime API while keeping task data in Markdown files. Canvas Bases is the TaskNotes canvas companion, adding canvas-style boards and JSON Canvas snapshots for Bases views, with optional TaskNotes badges, actions, and relationship edges. TaskNotes Workflows adds Markdown-defined automation for TaskNotes events, schedules, manual commands, and typed task actions. See Companion Plugins for details. REST API# External applications can interact with TaskNotes through its REST API for automation, reporting, and integration with other tools. See HTTP API for details."},{"title":"Calendar Integration","url":"/obsidian/features/calendar-integration/","description":"TaskNotes provides calendar integration through OAuth-connected calendar services, two Bases-powered calendar views, and read-only ICS calendar subscriptions.","product":"obsidian","text":"TaskNotes provides calendar integration through OAuth-connected calendar services, two Bases-powered calendar views, and read-only ICS calendar subscriptions. OAuth Calendar Integration# TaskNotes supports bidirectional synchronization with Google Calendar and Microsoft Outlook using OAuth authentication. This integration allows you to view external calendar events alongside your tasks and sync changes back to the calendar provider. Supported Providers# Google Calendar - OAuth 2.0 authentication with access to all calendars in your Google account Microsoft Outlook - OAuth 2.0 authentication with access to calendars in your Microsoft 365 or Outlook.com account Setup Requirements# OAuth calendar integration requires creating an OAuth application with your calendar provider. This process takes approximately 15 minutes per provider. You will need to: Create an OAuth application in Google Cloud Console or Microsoft Azure Portal Configure redirect URIs and scopes Obtain client ID and client secret Enter credentials in TaskNotes settings (Settings -> TaskNotes -> Integrations, OAuth calendar section) Synchronization Behavior# Events are fetched automatically every 15 minutes Events are also fetched when local changes occur (task creation, updates, rescheduling) Dragging calendar events to new dates/times updates the event in the calendar provider Per-calendar visibility toggles allow selective display of calendars Access tokens are automatically refreshed when expired Token Management# TaskNotes stores OAuth client credentials, access tokens, and refresh tokens in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system and kept separate from TaskNotes' data.json. Tokens are refreshed automatically before expiration. You can revoke account access or forget the saved OAuth app credentials through the integrations settings. Calendar Views# TaskNotes provides Calendar and Mini Calendar views that display tasks alongside OAuth calendar events and ICS subscriptions. Both views support drag-and-drop scheduling. For detailed view documentation, see Calendar Views. Notes linked from recurring external calendar events can be matched either across the loaded event series or only to the selected recurrence instance. Configure this in Integrations settings. Time Entry Editor# TaskNotes includes a time entry editor for tracking time spent on tasks. Time entries are created and managed through the Calendar View. Creating Time Entries# To create a time entry on the Calendar View: Click and drag on a time slot in the calendar to select a time range When the selection menu appears, choose Create time entry (timeblock appears only if the feature is enabled) Choose a task in the task selector modal A time entry is created for that task with the selected start/end range Time entries are always associated with a specific task and stored in that task's frontmatter. Multiple time entries can exist for one task. Managing Time Entries# The time entry editor modal provides functions to: View all time entries for a task Edit the start time, end time, and duration of time entries Delete time entries See the total time tracked across all entries for a task Access the time entry editor by clicking an existing time entry in the calendar. ICS Calendar Subscriptions# TaskNotes can subscribe to external calendar feeds using the iCalendar (ICS) format. This provides read-only access to events from calendar services. ICS subscriptions differ from OAuth calendar integration in that they are read-only—dragging ICS events to new dates does not update the source calendar. Add and manage ICS subscriptions from Settings -> TaskNotes -> Integrations (Calendar Subscriptions section). For details on creating notes and tasks from calendar events, see ICS Integration. Time Blocking# The Calendar View supports time blocking for scheduling dedicated work periods. To create a time block: Click and drag on a time slot in the calendar to select a time range A context menu will appear with available options Select \"Create timeblock\" from the menu (this option only appears if timeblocking is enabled in settings) Time blocks are stored in the frontmatter of daily notes and can be linked to specific tasks. This differs from time entries, which track actual time spent and are stored in task frontmatter rather than daily notes. Enable time blocking under Settings -> TaskNotes -> Features (Timeblocking section)."},{"title":"ICS Calendar Event Integration","url":"/obsidian/features/ics-integration/","description":"TaskNotes can use ICS calendar events to create notes and tasks directly from calendar entries. ICS integration creates linked notes and tasks from event data without manual re-...","product":"obsidian","text":"TaskNotes can use ICS calendar events to create notes and tasks directly from calendar entries. ICS integration creates linked notes and tasks from event data without manual re-entry. Overview# The ICS integration allows you to: View detailed information about calendar events Create notes from calendar events with customizable templates Generate tasks from events with proper scheduling and context Link existing vault content to calendar events Maintain relationships between events and created content Event context, notes, and follow-up tasks remain connected through frontmatter links. Event Information Modal# When you interact with a calendar event in TaskNotes, an information modal displays event details and available actions. The modal provides: Event Details# Event title and description Start and end times (formatted according to your locale) Location information Source calendar name Event URL (if available) Related Content# The modal shows a list of existing notes and tasks that are linked to the calendar event. Content is automatically categorized as: Task - Files containing the configured task tag Note - Files without the task tag The relationship is maintained through the ICS Event ID field in the content's frontmatter. Available Actions# Create Note - Opens a creation dialog for generating a new note from the event data. Create Task - Creates a task immediately using the event information with default settings. Link Note - Opens a file selection dialog to link an existing note to the calendar event. Refresh - Reloads the list of related content to reflect recent changes. Note Creation from Events# The note creation process allows customization of the generated content: Basic Settings# Title - Default combines event title and date, but can be modified Folder - Destination for the new note (uses default ICS note folder if configured) Template - Optional template file to structure the note content Template Usage# When a template is specified: The template file is processed with ICS-specific variables Standard TaskNotes template variables are also available Template content replaces the default event description format Frontmatter from templates is merged with required ICS fields Templates apply a consistent note structure across imported events. Default Content# Without a template, notes include: Event title as the main heading Formatted start and end times Location information Source calendar name Event description (if provided) Event URL (if available) Task Creation from Events# Tasks created from calendar events include relevant event data: Scheduled Date and Time# Tasks are scheduled using the event's start time as an ISO timestamp, preserving both date and time information. This allows for accurate scheduling that reflects the original event timing. Task Properties# Title - Uses the event title Status - Set to the default task status configured in settings Priority - Set to the default task priority Contexts - Event location is added as a context (if provided) Time Estimate - Calculated from event duration (if start and end times are available) Tags - Includes the ICS event tag and any default task tags After creation, priority, status, and schedule can be edited if event data does not match the final task plan. Content# Task content includes formatted event details similar to note creation, providing context about the original calendar event. Linking Existing Content# You can establish connections between existing vault content and calendar events: Link Process# Select an existing markdown file from your vault The file's frontmatter is updated to include the event ID The modification date is updated to reflect the change The connection appears in the related content list Bidirectional References# Calendar events can display all linked content Content files maintain references to their associated events Multiple pieces of content can be linked to a single event Content can be linked to multiple events (stored as an array) Field Mapping Integration# The ICS integration extends the field mapping system with two new fields: ICS Event ID Field# Stores the unique identifier connecting content to calendar events Default field name is icsEventId Values are stored as arrays to support multiple event associations Field name can be customized through field mapping settings ICS Event Tag Field# Tag automatically applied to content created from events Default tag is ics_event Used to identify ICS-related content throughout the system Can be customized through field mapping settings Template Variables# Templates used for ICS content creation have access to event-specific variables in addition to standard TaskNotes variables: Event Information# {{icsEventTitle}} - Event title {{icsEventStart}} - Start date and time (ISO format) {{icsEventEnd}} - End date and time (ISO format) {{icsEventLocation}} - Event location {{icsEventDescription}} - Event description {{icsEventUrl}} - Event URL {{icsEventSubscription}} - Calendar subscription name {{icsEventId}} - Unique event identifier Standard Variables# All standard TaskNotes template variables remain available: {{title}}, {{date}}, {{time}} {{priority}}, {{status}}, {{contexts}} And others as documented in the template system Configuration# ICS integration settings are located under Settings -> TaskNotes -> Integrations: Default Templates# Configure template files for consistent content creation from events. Templates are optional and the system provides sensible defaults when not specified. Default Folders# Set destination folders for content created from events. This helps organize ICS-generated content separately from other vault content if desired. Folder paths support template variables for dynamic organization: Date variables: {{year}}, {{month}}, {{day}}, {{monthName}}, etc. ICS event variables: {{icsEventTitle}}, {{icsEventLocation}}, {{icsEventDescription}} Other variables: See template variables section below Example folder paths: Daily/{{year}}/{{month}}/{{day}} creates date-based hierarchy Events/{{year}}/{{icsEventTitle}} organizes by year and event title Meetings/{{monthName}} groups by month name Filename Formats# The system uses the standard TaskNotes filename generation with event-specific context, ensuring unique and descriptive filenames for created content. Technical Implementation# Event Identification# Calendar events are identified by their unique ICS event ID, which is maintained in the frontmatter of created content. This allows the system to track relationships even if event details change. Content Type Detection# The system distinguishes between tasks and notes by checking for the presence of the configured task tag in the content's frontmatter tags array, rather than relying on file structure or naming conventions. Error Handling# The integration includes error boundaries for network issues, file operations, and template processing. Failed operations provide user feedback without interrupting the overall workflow."},{"title":"Inline Task Integration","url":"/obsidian/features/inline-tasks/","description":"TaskNotes integrates with the Obsidian editor to allow task management directly within notes. This is achieved through interactive widgets, a conversion feature for checkboxes,...","product":"obsidian","text":"TaskNotes integrates with the Obsidian editor to allow task management directly within notes. This is achieved through interactive widgets, a conversion feature for checkboxes, and natural language processing. Inline features support capture and task updates without leaving the current note. Task Link Overlays# When a wikilink to a task note is created, TaskNotes can replace it with an interactive Task Link Overlay. Enable or disable overlays from Settings -> TaskNotes -> Features (Task link overlay). The widget displays information about the task, such as status, priority, and due date, and allows actions like status/priority changes or opening the edit modal. Task link overlays in Live Preview mode show interactive widgets with status, dates, and quick actions In Source mode, task links appear as standard wikilinks until rendered Widget Features# The task link overlay displays: Status Dot: Clickable circular indicator showing current task status. Click to cycle through available statuses. Priority Dot: Color-coded indicator for task priority (only shown when assigned). Task Title: Displays the task name (truncated to 80 characters). Click to open the task edit modal. Date Information: Shows due dates (calendar icon) and scheduled dates (clock icon) with clickable context menus. Recurrence Indicator: Rotating arrow icon for recurring tasks with modification options. Action Menu: Ellipsis icon (shown on hover) provides additional task actions. The widget exposes common task actions at the link location, so status and metadata can be updated in-place. Mode-Specific Behavior# Task link overlays work in both Live Preview and Reading modes: Live Preview Mode: Widgets hide when the cursor is within the wikilink range, allowing for easy editing. Reading Mode: Widgets display with full functionality and integrate with the reading mode typography. The overlays support drag-and-drop to calendar views and provide keyboard shortcuts for quick navigation (Ctrl/Cmd+Click to open the source file). Create New Inline Task Command# The Create new inline task command opens the task creation modal from the editor and inserts a link to the new task when it is saved. This command is available in the command palette. When the cursor is on an empty line, the link is inserted at the cursor. When the cursor is on a line with content, TaskNotes inserts a new line below it and places the task link there. The command does not use the current line as the task title. To turn the current line into a TaskNote, use Convert to TaskNote or the instant conversion button next to a supported line. That flow uses the current line as the task title and replaces the original line with a link to the new task file. Instant Task Conversion# The Instant Task Conversion feature transforms lines in your notes into TaskNotes files. This works with both checkbox tasks and regular lines of text. Turn the feature on or off from Settings -> TaskNotes -> Features (Show convert button next to checkboxes). When enabled, a \"convert\" button appears next to content in edit mode. Clicking this button creates a new task note using the line text as the title and replaces the original line with a link to the new task file. This supports progressive conversion from draft notes to dedicated task files. Folder Configuration# By default, converted tasks are placed in the same folder as the current note ({{currentNotePath}}). You can change this behavior in Settings -> TaskNotes -> General (Folder for converted tasks): Leave empty: Uses your default tasks folder (configured in the same section) {{currentNotePath}}: Places tasks in the same folder as the note you're editing (default) {{currentNoteTitle}}: Creates a subfolder named after the current note Custom path: Specify any folder path (e.g., TaskNotes/Converted) Supported Line Types# The conversion feature works with: Checkbox tasks: - [ ] Task description becomes a TaskNote with task metadata Bullet points: - Some task idea becomes a TaskNote with the text as title Numbered lists: 1. Important item becomes a TaskNote Blockquoted content: > Task in callout becomes a TaskNote (preserves blockquote formatting) Plain text lines: Important thing to do becomes a TaskNote Mixed formats: > - [ ] Task in blockquote handles both blockquote and checkbox formatting Content Processing# When converting lines: Special characters like >, #, - are automatically removed from the task title Original formatting is preserved in the note (e.g., > [[Task Title]] for blockquoted content) Task metadata is extracted from checkbox tasks (due dates, priorities, etc.) Natural language processing can extract dates and metadata from plain text (if enabled) Conversion preserves surrounding formatting, including callouts, outlines, and nested lists. The feature handles edge cases like nested blockquotes and maintains proper indentation in the final link replacement. Bulk Task Conversion# The Bulk Task Conversion command converts all checkbox tasks in the current note to TaskNotes in a single operation. This command is available in the command palette as \"Convert all tasks in note to TaskNotes\". How It Works# The command: Scans the entire current note for checkbox tasks (- [ ], * [ ], 1. [ ], etc.) Includes tasks inside blockquotes (e.g., > - [ ] task in callout) Applies the same enhanced conversion logic as instant task conversion Creates individual TaskNote files for each task Replaces the original checkboxes with links to the new task files Preserves original indentation and formatting (including blockquote markers) The bulk conversion uses the same content processing as instant conversion, automatically removing special characters from task titles while preserving original formatting in the note. Usage# To use bulk conversion: Open a note containing checkbox tasks Access the command palette (Ctrl+P / Cmd+P) Search for \"Convert all tasks in note to TaskNotes\" Execute the command The command displays progress and shows a summary when complete (for example, \"Successfully converted 5 tasks to TaskNotes.\"). Important Considerations **This command modifies note content permanently.** Before using: - **Create a backup** of your note if it contains important data - **Review the tasks** to ensure they should become individual TaskNotes - **Expect processing time** - notes with many tasks may take several seconds to process - **Avoid interruption** - do not edit the note while conversion is running Performance Processing time depends on the number of tasks: - Small notes (1-10 tasks): Near-instant - Medium notes (10-50 tasks): 2-5 seconds - Large notes (50+ tasks): 10+ seconds The operation creates multiple files and updates the note content, which requires disk I/O and editor updates. Error Handling# If some tasks fail to convert, the command will: Complete successfully converted tasks Display a summary showing both successes and failures Log detailed error information to the console for troubleshooting Failed conversions typically occur due to: Tasks with titles containing invalid filename characters Insufficient disk permissions Very long task titles (over 200 characters) For large notes, converting a small section first helps validate folder and filename settings. Relationships Widget# New in v4: The Relationships Widget consolidates what were previously three separate widgets (project subtasks, task dependencies, and blocking tasks) into a single dynamic interface. The widget appears in task notes and automatically displays up to five tabs based on available relationship data: Subtasks Tab (Kanban): Shows tasks that reference the current note as a project. Uses Kanban layout for visual task management. Occurrences Tab (List): Shows materialized occurrence notes that reference the current recurring task as their parent. Uses list layout sorted by occurrence date. Projects Tab (List): Shows projects that the current task belongs to. Uses list layout. Blocked By Tab (List): Shows tasks that are blocking the current task. Uses list layout. Blocking Tab (Kanban): Shows tasks that the current task is blocking. Uses Kanban layout. Automatic Tab Management# Tabs automatically show or hide based on the presence of relationship data. If a task has no subtasks, the Subtasks tab does not appear. If a recurring task has no materialized occurrence notes, the Occurrences tab does not appear. If there are no blocking relationships, those tabs remain hidden. This keeps the interface focused on relevant information. The widget layout changes with available data, so simple tasks show fewer sections. Features# The widget embeds the TaskNotes/Views/relationships.base view directly in the editor. Every filter, grouping rule, or property shown in that .base file is exactly what appears inside the widget, so you can customize the experience by editing the file just like any other Bases view. Additional behavior: Collapsible Interface: Click the widget title to expand or collapse. The state is remembered between sessions. Persistent Grouping: Any grouping defined in the .base file is honoured, and collapsed groups retain their state per note. Task Details: Each task shows its status, priority, due date, and other configured properties. Real-time Updates: The widget updates automatically when tasks are added, modified, or deleted via Bases views. Configuration# Enable or disable the widget in Settings -> TaskNotes -> Appearance (Show relationships widget). Position the widget at the top (after frontmatter) or bottom of the note using the Relationships Position setting. Expandable Subtasks Chevron# Tasks with subtasks can display an expand/collapse chevron that toggles subtask visibility. The chevron can be positioned on the Right (default, hover to show) or on the Left (always visible, matches group chevrons). Configure this in Settings -> TaskNotes -> Appearance (Subtask chevron position). Migration from v3# In v3, TaskNotes provided three separate widgets controlled by individual settings: showProjectSubtasks and projectSubtasksPosition showTaskDependencies and taskDependenciesPosition showBlockingTasks and blockingTasksPosition These settings are replaced in v4 by: showRelationships and relationshipsPosition If you had project subtasks enabled in v3, the relationships widget is enabled automatically after upgrading to v4. The underlying Bases file changed from TaskNotes/Views/project-subtasks.base to TaskNotes/Views/relationships.base. Run the Create files action in Settings -> TaskNotes -> General -> Views & base files if relationships.base is missing. Natural Language Processing# TaskNotes includes a Natural Language Processor (NLP) that parses task descriptions to extract structured data. This allows for task creation from conversational language, such as \"Prepare quarterly report due Friday #work high priority,\" which would automatically set the due date, tag, and priority. The NLP engine supports multiple languages, including English, Spanish, French, German, Italian, Japanese, Dutch, Portuguese, Russian, Swedish, Chinese, and Ukrainian. Supported Syntax# The NLP engine recognizes: Tags and Contexts: #tag and @context syntax (triggers are customizable). Projects: +project for simple projects or +[[Project Name]] for projects with spaces. Priority Levels: Keywords like \"high,\" \"normal,\" and \"low\". Also supports a trigger character (default: !). Status Assignment: Keywords like \"open,\" \"in-progress,\" and \"done\". Also supports a trigger character (default: *). Dates and Times: Phrases like \"tomorrow,\" \"next Friday,\" and \"January 15th at 3pm\". Time Estimates: Formats like \"2h,\" \"30min,\" and \"1h30m\". Recurrence Patterns: Phrases like \"daily,\" \"weekly,\" and \"every Monday\". User-Defined Fields: Custom fields can be assigned using configured triggers (e.g., effort: high). Supports quoted values for multi-word entries. NLP parses common patterns during capture; fields can be refined in the modal afterward. Rich Markdown Editor# New in v4: The task creation modal uses a rich CodeMirror markdown editor instead of a plain textarea. Features include: Live Preview: Rendered markdown preview as you type. Syntax Highlighting: Code blocks, links, and formatting are highlighted. Wikilink Support: Create links to other notes using [[Note Name]] syntax. Keyboard Shortcuts: Ctrl/Cmd+Enter saves the task Esc or Tab to navigate out of the editor Placeholder Text: Shows an example task (e.g., \"Buy groceries tomorrow at 3pm @home #errands\") when the editor is empty. Customizable Triggers# New in v4: Triggers for NLP properties can be customized in Settings -> TaskNotes -> Features (NLP Triggers). You can configure trigger characters or strings for: Tags (default: #) - When set to #, Obsidian's native tag suggester is used Contexts (default: @) Projects (default: +) Status (default: *) Priority (default: !, disabled by default) User-Defined Fields (default: fieldname:) - Each custom field can have its own trigger Triggers support up to 10 characters and can include trailing spaces (e.g., \"def: \" for a custom field). Autocomplete# New in v4: When typing a trigger in the NLP editor, an autocomplete menu appears with available values. Navigate suggestions with arrow keys Select with Enter or Tab Autocomplete works for tags, contexts, projects, status, priority, and user-defined fields Tag autocomplete uses Obsidian's native tag suggester when using the # trigger For user fields with multi-word values, wrap the value in quotes (e.g., effort: \"very high\") The NLP engine is integrated with the task creation modal and bulk conversion features. Typing a natural language description populates the corresponding task fields automatically."},{"title":"Integrations","url":"/obsidian/features/integrations/","description":"TaskNotes integrates with external services and Obsidian's core plugins.","product":"obsidian","text":"TaskNotes integrates with external services and Obsidian's core plugins. Bases Core Plugin# TaskNotes v4 uses Obsidian's Bases core plugin for its main views (Task List, Kanban, Calendar, Agenda). Bases must be enabled in Settings -> Core Plugins. For details on Bases integration, see Core Concepts. External Calendars# TaskNotes supports bidirectional sync with Google Calendar and Microsoft Outlook via OAuth, plus read-only access to any calendar via ICS subscriptions. For setup instructions, see Calendar Integration. HTTP API# A REST API enables external applications to create, update, and query tasks. Use it for automation, browser extensions, or custom integrations. For API documentation, see HTTP API. Webhooks# Webhooks send task event payloads to external services when subscribed events occur. Optional payload transformations support service-specific formats. For configuration, see Webhooks. Companion Plugins# Companion plugins run inside Obsidian alongside TaskNotes and use the JavaScript runtime API for live task operations. They are useful when an integration needs a real Obsidian UI, command-palette commands, or vault-local configuration files. For the companion-plugin model and guides for Canvas Bases and TaskNotes Workflows, see Companion Plugins."},{"title":"Recurring Tasks","url":"/obsidian/features/recurring-tasks/","description":"TaskNotes recurring tasks use RFC 5545 RRule strings with DTSTART support and dynamic next-occurrence scheduling. The model separates recurrence patterns from the next planned i...","product":"obsidian","text":"TaskNotes recurring tasks use RFC 5545 RRule strings with DTSTART support and dynamic next-occurrence scheduling. The model separates recurrence patterns from the next planned instance, and can also create normal task notes for individual occurrences when an instance needs its own content. If you are new to recurring tasks in TaskNotes, think of the recurrence rule as the long-term plan and the scheduled field as the next concrete commitment. Most day-to-day editing affects scheduled, while recurrence editing changes the plan itself. Core Concepts# Recurring tasks operate on two independent levels: Recurring Pattern: Defines when pattern instances appear (controlled by DTSTART in the recurrence rule) Next Occurrence: The specific date/time when you plan to work on the next instance (controlled by the scheduled field) Materialized Occurrence Notes: Optional child task notes for specific occurrence dates, used when an occurrence needs its own checklist, status, time tracking, or body content This separation lets you reschedule the next occurrence without changing the pattern. Setting Up Recurring Tasks# In practice, setup is usually a two-step flow: choose a pattern, then check whether the next scheduled occurrence matches how you actually want to execute the next instance. Creating Recurrence Patterns# You can create recurring tasks through: Recurrence Context Menu in task modals for presets or custom options Preset Options such as daily, weekly, or monthly Custom Recurrence Modal with date/time pickers and RRule configuration Required Components# Recurring tasks require: Recurrence Rule: RRule string with DTSTART Scheduled Date: Next occurrence date (independent from the pattern) Materialized occurrence notes add two system fields to the occurrence note: recurrence_parent: link/path back to the recurring parent task occurrence_date: the occurrence date represented by the note DTSTART Integration# DTSTART is the anchor for pattern generation. It controls where the rule begins and, when time is included, the default time for future pattern instances. Date-only: DTSTART:20250804;FREQ=DAILY Date and time: DTSTART:20250804T090000Z;FREQ=DAILY Recurring Task Due Date# When a recurring task is completed, scheduled advances to the next occurrence. By default, due does not change. Enable Maintain due date offset in recurring tasks in Settings → TaskNotes → Features → Recurring Tasks to preserve due/scheduled spacing. Example: Scheduled: 2025-01-01 Due: 2025-01-03 Recurrence: weekly If the task advances to scheduled: 2025-01-08, the due date becomes 2025-01-10 when this setting is enabled. This setting is most useful when due dates represent a fixed lead/lag relative to scheduled work (for example, \"due two days after execution\"). If due dates are independent deadlines, leaving the setting off is usually clearer. Recurrence Pattern Examples# DTSTART:20250804T090000Z;FREQ=DAILY → Daily at 9:00 AM, starting August 4, 2025 DTSTART:20250804T140000Z;FREQ=WEEKLY;BYDAY=MO,WE,FR → Monday, Wednesday, Friday at 2:00 PM, starting August 4, 2025 DTSTART:20250815;FREQ=MONTHLY;BYMONTHDAY=15 → 15th of each month (all-day), starting August 15, 2025 DTSTART:20250831;FREQ=MONTHLY;BYMONTHDAY=-1 → Last day of each month (all-day), starting August 31, 2025 DTSTART:20250801T100000Z;FREQ=MONTHLY;BYDAY=-1FR → Last Friday of each month at 10:00 AM, starting August 1, 2025 Dynamic Scheduled Dates# The scheduled field automatically tracks the next uncompleted occurrence: Initially set to the DTSTART date Advances when occurrences are completed Recalculates when the rule changes Can be manually rescheduled independently This behavior keeps recurring tasks practical in real planning: you can preserve a stable weekly/monthly pattern while still adapting the immediate next occurrence to calendar realities. Materialized Occurrence Notes# Most recurring tasks can remain virtual: the parent task stores complete_instances and skipped_instances, and TaskNotes renders each calendar/list instance from that parent. Materialized occurrence notes are for heavier instances where the date-specific work needs its own note. Good uses include: A weekly review where each week needs a separate agenda and notes A maintenance task where each visit needs photos, links, or a checklist A recurring meeting where every occurrence should have its own time entries and completion state To create one manually, right-click a recurring task card or calendar occurrence and choose Open or create occurrence note. The Task Action Palette also exposes Open or create occurrence note for recurring tasks. If a matching note already exists for the same parent and date, TaskNotes opens it instead of creating a duplicate. An occurrence note is an ordinary TaskNotes task. It appears in views, can be edited like any other task, and shows an occurrence pill that links back to the recurring parent. On the calendar, a materialized occurrence replaces the matching virtual parent occurrence for the same parent/date pair, so you do not see both the generated instance and the note-backed instance at the same time. Its frontmatter includes: recurrence_parent: \"[[Tasks/Weekly review]]\" occurrence_date: \"2026-06-01\" scheduled: \"2026-06-01T09:30\" timeEstimate: 45 When TaskNotes creates an occurrence note, it copies the parent fields that describe how that instance should be planned: title, priority, scheduled time, due offset, contexts, projects, tags, reminders, dependencies, details, custom properties, and time estimate. Date-like fields are rebased onto the occurrence date, so a parent scheduled at 09:30 creates an occurrence scheduled at 09:30 on the selected date, and a due date one day after the parent scheduled date stays one day after the occurrence scheduled date. Occurrence notes can use a separate template from regular new tasks. Set occurrence_template on the recurring parent to point at a template note, or configure Settings → Features → Body template → Occurrence note template file as a global fallback. Parent-level occurrence_template wins over the global fallback. If neither occurrence-specific template is configured, occurrence note creation keeps the normal body template behavior. The parent task remains the source of the recurrence rule and series history. Occurrence notes do not copy the parent's recurrence, complete_instances, skipped_instances, completedDate, calendar provider IDs, or timeEntries. New time entries belong to the occurrence note once you track time there. Occurrence Filenames# By default, materialized occurrence notes use the existing filename behavior: the parent title followed by a numeric suffix. To opt in to custom filenames, set Occurrence filename template under Settings → Task Properties → Title. For example, {{title}} — {{occurrenceDate}} produces Weekly review — 2026-08-01.md. Occurrence filename templates support all regular filename variables plus these occurrence-specific variables: {{occurrenceDate}} - occurrence date, such as 2026-08-01 {{occurrenceWeek}} - ISO week, such as 2026-W31 {{occurrenceMonth}} - month, such as 2026-08 {{occurrenceYear}} - year, such as 2026 {{occurrenceMonthName}} - full month name, such as August Choose the date granularity explicitly in the template; TaskNotes does not infer it from the recurrence rule. A recurring parent can override the global template with the frontmatter property configured by Occurrence template override property (by default, occurrenceFilenameTemplate): occurrenceFilenameTemplate: \"{{title}} ({{occurrenceWeek}})\" Leaving the global template empty preserves the existing filename behavior. TaskNotes never renames existing occurrence notes, and filename collisions continue to receive a numeric suffix. Occurrence Note Policies# Each recurring parent has an Occurrence notes submenu under its recurrence menu: Create manually: occurrence notes are only created by explicit action. Create next after completion: after you complete a materialized occurrence note, TaskNotes creates the next occurrence note. Rolling window: defined by the TaskNotes spec, but not automated in the plugin yet. When Create next after completion is enabled, creating the first occurrence is still a deliberate action. After that, completing the occurrence note advances the parent recurrence state and materializes the next scheduled occurrence. HTTP API and MCP clients can create occurrence notes without using the desktop context menu. Use POST /api/tasks/:id/materialize-occurrence or the MCP tasknotes_materialize_occurrence tool with a parent task path and occurrence date. Completing a recurring instance through the API or MCP also respects existing occurrence notes and the Create next after completion policy. The same submenu also controls the next-note trigger: Completion only: create the next occurrence note only when the current occurrence is completed. Completion or skip: create the next occurrence note when the current occurrence is completed or skipped. Skip/unskip controls appear on materialized occurrence notes when a skipped status is configured. Skipping an occurrence preserves the note, updates its status, and reconciles the parent skipped_instances list. Completion Reconciliation# When a materialized occurrence note is completed, TaskNotes updates both sides of the relationship: The occurrence note is completed like a normal task. The parent adds the occurrence date to complete_instances. The parent removes that date from skipped_instances if needed. The parent recalculates scheduled to the next uncompleted occurrence. If the parent policy is Create next after completion, TaskNotes creates the next occurrence note idempotently. Uncompleting an occurrence note removes the date from the parent's complete_instances list, but it does not delete later occurrence notes that were already created. Example Behavior# # Initial state recurrence: \"DTSTART:20250804T090000Z;FREQ=DAILY\" scheduled: \"2025-08-04T09:00\" complete_instances: [] # After completing Aug 4 recurrence: \"DTSTART:20250804T090000Z;FREQ=DAILY\" scheduled: \"2025-08-05T09:00\" complete_instances: [\"2025-08-04\"] # After manually rescheduling next occurrence recurrence: \"DTSTART:20250804T090000Z;FREQ=DAILY\" scheduled: \"2025-08-05T14:30\" complete_instances: [\"2025-08-04\"] Calendar Drag and Drop# Calendar interactions follow the same model distinction: drag the concrete next item to reschedule execution, or drag a pattern instance to redefine the recurrence anchor. Recurring tasks can show: Next occurrence (solid border): dragging updates only scheduled Pattern instances (dashed border): dragging updates DTSTART and future pattern instances Materialized occurrence notes: dragging updates the occurrence note's own scheduled or due date like a normal task, without changing the parent's recurrence rule Materialized occurrence notes keep occurrence_date as their identity. If you drag the note for the June 1 occurrence to June 2, it is still the June 1 recurrence instance, now scheduled for June 2. TaskNotes suppresses the June 1 virtual parent event and leaves the June 2 virtual occurrence alone unless that date also has its own materialized note. Completion Tracking# Each occurrence can be completed or skipped independently (task cards, calendar menus, task edit modal completion calendar). Completed instances are stored in: complete_instances: [\"2025-08-04\", \"2025-08-06\", \"2025-08-08\"] Skipped instances are stored in: skipped_instances: [\"2025-08-05\"] When completion changes, scheduled updates to the next uncompleted instance. If a materialized occurrence note exists for a date, that note's own status takes precedence for that occurrence, and TaskNotes reconciles the parent compatibility lists during completion, uncompletion, skip, and unskip actions. This means completion history and next-action planning stay synchronized automatically, without manually advancing recurring tasks. Flexible Scheduling# TaskNotes intentionally allows off-pattern scheduling so recurring tasks can absorb real-world disruptions without rewriting the entire recurrence rule. The next occurrence can be: Before DTSTART Outside the pattern day At a different time than pattern instances Far ahead while pattern continues unchanged Examples# # Early start before DTSTART recurrence: \"DTSTART:20250810T090000Z;FREQ=WEEKLY;BYDAY=MO\" scheduled: \"2025-08-07T14:00\" # Off-pattern next occurrence recurrence: \"DTSTART:20250804T090000Z;FREQ=WEEKLY;BYDAY=MO\" scheduled: \"2025-08-06T15:30\" Timezone Handling# Recurring task logic uses a UTC anchor approach: Pattern generation uses UTC dates DTSTART dates are interpreted as UTC anchors Display adapts to local timezone Prevents common off-by-one date issues In other words, calculations stay stable internally while display remains local, which avoids drift when traveling or sharing vaults across timezones. Backward Compatibility# Recurring behavior remains compatible with older task data, so upgrades do not require manual note rewrites. Legacy RRule strings without DTSTART continue to work using scheduled as anchor Legacy recurrence objects are converted to RRule format Existing tasks continue to function without migration steps Mixed formats are handled transparently"},{"title":"Task Reminders","url":"/obsidian/features/reminders/","description":"TaskNotes reminders use iCalendar VALARM semantics and support both relative and absolute reminder types.","product":"obsidian","text":"TaskNotes reminders use iCalendar VALARM semantics and support both relative and absolute reminder types. The reminders system is designed to support both habit-like workflows (\"always remind me 15 minutes before\") and one-off commitments (\"alert me exactly at this date and time\"). Most users mix both styles depending on the task. Reminder Types# Relative Reminders# Relative reminders trigger from due or scheduled dates. Use relative reminders when you want reminder behavior to stay consistent even when task dates change. Examples: 15 minutes before due date 1 hour before scheduled date 2 days before due date 30 minutes after scheduled date Absolute Reminders# Absolute reminders trigger at a fixed date/time. Use absolute reminders when the reminder itself is tied to a specific moment, independent of task rescheduling. Examples: October 26, 2025 at 9:00 AM Tomorrow at 2:30 PM Next Monday at 10:00 AM Adding Reminders# You can add reminders from: Task Creation Modal Task Edit Modal Task Cards (bell icon) Reminder field context menu From a workflow perspective, task cards and context menus are fastest for quick reminders, while task modals are better for reviewing multiple reminders on the same task. Quick Reminder Options# Common shortcuts are available for both due and scheduled anchors, such as: 5 minutes before 15 minutes before 1 hour before 1 day before Quick options appear only when the anchor date exists. This prevents invalid reminder states and keeps the quick menu focused on options that can be applied immediately. Reminder Data Format# Reminders are stored in YAML frontmatter arrays. Because reminders are stored in frontmatter, they remain portable and scriptable. You can inspect or transform reminder data with any tooling that reads Markdown + YAML. Relative Structure# reminders: - id: \"rem_1678886400000_abc123xyz\" type: \"relative\" relatedTo: \"due\" offset: \"-PT15M\" description: \"Review task details\" Absolute Structure# reminders: - id: \"rem_1678886400001_def456uvw\" type: \"absolute\" absoluteTime: \"2025-10-26T09:00:00\" description: \"Follow up with client\" Field meanings: id: unique identifier type: relative or absolute relatedTo: due or scheduled (relative only) offset: ISO 8601 duration, negative before and positive after (relative only) absoluteTime: ISO 8601 timestamp (absolute only) description: optional message You typically do not need to edit these fields manually, but understanding the structure helps when debugging automation or importing task data. Visual Indicators# Tasks with reminders show a bell icon on task cards. Solid bell indicates active reminders Clicking opens quick reminder actions Reminder UI shows task context (due/scheduled dates and reminder count) These indicators are intended to make reminders discoverable in list-heavy views without opening every task. Default Reminders# Default reminders can be configured in: Settings -> TaskNotes -> Task Properties -> Reminders Defaults are applied to: Manual task creation Instant conversion Natural language task creation Default reminders are useful for recurring habits, such as pre-deadline checks or day-before planning prompts. Technical Notes# Reminders follow iCalendar VALARM concepts with ISO 8601 offsets The reminder property name can be customized through field mapping For settings-level behavior (notification channels, enable/disable state), see Features Settings."},{"title":"Task Management","url":"/obsidian/features/task-management/","description":"This page covers task creation, properties, projects, dependencies, recurring tasks, and reminders. For the underlying architecture, see Core Concepts.","product":"obsidian","text":"This page covers task creation, properties, projects, dependencies, recurring tasks, and reminders. For the underlying architecture, see Core Concepts. Use this page as the operational overview: how tasks are captured, how they are structured, and how relationships/automation behave. Detailed reference content for recurrence and reminders is split into dedicated pages linked near the end. Creating and Editing Tasks# You can create and edit tasks in a variety of ways. The primary method is through the Task Creation Modal, which can be accessed via the \"Create new task\" command or by clicking on dates or time slots in the calendar views. This modal provides an interface for setting all available task properties, including title, status, priority, and due dates. TaskNotes keeps a storage title and a filename-safe title separate. When Store title in filename is enabled, forbidden filename characters are removed from the filename while the task title is preserved whenever it cannot be represented exactly by that filename. With another filename format, such as timestamp or UUID, the full title is stored in frontmatter. For existing tasks, the Quick actions for current task command opens a keyboard-searchable action palette. It includes status, priority, time-tracking, archive, edit, and date actions, including built-in due and scheduled date presets such as today, tomorrow, this weekend, next week, and next month. TaskNotes also supports Natural Language Creation, which allows you to create tasks by typing descriptions in plain English. The built-in parser can extract structured data from phrases like \"Buy groceries tomorrow at 3pm @home #errands high priority.\" In most workflows, users combine both approaches: fast capture with natural language, then occasional structured edits in the modal when more precision is needed. Auto-Suggestions in Natural Language Input# The natural language input field includes auto-suggestion functionality that activates when typing specific trigger characters: @ - Shows available contexts from existing tasks # - Shows available tags from existing tasks + - Shows files from your vault as project suggestions * - Shows available status options (configurable trigger in Settings → Features) In task creation and edit fields, focusing the tags or contexts input also opens the available suggestions immediately, so you can pick from the current vocabulary without typing a first character. Project Suggestions# When typing + in the natural language input, you'll see up to 20 suggestions from your vault's markdown files. The suggestions display additional information to help identify files: project-alpha [title: Alpha Project Development | aliases: alpha, proj-alpha] meeting-notes [title: Weekly Team Meeting Notes] simple-project work-file [aliases: work, office-tasks] Project suggestions search across: File names (basename without extension) Frontmatter titles (using your configured field mapping) Frontmatter aliases Optional filtering by required tags, folders, and a specific frontmatter property/value defined in Settings → Appearance & UI → Project Autosuggest Selecting a project suggestion inserts it as +[[filename]], creating a wikilink to the file while maintaining the + project marker that the natural language parser recognizes. Enhanced Project Auto‑suggester (configurable cards)# Project suggestions can display configurable multi‑row cards and support smarter search. Configure up to 3 rows using a simple token syntax in Settings → Appearance & UI → Project Autosuggest. Properties: file.basename, file.name, file.path, file.parent, title, aliases, and any frontmatter key Flags: n or n(Label) → show the field name/label before the value s → include this field in + search (in addition to defaults) Literals: you can mix in fixed text or emojis between tokens Examples \"{title|n(Title)}\" → Title: Alpha Project \"🔖 {aliases|n(Aliases)}\" → 🔖 Aliases: alpha, proj-alpha \"{file.path|n(Path)|s}\" → include path in + search as well as display it Search behavior Defaults: + search always includes file basename, title (via your field mapping), and aliases |s flag: add more searchable fields on top of the defaults (e.g., file.path or a custom frontmatter key like customer) Fuzzy: optional fuzzy matching can be enabled in settings for broader, multi‑word matches Performance tips Keep rows to three or fewer for clarity and performance (the UI supports up to 3) Prefer specific searchable fields with |s on large vaults Demo Status Suggestions# When typing the status trigger character (default *) in the natural language input, you'll see suggestions for all configured status options: Status suggestions allow quick selection of statuses when creating tasks. For example, typing *in shows \"In Progress\" as a suggestion if that's one of your configured statuses. Clicking a task card's status indicator cycles through statuses in the order configured under Settings → Task Properties → Status. A status can optionally define a specific Next status for forward cycling; otherwise TaskNotes uses the configured order. Statuses marked Skip when cycling are left out of the ordered click cycle, but remain available through menus, suggestions, direct edits, and explicit next-status jumps. Additionally, you can convert any line type in your notes to TaskNotes using the Instant Conversion feature. This works with checkboxes, bullet points, numbered lists, blockquotes, headers, and plain text lines. Task Properties# Tasks store their data in YAML frontmatter with properties for status, priority, dates, contexts, projects, tags, time estimates, recurrence, and reminders. Custom fields can extend this structure. This frontmatter-first design keeps task data editable and portable while supporting consistent behavior across views and widgets. For property types and examples, see Core Concepts. For configuration options, see Task Properties Settings. Projects# TaskNotes supports organizing tasks into projects using note-based linking. Projects are represented as links to actual notes in your vault, allowing you to leverage Obsidian's linking and backlinking features for project management. This model avoids creating a separate project database. Any note can become a project anchor, and task/project relationships remain visible through normal Obsidian link tooling. Project Assignment# Tasks can be assigned to one or more projects through the task creation or editing interface. When creating or editing a task, click the \"Add Project\" button to open the project selection modal. This modal provides fuzzy search functionality to quickly find and select project notes from your vault. Project Links# Projects are stored as wikilinks in the task's frontmatter (e.g., projects: [\"[[Project A]]\", \"[[Project B]]\"]). These links are clickable in the task interface and will navigate directly to the project notes when clicked. Any note in your vault can serve as a project note simply by being linked from a task's projects field. Organization and Filtering# Tasks can be filtered and grouped by their associated projects in all Bases-driven task views. Use the Bases filter editor to add note.projects conditions, and configure the grouping menu to organize Task List or Kanban boards by project. Tasks assigned to multiple projects will appear in each relevant project group, providing flexibility in project-based organization. Project Indicators# TaskCards display visual indicators when tasks are used as projects. These indicators help identify which tasks have other tasks linked to them as subtasks, making project hierarchy visible at a glance. Subtask Creation# Tasks can have subtasks created directly from their context menu. When viewing a task that serves as a project, you can select \"Create subtask\" to create a new task automatically linked to the current project. Dependencies# Task dependencies capture prerequisite work using RFC 9253 terminology. Dependencies are stored in frontmatter as structured objects: blockedBy: - uid: \"[[Operations/Order hardware]]\" reltype: FINISHTOSTART gap: P1D uid references the blocking task, typically through an Obsidian wikilink. reltype is stored with each dependency and defaults to FINISHTOSTART for dependencies created in the UI. gap is optional and uses ISO 8601 duration syntax (for example PT4H or P2D). Whenever a dependency is added, TaskNotes updates the upstream note’s blocking list so the reverse relationship stays synchronized. Removing a dependency automatically clears both sides. Selecting dependencies in the UI# The task creation and edit modals expose “Blocked by” and “Blocking” buttons that launch a fuzzy task selector. The picker only offers valid tasks, excludes the current note, and prevents duplicate entries. The task context menu provides the same selector, enabling dependency management directly from the Task List, Kanban, and calendar views. Task cards show a fork icon whenever a task blocks other work. Clicking it expands an inline list of downstream tasks without triggering the parent card’s modal, so you can inspect dependents in place. These controls currently create and manage finish-to-start style blockers. Advanced reltype values and gap data are preserved in frontmatter, but blocking evaluation is currently based on whether unresolved dependencies exist rather than relationship-type-specific scheduling rules. Automation# Auto-Archiving# TaskNotes can automatically archive tasks when they transition into a status that has auto-archiving enabled. This keeps completed work out of your active lists without requiring manual cleanup. Configure auto-archiving per status from Settings → Task Properties → Task Statuses. Each status card includes an Auto-archive toggle and a Delay (minutes) input (1–1440). When you turn the toggle on for a status, any task moved into that status is queued for archiving once the delay elapses. Moving the task to a different status before the timer expires cancels the pending archive automatically. The auto-archive queue runs in the background and persists across plugin restarts. If TaskNotes was closed while an archive was pending, the task will be archived shortly after the plugin loads again as long as it still matches the configured status. This automation is intended to keep active views focused without manual cleanup, while still preserving archived task history in your vault. File Management and Templates# TaskNotes supports configurable task folder locations, filename generation patterns, archive behavior, and body templates for newly created tasks. These settings let you align task files with existing vault conventions (for example, date-based folders, project-based routing, or template-driven task note scaffolds). For configuration details, see Task Defaults.For template variables, see Template Variables Reference. Recurring Tasks# TaskNotes recurring tasks use RFC 5545 RRule syntax with DTSTART, separate pattern definition from next occurrence scheduling, and support independent instance completion. When an individual recurrence needs its own checklist, time entries, or notes, you can create a materialized occurrence note from the task or calendar context menu. For full behavior, examples, and edge cases, see Recurring Tasks. Task Reminders# Task reminders support relative offsets from due/scheduled dates and absolute date-time reminders. You can add reminders from task modals, task cards, and context menus. For full setup, data format, defaults, and UI behavior, see Task Reminders."},{"title":"Template Variables Reference","url":"/obsidian/features/template-variables/","description":"TaskNotes supports template variables for dynamic content generation in body templates, folder paths, and filenames. Variables use the {{variableName}} syntax and are replaced w...","product":"obsidian","text":"TaskNotes supports template variables for dynamic content generation in body templates, folder paths, and filenames. Variables use the {{variableName}} syntax and are replaced with actual values when content is created. Overview# Template variables are available in three contexts: Body templates - Content templates for task and note files Folder templates - Dynamic folder paths for file organization Filename templates - Dynamic filename generation Not all variables are available in every context. The tables below indicate where each variable can be used. Task Properties# Variables for task-specific data. Variable Description Body Folder Example {{title}} Task title Yes Yes My Task {{titleLower}} Title in lowercase Yes Yes my task {{titleUpper}} Title in uppercase Yes Yes MY TASK {{titleSnake}} Title in snake_case Yes Yes my_task {{titleKebab}} Title in kebab-case Yes Yes my-task {{titleCamel}} Title in camelCase Yes Yes myTask {{titlePascal}} Title in PascalCase Yes Yes MyTask {{priority}} Task priority value Yes Yes high {{priorityShort}} First character of priority (uppercase) Yes Yes H {{status}} Task status value Yes Yes active {{statusShort}} First character of status (uppercase) Yes Yes A {{context}} First context from contexts array No Yes work {{contexts}} All contexts (comma-separated in body, / in folder) Yes Yes work, home or work/home {{project}} First project from projects array No Yes ProjectA {{projects}} All projects joined by / No Yes ProjectA/ProjectB {{projectFilePath}} Full path of the first project, without .md No Yes Work/Projects/ProjectA {{projectFilePaths}} Full paths of all projects, joined by / No Yes Work/Alpha/Personal/Beta {{projectFolder}} Folder containing the first project note (its file path without the note's own name) No Yes Work/Projects {{projectFolders}} Folders of all projects, joined by / No Yes Work/Personal {{dueDate}} Task due date Yes Yes 2025-01-15 {{scheduledDate}} Task scheduled date Yes Yes 2025-01-10 Body Template Only# Variables available only in body templates (not folder templates). Variable Description Example {{details}} User-provided details/description Task description text {{parentNote}} Parent note name/path where task was created Projects/MyNote {{tags}} Task tags (comma-separated) urgent, review {{hashtags}} Task tags as space-separated hashtags #urgent #review {{timeEstimate}} Time estimate in minutes 30 Date and Time# Variables for current date and time values. Variable Description Format Example {{date}} Full current date YYYY-MM-DD 2025-01-07 {{year}} Current year YYYY 2025 {{shortYear}} Short year YY 25 {{month}} Current month MM 01 {{day}} Current day DD 07 {{monthName}} Full month name - January {{monthNameShort}} Abbreviated month name - Jan {{dayName}} Full day name - Tuesday {{dayNameShort}} Abbreviated day name - Tue {{week}} Week number of year WW 02 {{quarter}} Quarter of year Q 1 {{shortDate}} Compact date YYMMDD 250107 Time Variables# Variable Description Format Example {{time}} Current time (compact) HHmmss 143052 {{time24}} 24-hour time HH:mm 14:30 {{time12}} 12-hour time with AM/PM hh:mm a 02:30 PM {{hour}} Current hour (24-hour) HH 14 {{hourPadded}} Hour with leading zero HH 14 {{hour12}} Hour in 12-hour format hh 02 {{minute}} Current minute mm 30 {{second}} Current second ss 52 {{ampm}} AM/PM indicator a PM Timestamps# Variable Description Format Example {{timestamp}} Date and time combined YYYY-MM-DD-HHmmss 2025-01-07-143052 {{dateTime}} Date and time (no seconds) YYYY-MM-DD-HHmm 2025-01-07-1430 {{unix}} Unix timestamp (seconds) - 1736264852 {{unixMs}} Unix timestamp (milliseconds) - 1736264852000 {{milliseconds}} Current milliseconds SSS 123 {{ms}} Milliseconds (alias) SSS 123 Timezone# Variable Description Example {{timezone}} Timezone offset +01:00 {{timezoneShort}} Short timezone offset +0100 {{utcOffset}} UTC offset +01:00 {{utcOffsetShort}} Short UTC offset +0100 {{utcZ}} UTC Z indicator Z Unique Identifiers# Variable Description Example {{zettel}} Zettelkasten-style ID (date + seconds since midnight in base36) 250107abc {{nano}} Unique nano ID (timestamp + random string) 1736264852000x7k2m ICS Calendar Event Variables# Variables for content created from ICS calendar events. Available when creating notes or tasks from calendar events. Event Information# Variable Description Body Folder {{icsEventTitle}} Event title Yes Yes {{icsEventTitleLower}} Event title lowercase No Yes {{icsEventTitleUpper}} Event title uppercase No Yes {{icsEventTitleSnake}} Event title in snake_case No Yes {{icsEventTitleKebab}} Event title in kebab-case No Yes {{icsEventTitleCamel}} Event title in camelCase No Yes {{icsEventTitlePascal}} Event title in PascalCase No Yes {{icsEventStart}} Event start time (ISO format) Yes No {{icsEventEnd}} Event end time (ISO format) Yes No {{icsEventLocation}} Event location Yes Yes {{icsEventDescription}} Event description Yes Yes {{icsEventUrl}} Event URL Yes No {{icsEventSubscription}} Calendar subscription name Yes No {{icsEventId}} Unique event identifier (UUID) Yes No Current Note Folder Variables# Variables available for inline-created tasks and the default tasks folder. Variable Description Example {{currentNotePath}} Path to the current note's folder Projects/Notes {{currentNoteTitle}} Title/name of the current note Meeting Notes Examples# Body Template# --- created: {{date}} priority: {{priority}} status: {{status}} --- # {{title}} {{details}} Created from: {{parentNote}} Tags: {{hashtags}} Folder Template# Organize tasks by project and status: Tasks/{{project}}/{{status}} Result: Tasks/MyProject/active Organize by date hierarchy: Daily/{{year}}/{{month}}/{{day}} Result: Daily/2025/01/07 Organize ICS events by year and title: Events/{{year}}/{{icsEventTitleKebab}} Result: Events/2025/team-meeting Filename Template# Using Zettelkasten ID: {{zettel}}-{{titleKebab}} Result: 250107abc-my-task.md Using timestamp: {{shortDate}}-{{title}} Result: 250107-My Task.md Notes# YAML Safety# When used in YAML frontmatter, values containing special characters (colons, brackets, quotes) are automatically quoted to prevent parsing errors. Folder Path Sanitization# In folder templates, title values have filesystem-unsafe characters (<>:\"/\\|?*) replaced with underscores to ensure valid paths. Project file path variables preserve folder separators and sanitize unsafe characters within each path segment. Empty Values# If a variable references data that isn't available (e.g., {{project}} when no project is set), it resolves to an empty string. Case Transformations# The case transformation variables work as follows: Transform Input Output titleLower My Task Name my task name titleUpper My Task Name MY TASK NAME titleSnake My Task Name my_task_name titleKebab My Task Name my-task-name titleCamel My Task Name myTaskName titlePascal My Task Name MyTaskName"},{"title":"Time Management","url":"/obsidian/features/time-management/","description":"TaskNotes includes features for time tracking and productivity, such as a time tracker and a Pomodoro timer.","product":"obsidian","text":"TaskNotes includes features for time tracking and productivity, such as a time tracker and a Pomodoro timer. Time Tracking# TaskNotes has a time tracker to record the time spent on each task. Time tracking information is stored in the timeEntries array within each task's YAML frontmatter. Each time entry includes a start time and an end time. The time tracking interface includes controls to start and stop tracking in task views and task cards. TaskNotes prevents duplicate active sessions on the same task. Active sessions on different tasks can exist at the same time, and total time spent on each task is calculated from completed sessions. Auto-Stop Time Tracking# TaskNotes can automatically stop time tracking when a task is marked as completed. This feature ensures that time tracking data accurately reflects work completion without requiring manual timer management. The auto-stop feature works by monitoring task status changes across all views and interfaces. When a task's status changes from any non-completed state to a completed state (as defined by the custom status configuration), any active time tracking session for that task is automatically terminated. Configuration Options: Configure these under Settings -> TaskNotes -> Features (Time Tracking section). Auto-stop tracking - Enable or disable the automatic stopping behavior (enabled by default) Completion notification - Show a notice when auto-stop occurs (disabled by default) Behavior: Monitors all task status changes in real-time Stops only the specific task that was completed (other active timers continue) Preserves the recorded time data in the task's time entries Works with both standard and recurring task completions Functions across all task views (list, kanban, calendar, etc.) The feature integrates with the custom status system, so completion detection respects your configured workflow statuses rather than relying on hardcoded completion states. Pomodoro Timer# TaskNotes also includes a Pomodoro timer, which is a tool for time management that uses a timer to break down work into intervals, separated by short breaks. The Pomodoro timer in TaskNotes has a dedicated view with controls to start, stop, and reset the timer. When a task is associated with a Pomodoro session, the time is automatically recorded in the task's time tracking data upon completion of the session. Productivity Analytics# The Pomodoro Stats View provides analytics and historical data about your Pomodoro sessions. This includes a history of completed sessions, as well as metrics like completion rates and total time spent on tasks. The data can be visualized to show productivity patterns over time."},{"title":"User Fields","url":"/obsidian/features/user-fields/","description":"TaskNotes allows you to define your own custom fields for tasks. This feature allows you to add custom data to your tasks and use it for filtering, sorting, and grouping. User f...","product":"obsidian","text":"TaskNotes allows you to define your own custom fields for tasks. This feature allows you to add custom data to your tasks and use it for filtering, sorting, and grouping. User fields can store workflow-specific metadata such as owner, effort class, client, or review stage. Creating User Fields# User fields are created in the TaskNotes settings, under the \"Task Properties\" tab. To create a new user field, click the \"Add new user field\" button. Fields that are not used in filters or grouping still add frontmatter overhead, so this section focuses on fields used in views. Each user field has the following properties: Display Name: The name of the field as it will be displayed in the UI. Property Name: The name of the field as it will be stored in the frontmatter of the task note. Type: The data type of the field. The following types are supported: Text: A single line of text. Number: A numeric value (supports ranges in filters and sorting). Boolean: A true/false value stored as a checkbox in the task modal. Date: A date. List: A list of values. Default Value (optional): A default value to pre-fill when creating new tasks. The input format depends on the field type: Text: Enter the default text value. Number: Enter the default number. Boolean: Toggle to set the default state (checked/unchecked). Date: Select from presets: None, Today, Tomorrow, or Next Week. List: Enter comma-separated default values. Link Values# Use a Text field for one related link, such as a pull request or specification, and a List field for multiple related links. Task cards render wikilinks, markdown links, angle-bracket autolinks, and bare https:// URLs as clickable links. For internal note links, type [[ in a text or list field to use the same file suggestions as other TaskNotes link fields. Autosuggestion filters can narrow those note suggestions without changing how the stored field value is filtered, sorted, or grouped. File Suggestion Filtering (Advanced)# When using text or list type custom fields, you can configure autosuggestion filters to control which files appear in the autocomplete dropdown when you type [[ in the field. This is useful when you want to limit suggestions to specific types of notes. For example: An \"Assignee\" field that only suggests notes tagged with #person A \"Project\" field that only shows notes in the Projects/ folder A \"Related Document\" field filtered by a specific frontmatter property Filtering narrows wikilink suggestions in large vaults. Configuring Filters# To configure filters for a custom field: Go to Settings → Task Properties → Custom User Fields Expand the custom field card you want to configure Expand the \"Autosuggestion filters (Advanced)\" section Configure one or more of the following filters: Filter Options# Required tags: Only show files that have ANY of these tags (comma-separated) Example: person, team - shows files with either #person OR #team tag Supports hierarchical tags: project/active matches #project/active Include folders: Only show files in these folders (comma-separated) Example: People/, Teams/ - shows files in either folder Supports nested folders: Projects/Active/ matches files in that specific folder Required property key: Only show files that have this frontmatter property Example: role - shows files with a role: property in frontmatter Required property value: Expected value for the property (optional) Example: developer - when combined with property key role, shows files with role: developer Leave empty to match any value (just checks property exists) Filter Indicator# When filters are configured, a \"Filters On\" badge with a funnel icon appears next to the section title. This prevents you from forgetting that filters are active. Filter Behavior# All filters are combined with AND logic: Files must match ALL configured filters to appear Empty filters are ignored: If you don't configure a filter, it won't restrict results No filters = all files: If no filters are configured, all markdown files in your vault will appear Filters only affect autocomplete: They don't affect the actual field value or validation Autocomplete filtering and stored field values are handled independently. Example Configurations# Assignee Field (People Only)# Display Name: Assignee Property Key: assignee Type: List Autosuggestion filters: Required tags: person Include folders: People/ Project Field (Active Projects)# Display Name: Project Property Key: project Type: Text Autosuggestion filters: Required tags: project Required property key: status Required property value: active Related Note (Specific Folder)# Display Name: Related Note Property Key: related-note Type: Text Autosuggestion filters: Include folders: Documentation/, Guides/ Using User Fields# Once you have created a user field, it will be available in the following places: Task Modals: The user field will be displayed in the task creation and edit modals. Bases Filters: Add the field to Bases filter expressions (for example note.effort == \"high\") to narrow task lists and Kanban boards. Sorting: Use the Bases sort menu to order tasks by the user field. Grouping: Use the Bases group menu to create swimlanes or list groupings based on the user field. To verify a new field is active in workflow, add it to at least one saved view. Frontmatter# User field data is stored in the frontmatter of the task note. The property name you define for the user field is used as the key in the frontmatter. For example, if you create a user field with the property name \"my_field\", the data for that field will be stored in the frontmatter as follows: --- my_field: value ---"},{"title":"Adopt TaskNotes in an existing vault","url":"/obsidian/getting-started/existing-vault/","description":"Adopt TaskNotes in a vault that already contains tasks, tags, and custom frontmatter without rewriting everything first.","product":"obsidian","text":"TaskNotes can use your current folders and property names. Configure identification and field mapping before creating or converting tasks so the first write follows your vault conventions. 1. Back up the vault# Make a complete vault backup, including the hidden .obsidian directory. The task notes themselves are Markdown, while TaskNotes settings live in .obsidian/plugins/tasknotes/data.json. 2. Inspect a representative note# Choose one existing task and record: The property or tag that distinguishes tasks from ordinary notes The property names used for title, status, priority, due date, and scheduled date Whether contexts and tags are stored with or without display prefixes The folder patterns that should be included or excluded Canonical frontmatter values do not include natural-language trigger characters. Store office, not @office, and review, not #review. --- type: task status: open contexts: - office tags: - review --- 3. Choose task identification# Open Settings → TaskNotes → General. Choose Tag if every task contains one identifying tag, such as task. Choose Property if a property/value pair identifies tasks, such as type: task. Add archive, template, attachment, or other non-task locations to Excluded folders. Task identification controls indexing and every generated Base filter. Confirm it before regenerating Base files. 4. Map properties# Open Settings → TaskNotes → Task properties and map TaskNotes fields to the names already used in your notes. Avoid creating two properties for one concept, such as both due and deadline. Start with title, status, priority, due, scheduled, projects, contexts, and recurrence. Use the property types reference to check value shapes. 5. Test one note# Open one existing note and confirm that TaskNotes recognizes it. Use TaskNotes: Quick actions for current task and make a reversible edit, such as changing priority. Inspect the frontmatter before testing a larger set. If the note is not recognized, use the troubleshooting decision tree. 6. Generate views from the final mapping# Open Settings → TaskNotes → General → Views & base files and create or update the default Base files. Generated filters and columns use the current task identifier and field mapping. The update action replaces configured default Base files. Copy any customized Base to a new filename before updating it. 7. Convert incrementally# Convert or edit a small group first. Keep normal version-control or backup checkpoints between batches. Existing notes do not need to move into the default TaskNotes/Tasks folder if your storage and exclusion settings already cover their location."},{"title":"Obsidian mobile guide","url":"/obsidian/getting-started/mobile/","description":"What is shared between TaskNotes desktop and mobile, and which integrations differ on mobile.","product":"obsidian","text":"TaskNotes task files, Base files, settings, and most commands work on Obsidian mobile. Sync the complete vault, including .base files and .obsidian/plugins/tasknotes/data.json, when you want the same configuration on every device. Before opening TaskNotes# Install an Obsidian mobile version compatible with the current TaskNotes requirement. Enable the Bases core plugin. Confirm the TaskNotes plugin and its data.json have finished syncing before changing settings. Open a small default Base first and allow the initial index to finish. Mobile differences# Area Mobile behavior HTTP API and MCP server Desktop only. The HTTP API settings section is hidden on mobile. Calendar integrations Available, with an option to disable calendar integration on mobile when startup time or provider behavior is a problem. Settings layout Uses the same six tabs. Desktop-only controls are omitted where they cannot run. Keyboard commands Commands remain available in the command palette; desktop key bindings may not have a mobile equivalent. Wide views Calendar, Kanban, and large tables may require horizontal scrolling or a narrower Base configuration. A practical mobile setup# Keep task cards compact under Settings → Appearance and UI. Limit visible Base columns and calendar event layers. Increase remote calendar refresh intervals when mobile networking or battery use matters. Use the task creation modal or command palette for predictable capture. Keep HTTP automation on a desktop Obsidian instance. If mobile stops loading tasks# Wait for vault sync to finish, confirm Bases is enabled, and run TaskNotes: Refresh cache. Then reopen the affected Base. If the problem is isolated to calendar data, enable Disable calendar integration on mobile and restart Obsidian before investigating the provider connection on desktop."},{"title":"Backup, restore, and removal","url":"/obsidian/guides/backup-recovery/","description":"Back up, restore, reset, and uninstall TaskNotes while protecting task notes, views, settings, and integration data.","product":"obsidian","text":"TaskNotes keeps task content in your vault and configuration in the plugin data file. A complete backup includes both. What to back up# Data Typical location Why it matters Task notes Your configured task folders Titles, properties, details, recurrence, and time entries Base views TaskNotes/Views/ or custom paths Filters, formulas, layout, and custom views Plugin settings .obsidian/plugins/tasknotes/data.json Field mapping, statuses, defaults, integrations, and view command paths Daily notes Your daily-note folder Pomodoro history when daily-note storage is enabled mdbase configuration tasknotes.yaml, mdbase.yaml, or .mdbase/ when configured Shared collection and schema configuration Treat data.json as sensitive because integration configuration can include credentials or tokens. Store backups accordingly. Create a restorable backup# Close Obsidian or disable TaskNotes so settings are not being written. Copy the entire vault, including hidden files. Verify the backup contains .obsidian/plugins/tasknotes/data.json. Keep at least one version from before a migration or bulk edit. File-history sync is useful, but it is not a substitute for a separate tested backup. Restore# Close Obsidian. Restore task notes and Base files first. Restore .obsidian/plugins/tasknotes/data.json if you also need the previous settings. Reopen Obsidian and confirm Bases is enabled. Run TaskNotes: Refresh cache and open one default Base. If provider credentials have expired or were intentionally excluded from the backup, reconnect those integrations instead of restoring stale tokens. Reset configuration safely# Do not delete data.json as a first troubleshooting step. Close Obsidian. Rename data.json to data.json.backup-YYYY-MM-DD. Reopen Obsidian and test with fresh defaults. Restore the backup while Obsidian is closed if the reset does not help. A reset affects settings, configured statuses and priorities, integration state, saved views, and plugin-stored Pomodoro history. It does not delete task Markdown files. Uninstall# Disabling or uninstalling TaskNotes leaves task notes and .base files in the vault. After uninstalling, remove generated folders only if you have inspected them and confirmed they contain no content you want to keep. To remove plugin settings as well, close Obsidian and remove .obsidian/plugins/tasknotes/ after making a backup. Task metadata remains readable YAML, but TaskNotes-specific Base view types and interactive widgets will no longer render. Recovery checklist# Missing tasks: restore the note files, then verify task identification and excluded folders. Missing settings: restore data.json with Obsidian closed. Broken default views: regenerate them from General → Views & base files. Broken custom views: restore the individual .base files from history. Lost Pomodoro history: restore the configured storage source, which may be plugin data or daily-note frontmatter."},{"title":"Build a custom Base","url":"/obsidian/guides/custom-bases/","description":"Create a custom Obsidian Base for TaskNotes while keeping generated defaults safe and upgradeable.","product":"obsidian","text":"TaskNotes views are ordinary Obsidian .base files. The safest workflow is to copy a generated Base, give it a new path, and customize the copy. Start from a copy# Open TaskNotes/Views/ in the file explorer. Duplicate the closest default, such as tasks-default.base. Rename the copy, for example work-tasks.base. Open the copy and make changes with the Bases interface or source editor. Avoid editing the only copy of a generated default. Update default base files replaces the files configured as defaults. Preserve task identification# Every task view needs a filter that matches the identification method in Settings → TaskNotes → General. For tag identification: filters: and: - file.hasTag(\"task\") For property identification: filters: and: - note[\"type\"] == \"task\" Also preserve any excluded-folder conditions generated from your settings. Add a focused view# This example starts with recognized tasks, then limits the view to the work context: filters: and: - file.hasTag(\"task\") - list(contexts).contains(\"work\") views: - type: tasknotesTaskList name: Work order: - status - priority - due - file.name sort: - column: due direction: ASC Use canonical stored values in filters. Natural-language prefixes such as @ and # are input syntax, not part of stored context and tag values. Point a command at the custom Base# Open Settings → TaskNotes → General → View commands and change the relevant command path. Resetting that mapping returns it to the generated default path. Upgrade safely# When TaskNotes ships improved templates: Keep your custom file at its own path. Run Update default base files. Compare the regenerated default with your copy. Bring across only the formulas, filters, or view options you want. The generated template reference always reflects the current source and default field mapping. Recovery# If a custom Base no longer opens, validate its YAML indentation and remove the most recent filter or formula change. You can create a fresh default from settings at any time, then copy your custom view into it one section at a time."},{"title":"TaskNotes HTTP API","url":"/obsidian/HTTP_API/","description":"The TaskNotes HTTP API provides local HTTP access to tasks, time tracking, pomodoro, calendars, webhooks, and NLP parsing.","product":"obsidian","text":"The TaskNotes HTTP API provides local HTTP access to tasks, time tracking, pomodoro, calendars, webhooks, and NLP parsing. Availability# Desktop only Disabled by default Started when Obsidian starts and TaskNotes API is enabled Bound to loopback (127.0.0.1) only, not the local network Browser CORS requests are allowed only from loopback origins such as localhost, 127.0.0.1, and [::1] Not available on mobile Enable it in Settings -> TaskNotes -> Integrations -> HTTP API. Base URL# http://localhost:{PORT} Default port is 8080. Authentication# Authentication is optional. If apiAuthToken is empty, all API requests are accepted. If apiAuthToken is set, send Authorization: Bearer . Set a token for any workflow where local browser pages, scripts, or other desktop apps are not fully trusted. Example: curl -H \"Authorization: Bearer YOUR_TOKEN\" http://localhost:8080/api/health Response Format# Success: { \"success\": true, \"data\": {} } Error: { \"success\": false, \"error\": \"Error message\" } Endpoint Index# System# GET /api/health GET /api/docs GET /api/docs/ui POST /api/nlp/parse POST /api/nlp/create Tasks# GET /api/tasks POST /api/tasks GET /api/tasks/:id PUT /api/tasks/:id DELETE /api/tasks/:id POST /api/tasks/:id/toggle-status POST /api/tasks/:id/archive POST /api/tasks/:id/complete-instance POST /api/tasks/:id/materialize-occurrence POST /api/tasks/query GET /api/filter-options GET /api/stats Bases# POST /api/bases/default-files/update Time Tracking# POST /api/tasks/:id/time/start POST /api/tasks/:id/time/start-with-description POST /api/tasks/:id/time/stop GET /api/tasks/:id/time GET /api/time/active GET /api/time/summary Pomodoro# POST /api/pomodoro/start POST /api/pomodoro/stop POST /api/pomodoro/pause POST /api/pomodoro/resume GET /api/pomodoro/status GET /api/pomodoro/sessions GET /api/pomodoro/stats Calendars# GET /api/calendars GET /api/calendars/google GET /api/calendars/microsoft GET /api/calendars/subscriptions GET /api/calendars/events Webhooks# POST /api/webhooks GET /api/webhooks DELETE /api/webhooks/:id GET /api/webhooks/deliveries See docs/webhooks.md for event and transform details. Route Details# Health# GET /api/health# Returns service state plus vault metadata. curl http://localhost:8080/api/health Tasks# GET /api/tasks# Basic task listing with pagination only. Query params: limit (default 50, max 200) offset (default 0) Important: Filtering params such as status, priority, tag, project, context, due_before, due_after, overdue, completed, archived, and sort are rejected on this endpoint with HTTP 400. Use POST /api/tasks/query for filtering. Example: curl \"http://localhost:8080/api/tasks?limit=25&offset=0\" Response fields: data.tasks data.pagination with total, offset, limit, hasMore data.vault data.note Task objects include configured TaskNotes user fields in customProperties, keyed by their frontmatter property key. POST /api/tasks# Create one task. Required: title Common optional fields: details, status, priority, due, scheduled tags, contexts, projects recurrence, recurrence_anchor, timeEstimate, reminders blockedBy blockedBy accepts an array of dependency objects: uid: link or identifier for the blocking task, such as [[Project setup]] reltype: one of FINISHTOSTART, FINISHTOFINISH, STARTTOSTART, or STARTTOFINISH gap: optional ISO 8601 duration, such as P1D blocking is a read-only reverse relationship in API responses. To make a task block existing tasks, update those existing tasks' blockedBy fields. curl -X POST http://localhost:8080/api/tasks \\ -H \"Content-Type: application/json\" \\ -d '{\"title\":\"Review docs\",\"priority\":\"high\",\"blockedBy\":[{\"uid\":\"[[Draft docs]]\",\"reltype\":\"FINISHTOSTART\"}]}' Returns HTTP 201 with created task data. GET /api/tasks/:id# Get one task by path id. :id must be URL-encoded task path. Single-task reads include the task body in details. Configured TaskNotes user fields are returned in customProperties, keyed by their frontmatter property key. curl \"http://localhost:8080/api/tasks/TaskNotes%2FTasks%2FReview%20docs.md\" PUT /api/tasks/:id# Update task with partial payload. Configured TaskNotes user fields can be updated either by their frontmatter property key or via customProperties. curl -X PUT \"http://localhost:8080/api/tasks/TaskNotes%2FTasks%2FReview%20docs.md\" \\ -H \"Content-Type: application/json\" \\ -d '{\"status\":\"in-progress\"}' DELETE /api/tasks/:id# Delete task file. POST /api/tasks/:id/toggle-status# Toggle task status via configured workflow. POST /api/tasks/:id/archive# Toggle archive state. POST /api/tasks/:id/complete-instance# Complete recurring instance. Request body: Optional date (ISO string). If omitted, uses current date context. When the recurring parent uses materialized occurrence notes, this endpoint completes the matching occurrence note if one exists. If the parent is set to Create next after completion and no matching occurrence note exists yet, TaskNotes creates and completes that occurrence note instead of only recording a virtual complete_instances entry. POST /api/tasks/:id/materialize-occurrence# Create or return a materialized occurrence note for a recurring task date. This endpoint is idempotent for the same parent and date. Request body: Required date (ISO date string, for example 2026-06-01) POST /api/tasks/query# Advanced filtering. Request body is a FilterQuery object. FilterQuery is still the supported advanced query shape for the HTTP API. The root object is a group with: type: \"group\" id conjunction: \"and\" | \"or\" children (conditions or groups) Optional top-level query options: sortKey, sortDirection groupKey, subgroupKey Example: { \"type\": \"group\", \"id\": \"root\", \"conjunction\": \"and\", \"children\": [ { \"type\": \"condition\", \"id\": \"c1\", \"property\": \"status\", \"operator\": \"is\", \"value\": \"open\" } ], \"sortKey\": \"due\", \"sortDirection\": \"asc\" } Filter tasks by context: { \"type\": \"group\", \"id\": \"root\", \"conjunction\": \"and\", \"children\": [ { \"type\": \"condition\", \"id\": \"context\", \"property\": \"contexts\", \"operator\": \"contains\", \"value\": \"@office\" } ], \"sortKey\": \"due\", \"sortDirection\": \"asc\" } Filter active, unarchived tasks, similar to the default available-task view: { \"type\": \"group\", \"id\": \"root\", \"conjunction\": \"and\", \"children\": [ { \"type\": \"condition\", \"id\": \"not-archived\", \"property\": \"archived\", \"operator\": \"is-not-checked\" }, { \"type\": \"condition\", \"id\": \"not-completed\", \"property\": \"status.isCompleted\", \"operator\": \"is-not-checked\" } ], \"sortKey\": \"due\", \"sortDirection\": \"asc\", \"groupKey\": \"none\" } Condition fields: type: \"condition\" id: any stable string for your client property: a task property, such as title, status, priority, tags, contexts, projects, blockedBy, blocking, due, scheduled, completedDate, dateCreated, dateModified, archived, hasSubtasks, dependencies.isBlocked, dependencies.isBlocking, timeEstimate, recurrence, or status.isCompleted operator: one of is, is-not, contains, does-not-contain, is-before, is-after, is-on-or-before, is-on-or-after, is-empty, is-not-empty, is-checked, is-not-checked, is-greater-than, is-less-than, is-greater-than-or-equal, or is-less-than-or-equal value: required for comparison operators, omitted for empty/checked operators For user-defined fields, use property: \"user:\". Response: data.tasks data.total data.filtered data.vault GET /api/filter-options# Returns filter options for UI builders. GET /api/stats# Returns summary counts: total, completed, active, overdue, archived, withTimeTracking Bases# POST /api/bases/default-files/update# Overwrite the configured default TaskNotes .base files with templates generated from the current TaskNotes settings. This is the same write operation as Settings -> TaskNotes -> Views & base files -> Update files and replaces manual edits in those configured default files. curl -X POST http://localhost:8080/api/bases/default-files/update Response fields: data.created: default files created because they were missing data.updated: existing default files overwritten with current templates data.skipped: configured default files skipped Time Tracking# POST /api/tasks/:id/time/start# Starts a new active time entry for that task. POST /api/tasks/:id/time/start-with-description# Starts time tracking and writes description on the new active entry. Request body: { \"description\": \"Implementation\" } POST /api/tasks/:id/time/stop# Stops active time entry for that task. GET /api/tasks/:id/time# Returns per-task time summary and entries. GET /api/time/active# Returns currently active sessions across tasks. Important: Multiple active sessions can exist across different tasks. GET /api/time/summary# Returns aggregate time summary. Query params: period (for example today, week, month, all) from (ISO date) to (ISO date) Example: curl \"http://localhost:8080/api/time/summary?period=week\" Pomodoro# POST /api/pomodoro/start# Starts a session. Optional request fields: taskId (URL path of task) duration (number) POST /api/pomodoro/stop# Stops and resets current session. POST /api/pomodoro/pause# Pauses running session. POST /api/pomodoro/resume# Resumes paused session. GET /api/pomodoro/status# Returns current state plus computed totals (totalPomodoros, currentStreak, totalMinutesToday). GET /api/pomodoro/sessions# Returns history. Query params: limit date (YYYY-MM-DD) GET /api/pomodoro/stats# Returns stats for today or provided date. Query params: date (YYYY-MM-DD) Calendars# GET /api/calendars# Returns provider connectivity overview and subscription counts. GET /api/calendars/google# Returns Google provider details. If disconnected, returns { \"connected\": false }. GET /api/calendars/microsoft# Returns Microsoft provider details. If disconnected, returns { \"connected\": false }. GET /api/calendars/subscriptions# Returns ICS subscriptions with runtime fields such as lastFetched and lastError. GET /api/calendars/events# Returns merged event list from connected providers and ICS subscriptions. Query params: start (ISO date/datetime) end (ISO date/datetime) Response includes: events total sources (counts by provider) Webhooks# POST /api/webhooks# Registers webhook. Required fields: url events (non-empty array) Optional fields: id secret active transformFile corsHeaders GET /api/webhooks# Lists registered webhooks. Stored secrets are not returned. DELETE /api/webhooks/:id# Deletes webhook. GET /api/webhooks/deliveries# Returns last 100 delivery records. OpenAPI Docs# GET /api/docs# Returns OpenAPI JSON generated from registered controllers. GET /api/docs/ui# Returns Swagger UI. Errors# Common status codes: 400 invalid request or invalid state 401 missing/invalid bearer token (when auth token is configured) 404 missing task/webhook/resource 500 internal error Security Notes# Current behavior: CORS allows all origins (*). Transport is HTTP only (no TLS). Node server is started with server.listen(port) and does not explicitly bind to 127.0.0.1. Practical guidance: Set an auth token. Treat API port as sensitive and keep it firewalled. If you expose this port outside localhost, route through a trusted reverse proxy and TLS. Troubleshooting# API unavailable# Confirm API is enabled in settings. Confirm Obsidian is running. Confirm selected port is free. Reload plugin or restart Obsidian after changing API enable/port. 401 Authentication required# Check token value. Check Bearer prefix. Remove whitespace around token. Unexpected task list behavior# If you pass filters to GET /api/tasks, the endpoint returns 400 by design. Use POST /api/tasks/query."},{"title":"TaskNotes JavaScript Runtime API","url":"/obsidian/javascript-api/","description":"TaskNotes exposes an in-process runtime API on the loaded Obsidian plugin instance:","product":"obsidian","text":"TaskNotes exposes an in-process runtime API on the loaded Obsidian plugin instance: const tasknotes = app.plugins.plugins.tasknotes; const api = tasknotes?.api; This API is for Obsidian companion plugins and in-vault scripting tools such as Templater, QuickAdd, and MetaBind. It runs inside Obsidian and uses the same TaskNotes services, settings, cache, and vault permissions as the plugin UI. This is separate from the HTTP API. The runtime API does not start a server, does not use bearer-token authentication, and is only available inside the running Obsidian app. For user-facing extensions built on this API, see Companion Plugins. For a concrete automation companion plugin, see TaskNotes Workflows. The TypeScript contract lives in src/api/runtime-api.ts. It is intentionally small and type-focused so it can later become a standalone @tasknotes/runtime-api package for companion plugins. Version and Capabilities# Check the API version and capabilities before using methods that may not exist in older TaskNotes versions: const tasknotes = app.plugins.plugins.tasknotes; const api = tasknotes?.api; if (!api || api.apiVersion !== 1 || !api.hasCapability(\"tasks.write\")) { throw new Error(\"This workflow requires TaskNotes runtime API v1 task writes\"); } Current capabilities: model.read model.validate catalog.read extensions.read extensions.register tasks.read tasks.write tasks.delete tasks.move tasks.events relationships.read events.list time.read time.write time.summary pomodoro.read pomodoro.write pomodoro.events recurring.write recurring.materialize recurring.events settings.snapshot bases.write nlp.parse ui.task-menu query.tasks query.validate query.explain query.filter-options stats.tasks system.health lifecycle.events errors.typed Namespaces# Prefer the namespaced API for new code: await api.tasks.update(\"Tasks/example.md\", { status: \"active\" }); const subtasks = await api.relationships.subtasks(\"Tasks/example.md\"); await api.time.start(\"Tasks/example.md\", { description: \"Deep work\" }); await api.pomodoro.start({ taskPath: \"Tasks/example.md\", duration: 25 }); The older flat methods, such as api.getTask(path) and api.parseNaturalLanguage(text), remain available as compatibility aliases. Extension Registry# Companion plugins can publish their own runtime API namespace through api.extensions. This is the preferred way to extend TaskNotes without adding arbitrary properties to the core API object. const tasknotes = this.app.plugins.getPlugin(\"tasknotes\"); const api = tasknotes?.api; if (!api?.hasCapability(\"extensions.register\")) { return; } const handle = api.extensions.register({ id: this.manifest.id, namespace: \"tasknotes-workflows\", displayName: \"TaskNotes Workflows\", version: this.manifest.version, capabilities: [\"tasknotes-workflows.run\", \"tasknotes-workflows.events\"], api: { runWorkflow: async (workflowId, input) => { // companion plugin implementation }, }, }); this.register(() => handle.unregister()); Other plugins can discover and consume extension namespaces: const workflows = api.extensions.get(\"tasknotes-workflows\"); if (api.hasCapability(\"tasknotes-workflows.run\")) { await workflows.runWorkflow(\"start-timer-on-active\", { taskPath: \"Tasks/example.md\" }); } Extension namespaces are normalized to lowercase and may use letters, numbers, dots, underscores, or dashes. Capability names are also normalized to lowercase. Prefix extension capabilities with the extension namespace to avoid collisions. Companion Plugin Access# Companion plugins can read the TaskNotes plugin instance from Obsidian's plugin registry: const tasknotes = this.app.plugins.getPlugin(\"tasknotes\"); const api = tasknotes?.api; if (!api?.hasCapability(\"tasks.events\")) { return; } this.registerEvent( api.events.on(\"task.status.changed\", (event) => { console.log(event.taskPath, event.changes.status); }) ); If TaskNotes is disabled or has not loaded yet, api will be unavailable. Companion plugins should handle that case and retry after plugin load if needed. TypeScript# Use the exported runtime contract for type safety: import type { TaskNotesRuntimeApiV1 } from \"tasknotes/src/api/runtime-api\"; type TaskNotesPluginInstance = { api?: TaskNotesRuntimeApiV1; }; const tasknotes = app.plugins.getPlugin(\"tasknotes\") as TaskNotesPluginInstance | null; const api = tasknotes?.api; if (api?.apiVersion === 1 && api.hasCapability(\"tasks.write\")) { await api.tasks.setStatus(\"Tasks/example.md\", \"active\"); } TaskNotes is still loaded by Obsidian at runtime. The TypeScript contract only gives companion plugins compile-time checking and autocomplete. Model# The runtime API exposes a small model namespace backed by @tasknotes/model: const info = api.model.info(); const config = api.model.config(); const validation = api.model.validateTask(task); Method Description api.model.info() Returns the model package name, TaskNotes spec version, and runtime API version. api.model.config() Returns a resolved, Obsidian-free model configuration snapshot derived from TaskNotes settings. api.model.validateTask(task) Validates a partial or complete task against the shared model schema and TaskNotes status rules. api.model.validatePatch(patch) Validates a task patch before passing it to a runtime task mutation. Catalog# Use api.catalog to build companion-plugin editors without hardcoding TaskNotes values: const statuses = api.catalog.statuses(); const writableFields = api.catalog.writableFields(); const operators = api.catalog.filterOperators(); Method Description api.catalog.statuses() Returns configured TaskNotes status definitions. api.catalog.priorities() Returns configured TaskNotes priority definitions. api.catalog.userFields() Returns configured user-defined field mappings. api.catalog.fields() Returns core, computed, and user field metadata with value type, writability, and frontmatter key when available. api.catalog.writableFields() Returns only fields that runtime task mutations may write. api.catalog.filterProperties() Returns canonical query fields, aliases, value types, and supported operators. api.catalog.filterOperators() Returns canonical query operators, labels, value requirements, and accepted aliases. api.catalog.relationships() Returns relationship categories supported by api.relationships. api.catalog.dependencyRelTypes() Returns dependency relationship types accepted by api.tasks.addDependency. api.catalog.events() Returns the same runtime event catalogue as api.events.list(). Tasks# All paths are vault-relative Markdown file paths. Method Description api.tasks.get(path) Returns a task by path, or null when no task is cached at that path. api.tasks.list(query?) Returns all tasks, or tasks matching a runtime task query. Prefer api.query.tasks() when count and grouping metadata matters. api.tasks.create(taskData, context?) Creates a task using the normal TaskNotes creation service. api.tasks.update(path, patch, context?) Updates one or more task fields using the normal TaskNotes update service. api.tasks.delete(path, context?) Deletes the task file through TaskNotes' delete service. api.tasks.complete(path, options?, context?) Marks a task complete. api.tasks.uncomplete(path, options?, context?) Moves a completed task back to a non-completed status. api.tasks.setStatus(path, status, context?) Sets task status. api.tasks.setPriority(path, priority, context?) Sets task priority. api.tasks.setDue(path, date, context?) / clearDue(path, context?) Sets or clears due date. api.tasks.setScheduled(path, date, context?) / clearScheduled(path, context?) Sets or clears scheduled date. api.tasks.archive(path, archived, context?) Archives or unarchives a task, including archive-folder movement when configured. api.tasks.move(path, targetFolder, context?) Moves the task note and refuses to overwrite an existing file. api.tasks.addTag/removeTag Mutates task tags. api.tasks.addProject/removeProject Mutates project links. api.tasks.addContext/removeContext Mutates contexts. api.tasks.setReminders/addReminder/removeReminder Mutates reminders. api.tasks.addDependency/removeDependency Mutates blocking dependencies stored in blockedBy. Example: const task = await api.tasks.create( { title: \"Review automation design\", status: \"open\", priority: \"normal\", scheduled: \"2026-06-01\", tags: [\"tasknotes\"], }, { source: \"my-companion-plugin\", correlationId: crypto.randomUUID(), reason: \"manual workflow command\", } ); await api.tasks.complete(task.path); Relationships# Relationship methods resolve TaskNotes' project-as-parent links and blockedBy dependencies into task records where possible. Method Description api.relationships.parents(path) Returns parent tasks referenced from the task's projects. api.relationships.subtasks(path) Returns tasks that reference this task as a project. api.relationships.dependencies(path) Returns blockedBy dependencies with resolved task data when available. api.relationships.blocking(path) Returns tasks that are blocked by this task. api.relationships.all(path) Returns the task plus parents, subtasks, dependencies, and blocking tasks. Example: const relationships = await api.relationships.all(\"Tasks/example.md\"); for (const subtask of relationships.subtasks) { await api.tasks.setPriority(subtask.path, relationships.task.priority); } Time Tracking# Method Description api.time.start(path, options?, context?) Starts time tracking and returns the updated task. api.time.stop(path, context?) Stops the active time entry and returns the updated task. api.time.active() Returns active time entries with task, path, entry, and entry index. api.time.summary(options?) Returns aggregate time totals, top tasks, projects, and tags. api.time.task(path) Returns one task's time summary and normalized time entries. api.time.append(path, entry, context?) Appends a time entry. api.time.deleteEntry(path, entryIndex, context?) Deletes a time entry through TaskNotes' service. Query, Stats, And System# The query, stats, and system namespaces expose HTTP/MCP-style support data without requiring companion plugins to reach into TaskNotes internals. Runtime queries use a stable DTO rather than TaskNotes' internal view state. const result = await api.query.tasks({ where: { all: [ { field: \"task.status\", op: \"eq\", value: \"active\" }, { field: \"task.due\", op: \"lte\", value: { fn: \"today\" } }, ], }, sort: [{ field: \"task.due\", direction: \"asc\" }], group: [{ field: \"task.status\" }], limit: 25, scope: { includeArchived: false, folders: [\"Tasks\"], }, }); Runtime query fields are canonical IDs such as task.status, task.priority, task.due, task.projects, task.isBlocked, file.path, and user.. api.catalog.filterProperties() returns the complete queryable field catalog, including aliases such as status and user:. Canonical operators are eq, ne, contains, notContains, in, notIn, exists, missing, lt, lte, gt, gte, isTrue, and isFalse. Legacy operator aliases such as is, is-not, is-on-or-before, and is-not-empty are accepted and normalized. api.query.tasks() returns explicit count semantics: total: tasks in scope before filtering matched: tasks matching where before offset and limit returned: tasks returned after offset and limit tasks: returned task records groups: optional group details with task paths query: the normalized canonical query warnings: non-fatal normalization notes Method Description api.query.tasks(query?) Validates, normalizes, and executes a runtime task query. api.query.validate(query) Validates a query without executing it. api.query.normalize(query) Returns the canonical normalized query, or throws a typed invalid_input API error. api.query.explain(query) Returns validation, normalized query, count, grouping, and applied sort/limit details for dry run. api.query.filterOptions() Returns available statuses, priorities, contexts, projects, tags, folders, and user properties. api.stats.tasks(query?) Returns task counts, status/priority counts, archive/completion counts, and time-tracking totals. api.system.health() Returns runtime status, API version, capabilities, vault identity, and task count. TaskNotes compiles this DTO into its internal filter engine. Companion plugins should treat the runtime DTO and the catalog metadata as the public query contract. Task Menu UI# Companion plugins can reuse the standard TaskNotes task context menu through api.ui.taskMenu. This keeps task actions, relationship actions, recurrence controls, and future menu changes behind the runtime API boundary instead of requiring companion plugins to import TaskNotes internals. This surface is only available inside Obsidian. It is not exposed through the HTTP API. Method Description api.ui.taskMenu.show({ taskPath, event, targetDate?, onUpdate?, promoteOccurrenceControls? }) Shows the standard TaskNotes task context menu at a mouse event. api.ui.taskMenu.showAtElement({ taskPath, element, targetDate?, onUpdate?, ... }) Shows the standard TaskNotes task context menu anchored to an element. api.ui.taskMenu.populate(menu, { taskPath, targetDate?, onUpdate?, ... }) Adds the standard TaskNotes task context menu items to an existing Obsidian Menu so plugins can extend it. All methods resolve taskPath through the TaskNotes task cache and throw a typed task_not_found error when the path does not point to a cached task. targetDate defaults to today and is used by date-sensitive recurring-task menu items. onUpdate is called after menu actions mutate the task; when omitted, TaskNotes refreshes its own task views. promoteOccurrenceControls moves recurring-instance controls to the top of the menu. Example context menu: nodeEl.addEventListener(\"contextmenu\", async (event) => { event.preventDefault(); await api.ui.taskMenu.show({ taskPath: task.path, event, onUpdate: () => refreshGraph(), }); }); Example composed menu: const menu = new Menu(); await api.ui.taskMenu.populate(menu, { taskPath: task.path, onUpdate: () => refreshGraph(), }); menu.addSeparator(); menu.addItem((item) => item .setTitle(\"Focus in graph\") .setIcon(\"network\") .onClick(() => selectGraphNode(task.path)) ); menu.showAtMouseEvent(event); Pomodoro# Method Description api.pomodoro.status() Returns current Pomodoro state. api.pomodoro.start(options?, context?) Starts a Pomodoro session. api.pomodoro.stop(context?) Stops and resets the active Pomodoro session. api.pomodoro.pause(context?) Pauses the current session. api.pomodoro.resume(context?) Resumes a paused session. api.pomodoro.assignTask(pathOrNull, context?) Assigns or clears the current session task. api.pomodoro.sessions(options?) Returns Pomodoro session history. api.pomodoro.stats(date?) Returns Pomodoro stats for a date or today. Recurring Tasks# Method Description api.recurring.toggleCompleteInstance(path, date?, context?) Toggles completion for a recurring task instance. api.recurring.toggleSkippedInstance(path, date?, context?) Toggles skipped state for a recurring task instance. api.recurring.materializeOccurrence(path, date, context?) Creates or returns an occurrence note for a recurring task date. Natural Language Parser# const parsed = api.nlp.parse(\"Write draft friday 2pm #writing @desk\"); api.parseNaturalLanguage(text) remains as a compatibility alias. Parsing does not create or modify task files. See NLP API for HTTP endpoint details and parser behavior. Settings Snapshot# const settings = api.settings.snapshot(); console.log(settings.defaultTaskStatus); The returned object is a snapshot. Mutating it does not change TaskNotes settings. api.getSettingsSnapshot() remains available as a compatibility alias. Bases# api.bases.updateDefaultFiles() regenerates the configured default TaskNotes .base files from the current TaskNotes settings and returns the created, updated, and skipped file paths. const result = await api.bases.updateDefaultFiles(); console.log(result.updated); Mutation Context# Mutating methods accept an optional context object: { source: \"tasknotes-workflows\", correlationId: \"run-2026-06-01T09-00-00\", reason: \"status chang"},{"title":"mdbase-tasknotes CLI","url":"/obsidian/mdbase-tasknotes-cli/","description":"mdbase-tasknotes (mtn) is a standalone command-line tool for managing TaskNotes tasks directly on markdown files. It uses mdbase to read and write task files and tasknotes-nlp-c...","product":"obsidian","text":"mdbase-tasknotes (mtn) is a standalone command-line tool for managing TaskNotes tasks directly on markdown files. It uses mdbase to read and write task files and tasknotes-nlp-core for natural language parsing. When to use this vs TaskNotes Obsidian CLI# If you are looking for the built-in obsidian tasknotes:* commands exposed by the plugin itself, see TaskNotes Obsidian CLI. TaskNotes ships with tasknotes-cli (tn), which communicates with the Obsidian plugin over its HTTP API. mdbase-tasknotes operates directly on the markdown files instead. tn (tasknotes-cli) mtn (mdbase-tasknotes) Requires Obsidian Yes — plugin must be running with API enabled No Operates on HTTP API Markdown files directly via mdbase Use when Obsidian is open and you want live sync Obsidian is closed, on a server, or in scripts Time tracking Via plugin API Via frontmatter timeEntries Task creation NLP via API NLP via bundled tasknotes-nlp-core Install npm install -g tasknotes-cli npm install -g mdbase-tasknotes Use mtn when: Obsidian isn't running or isn't available (headless servers, SSH sessions, CI pipelines) You want to manage tasks from the terminal without any background process You're scripting task creation or querying in shell workflows You're on a machine where Obsidian isn't installed Both tools read and write the same task files, so they can be used interchangeably on the same vault. Install# npm install -g mdbase-tasknotes Setup# Using an existing TaskNotes vault# If you already use TaskNotes with mdbase spec generation enabled (Settings → Integrations → Enable mdbase spec), point mtn at your vault root: mtn config --set collectionPath=/path/to/your/vault The plugin generates mdbase.yaml and _types/task.md automatically — mtn reads these to understand your task schema, including your custom statuses and priorities. Creating a standalone collection# To create a new collection without Obsidian: mtn init ~/tasks mtn config --set collectionPath=~/tasks This generates mdbase.yaml, _types/task.md, and a tasks/ folder with sensible defaults (statuses: open, in-progress, done, cancelled; priorities: low, normal, high, urgent). Creating tasks# Create tasks using natural language. Tags, contexts, projects, dates, priorities, and recurrence are extracted automatically: mtn create \"Buy groceries tomorrow #shopping @errands\" mtn create \"Write quarterly report due friday #work +quarterly-review\" mtn create \"Call dentist high priority @phone\" mtn create \"Water plants every monday #home\" Supported patterns# Pattern Example Extracted as #tag #shopping Tag @context @errands Context +project +quarterly-review Project (stored as wikilink) Date words tomorrow, friday, next week Due date Priority words high priority, urgent Priority Recurrence every day, weekly, every monday Recurrence rule Estimate ~30m, ~2h Time estimate The NLP parser reads your collection's status and priority enum values from _types/task.md, so any custom values you define there are automatically recognized. Querying tasks# List tasks# # Default: open tasks ordered by due date mtn list # Filter by status, priority, or tag mtn list --status in-progress mtn list --priority high mtn list --tag work # Show overdue tasks mtn list --overdue # Raw mdbase where expression mtn list --where 'due < \"2026-03-01\" && priority == \"urgent\"' # JSON output for scripting mtn list --json Show task detail# mtn show \"Buy groceries\" mtn show tasks/Buy\\ groceries.md Tasks can be referenced by title or file path. Title matching tries exact match first, then substring. Search# Full-text search across titles, body content, tags, contexts, and projects: mtn search quarterly Updating tasks# Complete a task# mtn complete \"Buy groceries\" Sets status to done and records the completion date. Update fields# mtn update \"Write report\" --status in-progress mtn update \"Write report\" --priority urgent --due 2026-03-01 mtn update \"Write report\" --add-tag important --remove-tag draft mtn update \"Write report\" --add-context office Archive and delete# mtn archive \"Write report\" # Adds \"archive\" tag mtn delete \"Old task\" # Checks for backlinks first mtn delete \"Old task\" --force # Skip backlink check Time tracking# Track time spent on tasks via the timeEntries frontmatter field — the same format TaskNotes uses. # Start a timer mtn timer start \"Write report\" mtn timer start \"Write report\" -d \"Drafting introduction\" # Check active timers mtn timer status # Stop the running timer mtn timer stop # View time log mtn timer log mtn timer log --period today mtn timer log --period week mtn timer log --from 2026-02-01 --to 2026-02-28 Projects and statistics# Projects# # List all projects mtn projects list mtn projects list --stats # With completion percentages # Show tasks for a project mtn projects show quarterly-review Statistics# mtn stats Shows total tasks, completion rate, overdue count, breakdown by status and priority, and total time tracked. Interactive mode# Launch a REPL with live NLP preview that updates as you type: mtn interactive # or mtn i Type a task description and the preview line shows how it will be parsed (title, tags, dates, priority). Press Enter to create the task. Configuration# Configuration is stored at ~/.config/mdbase-tasknotes/config.json. mtn config --list # Show all settings mtn config --set collectionPath=/path/to/vault # Set collection path mtn config --get collectionPath # Get a setting Collection path resolution# The collection path is resolved in order: --path / -p flag on any command MDBASE_TASKNOTES_PATH environment variable collectionPath in config file Current working directory Command reference# Command Alias Description mtn init [path] Initialize a new collection mtn create Create a task from natural language mtn list [options] ls List tasks with filters mtn show Show full task detail mtn complete done Mark task as completed mtn update [options] Update task fields mtn delete rm Delete a task mtn archive Add archive tag mtn search Full-text search mtn timer start Start time tracking mtn timer stop Stop running timer mtn timer status Show active timers mtn timer log Show time entry log mtn projects list List projects mtn projects show Show project tasks mtn stats Show task statistics mtn interactive i Interactive REPL mtn config [options] Manage configuration"},{"title":"Migrating from v3 to v4","url":"/obsidian/migration-v3-to-v4/","description":"TaskNotes v4 migrates all views to the Bases system. This guide covers what changed and how to update your setup.","product":"obsidian","text":"TaskNotes v4 migrates all views to the Bases system. This guide covers what changed and how to update your setup. Back up before migratingBack up the complete vault, including the hidden .obsidian directory, before changing views or plugin data. Requirements# Obsidian 1.10.1 or later for early TaskNotes v4 releases Obsidian 1.12.2 or later for the current TaskNotes 4.12.3 release Bases core plugin enabled (Settings → Core Plugins → Bases) What Changed# Views are Now Bases Files# All task views (Task List, Kanban, Calendar, Agenda) are now .base files stored in TaskNotes/Views/. This replaces the custom view system in v3. v3 v4 Views stored in plugin settings Views stored as .base files Custom filter UI Bases filter syntax Saved views in settings Default views are separate files; exported v3 saved views share one multi-view file Automatic Migration on First Launch# When you first open TaskNotes v4: Default .base files are created in TaskNotes/Views/ Ribbon icons and commands now open these .base files Your existing task files are unchanged Converting Saved Filter Views# If you had saved filter views in v3, you can export them to one .base file: Go to Settings → TaskNotes → General → Views & base files. Find Export v3 saved views to Bases. Run the export. TaskNotes creates TaskNotes/Views/all-saved-views.base with one Base view for each saved v3 view. This is a one-way conversion. The original saved views remain in settings until you delete them. Breaking Changes# View Configuration# v3 saved views with custom filters need manual conversion to Bases filter syntax. Simple filters (status, priority, due date) convert automatically. Complex filters may need adjustment. v3 Filter Example: status: in-progress priority: high v4 Bases Syntax: filters: and: - status == \"in-progress\" - priority == \"high\" See the Obsidian Bases documentation for filter syntax details. Minimum Obsidian Version# Early v4 releases required Obsidian 1.10.1. The current release requirement is generated on the version compatibility page. Use the manifest requirement for the exact TaskNotes version you install. New Features in v4# OAuth Calendar Integration# v4 adds Google Calendar and Microsoft Outlook integration: View external calendar events alongside tasks Drag events to reschedule (syncs back to calendar provider) Events sync every 15 minutes See Calendar Setup for configuration. Kanban Swimlanes# The Kanban view now supports horizontal swimlane grouping: views: - type: tasknotesKanban groupBy: property: status config: swimLane: priority Time Entry Editor# A dedicated modal for managing time entries: Alt-drag on calendar to create time entries View total tracked time per task Edit and delete time entries Troubleshooting# Views Not Loading# Verify Bases core plugin is enabled (Settings → Core Plugins) Check that .base files exist in TaskNotes/Views/ Restart Obsidian Missing Saved Views After Upgrade# Saved views from v3 are preserved in settings. Use Export v3 saved views to Bases in Settings → TaskNotes → General → Views & base files to create the multi-view .base file. Filter Syntax Errors# Bases uses different filter syntax than v3. Common issues: Problem Solution status: done Use status == \"done\" Multiple conditions Wrap in and: or or: block Date comparisons Use date(due) < today() Downgrading to v3# Migration is one-way. If you need to downgrade: Uninstall TaskNotes v4 Install TaskNotes v3 from releases Reconfigure your saved views manually Your task files are unaffected—only view configurations change. View Templates# For complete .base file examples, see Default Base Templates."},{"title":"TaskNotes NLP API","url":"/obsidian/nlp-api/","description":"The NLP API parses natural-language task text and optionally creates a task.","product":"obsidian","text":"The NLP API parses natural-language task text and optionally creates a task. In-vault scripts can also call the parser directly from the loaded plugin: const tasknotes = app.plugins.plugins.tasknotes; const parsed = tasknotes.api.parseNaturalLanguage(\"Review PR tomorrow #code @work\"); For the full in-process API exposed at tasknotes.api, including task updates, time tracking, settings snapshots, and events, see TaskNotes JavaScript API. Endpoints# POST /api/nlp/parse POST /api/nlp/create Both endpoints require a JSON body with text. Request Format# { \"text\": \"Review PR #123 tomorrow high priority @work\" } Notes: text is required and must be a string. Per-request locale is not currently supported. Parser language comes from TaskNotes settings (nlpLanguage). POST /api/nlp/parse# Parses text and returns two objects: parsed: direct parser output taskData: normalized task payload that would be used for creation Example response (shape): { \"success\": true, \"data\": { \"parsed\": { \"title\": \"Review PR\", \"tags\": [\"123\"], \"contexts\": [\"work\"], \"projects\": [], \"priority\": \"high\", \"status\": null, \"dueDate\": \"2026-02-22\", \"scheduledDate\": null, \"dueTime\": null, \"scheduledTime\": null, \"recurrence\": null, \"estimate\": null, \"isCompleted\": false }, \"taskData\": { \"title\": \"Review PR\", \"priority\": \"high\", \"status\": \"open\", \"tags\": [\"123\"], \"contexts\": [\"work\"], \"due\": \"2026-02-22\", \"dateCreated\": \"2026-02-22T09:00:00.000Z\", \"dateModified\": \"2026-02-22T09:00:00.000Z\" } } } If parser does not detect status, taskData.status falls back to your configured default task status. Parsed due and scheduled date-times in taskData use the same YYYY-MM-DDTHH:mm format as created tasks, and NLP trigger values for user-defined fields are returned under customFrontmatter. POST /api/nlp/create# Parses text and creates a task in one call. Returns HTTP 201 on success. Example: curl -X POST http://localhost:8080/api/nlp/create \\ -H \"Content-Type: application/json\" \\ -d '{\"text\":\"Call mom due friday 2pm #personal\"}' Response fields: data.task (created task) data.parsed (parser output) What the Parser Extracts# The parser can extract: Dates and times (tomorrow, friday 2pm, ISO dates) Priority terms (high priority, urgent, symbol patterns) Status terms (mapped to your configured statuses) Tags (#tag) Contexts (@context) Projects (+project) Time estimates (2h, 30min, estimate 45m) Recurrence (daily, weekly, every monday) Exact parsing behavior depends on your TaskNotes NLP settings and trigger configuration. In-Vault Parser Method# Templater, QuickAdd, MetaBind, and other in-vault scripts can use the loaded plugin instance directly: const tasknotes = app.plugins.plugins.tasknotes; const parsed = tasknotes.api.parseNaturalLanguage(\"Write draft friday 2pm #writing @desk\"); parseNaturalLanguage(text) returns the same parser output shape as data.parsed from POST /api/nlp/parse. It uses your current TaskNotes settings, including custom status values, priority values, NLP language, NLP trigger configuration, user fields, and calendar locale. This method only parses text. It does not create or modify task files. For task creation and updates from in-vault scripts or companion plugins, use the broader TaskNotes JavaScript API. Example Templater use: <%* const tasknotes = app.plugins.plugins.tasknotes; const text = await tp.system.prompt(\"Task\"); const parsed = tasknotes.api.parseNaturalLanguage(text); tR += `title: ${parsed.title}`; %> Error Responses# Common errors: 400: missing/invalid text 401: auth required (if API token is enabled) 500: parse/processing error Error shape: { \"success\": false, \"error\": \"Text field is required and must be a string\" } Client Examples# JavaScript# async function parseTask(text) { const response = await fetch(\"http://localhost:8080/api/nlp/parse\", { method: \"POST\", headers: { \"Content-Type\": \"application/json\" }, body: JSON.stringify({ text }) }); return response.json(); } async function createTaskFromText(text) { const response = await fetch(\"http://localhost:8080/api/nlp/create\", { method: \"POST\", headers: { \"Content-Type\": \"application/json\" }, body: JSON.stringify({ text }) }); return response.json(); } Python# import requests def parse_task(text): response = requests.post( \"http://localhost:8080/api/nlp/parse\", json={\"text\": text}, ) return response.json() def create_task_from_text(text): response = requests.post( \"http://localhost:8080/api/nlp/create\", json={\"text\": text}, ) return response.json() Authentication# If API auth token is enabled, include bearer token: Authorization: Bearer YOUR_TOKEN"},{"title":"TaskNotes Obsidian CLI","url":"/obsidian/obsidian-cli/","description":"TaskNotes can register commands directly with the Obsidian desktop CLI. This is useful when Obsidian is already running and you want shell access to task creation, time tracking...","product":"obsidian","text":"TaskNotes can register commands directly with the Obsidian desktop CLI. This is useful when Obsidian is already running and you want shell access to task creation, time tracking, or Pomodoro control without going through the HTTP API. Use this page for the built-in obsidian ... commands exposed by the plugin itself. If you want a standalone terminal tool that works directly on Markdown files without Obsidian running, see mdbase-tasknotes CLI. Requirements# Obsidian desktop 1.12.2 or newer TaskNotes installed and enabled in the target vault Obsidian running when you invoke the CLI The Obsidian CLI resolves commands against a vault context. In practice, it is safer to pass vault= explicitly instead of relying on the default vault. Discovering commands# List available TaskNotes commands: obsidian help | rg 'tasknotes:' You should see: tasknotes:capture tasknotes:start-time tasknotes:stop-time tasknotes:time-status tasknotes:pomodoro tasknotes:capture# Create a task from free text, explicit flags, or both. obsidian tasknotes:capture vault=test text=\"Review PR tomorrow #work @desk\" By default, text= is parsed with TaskNotes NLP. Explicit flags override parsed values. Literal title mode# Use literal when you want the text treated as an exact title instead of being parsed. obsidian tasknotes:capture vault=test text=\"Fix parser edge case\" literal Explicit fields# Supported override flags: title details status priority due scheduled tags contexts projects recurrence recurrence-anchor reminders estimate Example: obsidian tasknotes:capture vault=test \\ text=\"Write release notes tomorrow #docs\" \\ priority=high \\ status=in-progress \\ reminders='due:-PT1H' Reminder format# reminders= accepts either: a semicolon-separated shorthand such as due:-PT1H;scheduled:-PT30M;at:2026-04-02T09:00 a JSON array in the same shape TaskNotes stores internally Recurrence anchor# Use recurrence-anchor=scheduled or recurrence-anchor=completion to control how recurring tasks advance. tasknotes:start-time# Start time tracking for a task. You can target a task by: path exact title fuzzy query Examples: obsidian tasknotes:start-time vault=test title=\"Write release notes\" obsidian tasknotes:start-time vault=test query=\"release notes\" description=\"Drafting first pass\" obsidian tasknotes:start-time vault=test path=\"TaskNotes/Write release notes.md\" tasknotes:stop-time# Stop time tracking for a task. Examples: obsidian tasknotes:stop-time vault=test title=\"Write release notes\" obsidian tasknotes:stop-time vault=test path=\"TaskNotes/Write release notes.md\" If you omit task lookup flags, TaskNotes will stop the only active session when that is unambiguous. tasknotes:time-status# Show time-tracking status for either: all active sessions one resolved task Examples: obsidian tasknotes:time-status vault=test obsidian tasknotes:time-status vault=test title=\"Write release notes\" obsidian tasknotes:time-status vault=test path=\"TaskNotes/Write release notes.md\" When a task is targeted, the command returns that task's summary, active session, and time entries. With no lookup flags, it returns the currently active sessions across the vault. tasknotes:pomodoro# Control Pomodoro state from the CLI. Supported actions: status start pause resume stop short-break long-break Inspect state# obsidian tasknotes:pomodoro vault=test action=status Start a work session# You can start a Pomodoro with or without a linked task. obsidian tasknotes:pomodoro vault=test action=start duration=25 obsidian tasknotes:pomodoro vault=test action=start title=\"Write release notes\" duration=25 Task lookup for action=start supports the same selectors as time tracking: path exact title fuzzy query Pause, resume, and stop# obsidian tasknotes:pomodoro vault=test action=pause obsidian tasknotes:pomodoro vault=test action=resume obsidian tasknotes:pomodoro vault=test action=stop Breaks# obsidian tasknotes:pomodoro vault=test action=short-break obsidian tasknotes:pomodoro vault=test action=long-break Choosing between CLI surfaces# Use the built-in Obsidian CLI when: Obsidian is already open you want plugin-aware behavior, including current cache, defaults, templates, time tracking, and Pomodoro state you are scripting on the same machine as the running vault Use mdbase-tasknotes CLI when: Obsidian is not running you need headless/server workflows you want direct file-level automation over a task collection Notes# path is the most reliable task selector for automation. Immediately after creating a task, exact title lookup can lag briefly until the in-memory cache catches up. These commands are desktop-only because they depend on the Obsidian desktop CLI."},{"title":"Command reference","url":"/obsidian/reference/commands/","description":"Every TaskNotes command registered with Obsidian, generated from the plugin command definitions.","product":"obsidian","text":"This page is generated from the commands registered by TaskNotes. Command IDs are stable integration identifiers; names are the English labels shown in Obsidian. Command ID Available in Open mini calendar view open-calendar-view Global Open calendar view open-advanced-calendar-view Global Open tasks view open-tasks-view Global Open agenda view open-agenda-view Global Open Pomodoro timer open-pomodoro-view Global Open Kanban board open-kanban-view Global Update default base files update-default-base-files Global Open Pomodoro statistics open-pomodoro-stats Global Open task & project statistics open-statistics Global Create new task create-new-task Global Convert current note to task convert-current-note-to-task Global Convert checkbox task to TaskNote convert-to-tasknote Editor Convert all tasks in note batch-convert-all-tasks Editor Insert tasknote link insert-tasknote-link Editor Create new inline task create-inline-task Editor Quick actions for current task quick-actions-current-task Global Quick actions for task under cursor quick-actions-task-under-cursor Editor Edit current task edit-current-task Global Cycle current task status cycle-current-task-status Global Cycle current task priority cycle-current-task-priority Global Add project to current task add-project-to-current-task Global Add subtask to current note add-subtask-to-current-note Global Go to today's note go-to-today Global Start Pomodoro timer start-pomodoro Global Stop Pomodoro timer stop-pomodoro Global Pause/resume Pomodoro timer pause-pomodoro Global Refresh cache refresh-cache Global Export all tasks as ICS file export-all-tasks-ics Global Sync all tasks to Google Calendar sync-all-tasks-google-calendar Global Sync current task to Google Calendar sync-current-task-google-calendar Global View release notes view-release-notes Global Start time tracking (select task) start-time-tracking-with-selector Global Edit time entries (select task) edit-time-entries Global Create or open task create-or-open-task Global Create or open task and start time tracking create-or-open-task-with-time-tracking Global Postpone overdue scheduled tasks to today rollover-overdue-scheduled-tasks Global Generated from 36 registered commands."},{"title":"Version compatibility","url":"/obsidian/reference/compatibility/","description":"Current TaskNotes and Obsidian compatibility requirements, generated from the plugin manifest.","product":"obsidian","text":"Current release# Item Value TaskNotes 4.12.3 Minimum Obsidian version 1.12.2 Desktop only No Bases core plugin Required The minimum version above applies to the current TaskNotes release. Older releases had different requirements; consult versions.json or the relevant release note when maintaining an older installation."},{"title":"Generated default Base templates","url":"/obsidian/reference/default-base-templates/","description":"Exact default Obsidian Base files generated by the current TaskNotes source and default settings.","product":"obsidian","text":"These are the exact templates TaskNotes 4.12.3 produces with default settings. Your generated files reflect your own field mapping and other settings, so customized output can differ. Regenerating with Update files overwrites configured default Base files. Copy a customized file to a new path before updating it. mini-calendar-default.base# Command/template ID: open-calendar-view # Mini Calendar # Generated with your TaskNotes settings filters: and: - file.hasTag(\"task\") formulas: priorityWeight: 'if(priority==\"none\",0,if(priority==\"low\",1,if(priority==\"normal\",2,if(priority==\"high\",3,999))))' daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)' dueIn: 'if(due.isEmpty(), \"\", if(formula.daysUntilDue == 0, \"Today\", if(formula.daysUntilDue == 1, \"1 day\", if(formula.daysUntilDue > 1, formula.daysUntilDue + \" days\", if(formula.daysUntilDue == -1, \"1 day overdue\", formula.daysUntilDue * -1 + \" days overdue\")))))' daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)' daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()' daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()' isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != \"done\"' isDueToday: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")' isDueThisWeek: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")' isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")' isRecurring: 'recurrence && !recurrence.isEmpty()' hasTimeEstimate: 'timeEstimate && timeEstimate > 0' timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)' efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)' timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - \"7d\").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)' timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)' dueMonth: 'if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), \"No due date\")' dueWeek: 'if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), \"No due date\")' scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"Not scheduled\")' scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"Not scheduled\")' dueDateCategory: 'if(due.isEmpty(), \"No due date\", if(date(due) < today(), \"Overdue\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), \"This week\", \"Later\")))))' timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(timeEstimate < 30, \"Quick (<30m)\", if(timeEstimate <= 120, \"Medium (30m-2h)\", \"Long (>2h)\")))' ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, \"Today\", if(((number(now()) - number(file.ctime)) / 86400000) < 7, \"This week\", if(((number(now()) - number(file.ctime)) / 86400000) < 30, \"This month\", \"Older\")))' createdMonth: 'file.ctime.format(\"YYYY-MM\")' modifiedMonth: 'file.mtime.format(\"YYYY-MM\")' priorityCategory: 'if(priority==\"none\",\"None\",if(priority==\"low\",\"Low\",if(priority==\"normal\",\"Normal\",if(priority==\"high\",\"High\",\"No priority\"))))' projectCount: 'if(!projects || list(projects).length == 0, \"No projects\", if(list(projects).length == 1, \"Single project\", \"Multiple projects\"))' contextCount: 'if(!contexts || list(contexts).length == 0, \"No contexts\", if(list(contexts).length == 1, \"Single context\", \"Multiple contexts\"))' trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(!timeEntries || list(timeEntries).length == 0, \"Not started\", if(formula.efficiencyRatio < 100, \"Under estimate\", \"Over estimate\")))' nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))' daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))' hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)' isToday: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"))' isThisWeek: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"))' nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), \"No date\", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), \"Overdue/Past\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")), \"Today\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")), \"Tomorrow\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")), \"This week\", \"Later\")))))' nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-MM\"), date(scheduled).format(\"YYYY-MM\")), if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"No date\")))' nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-[W]WW\"), date(scheduled).format(\"YYYY-[W]WW\")), if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"No date\")))' urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format(\"YYYY-MM-DD\")))) / 86400000)))' timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + \"h \" + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + \"m\", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + \"m\"), \"0m\")' dueDateDisplay: 'if(due.isEmpty(), \"\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") == (today() - \"1 day\").format(\"YYYY-MM-DD\"), \"Yesterday\", if(date(due) < today(), formula.daysUntilDue * -1 + \"d ago\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), date(due).format(\"ddd\"), date(due).format(\"MMM D\")))))))' views: - type: tasknotesMiniCalendar name: \"Due\" order: - status - priority - due - scheduled - projects - contexts - file.tags - blockedBy - file.name - recurrence - complete_instances - file.tasks sort: - property: due direction: ASC dateProperty: due - type: tasknotesMiniCalendar name: \"Scheduled\" order: [] dateProperty: scheduled - type: tasknotesMiniCalendar name: \"Created\" dateProperty: file.ctime - type: tasknotesMiniCalendar name: \"Modified\" dateProperty: file.mtime kanban-default.base# Command/template ID: open-kanban-view # Kanban Board filters: and: - file.hasTag(\"task\") formulas: priorityWeight: 'if(priority==\"none\",0,if(priority==\"low\",1,if(priority==\"normal\",2,if(priority==\"high\",3,999))))' daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)' dueIn: 'if(due.isEmpty(), \"\", if(formula.daysUntilDue == 0, \"Today\", if(formula.daysUntilDue == 1, \"1 day\", if(formula.daysUntilDue > 1, formula.daysUntilDue + \" days\", if(formula.daysUntilDue == -1, \"1 day overdue\", formula.daysUntilDue * -1 + \" days overdue\")))))' daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)' daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()' daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()' isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != \"done\"' isDueToday: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")' isDueThisWeek: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")' isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")' isRecurring: 'recurrence && !recurrence.isEmpty()' hasTimeEstimate: 'timeEstimate && timeEstimate > 0' timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)' efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)' timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - \"7d\").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)' timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)' dueMonth: 'if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), \"No due date\")' dueWeek: 'if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), \"No due date\")' scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"Not scheduled\")' scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"Not scheduled\")' dueDateCategory: 'if(due.isEmpty(), \"No due date\", if(date(due) < today(), \"Overdue\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), \"This week\", \"Later\")))))' timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(timeEstimate < 30, \"Quick (<30m)\", if(timeEstimate <= 120, \"Medium (30m-2h)\", \"Long (>2h)\")))' ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, \"Today\", if(((number(now()) - number(file.ctime)) / 86400000) < 7, \"This week\", if(((number(now()) - number(file.ctime)) / 86400000) < 30, \"This month\", \"Older\")))' createdMonth: 'file.ctime.format(\"YYYY-MM\")' modifiedMonth: 'file.mtime.format(\"YYYY-MM\")' priorityCategory: 'if(priority==\"none\",\"None\",if(priority==\"low\",\"Low\",if(priority==\"normal\",\"Normal\",if(priority==\"high\",\"High\",\"No priority\"))))' projectCount: 'if(!projects || list(projects).length == 0, \"No projects\", if(list(projects).length == 1, \"Single project\", \"Multiple projects\"))' contextCount: 'if(!contexts || list(contexts).length == 0, \"No contexts\", if(list(contexts).length == 1, \"Single context\", \"Multiple contexts\"))' trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(!timeEntries || list(timeEntries).length == 0, \"Not started\", if(formula.efficiencyRatio < 100, \"Under estimate\", \"Over estimate\")))' nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))' daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))' hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)' isToday: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"))' isThisWeek: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"))' nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), \"No date\", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), \"Overdue/Past\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")), \"Today\", if(((due.isEmpty() == false) && date(due).fo"},{"title":"HTTP route index","url":"/obsidian/reference/http-routes/","description":"Implemented TaskNotes HTTP API routes generated from controller decorators.","product":"obsidian","text":"This index is generated from controller route decorators. The build fails if an implemented route is absent from the narrative HTTP API guide or NLP API guide. Method Path Controller POST /api/bases/default-files/update BasesController GET /api/calendars CalendarsController GET /api/calendars/events CalendarsController GET /api/calendars/google CalendarsController GET /api/calendars/microsoft CalendarsController GET /api/calendars/subscriptions CalendarsController GET /api/docs SystemController GET /api/docs/ui SystemController GET /api/filter-options TasksController GET /api/health SystemController POST /api/nlp/create SystemController POST /api/nlp/parse SystemController POST /api/pomodoro/pause PomodoroController POST /api/pomodoro/resume PomodoroController GET /api/pomodoro/sessions PomodoroController POST /api/pomodoro/start PomodoroController GET /api/pomodoro/stats PomodoroController GET /api/pomodoro/status PomodoroController POST /api/pomodoro/stop PomodoroController GET /api/stats TasksController GET /api/tasks TasksController POST /api/tasks TasksController DELETE /api/tasks/:id TasksController GET /api/tasks/:id TasksController PUT /api/tasks/:id TasksController POST /api/tasks/:id/archive TasksController POST /api/tasks/:id/complete-instance TasksController POST /api/tasks/:id/materialize-occurrence TasksController GET /api/tasks/:id/time TimeTrackingController POST /api/tasks/:id/time/start TimeTrackingController POST /api/tasks/:id/time/start-with-description TimeTrackingController POST /api/tasks/:id/time/stop TimeTrackingController POST /api/tasks/:id/toggle-status TasksController POST /api/tasks/query TasksController GET /api/time/active TimeTrackingController GET /api/time/summary TimeTrackingController GET /api/webhooks WebhookController POST /api/webhooks WebhookController DELETE /api/webhooks/:id WebhookController GET /api/webhooks/deliveries WebhookController Generated from 40 implemented routes."},{"title":"Settings source reference","url":"/obsidian/reference/settings-source/","description":"The six TaskNotes settings tabs, their controls, and the complete default settings snapshot generated from source.","product":"obsidian","text":"TaskNotes currently exposes 6 settings tabs. This inventory is generated from the tab renderer and English translation source so additions cannot silently disappear from the documentation. General# Source: src/settings/tabs/generalTab.ts Setting Purpose Default tasks folder Default location for new tasks. Supports folder template variables like {{currentNotePath}}, {{currentNoteTitle}}, and {{projectFilePath}}, plus Daily Notes-style date tokens like YYYY/MM/DD. Folder for inline-created tasks Folder where tasks created from inline commands or checkbox conversion will be created. Leave empty to use the default tasks folder. Use {{currentNotePath}} for the current note's folder, or {{currentNoteTitle}} for a subfolder named after the current note. Move archived tasks to folder Automatically move archived tasks to an archive folder Archive folder Folder to move tasks to when archived. Supports template variables like {{year}}, {{month}}, {{priority}}, etc. Identify tasks by Choose whether to identify tasks by tag or by a frontmatter property Task tag Tag that identifies notes as tasks (without #). Existing .base view filters keep their old tag when this changes; update default Base files or edit those filters. Hide identification tags in task cards When enabled, tags matching the task identification tag (including hierarchical matches like 'task/project') will be hidden from task card displays Hidden tag scope Choose whether hiding identification tags also hides nested tags. Task property name The frontmatter property name (e.g., \"category\") Task property value The value that identifies a note as a task (e.g., \"task\") Auto-create default files Automatically create missing default base view files on startup. Disable to prevent deleted sample files from being recreated. Create default files Create the default .base files in TaskNotes/Views/ directory. Existing files will not be overwritten. Update default files Overwrite the configured default .base files with templates generated from your current TaskNotes settings. Export v3 saved views to Bases Convert all your saved views from TaskNotes v3 into a single .base file with multiple views. This helps migrate your v3 filter configurations to the new Bases system. Excluded folders Comma-separated list of folders to exclude from task indexing and project suggestions UI language Select the language used for TaskNotes interface text Use Markdown links in frontmatter Generate markdown links ([text](path)) instead of wikilinks ([[link]]) in frontmatter properties. ⚠️ Requires the 'obsidian-frontmatter-markdown-links' plugin to work correctly. Show release notes after update Automatically open release notes when TaskNotes is updated to a new version Check for new releases on startup Check GitHub once when TaskNotes starts and show a notice when a newer compatible release is available View release notes See what's new in the latest version of TaskNotes Task properties# Source: src/settings/tabs/taskPropertiesTab.ts Setting Purpose No static controls detected This tab is assembled dynamically. Modal fields# Source: src/settings/tabs/modalFieldsTab.ts Setting Purpose No static controls detected This tab is assembled dynamically. Appearance & UI# Source: src/settings/tabs/appearanceTab.ts Setting Purpose Default visible properties Choose which properties appear on task cards by default. Time format Display time in 12-hour or 24-hour format throughout the plugin Default view The calendar view shown when opening the calendar tab Custom view day count Number of days to show in custom multi-day view First day of week Which day should be the first column in week views Show weekends Display weekends in calendar views Show week numbers Display week numbers in calendar views Show today highlight Highlight the current day in calendar views Show current time indicator Display a line showing the current time in timeline views Selection mirror Show a visual preview while dragging to select time ranges Calendar locale Calendar locale for date formatting and calendar system (e.g., \"en\", \"fa\" for Farsi/Persian, \"de\" for German). Leave empty to auto-detect from browser. Show scheduled tasks Display tasks with scheduled dates by default Show due dates Display task due dates by default Show due dates when scheduled Display due dates even for tasks that already have scheduled dates Show time entries Display completed time tracking entries by default Show recurring tasks Display recurring task instances by default Show ICS events Display events from ICS subscriptions by default Time slot duration Duration of each time slot in timeline views Start time Earliest time shown in timeline views (HH:MM format) End time Latest time shown in timeline views (HH:MM format). Use values above 24:00 to show early next-day hours, such as 26:00 for 2 AM. Initial scroll time Time to scroll to when opening timeline views (HH:MM format) Event minimum height Minimum height for events in timeline views (pixels) Show tracked tasks in status bar Display currently tracked tasks in Obsidian's status bar Show relationships widget Display a widget showing all relationships for the current note (subtasks, projects, dependencies) Relationships position Where to position the relationships widget Show task card in note Display a task card widget at the top of task notes showing the task details and actions Strike through completed task titles Draw a line through completed task card titles. Turn off to keep completed tasks easier to read Show expandable subtasks Allow expanding/collapsing subtask sections in task cards Expand subtasks by default Show project subtasks expanded when task cards are rendered Subtask chevron position Position of expand/collapse chevrons in task cards Views button alignment Alignment of the views/filters button in the task interface Single-click action Action performed when single-clicking a task card Double-click action Action performed when double-clicking a task card Features# Source: src/settings/tabs/featuresTab.ts Setting Purpose Task link overlay Show interactive overlays when hovering over task links Disable overlay for aliased links Do not show the task widget if the link contains an alias (e.g. [[Task|Alias]]). Show convert button next to checkboxes Display an inline button next to Markdown checkboxes that converts them to TaskNotes Keep checkbox when converting Leave the original Markdown checkbox marker in place when converting a checkbox to a TaskNote link Enable natural language task input Parse due dates, priorities, and contexts from natural language when creating tasks Default to scheduled When NLP detects a date without context, treat it as scheduled rather than due NLP language Language for natural language processing patterns and date parsing Open task after creation Choose whether the task creation modal opens the new task note after saving. Use body template Use a template file for task body content Body template file Path to template file for task body content. Supports template variables like {{title}}, {{date}}, {{time}}, {{priority}}, {{status}}, etc. Use occurrence note template Use a separate fallback template for materialized occurrence notes when the recurring task has no occurrence_template Occurrence note template file Path to template file for materialized occurrence notes. A recurring task's occurrence_template field takes priority over this fallback. Template variables: See the setting in Obsidian for contextual details. Use task defaults on instant convert Apply default task settings when converting text to tasks instantly Work duration Duration of work intervals in minutes Short break duration Duration of short breaks in minutes Long break duration Duration of long breaks in minutes Long break interval Number of work sessions before a long break Auto-start breaks Automatically start break timers after work sessions Auto-start work Automatically start work sessions after breaks Pomodoro notifications Show notifications when Pomodoro sessions end Show Pomodoro in status bar Display the active Pomodoro countdown in Obsidian's status bar Sound enabled Play sound when Pomodoro sessions end Sound volume Volume for Pomodoro sounds (0-100) Pomodoro data storage Configure where Pomodoro session data is stored and how it's managed. Mobile sidebar Where to open the Pomodoro timer on mobile devices Enable notifications Enable task reminder notifications Notification type Type of notifications to show Send test reminder Send a test reminder using the current notification type and sound settings. Notification sound Play a sound when task reminders trigger Sound volume Volume for task reminder sounds (0-100) Preview notification sound Play the configured task reminder sound Hide completed tasks from overdue Exclude completed tasks from overdue task calculations Disable note indexing Disable automatic indexing of note content for better performance Suggestion debounce Delay in milliseconds before showing suggestions Auto-stop time tracking Automatically stop time tracking when a task is marked complete Time tracking stop notification Show notification when time tracking is automatically stopped Maintain due date offset in recurring tasks Keep the offset between due date and scheduled date when recurring tasks are completed Reset checkboxes on recurrence Reset all Markdown checkboxes in the task body when a recurring task is completed and rescheduled Enable timeblocking Enable timeblocking feature for lightweight scheduling in daily notes. When enabled, 'Timeblock' option appears in the calendar drag context menu. Show timeblocks Display timeblocks from daily notes by default Default timeblock color The default color used when creating new timeblocks Enable debug logging Log detailed drag-and-drop and view diagnostics to the developer console. Useful for troubleshooting. Integrations# Source: src/settings/tabs/integrationsTab.ts Setting Purpose Generate mdbase type definitions See the setting in Obsidian for contextual details. Disable calendar integrations on mobile Skip Google, Microsoft, and ICS calendar loading on Obsidian mobile. Desktop calendar integrations are unchanged. Calendar integrations are disabled on this mobile device See the setting in Obsidian for contextual details. Enable task export When enabled, tasks with dates will be automatically synced to Google Calendar as events. Target calendar See the setting in Obsidian for contextual details. Sync trigger Which task date should trigger calendar event creation. Create as all-day events When enabled, tasks are created as all-day events. When disabled, uses time estimate for duration. Default event duration Duration in minutes for timed events (used when task has no time estimate). Event title template Template for event titles. Available variables: {{title}}, {{status}}, {{priority}} Include task details in description Add task metadata (priority, status, tags, etc.) to the event description. Include Obsidian link Add a link back to the task in Obsidian in the event description. Default reminder Add popup reminders to timed Google Calendar events. Enter minutes before the event, separated by commas. Leave empty to use calendar defaults. Common values: 15, 30, 60, 1440. Automatic sync behavior See the setting in Obsidian for contextual details. Sync on task create Automatically create calendar event when a new task is created. Sync on task update Automatically update calendar event when a task is modified. Sync on task complete Update calendar event when a task is completed (adds checkmark to title). Delete event on task delete Remove calendar event when the corresponding task is deleted. Manual sync actions See the setting in Obsidian for contextual details. Sync all tasks Sync all existing tasks to Google Calendar. This will create events for tasks that haven't been synced yet. Unlink all tasks Remove all task-event links without deleting calendar events. Default note template Path to template file for notes created from ICS events Default note folder Folder for notes created from ICS events ICS note filename format How filenames are generated for notes created from ICS events Custom ICS filename template Template for custom ICS event filenames Use ICS event end time as task due date When enabled, tasks created from calendar events will have their due date set to the event's end time. For all-day events, the due date will be set to the event date. For timed events, the due date will include the end time. Recurring event related notes Choose whether notes linked to one recurrence of an external calendar event appear across the loaded series or only on the selected instance. Add calendar subscription Add a new calendar subscription from ICS/iCal URL or local file New calendar See the setting in Obsidian for contextual details. Refresh all subscriptions Manually refresh all enabled calendar subscriptions Enable automatic export Automatically keep an ICS file updated with all your tasks Export file path Path where the ICS file will be saved (relative to vault root) Update interval (between 5 and 1440 minutes) How often to update the export file Use task duration for event length When enabled, uses the task's time estimate (duration) instead of due date for the calendar event end time. This is useful for GTD workflows where scheduled + duration represents work planning, while due date represents deadlines. Exclude completed tasks When enabled, completed tasks are omitted from ICS exports. Completed statuses are taken from your task statuses settings. Exclude archived tasks When enabled, archived tasks are omitted from ICS exports. Require due date When enabled, only tasks with a due date are included in ICS exports. Require scheduled date When enabled, only tasks with a scheduled date are included in ICS exports. Export now Manually trigger an immediate export Export status: See the setting in Obsidian for contextual details. Enable HTTP API Start local HTTP server for API access API port Port number for the HTTP API server API authentication token Token required for API authentication (leave empty for no auth) Enable MCP server Expose TaskNotes tools via Model Context Protocol at /mcp endpoint. Requires HTTP API to be enabled. Add webhook Register a new webhook endpoint Complete default settings snapshot# The following JSON is generated from DEFAULT_SETTINGS. Empty strings and disabled flags are intentional defaults. { \"tasksFolder\": \"TaskNotes/Tasks\", \"moveArchivedTasks\": false, \"archiveFolder\": \"TaskNotes/Archive\", \"taskTag\": \"task\", \"taskIdentificationMethod\": \"tag\", \"hideIdentifyingTagsInCards\": false, \"hideIdentifyingTagsMode\": \"all\", \"taskPropertyName\": \"\", \"taskPropertyValue\": \"\", \"excludedFolders\": \"\", \"defaultTaskPriority\": \"normal\", \"defaultTaskStatus\": \"open\", \"taskOrgFiltersCollapsed\": false, \"taskFilenameFormat\": \"zettel\", \"storeTitleInFilename\": true, \"customFilenameTemplate\": \"{{title}}\", \"occurrenceFilenameTemplate\": \"\", \"occurrenceFilenameTemplateProperty\": \"occurrenceFilenameTemplate\", \"taskCreationDefaults\": { \"defaultContexts\": \"\", \"defaultTags\": \"\", \"defaultProjects\": \"\", \"useParentNoteForTaskCreation\": false, \"useParentNoteAsProject\": false, \"useParentHeaderAsProject\": false, \"inheritParentTaskProperties\": false, \"defaultTimeEstimate\": 0, \"defaultRecurrence\": \"none\", \"defaultDueDate\": \"none\", \"defaultDueTime\": \"none\", \"defaultScheduledDate\": \"today\", \"defaultScheduledTime\": \"none\", \"bodyTemplate\": \"\", \"useBodyTemplate\": false, \"occurrenceBodyTemplate\": \"\", \"useOccurrenceBodyTemplate\": false, \"defaultReminders\": [] }, \"openTaskAfterCreation\": \"none\", \"calendarViewSettings\": { \"defaultView\": \"dayGridMonth\", \"customDayCount\": 3, \"slotDuration\": \"00:30:00\", \"slotMinTime\": \"00:00:00\", \"slotMaxTime\": \"24:00:00\", \"scrollTime\": \"08:00:00\", \"firstDay\": 1, \"timeFormat\": \"24\", \"showWeekends\": true, \"locale\": \"\", \"defaultShowSchedu"},{"title":"Release Notes","url":"/obsidian/releases/","description":"Welcome to the TaskNotes release notes. Here you can find detailed information about each version, including new features, bug fixes, and improvements.","product":"obsidian","text":"Welcome to the TaskNotes release notes. Here you can find detailed information about each version, including new features, bug fixes, and improvements. Latest Releases# Version 4.x (Current)# 4.12.3 4.12.2 4.12.1 4.12.0 4.11.1 4.11.0 4.10.2 4.10.1 4.10.0 4.9.2 4.9.1 4.9.0 4.8.1 4.8.0 4.7.2 4.7.1 4.7.0 4.6.0 4.5.3 4.5.2 4.5.1 4.5.0 4.4.0 4.3.3 4.3.2 4.3.1 4.3.0 4.2.1 4.2.0 4.1.3 4.1.2 4.1.1 4.1.0 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 4.0.0-beta.3 4.0.0-beta.2 4.0.0-beta.1 4.0.0-beta.0 Version 3.x# 3.25.6 3.25.4 3.25.3 3.25.2 3.25.1 3.25.0 3.24.6 3.24.5 3.24.4 3.24.3 3.24.2 3.24.1 3.24.0 3.23.4 3.23.3 3.23.2 3.23.1 3.23.0 3.22.1 3.22.0 3.21.0 3.20.1 3.20.0 3.19.1 3.19.0 3.18.2 3.18.1 3.18.0 3.17.1 3.17.0 3.16.4 3.16.3 3.16.2 3.16.1 3.16.0 3.15.1 3.15.0 3.14.0 3.13.4 3.13.3 3.13.2 3.13.1 3.13.0 3.12.2 3.12.1 3.12.0 3.11.2 3.11.1 3.11.0 3.10.0 3.9.1 3.9.0 3.8.7 3.8.6 3.8.5 3.8.1 3.7.1 3.7.0 3.6.0 3.5.1 3.4.2 3.4.1 3.4.0 3.3.0 3.1.1 3.1.0 3.0.1 3.0.0 Version 2.x# 2.2.3 2.2.2 2.2.1 2.2.0 2.1.0 2.0.4 2.0.3 2.0.2 2.0.1 2.0.0 Version 1.x# 1.2.0 1.1.0 1.0.0 Early Versions (0.x)# 0.8.0 0.7.0 0.6.3 0.6.2 0.6.1 0.6.0 0.4.2 0.4.1 0.4.0 0.3.0 0.2.4 0.2.3 0.2.2 Getting Updates# To update TaskNotes: Open Obsidian Go to Settings → Community Plugins Find TaskNotes and click \"Update\" Restart Obsidian if prompted Feedback# Found a bug or have a feature request? Please: Check existing GitHub Issues Create a new issue with details"},{"title":"Untitled","url":"/obsidian/releases/0.2.2/","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.1...0.2.2","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.1...0.2.2"},{"title":"Untitled","url":"/obsidian/releases/0.2.3/","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.2...0.2.3","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.2...0.2.3"},{"title":"Untitled","url":"/obsidian/releases/0.2.4/","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.3...0.2.4","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.3...0.2.4"},{"title":"Untitled","url":"/obsidian/releases/0.3.0/","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.4...0.3.0","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.4...0.3.0"},{"title":"Untitled","url":"/obsidian/releases/0.4.0/","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.3.0...0.4.0","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.3.0...0.4.0"},{"title":"Untitled","url":"/obsidian/releases/0.4.1/","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.1","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.1"},{"title":"Untitled","url":"/obsidian/releases/0.4.2/","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.2","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.2"},{"title":"Untitled","url":"/obsidian/releases/0.6.0/","description":"TaskNotes documentation.","product":"obsidian","text":""},{"title":"Untitled","url":"/obsidian/releases/0.6.1/","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.0...0.6.1","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.0...0.6.1"},{"title":"Untitled","url":"/obsidian/releases/0.6.2/","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.1...0.6.2","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.1...0.6.2"},{"title":"Untitled","url":"/obsidian/releases/0.6.3/","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.2...0.6.3","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.2...0.6.3"},{"title":"Untitled","url":"/obsidian/releases/0.7.0/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.7.0","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.7.0"},{"title":"Untitled","url":"/obsidian/releases/0.8.0/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.8.0","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.8.0"},{"title":"Untitled","url":"/obsidian/releases/1.0.0/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.8.0...1.0.0","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.8.0...1.0.0"},{"title":"Untitled","url":"/obsidian/releases/1.1.0/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/1.0.0...1.1.0","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/1.0.0...1.1.0"},{"title":"Untitled","url":"/obsidian/releases/1.2.0/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/1.1.0...1.2.0","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/1.1.0...1.2.0"},{"title":"Untitled","url":"/obsidian/releases/2.0.0/","description":"TaskNotes 2.0.0 - Major Feature Release","product":"obsidian","text":"TaskNotes 2.0.0 - Major Feature Release Major New Features: Kanban Board View Visual task management with drag-and-drop functionality Dynamic grouping by status, priority, or context Search filtering across all columns Real-time updates and collapsible columns Enhanced Pomodoro System SVG progress circle with refined visual timer Persistent session history and statistics tracking Dedicated Pomodoro Statistics view with completion metrics Enhanced UI with improved controls and display Advanced Task Filtering & Grouping Unified filtering system with search, status, context, priority filters Date range filtering with overdue task support Flexible grouping options (status, priority, context, due date) Performance-optimized filtering using cache indexes Enhanced Recurring Tasks Visual distinction with special styling and indicators Per-date completion tracking with smart UI controls Context menus filtered to prevent status conflicts Clear completion status display for selected dates UI/UX Improvements: Task Management Enhanced task edit modal with improved form layout Context menu (right-click) for quick property changes Autocomplete for contexts and tags in task forms Optimistic UI updates for better responsiveness View Enhancements Agenda view with improved layout and timeline organization Enhanced note cards with consistent styling across views Improved calendar integration with better visual indicators Unified card styling system across all views Performance & Reliability Migrated to unified CacheManager from legacy FileIndexer DOM reconciliation system for efficient UI updates Enhanced async handling and error management Improved cache update handling and race condition prevention Additional Improvements: Enhanced due date modal with better styling Improved time tracking UX with visual feedback Better task archival feedback and UI consistency Refined keyboard navigation and accessibility Updated README with comprehensive feature documentation Bug Fixes: Fixed 'No due date' group positioning in task list Resolved various UI spacing and alignment issues Improved handling of edge cases in recurring task logic Enhanced stability of cache operations and file handling This major release significantly expands TaskNotes capabilities with new views, enhanced filtering, and improved user experience while maintaining data compatibility with previous versions."},{"title":"Untitled","url":"/obsidian/releases/2.0.1/","description":"Bug Fixes and Enhancements:","product":"obsidian","text":"TaskNotes 2.0.1 - Recurring Tasks and Filtering Improvements# Bug Fixes and Enhancements: Recurring Task Improvements: Fixed recurring tasks not appearing in correct due date groups (Today, Tomorrow, etc.) Recurring tasks now properly appear in 'Today' group when selected date matches recurrence pattern Enhanced recurring task visual styling with distinctive indicators and backgrounds Smart context menus for recurring tasks that prevent conflicting status changes Fixed recurrence values not loading properly in task edit modal Task Filtering and Grouping: Improved 'No due date' group positioning to appear at bottom of task list Enhanced FilterService with target date awareness for intelligent recurring task grouping Fixed cache integration issues where recurrence changes didn't trigger proper view updates All views now properly refresh and regroup tasks when recurrence properties change UI and Data Consistency: Fixed data format mismatch between stored abbreviations and UI display for day names Improved task edit modal to properly convert between storage format and UI format Enhanced cache workflow integration for seamless task property updates Better synchronization between task edits and view refreshes Technical Improvements: Added conversion helper methods for consistent day name handling Enhanced cache manager with proper recurring task support Improved event emission and handling for task updates Better error handling and data validation in task modals This release focuses on making recurring tasks work seamlessly with the filtering and grouping system while maintaining data consistency and improving the overall user experience."},{"title":"Untitled","url":"/obsidian/releases/2.0.2/","description":"Bug Fixes:","product":"obsidian","text":"TaskNotes v2.0.2# Bug Fixes: Fixed recurring tasks without due dates not appearing in agenda view Recurring tasks now properly show on their scheduled days in agenda view Settings Improvements: Enhanced Priorities settings tab with comprehensive usability improvements Added detailed descriptions, help sections, and column headers Added input validation and better visual organization Matches the improved usability of the Statuses settings tab Technical Details: Modified FilterService date range filtering to properly handle recurring tasks without due dates Added logic to check if recurring tasks should appear on any date within the specified range Uses existing isRecurringTaskDueOn helper for accurate recurrence calculations Maintains full backward compatibility for all existing functionality"},{"title":"Untitled","url":"/obsidian/releases/2.0.3/","description":"Bug Fixes:","product":"obsidian","text":"Bug Fixes: Fixed recurring tasks without due dates not appearing in agenda view Recurring tasks now properly show on their scheduled days in agenda view Command Improvements: Removed layout-specific commands (open-linked-views, open-grid-layout, open-tabs-layout) Removed popout window commands for cleaner command palette Added 'Refresh TaskNotes cache' command for troubleshooting Simplified ribbon icons to focus on core functionality Technical Details: Enhanced FilterService initial task set logic to include recurring tasks without due dates Modified getTaskPathsInDateRange() to check all recurring tasks for date range inclusion Added async processing with batched performance optimizations Maintained backward compatibility and existing performance characteristics Root cause: CacheManager only indexed tasks by actual due dates, excluding recurring tasks without due dates from date-based queries The agenda view now correctly displays recurring tasks without due dates on their appropriate scheduled days."},{"title":"TaskNotes v2.0.4","url":"/obsidian/releases/2.0.4/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.0.3...2.0.4","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.0.3...2.0.4 Allow multiple statuses to be filtered for at the same time, bringing status filtering in line with context and priority filtering Fix flickering during kanban drag and drop"},{"title":"TaskNotes v2.1.0 - Major Feature Release","url":"/obsidian/releases/2.1.0/","description":"This release introduces significant workflow enhancements and editor integration features that streamline task management directly within the Obsidian editing experience.","product":"obsidian","text":"This release introduces significant workflow enhancements and editor integration features that streamline task management directly within the Obsidian editing experience. NEW FEATURES:# Instant Task Conversion One-click conversion of checkbox tasks to dedicated TaskNotes with inline convert buttons Streamlined workflow for transforming simple tasks into structured task files Configurable via settings to enable/disable the feature Interactive Task Link Overlays Live task previews displayed on wikilinks in live preview mode Hover and click interactions for editing tasks without leaving the current note Context menus and inline task information display Smart detection of task-related wikilinks with automatic enhancement Enhanced Date Handling Improved overdue task detection that considers both due and scheduled dates Better date consistency across all views and components Expanded field mapping support for time tracking and completion data IMPROVEMENTS:# Performance & Reliability Comprehensive resource cleanup to prevent memory leaks Enhanced error handling with better user feedback Performance optimizations in calendar view and task rendering Improved DOM reconciliation and widget management Accessibility & UX Enhanced accessibility with ARIA attributes and keyboard navigation Consistent BEM CSS naming across all components Better input validation and security measures Improved visual consistency throughout the interface Technical Enhancements Fixed deprecated Obsidian API usage for better compatibility Standardized date handling using date-fns library Configurable pomodoro field mapping Better separation of concerns in component architecture This release maintains full backward compatibility while adding new features that enhance the daily task management workflow."},{"title":"TaskNotes v2.2.0","url":"/obsidian/releases/2.2.0/","description":"TaskNotes documentation.","product":"obsidian","text":"Major Features# Task Deletion: Added task deletion functionality with confirmation modal and proper event handling Pomodoro Data Migration: Implemented migration utility for backward compatibility with existing Pomodoro session data Enhanced Calendar Navigation: Improved CalendarView date navigation and refresh logic Core Improvements# Timezone-Safe Date Handling: Complete overhaul of date utilities to ensure consistent timezone handling across the codebase Centralized Task Management: Refactored task creation and editing to use centralized TaskService architecture Improved Date Filtering: Enhanced FilterService with better date comparison logic for due and scheduled tasks Pomodoro Session Tracking: Refactored session tracking and duration calculations for better accuracy UI/UX Enhancements# Visual Consistency: Updated font sizes and UI element widths for better readability Pomodoro Button Styling: Enhanced button styles with consistent visual feedback Inline Widget Cleanup: Improved task update handling and cleaned up inline widget styles Technical Improvements# Safer Date Parsing: Replaced parseISO with parseDate utilities for more robust date handling ISO Timestamp Support: Updated timestamp generation to return ISO format with local timezone offset Performance Optimizations: Various refactoring improvements for better code maintainability and performance"},{"title":"Untitled","url":"/obsidian/releases/2.2.1/","description":"Fix #22 and #24","product":"obsidian","text":"Fix #22 and #24"},{"title":"Untitled","url":"/obsidian/releases/2.2.2/","description":"TaskNotes documentation.","product":"obsidian","text":""},{"title":"Untitled","url":"/obsidian/releases/2.2.3/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.2.2...2.2.3","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.2.2...2.2.3"},{"title":"Untitled","url":"/obsidian/releases/3.0.0/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.3.0...3.0.0","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.3.0...3.0.0"},{"title":"Untitled","url":"/obsidian/releases/3.0.1/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.0.0...3.0.1","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.0.0...3.0.1"},{"title":"Untitled","url":"/obsidian/releases/3.1.0/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.0.1...3.1.0","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.0.1...3.1.0"},{"title":"Untitled","url":"/obsidian/releases/3.1.1/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.1.0...3.1.1","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.1.0...3.1.1"},{"title":"Release Notes: 3.10.0","url":"/obsidian/releases/3.10.0/","description":"This version introduces a new data storage option for tasks, adds a status bar component for time tracking, and includes several bug fixes and internal improvements.","product":"obsidian","text":"This version introduces a new data storage option for tasks, adds a status bar component for time tracking, and includes several bug fixes and internal improvements. New Features# Option to Store Task Title in Filename# A new setting, storeTitleInFilename, is available under \"Task Filenames\" in the settings tab. This feature changes how task titles are stored. Implementation Details: When this setting is enabled, creating a new task will use its title to generate the filename (e.g., My New Task.md). The title field will be omitted from the task's frontmatter. For reading tasks, the application will first look for a title field in the frontmatter. If it is not found, the system will use the filename as the task's title. This ensures backward compatibility with existing tasks. When a task's title is updated, and this setting is active, the file itself is automatically renamed to match the new title. The file's frontmatter is updated before the rename operation occurs to ensure data integrity. Enabling this setting disables and hides the other filename format options (Zettelkasten, timestamp, custom). This setting is disabled by default. Status Bar Component for Tracked Tasks# A new UI component has been added to the app's status bar to display tasks with active time-tracking sessions. Functionality: When a single task is being tracked, its title (truncated if necessary) is displayed in the status bar. The full title is visible in a tooltip. When multiple tasks are being tracked, a count of these tasks is displayed. The tooltip lists the titles of the tracked tasks. The status bar item is hidden when no tasks are being tracked. This feature is controlled by the \"Show tracked tasks in status bar\" setting and is disabled by default. Customizable First Day of Week for Mini Calendar# The mini calendar view now respects the \"First day of the week\" setting in Obsidian's general settings. The calendar grid will adjust to start the week on the day you have configured (e.g., Sunday or Monday). Bug Fixes# Search Functionality: Resolved a type error in the search filter that occurred when a task's title or context field was null. The code now handles null values gracefully during search operations. File Renaming: Corrected the order of operations when storeTitleInFilename is enabled. The previous implementation could rename the file before its frontmatter was updated, which has now been fixed. Internal Improvements & Documentation# Service Refactoring: The TaskService, FieldMapper, and MinimalNativeCache have been updated to handle the new logic for storing and retrieving task titles from filenames. StatusBarService: A new StatusBarService was implemented to encapsulate the logic for the new status bar component, including its creation, updates, and event handling. Issue Templates: The GitHub issue templates for bug reports and questions have been updated to be more structured and improve the quality of submitted reports. Documentation: Added a new section to the documentation explaining the storeTitleInFilename feature in detail."},{"title":"Release Notes: 3.11.0","url":"/obsidian/releases/3.11.0/","description":"This release introduces a new project management system, significant enhancements to the Pomodoro timer and workflows, and a number of quality-of-life improvements and bug fixes.","product":"obsidian","text":"This release introduces a new project management system, significant enhancements to the Pomodoro timer and workflows, and a number of quality-of-life improvements and bug fixes. New Features# Project Management# A new project management system has been integrated, allowing for better organization and tracking of tasks within projects. Note-Based Projects: Projects are now properly integrated into TaskNotes. You can link tasks to any note in your vault, effectively turning that note into a project. This leverages Obsidian's core linking capabilities, allowing you to see all tasks related to a project in the backlinks of the project note. Project Selection UI: A new project selection modal has been added to the task creation and editing modals. It features fuzzy search to quickly find and assign tasks to project notes. Filtering and Grouping by Project: The Filter Bar in all views now includes a \"Project\" filter, allowing you to see tasks for one or more specific projects. The \"Group By\" option now includes \"Project\", which organizes the Task List and Kanban views by project. Clickable Project Links: In task cards and other views, project names are now clickable links that take you directly to the project note. Workflow and UI Enhancements# Redesigned Pomodoro Timer: The Pomodoro timer has been completely redesigned for a more modern and user-friendly experience. New Interface: A more compact and visually appealing interface. Time Adjustment: You can now add or subtract time from the current session or the prepared timer. Skip Break: A \"Skip break\" button is now available after a work session. Enhanced Pomodoro Stats: The Pomodoro statistics view has been improved to provide more insights. Overview Section: A new overview section shows today's completed Pomodoros, total focus time, and a comparison with yesterday's performance. Instant Task Conversion: The \"Convert task to TaskNote\" command has been streamlined. It now instantly converts a checkbox task into a TaskNote without opening the creation modal, reducing friction. Quick Actions for Current Task: A new command, \"Quick actions for current task,\" allows you to open the action palette for the currently active TaskNote, providing quick access to common operations. Improved Sorting Logic: The task sorting algorithm has been enhanced. When the primary sorting criterion (e.g., due date) is the same for multiple tasks, a fallback sorting order is applied: scheduled date -> due date -> priority -> title. This ensures a more predictable and logical ordering of tasks. Archive Button in Edit Modal: An \"Archive\" button has been added to the task edit modal, allowing for quick archiving and unarchiving of tasks. Week Start Day Setting: All calendar views now respect the \"Start week on\" setting from Obsidian's calendar preferences. Bug Fixes and Minor Improvements# Recurring Task Date Consistency: A critical bug has been fixed where recurring task dates could appear on the wrong day in different timezones (especially CST). The handling of dates and timezones for recurring tasks is now more robust, ensuring consistency across all views. Pomodoro Daily Note Integration: The Pomodoro service now correctly handles adding session history to daily notes, preventing the creation of duplicate entries. Template Processing: The {{parentNote}} template variable now correctly resolves to a properly formatted markdown link. YAML frontmatter in templates is now processed more safely to avoid parsing errors. Date Validation: The complete_instances field for recurring tasks now has stricter validation to filter out invalid entries, improving data integrity. Natural Language Processing: The natural language parser now correctly applies scheduled times (e.g., \"do something at 5pm\") to created tasks. Agenda View Quick Select: A bug that prevented the date quick-select menus in the Agenda View from working after the first use has been fixed. Styling and CSS: Numerous styling improvements have been made across the plugin for a more polished and consistent look and feel, including to the Pomodoro views, task cards, and modals. Documentation: The documentation has been updated to reflect the new project management features. New workflow guides for \"Habit Tracking\" and \"Project Management\" have been added."},{"title":"Release Notes 3.11.1","url":"/obsidian/releases/3.11.1/","description":"This release focuses on adopting Obsidian's official APIs and improving plugin stability through better resource management.","product":"obsidian","text":"API Modernization & Performance Improvements# This release focuses on adopting Obsidian's official APIs and improving plugin stability through better resource management. Improved autocomplete# Replaced custom autocomplete implementation with Obsidian's native AbstractInputSuggest API Better keyboard navigation and visual consistency More responsive type-ahead support for contexts and tags in task modals API modernization# Atomic Frontmatter Updates: Now uses FileManager.processFrontMatter for safer file modifications Eliminates risk of data corruption during migration processes More reliable handling of YAML frontmatter updates Native Link Parsing: Switched to Obsidian's built-in parseLinktext API More robust wikilink parsing with better edge case handling Improved consistency with Obsidian's internal link processing Vault-Specific Storage: View preferences now use App.loadLocalStorage/saveLocalStorage Fixes issue where settings were shared across different vaults Each vault now maintains its own view state and preferences Bug fixes & stability# Memory Leak Prevention: Properly register and cleanup event listeners Event listeners are now tracked with EventRef objects for proper cleanup Prevents memory leaks when plugin is disabled or reloaded Debounce Optimization: Uses Obsidian's built-in debounce function More efficient calendar refresh operations Better performance consistency UI Polish: Fixed sentence case issues throughout the interface Security & reliability# Resource Cleanup: Enhanced plugin lifecycle management Better cleanup of event listeners and cached data Improved plugin disable/enable reliability"},{"title":"Release Notes - 3.11.2","url":"/obsidian/releases/3.11.2/","description":"TaskNotes documentation.","product":"obsidian","text":"Internal Improvements# API Standardization# Replaced custom wikilink parsing with Obsidian's native parseLinktext API Migrated from custom debounce function to Obsidian's built-in debounce utility Files Updated# TaskLinkOverlay.ts: Updated wikilink parsing FilterService.ts: Improved project link resolution TaskLinkDetectionService.ts: Simplified link detection MinimalNativeCache.ts: Standardized project link handling KanbanView.ts: Replaced custom debounce implementation Test files: Updated mocks accordingly"},{"title":"Release Notes - 3.12.0","url":"/obsidian/releases/3.12.0/","description":"TaskNotes documentation.","product":"obsidian","text":"New Features# Project Subtasks Widget# Add a collapsible widget that displays tasks linked to the current project note Widget appears automatically in project notes and shows all tasks that reference the rpoject Includes collapsible interface with persistent state across sessions Updates automatically when tasks are modified or deleted Can be enabled or disabled in plugin settings under \"Show project subtasks widget\" Bug Fixes# FilterBar Improvements# Fixed FilterBar not updating dynamically when tasks get new contexts or projects (#138) Fixed archived tasks' contexts and projects still appearing in filter bar (#139) Resolved FilterBar showing projects with [[]] brackets Fixed empty status list display on initial load Improved initialization reliability with better event handling Task Display# Fixed wikilink alias handling in TaskCard and inline displays (#145, #147) Fixed projects not loading correctly in task edit modal (#141) Improved cursor positioning in live preview mode Documentation# Added documentation for project subtasks widget feature Updated inline task integration documentation Added configuration settings documentation"},{"title":"Release Notes - 3.12.1","url":"/obsidian/releases/3.12.1/","description":"TaskNotes documentation.","product":"obsidian","text":"New Features# Project Subtasks Widget Enhancements# New button for task creation - Added \"New\" button to widget header for quick task creation Auto-populated project field - New tasks automatically reference the current note as their project Improved positioning - Widget now appears at the end of documents for better user experience Improve visual design - Added dashed border to indicate virtual/generated content and improved styling Bug Fixes# Timezone and Date Handling# Fixed timezone boundary issues in Agenda view date filtering (#153) Resolved missing tasks that were scheduled 7 days ago or yesterday due to timezone drift Enhanced date normalization in AgendaView for consistent behavior across timezones Improved task filtering with better date handling in getTasksForDate() UI and Display Improvements# Fixed cursor positioning to prevent cursor appearing after project subtasks widget Resolved pre-populated projects not displaying correctly in task creation modal Improved widget rendering with CSS-only styling approach for better performance Settings Reorganization# New Misc Tab# Renamed \"Performance\" tab to \"Misc\" and moved to end of settings tab list Consolidated miscellaneous features into a single organized location Improved settings navigation by grouping related toggles together Settings Moved to Misc Tab# Status bar toggle - Show tracked tasks in status bar Project subtasks widget toggle - Show project subtasks widget in notes Notes indexing toggle - Disable note indexing for performance optimization Documentation Updates# Settings Documentation# Updated all documentation to reflect new settings organization Created comprehensive Misc Settings documentation with detailed explanations Removed outdated references from Advanced Settings documentation Updated troubleshooting guides with correct setting locations Reference Updates# Updated inline task feature documentation to reference new Misc tab location Fixed all setting location references throughout documentation Maintained backward compatibility information for users upgrading"},{"title":"Release Notes - 3.12.2","url":"/obsidian/releases/3.12.2/","description":"TaskNotes documentation.","product":"obsidian","text":"Bug Fixes# Calendar & Date Handling# Fixed off-by-one date bugs in completion calendar (#160) Resolved timezone inconsistency where calendar showed one date but completion was recorded for another Calendar rendering now uses UTC dates consistently across all components Fixed \"Friday tasks appearing on Saturday\" issue in completion tracking Task Management# Fixed project filters not working in agenda view (#161) Project filtering now works consistently across all views Fixed edit modal crash when tasks have empty project properties Added null checks to prevent \"Cannot read properties of null\" errors Handles null, undefined, and empty string project values gracefully Fixed autofill suggestions not updating internal state (#159) Context and tag suggestions now properly sync with modal internal state Clicking suggestions now correctly updates the task data UI & Styling# Fixed consistent styling for priorities and statuses settings tabs (#130) Added missing BEM classes for proper grid alignment Priority inputs now use same styling as status inputs Fixed table column misalignment issues Documentation# Improved README and documentation Enhanced overview section with better flow and natural language Added time-tracking and pomodoro feature descriptions Fixed broken documentation links Updated Core Features section with more accurate descriptions Testing# Added comprehensive tests for date handling issues Increased test coverage for calendar and completion functionality Added tests reproducing and verifying fixes for off-by-one date bugs"},{"title":"Release Notes - 3.13.0","url":"/obsidian/releases/3.13.0/","description":"##Technical Changes","product":"obsidian","text":"Major Changes# Filtering System Overhaul# Hierarchical Query Builder: Complete redesign of the filtering system with a query builder interface Saved Views: Users can save, manage, and switch between custom filter configurations FilterBar Redesign: Updated to use Obsidian components with improved styling UI Updates# FilterBar Integration: Added to all task views (Kanban, List, Calendar, Agenda) with state management Dropdown Improvements: Status and priority filters now use display labels Dropdown Positioning: Fixed positioning and CSS styling issues New Features# Natural Language Processing# Nested Tag Support: Tags with forward slashes are now supported (e.g., project/subtask) Interface# Project Note Decorations: Updated styling and visual elements Task Modal Styling: Refined task creation and editing interfaces Bug Fixes# Filter System# Fixed handling of empty arrays in \"Projects is not empty\" conditions Fixed incomplete filter conditions handling Fixed saved views dropdown persistence when filters change Fixed view options disappearing on refresh Fixed view selector dropdown behavior Testing# Fixed multiple unit and integration test failures Fixed migration workflow test for YAML parsing errors Expanded test coverage for task service completion Code Quality# Removed debug console.log statements Improved async handling and import organization Better search functionality implementation ##Technical Changes Refactoring# Refactored FilterBar with Obsidian components Updated filter rule definitions and UI components Improved state management across views Updated ViewStateManager Development# Updated Typescript configuration Added new Filter Utils.ts utility module Improved code organization"},{"title":"Release Notes - 3.13.1","url":"/obsidian/releases/3.13.1/","description":"TaskNotes documentation.","product":"obsidian","text":"New Features# Saved Filter Views Storage# Saved filter views now sync across devices with your vault Views are stored in plugin data instead of browser localStorage Automatic migration from previous storage system on first load FilterBar Behavior# Filter panel now stays open when clicking elsewhere in the interface Panel only closes when the filter button is clicked again Eliminates accidental filter panel closures during normal use Performance Improvements# Filter Operations# Adding and removing filters is now significantly faster Reduced lag when building complex filter queries Search input state preserved during filter modifications Migration System# Early migration detection prevents DOM errors on first use Better error handling during plugin initialization Cleaner migration process for new users Bug Fixes# First-Time User Experience# Fixed \"removeChild\" DOM errors when using filters for the first time Resolved race conditions between migration and UI initialization Added fallback UI states for improved reliability FilterBar Stability# Added DOM connection checks before manipulation Improved error boundaries in filter rendering Better cleanup of event listeners on component destruction Technical Changes# View State Management# Saved views migrate from localStorage to plugin data system ViewStateManager now uses plugin settings for persistence Enhanced migration detection and completion tracking Error Handling# Added safety checks for DOM element manipulation Graceful degradation when filter operations fail Improved logging for troubleshooting migration issues"},{"title":"Release Notes - 3.13.2","url":"/obsidian/releases/3.13.2/","description":"TaskNotes documentation.","product":"obsidian","text":"Performance Improvements# FilterBar and Saved Views# Fixed performance issue where adding new filter conditions would unnecessarily re-evaluate all existing filters Added \"Select...\" placeholder option for new filter conditions to prevent premature filtering Eliminated unnecessary cache re-indexing when saving or deleting saved views Made settings system smarter to only trigger cache updates when indexing-related settings actually change Filter Processing# Implemented index-backed filtering that processes significantly fewer tasks for filtered views Added intelligent query result caching with automatic expiration to eliminate redundant operations Improved candidate selection using existing status, date, and overdue task indexes Enhanced set intersection logic for multiple AND conditions to further reduce processing Bug Fixes# Filter Logic# Fixed critical bug where index optimization incorrectly excluded valid results for OR queries containing indexed conditions Added detection logic to prevent unsafe optimizations when indexed conditions are part of OR groups Improved query structure analysis to ensure filter correctness Saved Views# Fixed issue where modifying one saved view could affect others due to shared object references Added proper deep cloning of FilterQuery objects throughout the ViewStateManager Ensured saved views remain independent when modified Technical Details# Index Optimization Safety# Index optimizations now only apply when provably safe (AND relationships between indexed conditions) Added recursive query analysis to detect OR groups containing indexed conditions Maintains filter correctness while providing performance benefits where safe Cache Management# Cache-related settings tracking: taskTag, excludedFolders, disableNoteIndexing, storeTitleInFilename, fieldMapping Query result caching with 30-second auto-expiration and immediate invalidation on data changes Debug logging available for performance monitoring Performance Impact# Filter building is now responsive with no lag when adding conditions Saved view operations are instant with no unnecessary re-indexing Repeated filter operations are nearly instant due to intelligent caching Significant memory usage reduction for large vaults"},{"title":"Release Notes - 3.13.3","url":"/obsidian/releases/3.13.3/","description":"TaskNotes documentation.","product":"obsidian","text":"Bug Fixes# Fixed recurring task completion date recording# Resolved issue where \"mark completed for this date\" context menu option recorded completion for the wrong date Fixed timezone inconsistency between completion date storage and checking logic Recurring tasks now properly track completion status per calendar date Improved recurring task filtering# Fixed \"Is completed\" filter condition to respect per-date completion status for recurring tasks Filter results now accurately reflect whether recurring tasks are completed for specific dates Enhancements# AgendaView improvements# Restored Today button with improved header layout Reorganized header into three sections: navigation controls, period title, and actions Fixed recurring task display to show tasks on their actual recurrence dates rather than just scheduled dates Removed keyboard navigation shortcuts (left/right arrows) Interface updates# Enhanced AgendaView header styling with better spacing and visual hierarchy Added responsive design for mobile layouts Improved button styling with proper hover and focus states Technical Changes# Updated TaskService to use consistent local timezone formatting for completion dates Enhanced FilterService to properly evaluate recurring task completion status Improved AgendaView task fetching to use FilterService.getTasksForDate() for better recurrence handling Testing# Added comprehensive test coverage for timezone handling and date formatting consistency Added tests to verify recurring task completion behavior across different scenarios"},{"title":"Release Notes - 3.13.4","url":"/obsidian/releases/3.13.4/","description":"Thanks to @cathywu, @Crunchnuggetz, @Poly-0000, @jpmoo and finally @bcohen44 for reporting the FilterBar crashes that led to identifying these migration issues.","product":"obsidian","text":"Bug Fixes# FilterBar Migration Issues# Fixed critical TypeError crashes when upgrading from versions prior to 3.13.0 Resolved Cannot read properties of undefined (reading 'forEach') and Cannot read properties of undefined (reading 'find') errors in FilterBar rendering Added detection for old FilterQuery format and automatic replacement with fresh defaults Users upgrading from older versions now get clean filter states instead of broken data structures Preserved valid sort and grouping settings when replacing incompatible filter data Added error boundaries with console warnings for better debugging Thanks to @cathywu, @Crunchnuggetz, @Poly-0000, @jpmoo and finally @bcohen44 for reporting the FilterBar crashes that led to identifying these migration issues. Features# Calendar View Improvements# Added ICS refresh button directly in the Advanced Calendar view toolbar ICS calendar subscriptions can now be refreshed without opening settings Button integrates with existing ICS subscription service and triggers immediate calendar re-render Improved ICS settings layout with horizontal button arrangement Enhanced calendar styling with proper hover states and removed unnecessary CSS overrides Extended today highlight disable to timegrid columns for visual consistency Notes# This release focuses on stability improvements for users upgrading from older versions. The FilterBar migration fixes ensure that users moving from pre-3.13.0 versions will have a smooth experience with the new filtering system introduced in 3.13.0. The ICS refresh button provides better user experience by allowing calendar data to be updated directly from the calendar view without navigating to settings."},{"title":"Release 3.14.0","url":"/obsidian/releases/3.14.0/","description":"TaskNotes documentation.","product":"obsidian","text":"New Features# Project Management Enhancements# Project Indicator Icons: TaskCard now displays visual indicators when tasks are used as projects [#191] - Thanks to @Poly-0000 for the suggestion Project Filtering: Added comprehensive project filtering functionality to the main plugin [#191] Create Subtask Option: Added \"Create subtask\" option to task card context menu for improved project workflow [#192] - Thanks to @Poly-0000 for the feature request Project Detection: Enhanced ProjectSubtasksService with isTaskUsedAsProject method for better project identification [#191] User Interface Improvements# Drag-and-Drop Saved Views: Implemented drag-and-drop reordering for saved views to improve workflow customization [#203] - Thanks to @jpmoo for the suggestion Project Styling: Added CSS styling for project indicator icons to improve visual hierarchy [#191] Created Date Sorting: Added 'Created Date' as a sort key option for better task organization [#188] - Thanks to @bl4z3ng41n for the PR Bug Fixes# Calendar and Recurring Tasks# Calendar Resize Support: Fixed duration updates for recurring tasks via calendar resize operations All-Day Handling: Improved recurring task all-day handling in calendar view [#201] - Thanks to @anomatomato and @bespokecomp for reporting Settings and State Management# Pomodoro Session Persistence: Fixed issue where pomodoro sessions were being cleared when changing settings [#196] - Thanks to @anomatomato for the bug report Technical Changes# Performance and Stability# Enhanced cache management and event handling for project-related functionality Improved error handling in project subtask operations Optimized project detection algorithms for better performance Code Organization# Refactored project-related services for better modularity Enhanced TypeScript type definitions for project functionality Improved service initialization and cleanup processes Documentation# Updated README with new project assets and feature documentation"},{"title":"Release 3.15.0","url":"/obsidian/releases/3.15.0/","description":"TaskNotes documentation.","product":"obsidian","text":"New Features# NLP Input Enhancements# Auto-suggestions: Added autocomplete functionality for tags and contexts in NLP input [#131] - Thanks to @Poly-0000 for the suggestion Project Auto-suggestions: Enhanced project auto-suggestions with rich display and field mapper integration Context and Tag Suggestions: Implemented auto-suggestion system to prevent typos and improve consistency [#131] Calendar Integration# ICS Event Integration: Added comprehensive ICS calendar event support with content creation capabilities [#122, #220] - Thanks to @donjjones and @Crunchnuggetz for the feature requests ICS Event Creation: Integrated ICS events into field mapping and type system for note creation [#122, #220] ICS Settings: Added ICS integration settings to calendar tab Calendar Hover Previews: Implemented hover preview functionality for advanced calendar - Thanks @nightroman for noticing this Time Entry Interaction: Added time entry interaction functionality to advanced calendar Time Management# Auto-stop Tracking: Added automatic time tracking termination when tasks are completed - Thanks to @cathywu for the suggestion [#184] Total Tracked Time: Enhanced edit modal to display total tracked time information [#181] - Thanks to @bcohen44 for the feature request Pomodoro View: Added task card display and improved controls to pomodoro view [#184] Timeblock Management: Enhanced TimeblockInfoModal with editing and deletion capabilities [#74] - Thanks to @bepolymathe for the suggestion User Interface Improvements# Fuzzy Note Pickers: Enhanced note pickers with title and alias support [#192] - Thanks to @Poly-0000 for the feedback Persistent Column Ordering: Added persistent column ordering to kanban board [#61] - Thanks to @slepsl for the suggestion Click-outside Support: Added click-outside and keyboard support to filter bar [#227] - Thanks to @cstelmach for the UX improvement request UI Polish: Removed unnecessary borders, shadows and transitions from various UI elements Bug Fixes# Task Management# Nested Tags: Fixed support for nested tags in FilterBar TypeError Resolution: Resolved TypeError when calling includes on non-array values Calendar Integration# Default Time Estimate: Fixed calendar click-to-add operations to respect default time estimate setting [#233] - Thanks to @nightroman for the bug report Time Slot Duration: Improved click detection in calendar to use time slot duration setting [#233] Documentation# Auto-suggestion Documentation: Added comprehensive documentation for auto-suggestion functionality ICS Integration Guide: Created detailed ICS calendar integration documentation Release Notes: Added comprehensive release notes documentation with links to all versions Inline Task Widget: Added screenshots and documentation for inline task widgets Technical Changes# Code Organization# Enhanced service architecture for ICS integration Improved field mapping system for calendar events Optimized auto-suggestion algorithms Enhanced type definitions for new functionality Performance# Improved rendering performance for pomodoro view Optimized calendar event handling Enhanced note picker search capabilities"},{"title":"Release 3.15.1","url":"/obsidian/releases/3.15.1/","description":"TaskNotes documentation.","product":"obsidian","text":"New Features# Kanban Board Enhancements# Show Empty Status Columns: Kanban board now displays empty columns for all configured statuses, providing better visual structure and workflow clarity Enhanced Task Grouping: Introduced GetGroupedTasksOptions interface for improved task grouping functionality with target date support and group pre-population [#236] - Thanks to @srcnDev for the implementation Calendar Improvements# All-Day Event Styling: Added line-through styling for completed all-day events in the Advanced Calendar view [#252, #254] - Thanks to @anomatomato for reporting the issue and submitting the PR Task Event Customization: Task events in the Advanced Calendar now include CSS classes based on their tags (e.g., fc-tag-meeting, fc-tag-work), enabling custom styling per tag [#243, #244] - Thanks to @jradam for the feature request and implementation Bug Fixes# Kanban Board# Duplicate Column Prevention: Fixed issue where renaming existing statuses in Kanban configuration could result in duplicate columns appearing in the board [#258] - Thanks to @mat2022a for the bug report Subtask Widget Issues# Split Pane Display: Resolved issue where subtask widgets would inappropriately appear on notes in split panes when focusing on different notes [#234] Table Cell Interference: Fixed subtask widgets appearing inside table cells when editing tables in project notes [#207] Technical Changes# Documentation# Fixed line break formatting issues in documentation files Code Organization# Improved task grouping architecture with new options interface Enhanced calendar event rendering system for better tag-based customization Refined subtask widget positioning logic for better editor integration"},{"title":"TaskNotes 3.16.0","url":"/obsidian/releases/3.16.0/","description":"Extra thanks to @Totobal5 for multiple code contributions including (tricky!) Pomodoro timer fixes and advanced calendar resizing fixes","product":"obsidian","text":"New Features# Task Management# Bulk Task Conversion: Added command to convert all checkbox tasks in a note to TaskNotes at once (#28) - Thanks to @TheSnakePolyglot for the feature request Instant Task Conversion Enhancement: Enable instant task conversion for any line type, not just existing tasks (#259, #262) - Thanks to @ghelton and @cathywu for the suggestions Default Project Setting: Added option to set a default project for new tasks in task creation settings (#250) - Thanks to @davidszerman for the request Advanced Tag and Project Parsing: Implement intelligent parsing of tags and projects during instant task conversion (#260) - Thanks to @mdbraber for reporting this bug Enhanced Filter Bar Integration: Added FilterBar integration to subtask widget for better task organization (#267) - Thanks to @mdbraber for the suggestion Calendar and Views# Custom Multi-Day Calendar View: Added configurable custom multi-day calendar view with support for 3-day, work week, and full week layouts (#282) - Thanks to @girisumit for the feature request Responsive Calendar UI: Hide calendar title in narrow containers for better responsive design (#285) - Thanks to @girisumit for the improvement suggestion Locale-Aware Date Formatting: Added locale-aware date formatting to advanced calendar view (#210) - Thanks to @emes81 for highlighting this usability issue Saved Views Enhancement: Added view options support to saved views with active view name display in filter condition builder (#245) - Thanks to @kmaustral and @digitaldoctors for the feedback Task Organization# Drag and Drop Status Reordering: Added drag and drop reordering for status configurations with hamburger menu icon (#291) - Thanks to @23426356587 for the suggestion Overdue Tasks Filter: Added setting to hide completed tasks from overdue status display (#300) - Thanks to @Lankly and @violetbp for reporting the issue Project Group Enhancements: Made project group labels clickable in Task List View with ctrl+hover preview support (#198) - Thanks to @jpmoo for the suggestion Pomodoro Timer# Background Timer Continuity: Pomodoro timer now continues running when app is minimized or loses focus (#136) - Thanks to @Poly_0000 for reporting and @Totobal5 for the fix System Notifications: Convert Pomodoro notices to system notifications for better visibility (#136) Manual Duration Adjustment: Fixed manually adjusted Pomodoro duration being ignored on start (#293) - Thanks to @Totobal5 for identifying and fixing Task Completion Sorting: Sort completed tasks to end of Pomodoro task selector for better organization Bug Fixes# UI and Interaction# Tooltip Standardization: Standardized tooltips to use Obsidian's native setTooltip function to eliminate duplicate tooltips (#257) - Thanks to @digitaldoctors for the bug report Open Note Button Stability: Stabilized Open note button hover behavior and made font size consistent with other modal buttons Date Context Menu Clarity: Added titles to date context menus for better user clarity (#253) - Thanks to @digitaldoctors for the suggestion Project Removal: Fixed project removal in edit modal not saving changes properly (#213) Advanced Calendar Resizing: Fixed Advanced Calendar view not resizing correctly in detached windows (#137) - Thanks to @macbikegeek for reporting and very much to @Totobal5 for the fix Calendar and Recurring Tasks# Timezone Bug Fixes: Resolved multiple timezone-related off-by-one bugs in recurring task completion and agenda view display - A big thanks to @jpmoo and @kmaustral for reporting and describing in detail this bug Custom Calendar Display: Fixed undefined days display in custom calendar view Calendar Recurrence: Resolved timezone-based off-by-one bugs in calendar recurrence calculations - Thanks to @jpmoo and @kmaustral for reporting this bug Task Management# Pomodoro Task Tracking: Handle task filename changes in pomodoro view to prevent tracking issues (#289) - Thanks to @cathywu for the report Plugin Conflict Protection: Made suggestion objects defensive against potential plugin conflicts (#304) - Thanks to @zeltak for reporting the plugin conflict Instant Conversion Improvements: Use cleaned title for NLP parsing in instant task conversion with fallback to default tasks folder (#128) - Thanks to @bepolymathe for reporting the folder issues Improvements# User Interface# Minimalist Design System: Implemented consistent borderless button design system across all components UI Polish: Applied minimalist styling with cleaned up borders and shadows throughout the interface Settings Enhancement: Enhanced settings explanatory sections with improved minimalist styling Advanced Calendar Title: Made advanced calendar title smaller for better proportions Search and Filtering# Enhanced Search: Improved search functionality to preserve existing filters when performing new searches Filter Preservation: Better handling of filter states across different search operations Development and Code Quality# Code Documentation: Improved code comments and documentation throughout the codebase Linting Cleanup: Resolved various linting errors and improved code consistency Test Infrastructure: Updated timezone-related tests to work reliably in CI environment GitHub Actions: Added timeouts and offline preferences to improve CI reliability Technical Improvements# Reduced excessive console logging from filter components Updated Jest coverage thresholds to realistic levels Improved error handling in various components Improved defensive programming practices throughout the codebase Contributors# Extra thanks to @Totobal5 for multiple code contributions including (tricky!) Pomodoro timer fixes and advanced calendar resizing fixes"},{"title":"TaskNotes 3.16.1","url":"/obsidian/releases/3.16.1/","description":"TaskNotes documentation.","product":"obsidian","text":"New Features# Task Management# Visual Filter State Indicators: Added visual state indicators for active saved views in FilterBar to provide better feedback when a saved view is currently active Bug Fixes# Link Generation and Consistency# Obsidian Link Format Compliance: Fixed \"Insert tasknote link\" and \"Convert task to TaskNote\" commands to use Obsidian's native generateMarkdownLink method, respecting user's link format preferences in Files & Links settings [#312] - Thanks to @nightroman for reporting the inconsistency and requesting proper format support Consistent Link Formatting: Both commands now generate links in the same format and are compatible with external tools when markdown links are preferred Timezone and Date Handling# Recurring Task Completion Fix: Resolved critical timezone bug where recurring task completion dates were stored incorrectly in non-UTC timezones [#314] - Thanks to @kmaustral for detailed reporting and testing across multiple views UTC Date Consistency: Updated all date utilities to use UTC methods consistently across calendar components, fixing off-by-one date issues in task completion tracking Calendar Date Normalization: Added createSafeUTCDate utility function and converted MiniCalendarView navigation to UTC methods for reliable date handling User Interface# Sort Arrow Visibility: Enhanced sort direction arrow visibility and positioning in filter condition builder with increased font size, bold weight, and accent color [#307] - Thanks to @kmaustral for noting the arrow was difficult to see in dark mode Duplicate Tooltip Prevention: Removed duplicate tooltips on recurring task indicators by using Obsidian's native setTooltip function instead of HTML title attributes Pointer Cursor Consistency: Added pointer cursor styling to all buttons in Pomodoro view for better usability [#308] - Thanks to @anomatomato for the contribution Error Handling and Stability# Daily Note Creation Protection: Added proper error handling for createDailyNote failures across TimeblockCreationModal, PomodoroService, and helper utilities, preventing \"Cannot read properties of undefined\" errors Security Compliance: Replaced unsafe innerHTML assignment with textContent in drag handle creation to resolve ESLint security violations Improvements# User Interface# Calendar Styling Enhancements: Improved advanced calendar view with better borders, header text readability, and removed custom scrollbar styling for system consistency Enhanced Visual Definition: Added border and border radius to calendar container, plus consistent borders on column headers and toolbar for cleaner appearance Development and Code Quality# Test Infrastructure: Added missing setTooltip mock to resolve 39 failing TaskCard tests Documentation Updates: Improved documentation formatting and appearance Technical Improvements# Enhanced date handling throughout the codebase with UTC method standardization Improved defensive programming practices for timezone-sensitive operations Better error messaging for daily note creation failures Code security improvements with ESLint compliance"},{"title":"TaskNotes 3.16.2","url":"/obsidian/releases/3.16.2/","description":"TaskNotes documentation.","product":"obsidian","text":"New Features# Task Link Integration# Markdown Link Support for Inline Task Widgets: Extended task link detection and rendering to support both wikilinks and markdown links. The plugin now properly renders [text](path) markdown links as interactive inline task widgets in both live preview and reading modes [#312] - Thanks to @nightroman for noting the missing link overlays on markdown links Improvements# Link Processing# Link Detection: Improved TaskLinkDetectionService to detect both [[wikilinks]] and [markdown](links) with proper URL decoding for paths containing spaces Link Rendering: Updated both TaskLinkOverlay (live preview) and ReadingModeTaskLinkProcessor (reading mode) to handle both link types consistently API Integration: Uses proper Obsidian API functions (parseLinktext() and getFirstLinkpathDest()) for reliable link resolution"},{"title":"TaskNotes 3.16.3","url":"/obsidian/releases/3.16.3/","description":"TaskNotes documentation.","product":"obsidian","text":"Bug Fixes# User Interface# Create Task Modal Accessibility: Fixed UI issues when creating tasks with natural language input disabled. The modal now opens in an expanded state with immediate access to all input fields, eliminating the need to click or tab before entering task details [#324] - Thanks to @nightroman for reporting this usability issue Timezone Handling# Recurring Task Calendar Display: Fixed timezone-related display bug where recurring tasks appeared on the wrong day for users in negative UTC timezones. Tuesday tasks no longer incorrectly appear on Monday in the calendar view Task Completion Calendar: Improved timezone consistency in the TaskEditModal completion calendar to ensure dates display correctly across all timezones Task Conversion# Context Detection in Instant Tasks: Fixed instant task conversion to properly detect and preserve contexts specified with \"@context\" syntax when converting inline tasks to TaskNotes [#320] - Thanks to @nslee123 for reporting this issue Time Preservation: Fixed instant task conversion to preserve time information when converting tasks with scheduled or due times. Time components are now correctly carried over during the conversion process Improvements# Code Quality# Test Coverage: Added comprehensive unit tests for InstantTaskConvertService context detection to ensure reliable context parsing in future releases"},{"title":"TaskNotes 3.16.4","url":"/obsidian/releases/3.16.4/","description":"This ensures users can always edit task titles regardless of the modal type or natural language input settings.","product":"obsidian","text":"Bug Fixes# User Interface# Task Modal Title Field: Fixed regression from version 3.16.3 where the title field was inadvertently removed from all task modals. The title field is now properly displayed with correct visibility logic: Edit modals: Title field always visible in the details section Create modals with natural language input enabled: Title field visible in details section (as the main input becomes the NLP textarea) Create modals with natural language input disabled: Title field only appears at the top of the modal This ensures users can always edit task titles regardless of the modal type or natural language input settings."},{"title":"TaskNotes 3.17.0","url":"/obsidian/releases/3.17.0/","description":"This release introduces improvements to recurring task handling with full DTSTART (start date/time) integration, addressing long-standing challenges in recurring task management...","product":"obsidian","text":"Major Features# Enhanced Recurring Tasks with DTSTART Support# This release introduces improvements to recurring task handling with full DTSTART (start date/time) integration, addressing long-standing challenges in recurring task management and filtering. Background and Motivation: The previous recurring task system created difficulties for users in filtering and managing task schedules. Users experienced unintuitive behavior where recurring tasks couldn't be treated consistently with regular tasks, making it challenging to see when the next occurrence would appear or to dynamically update task schedules upon completion. This implementation follows RFC 5545 standards to provide a more robust foundation for recurring task behavior. Key Improvements: DTSTART Integration: All recurring tasks now include proper start dates and times in their recurrence rules, ensuring consistent behavior across timezones and providing a clear anchor point for the recurring pattern Dynamic Date Updates: The task.scheduled field now always shows the next uncompleted occurrence, automatically updating when tasks are completed rather than showing static pattern dates Flexible Next Occurrence Scheduling: The next scheduled occurrence can now be placed anywhere - before the pattern start date, outside the recurring pattern, or at any custom time, giving users complete control over scheduling Visual Hierarchy: Pattern instances display with dashed borders while the next scheduled occurrence shows with solid borders, providing clear visual distinction between the recurring pattern and the active next task Independent Time Control: Pattern instances and next occurrences can have different times (e.g., daily pattern at 9 AM, next occurrence at 2:30 PM), allowing for exceptions without breaking the recurring pattern Dual Drag Behavior: Dragging pattern instances updates the recurring pattern timing globally, while dragging the next occurrence reschedules only that specific instance Automatic DTSTART Addition: The system automatically adds DTSTART when completing recurring tasks, editing recurrence rules, or converting tasks to recurring, ensuring backward compatibility while upgrading task definitions Manual Rescheduling Support: Clear flags indicate when tasks have been manually rescheduled, maintaining transparency about schedule modifications Expandable Project Subtasks# A new feature allows users to expand project task cards to view subtasks inline with proper visual hierarchy. Features: Chevron Controls: Click chevron icons on project task cards to expand/collapse subtask display Configurable: New \"Show expandable subtasks\" setting allows users to enable/disable the feature Responsive Pomodoro View# The Pomodoro view now adapts seamlessly to different container sizes with comprehensive responsive design. Thanks to @oliverlalan for requesting this improvement (#339). Enhanced Filename Templates# Significant expansion of available template variables for task creation, providing much greater flexibility in filename patterns. New Template Variables: Date/Time Variations: shortDate, monthName, dayName, week, quarter, time12, time24 Unix Timestamps: unix (seconds), unixMs (milliseconds) Title Case Variations: titleLower, titleUpper, titleSnake, titleKebab, titleCamel, titlePascal Short Forms: priorityShort, statusShort for single-letter representations Unique Identifiers: zettel (Zettelkasten ID), nano (high-precision unique ID) The settings UI now documents all 40+ available template variables for easy reference. Thanks to @fastrick for the original unix timestamp request. Bug Fixes# Critical Timezone Handling Fixes# This release resolves multiple timezone-related bugs that affected users worldwide, particularly those in non-UTC timezones. These fixes implement the \"UTC Anchor\" principle for consistent date handling. Major Timezone Bugs Fixed: Recurring Task Completion: Fixed critical issue where marking recurring tasks complete would affect the wrong day for users in certain timezones, addressing reports from multiple users including issues #327, #322, and #314 Calendar Date Misalignment: Resolved off-by-one day errors in calendar rendering and task indicators, addressing inconsistencies across different views (originally reported by @Crunchnuggetz in issue #129, with additional reports from @donjjones and @robmikulec) Weekly Task Display: Fixed issue where weekly recurring tasks set for specific days (e.g., Tuesdays) were showing completion dates on the wrong day (Monday) - reported by @jpmoo in issue #322 Task Completion Date Bug: Resolved bug where complete_instances was being set to the previous day, causing tasks to remain visible in Agenda view until manually corrected - reported in issue #314 Date Parsing Inconsistencies: Eliminated mixing of UTC and local date parsing that caused timezone-dependent behavior across the application Filter Date Handling: Fixed date filtering to work consistently across all timezones Agenda View \"Today\" Detection: Corrected timezone-sensitive today detection that affected agenda headers ICS Import Timezone Issues: Resolved timezone problems with both recurring and single events from ICS imports Technical Implementation: Introduced parseDateToUTC() function for consistent UTC anchoring of date-only strings Updated date comparison functions to use UTC anchors throughout Replaced timezone-sensitive date operations with consistent UTC-based alternatives Comprehensive audit and fix of all date handling patterns in the codebase Project Filtering Improvements# Resolved critical bugs in project filtering that prevented proper task display and project selection. Fixes: Wikilink Resolution: Fixed handling of relative vs absolute project wikilinks (e.g., [[../Projects/My Project]] vs [[My Project]]) - thanks to @xorander00 for the detailed bug report Filter Grouping Logic: Corrected AND/OR grouping in project filters to prevent showing too many tasks Missing Projects: Fixed issue where not all projects appeared in filter dropdown selection Cache Management: Improved cache invalidation and project name extraction with better validation Subtask Widget Improvements# Fixed several issues with the project subtasks widget affecting user experience and reliability. Widget Fixes: View State Persistence: Fixed issue where subtask widget views would reset when switching between notes or modifying subtasks (reported by @Poly-0000 in issue #329) Filter State Isolation: Prevented filter settings from bleeding between different notes' subtask widgets Configurable Positioning: Added setting to control widget placement at top or bottom of notes (requested by @michelebugio in issue #164) Event Listener Management: Improved cleanup to prevent memory leaks and event accumulation Event Bubbling: Fixed issue where clicking subtasks would trigger both subtask and parent task modals Styling Isolation: Prevented completion styles from affecting nested subtasks incorrectly ICS Calendar Integration# Timezone Processing: Fixed timezone handling bug in ICS calendar subscriptions where VTIMEZONE components weren't being registered before parsing events, causing incorrect display times for timezone-specific calendar events. Performance and Reliability# Cache Optimization: Restored FilterService cache TTL to 30 seconds after temporary reduction, balancing performance with data freshness. Type Safety: Added proper type assertions for ICAL.TimezoneService calls to resolve TypeScript compilation issues. Error Handling: Enhanced error handling and null safety checks throughout project filtering and service initialization. Technical Improvements# UTC Anchor Implementation# Comprehensive implementation of the UTC Anchor principle for robust timezone handling: All date-only strings now consistently parsed as UTC anchors Date comparison operations standardized using UTC methods Eliminated timezone-dependent date creation patterns Added comprehensive timezone test coverage Service Architecture# Expanded Projects Service: Enhanced state management and tracking for expandable project subtasks with proper cleanup and memory management. View State Manager: Improved view state persistence across different contexts and note switches. Documentation Updates# Updated recurring tasks documentation to reflect new behavior Added timezone handling guides for developers Enhanced calendar views documentation with drag behavior explanations Comprehensive template variable documentation Breaking Changes# Date Handling: While maintaining backward compatibility for user data, the internal date handling now consistently uses the UTC Anchor principle. Migration Notes# Existing recurring tasks will continue to work without modification. The system automatically adds DTSTART components when users interact with recurring tasks (completing, editing, or rescheduling)."},{"title":"TaskNotes 3.17.1","url":"/obsidian/releases/3.17.1/","description":"This patch release resolves three critical timezone-related bugs that affected users in specific timezones, particularly those west of UTC (such as users in the Americas). These...","product":"obsidian","text":"Bug Fixes# Critical Timezone Handling Fixes# This patch release resolves three critical timezone-related bugs that affected users in specific timezones, particularly those west of UTC (such as users in the Americas). These fixes ensure consistent calendar rendering and task interaction behavior across all timezones. Completions Calendar Rendering (#322)# Fixed three critical timezone bugs in the completions calendar that caused visual misalignment for users in timezones west of UTC: Day Number Display: Corrected day numbers in the calendar grid to display accurately regardless of user timezone by replacing timezone-sensitive formatting with UTC-anchored date extraction Month Comparison Logic: Fixed current month highlighting logic that was mixing local and UTC date values, causing incorrect month boundary detection Calendar Navigation: Updated previous/next month navigation to use consistent UTC methods, preventing timezone drift when navigating between months These fixes ensure the completions calendar visual representation aligns with the underlying UTC-anchored recurrence data for all users. Advanced Calendar Drag-and-Drop Operations (#344)# Resolved a critical bug where all-day tasks would shift back by one day after dragging and dropping them in the Advanced Calendar view. This issue particularly affected users in timezones ahead of UTC. Thanks to @trang-ngn for reporting this issue with clear reproduction steps. Root Cause: The drag-and-drop system was using formatDateForStorage() which applies UTC methods to Date objects provided by FullCalendar. For users in positive UTC offset timezones, this would cause the stored date to be one day earlier than the date shown in the UI. Fixed Operations: All-day and timed event drag-and-drop (handleEventDrop) External task drag-and-drop from outside the calendar (handleExternalDrop) Modal-based task scheduling (scheduleTask) Date selection task creation (handleDateSelect) Timeblock creation and event resizing operations Event context menu date handling The fix ensures that the date displayed in the calendar UI exactly matches the date that gets stored in the task data. Task Completion Status Checks (#322)# Fixed incorrect completion status checks in recurring tasks caused by timezone-sensitive date formatting in getEffectiveTaskStatus(). Root Cause: The function was using timezone-sensitive date-fns format() for completion date comparisons, causing completion status to be checked against the wrong date for users west of UTC (e.g., checking October 26 instead of October 27 for EDT users). Solution: Replaced timezone-sensitive formatting with formatDateForStorage() to ensure consistent UTC-anchored date strings that match the format used in complete_instances. This fix ensures recurring task completions are correctly identified regardless of user timezone, preventing tasks from incorrectly appearing as incomplete. Technical Implementation# All fixes implement the established \"UTC Anchor\" principle for consistent timezone handling: Consistent use of UTC-anchored date operations for date-only comparisons Replacement of timezone-sensitive date formatting with UTC-based alternatives Proper separation of display dates (which can be timezone-sensitive) from storage dates (which must be timezone-neutral)"},{"title":"TaskNotes 3.18.0","url":"/obsidian/releases/3.18.0/","description":"A complete reminder system has been added to TaskNotes, providing iCalendar VALARM-compliant reminder functionality.","product":"obsidian","text":"New Features# Task Reminders System# A complete reminder system has been added to TaskNotes, providing iCalendar VALARM-compliant reminder functionality. Core Features: Support for both relative reminders (e.g., \"15 minutes before due date\") and absolute reminders (specific date/time) Visual reminder indicators on task cards with clickable bell icons Integration with task creation and editing workflows User Interface: Reminder Modal: Modal for managing task reminders with form validation and real-time preview Reminder Context Menu: Quick access to common reminder options (5min, 15min, 1hr, 1day before due/scheduled dates) Reminder management accessible from task creation modal, edit modal, and task cards Default Reminders: Configure default reminders that automatically apply to new tasks Support for multiple default reminders per task type Applies to both manual task creation and instant conversion workflows Property-Based Task Identification# Tasks can now be identified using frontmatter properties instead of requiring tags. Configure property name and value for task identification (e.g., categories: [[Tasks]]) Full backward compatibility with existing tag-based workflows Addresses modern Obsidian property-based vault organization patterns Thanks to @mdbraber for the feature request (#340) Enhanced Saved Views# Clicking an active saved view now clears all filters, providing quick access to unfiltered task list Preserves sort and group settings while resetting filters Thanks to @oldjove for the suggestion (#351) Parent Note as Project Option# New setting to automatically use parent note as project during instant task conversion Useful for users who organize tasks within project-specific notes Merges with existing default projects to avoid duplicates Thanks to @FindingJohnny for the feature request (#348) Bug Fixes# ICS Calendar Integration# Fixed recurring event exceptions: Properly handle EXDATE properties and RECURRENCE-ID for modified instances Eliminated duplicate events: Resolved issue where deleted or rescheduled recurring events from external calendars still appeared Thanks to @robmikulec for reporting the recurring events issue (#342) Settings Persistence# Fixed settings reset during updates: Prevent user configuration loss when plugin updates introduce new default settings Apply deep merge strategy to preserve customizations in nested configuration objects Improvements# User Interface# Reminder modal uses consistent design patterns with task creation/edit modals Fixed task card icon overlap issues with proper spacing for multiple indicators Code Quality# Added unit test coverage for new reminder functionality Improved type safety with proper TypeScript interfaces for reminder data structures Improved error handling and user feedback across reminder operations Technical Details# Data Model Changes# Added optional reminders array field to TaskInfo interface Extended field mapping support for custom reminder property names Enhanced cache system to include reminder data in task extraction"},{"title":"TaskNotes 3.18.1","url":"/obsidian/releases/3.18.1/","description":"Fixed critical race conditions in cache synchronization that occurred when task operations completed before Obsidian's metadata cache had fully processed file changes. This...","product":"obsidian","text":"Bug Fixes# Cache Synchronization Race Conditions (#358)# Fixed critical race conditions in cache synchronization that occurred when task operations completed before Obsidian's metadata cache had fully processed file changes. This resulted in stale or missing task data across all calendar views and task operations. Thanks to @willgraham345 for reporting the calendar auto-refresh issue Code Quality Improvements# Event Listener Management# Simplified event listener cleanup in AdvancedCalendarView by removing manual listener tracking array. Technical Details# Cache Synchronization Strategy: The implementation follows a \"wait-then-update\" pattern where all cache modifications are preceded by verification that Obsidian's metadata cache contains the expected changes. This prevents race conditions while maintaining performance through minimal wait times."},{"title":"TaskNotes 3.18.2","url":"/obsidian/releases/3.18.2/","description":"Fixed timeblocks appearing one day earlier than expected by implementing the UTC Anchor pattern throughout the timeblocking feature. The previous implementation used problematic...","product":"obsidian","text":"Bug Fixes# Timeblock Date Shift Issue (#368)# Fixed timeblocks appearing one day earlier than expected by implementing the UTC Anchor pattern throughout the timeblocking feature. The previous implementation used problematic millisecond-based date iteration that caused timezone-dependent date shift bugs. Timeblocks now appear on the correct calendar day regardless of user timezone or DST transitions. Thanks to @zolotyh-dk for reporting this issue with detailed screenshots and system information. Performance Issues with Task Views# Eliminated typing lag that occurred when Task, Agenda, and Kanban views were open in large vaults. The plugin was triggering unnecessary view updates during text editing. New Features# Enhanced Filename Template Variables (#370)# Added new timestamp variables for filename templates to support ISO 8601 formats and Google Keep compatibility: {milliseconds}, {ms} - 3-digit milliseconds (000-999) {timezone}, {utcOffset} - UTC offset in ±HH:MM format {timezoneShort}, {utcOffsetShort} - UTC offset in ±HHMM format Thanks to @mnipritom for requesting these variables. Boolean Property Identification# Enhanced property-based task identification to handle boolean values correctly. Tasks can now be identified using boolean properties in frontmatter. A big thanks to @renatomen for contributing the boolean property identification implementation, documentation, and test coverage Boolean Status Field Support (#108)# Added automatic boolean conversion for status values to support Obsidian's checkbox property format. The status field now handles boolean true/false values: String \"true\" → boolean true (in frontmatter) String \"false\" → boolean false (in frontmatter) Boolean true → string \"true\" (when read back) Boolean false → string \"false\" (when read back) Other status values remain unchanged as strings Thanks to @arminta7 for reporting the checkbox property compatibility issue and @imed-ghomari for contributing to the discussion on status field handling. And thanks again to @renatomen--the boolean property identification fix inspired this change!"},{"title":"TaskNotes 3.19.0","url":"/obsidian/releases/3.19.0/","description":"TaskNotes now includes a HTTP REST API that enables external integrations and powers companion projects. The API provides full task management capabilities with intelligent natu...","product":"obsidian","text":"New Features# HTTP REST API with Natural Language Processing# TaskNotes now includes a HTTP REST API that enables external integrations and powers companion projects. The API provides full task management capabilities with intelligent natural language processing. Key API Features: Complete CRUD operations for tasks Time tracking endpoints Task statistics and filtering Bearer token authentication CORS support for browser extensions Desktop-only implementation with mobile-safe architecture Natural Language Processing Endpoints: /api/nlp/parse - Parse natural language into structured task data /api/nlp/create - Create tasks directly from natural language input Supports extraction of dates, times, priorities, tags, contexts, projects, and recurrence Intelligent parsing of expressions like \"Review PR #123 tomorrow high priority @work\" Companion Project Integration: The HTTP API enables two new companion projects: tasknotes-cli - Command-line interface for TaskNotes task management tasknotes-browser-extension - Browser extension for quick task creation Configuration: Enable via Settings → HTTP API tab (desktop only) Configurable port (default 8080) and optional authentication token Documentation at /docs/HTTP_API.md and /docs/nlp-api.md Enhanced Calendar Integration# Calendar Export and Context Menu System# Task Calendar Export: Add tasks to external calendars (Google, Outlook, Yahoo) Download ICS files Right-click context menu support for quick calendar actions Agenda View Calendar Improvements# ICS Integration in Agenda: Calendar event cards now display in Agenda view Toggle calendar subscriptions visibility via FilterBar Always-available \"Refresh calendars\" button Normalized scheduled date handling for all-day and timed events Thanks @scottaltham-payroc for the feature request! Bug Fixes# Task Styling Enhancement (#355)# Added CSS class task-card--has-projects to task cards that contain projects. Thanks @mdbraber for the suggestion Calendar Event Scheduling# Fixed scheduled date normalization when creating tasks from ICS events: All-day events: Use YYYY-MM-DD format Timed events: Use YYYY-MM-DDTHH:mm format Consistent behavior across all calendar interfaces File Copy Script Improvements# Enhanced copy-files script with better error handling: Improved default path handling Destination directory creation Better ENOENT error handling API Documentation# New Documentation Files# HTTP_API.md - Complete API reference with examples nlp-api.md - Natural language processing capabilities and usage Technical Enhancements# Core Infrastructure# API Service Architecture: Mobile-compatible implementation using Node.js http module Platform detection prevents mobile loading Express.js alternative for lightweight operation Full error handling and validation Calendar Service Integration: Extracted reusable CalendarExportService Unified TaskContextMenu component Enhanced event listener management Development Improvements# Code Organization: Modular component extraction for better reusability Consistent API response formats Comprehensive test coverage for new features TypeScript improvements for icon handling Migration Notes# HTTP API Setup# For users wanting to enable the new HTTP API: Navigate to Settings → HTTP API tab (desktop only) Configure desired port (default 8080) Optionally set authentication token for security Restart Obsidian to start the API server Test with: curl http://localhost:8080/api/health"},{"title":"TaskNotes 3.19.1","url":"/obsidian/releases/3.19.1/","description":"Added webhook system enabling integrations with external services and automation workflows.","product":"obsidian","text":"New Features# Webhook Support# Added webhook system enabling integrations with external services and automation workflows. Webhook Management: CRUD operations for webhook configuration HTTP API endpoints for webhook management (POST /api/webhooks, GET /api/webhooks, DELETE /api/webhooks/{id}) Delivery history tracking (GET /api/webhooks/deliveries) Settings UI integration with event subscription controls Event Types: Task events: created, updated, deleted, completed, archived, unarchived Time tracking: started, stopped Pomodoro: started, completed, interrupted Recurring tasks: instance completed Reminders: triggered Security and Reliability: HMAC-SHA256 signature verification for payload authentication Automatic retries with exponential backoff (3 attempts) 10-second delivery timeout with failure monitoring Auto-disable webhooks after repeated failures Non-blocking async delivery maintains TaskNotes responsiveness Documentation and testing utilities included in docs/webhooks.md and test-webhook.js. Bug Fixes# Boolean Property Identification Regression (#367)# Fixed regression from version 3.18.2 where boolean checkbox properties stopped working for property-based task identification. During code refactoring, the comparePropertyValues function was accidentally removed, breaking boolean-to-string coercion needed for Obsidian checkbox properties. The fix restores this function with proper type-aware comparison logic, allowing boolean true/false frontmatter values to correctly match \"true\"/\"false\" setting values. Thanks to @renatomen for reporting this regression"},{"title":"TaskNotes 3.20.0","url":"/obsidian/releases/3.20.0/","description":"Folder-Based Task Filtering - Added task filtering by folder location with dropdown selection of vault folder paths, special handling for root-level tasks, and support for conta...","product":"obsidian","text":"New Features# Task Organization and Filtering# Folder-Based Task Filtering - Added task filtering by folder location with dropdown selection of vault folder paths, special handling for root-level tasks, and support for contains/empty operators. Addresses issue #369 reported by kmaustral Dynamic Task Folder Organization - Added template variable support for default task folder setting with task variables ({{context}}, {{project}}, {{priority}}, {{status}}, {{title}}) and date variables ({{year}}, {{month}}, {{day}}, {{date}}). Supports automatic folder creation and title sanitization. Addresses feature request #376 by Mara-Li Archive Task Organization - Added optional bidirectional task movement between archive folder and default tasks folder. Disabled by default with settings in Task defaults → Task organization (moveArchivedTasks, archiveFolder). Addresses feature request #402 by anareaty Enhanced UI and Controls# Enhanced Filter Bar - Improved filter bar with instant badge updates, right-click clear functionality, \"Clear All Filters\" button, and better UI synchronization across main and subtask views. Contributed by renatomen Collapsible Groups - Added collapsible groups with persisted state, chevron indicators, and keyboard navigation. Works with all grouping options while preserving wikilink functionality. Extended to subtask widget with consistent behavior. Contributed by renatomen Expand/Collapse All Controls - Added \"Expand All\" and \"Collapse All\" buttons to task list toolbar that appear when grouping is active. Contributed by renatomen Configurable UI Elements - Added settings for subtask chevron position (right/left) and saved views button positioning in task view toolbar. Contributed by renatomen Advanced API Architecture and Webhook System# Refactored HTTP API from monolithic design to controller/service pattern, reducing HTTPAPIService from 1,061 to 231 lines (78% reduction). Added dedicated controllers for tasks, time tracking, Pomodoro, system, and webhooks with 100% backward compatibility. Webhook System - Added complete webhook infrastructure with signature verification, automatic retries with exponential backoff, 10-second delivery timeout, and auto-disable after repeated failures. Supports all task lifecycle events (created, updated, deleted, completed, archived, unarchived), time tracking events, Pomodoro sessions, recurring task instances, and reminders. Webhook Testing and Development - Included standalone webhook testing server (test-webhook.js) with real-time payload inspection, signature verification testing, and comprehensive event logging for development and debugging. Improvements# UI and Visual Enhancements# TaskNotes Icons - Added TaskNotes icons throughout interface and edit task modal headers with new SVG assets. Task Card Polish - Improved status and priority dot alignment and reordered context menu (\"Copy task title\" moved to top). Addresses alignment issue #410 reported by kmaustral Button Styling - Fixed agenda view and filter popup button backgrounds with improved styling consistency. Technical Improvements# Settings Architecture - Decomposed monolithic settings.ts into focused modules: defaults, settings management, type definitions, and utilities for better maintainability. Documentation - Added extensive webhook documentation in docs/examples/webhook-transforms/ with ready-to-use transform examples for Discord (rich embeds with colors), Slack (compatible attachments), Microsoft Teams (MessageCard format), and generic JSON templates. Expanded API documentation with complete endpoint reference, examples, error handling, authentication, and OpenAPI specification. Webhook Integration Services - Enhanced core services (TaskService, PomodoroService) with webhook notifications integrated into task lifecycle events, ensuring all user actions trigger appropriate webhook deliveries for external automation and monitoring. Bug Fixes# Mobile Modal Close Button - Fixed close button (X) touch event handling in task edit modals on mobile devices, particularly Android. Addresses issue #404 reported by anareaty Test Suite Stabilization - Resolved test failures and linting errors HTTP API Field Consistency - Updated API examples to use correct 'details' field instead of deprecated 'notes' field. Addresses issue #393 reported by @nightroman Missing Webhook Trigger - Added webhook trigger for recurring task completion events. Documentation Updates# Task defaults documentation with template variables Miscellaneous settings documentation Webhook transform documentation and examples Demo GIFs for new features Thanks @renatomen! Contributors# Special thanks to the following contributors: @Mara-Li - Feature request for template variables in task folders @kmaustral - Feature requests for folder filtering and UI alignment improvements @anareaty - Bug report for mobile modal close button issue @nightroman - Reported mislead API documentation A really big thanks to @renatomen whose very polished contributions form the bulk of this update!"},{"title":"TaskNotes 3.20.1","url":"/obsidian/releases/3.20.1/","description":"Saved View Headings with Completion Counts - Added visible filter headings across all views (Task List, Subtask Widget, and Agenda) that display the current saved view name and...","product":"obsidian","text":"New Features# Enhanced View Organization and Visual Feedback# Saved View Headings with Completion Counts - Added visible filter headings across all views (Task List, Subtask Widget, and Agenda) that display the current saved view name and completion statistics in \"completed / total\" format. Shows \"All\" when no saved view is active. Headings update immediately on filter changes and persist correctly when switching tabs or reloading. Contributed by @renatomen Consistent Group Count Badges - Standardized completion count display across all group headers in Task List, Subtask Widget, and Agenda views using unified \"completed / total\" format. Removed redundant bracketed counts for cleaner presentation. Contributed by @renatomen Collapsible Agenda Date Groups - Added collapsible date headers to Agenda view with persistent state management. Date sections can be collapsed individually or controlled via \"Expand All\" / \"Collapse All\" buttons that are always visible in the FilterBar. Collapsed state is preserved between sessions using ViewStateManager. Contributed by @renatomen Improved User Interface# Reorganized Task Context Menu - Enhanced context menu organization by replacing individual buttons with logical submenus for status, priority, dates, recurrence, and reminders. Applied user-configured colors to main menu icons while maintaining all existing functionality. Bug Fixes# Calendar Integration Fixes# Outlook Calendar 500 Errors - Fixed Microsoft Outlook ICS endpoint failures by updating User-Agent header from 'TaskNotes-Plugin/1.0' to browser-compatible string and adding Accept-Language header. Improved error handling with specific guidance for Outlook 500 errors. Fixes issue #458 reported by @girisumit and @heinzochsner Recurring Tasks Date Display - Fixed timezone-dependent bug where recurring tasks appeared one day ahead or behind their actual due date in Agenda View. Replaced manual UTC date construction with parseDateToUTC() following UTC Anchor principle from development guidelines. Added regression test for consistent date handling. Fixes issue #439 reported by @brianarn and @jpmoo Task Management Fixes# Project Suggestions Crash Prevention - Fixed crash in Task Creation modal when typing \"+\" to add projects inline, caused by non-string title values in frontmatter. Added title normalization (arrays join with \", \", numbers/booleans stringify, objects become empty strings) and defensive guards in suggestion filtering. Particularly important for large vaults with heterogeneous frontmatter. Contributed by @renatomen Documentation Updates# Added screenshots demonstrating saved view headings and completion counts for Task List and Subtask Widget Created demo GIF showing Agenda view collapsible groups with Expand/Collapse All functionality Updated view documentation with new visual features Enhanced inline task documentation for Subtask Widget improvements Contributed by @renatomen Contributors# Special recognition goes to @renatomen for the substantial contributions that form the core of this release, including the saved view headings system, consistent count badges, and collapsible Agenda functionality. Thanks to the following community members for their bug reports and feedback: @girisumit and @heinzochsner - Reported Outlook calendar integration issues @brianarn and @jpmoo - Identified recurring tasks date display bug with detailed reproduction steps"},{"title":"TaskNotes 3.21.0","url":"/obsidian/releases/3.21.0/","description":"Custom User Fields Mapping - Added ability to define custom frontmatter properties for task filtering, grouping, and sorting. Users can configure field mappings in Settings → Ad...","product":"obsidian","text":"New Features# Custom User Fields System# Custom User Fields Mapping - Added ability to define custom frontmatter properties for task filtering, grouping, and sorting. Users can configure field mappings in Settings → Advanced → User Fields with support for text, number, date, boolean, and list field types. List fields preserve wikilinks and quoted tokens, while numeric fields intelligently parse mixed text-number values like \"2-Medium\" as numeric 2. Contributed by @renatomen Group and Sort by Custom User Fields - Extended grouping and sorting functionality to work with user-defined custom fields. Includes type-aware comparators for each field type and proper group header ordering when grouping and sorting by the same field. Contributed by @renatomen User Fields in Task Modals - Added custom user field support to task creation and edit modals with autocomplete suggestions from existing field values. Fields are stored as frontmatter properties and include change detection for edit scenarios. Contributed by @callumalpass Enhanced Task Interaction# Configurable Click Behavior - Added option to configure single-click and double-click behavior for task cards and inline task widgets. Users can choose between opening the edit modal or the source note file for each click type. Includes shared click handler utility with 250ms detection delay. Contributed by @fastrick Calendar Integration Enhancements# Calendar Event Filename Templates - Added separate filename template configuration for notes created from calendar events. Supports ICS-specific template variables including {icsEventTitle}, {icsEventLocation}, {icsEventDescription}, and {icsEventTitleWithDate}. The {title} variable now uses clean event titles without date suffixes. Fixes issue #362 reported by @bepolymathe Chronological ICS Event Sorting - Fixed ICS calendar events to display in chronological order by start time within each day in the agenda view. Applied to both grouped and flat agenda view modes. Fixes issue #472 reported by @Crunchnuggetz Bug Fixes# API Endpoint Improvements# Custom Status Configuration Support - Fixed API endpoints (/api/nlp/parse and /api/nlp/create) not respecting custom status configurations. API now uses proper default status logic matching the UI instead of hardcoded 'todo' values, with proper handling of boolean status values. Fixes issue #487 reported by @23maverick23 Task Creation Defaults - Fixed REST API endpoint (POST /api/tasks) missing default properties like scheduled dates, tags, and reminders. API-created tasks now receive the same defaults as UI-created tasks. Fixes issue reported by @nightroman Project Management Fixes# Project Consolidation and Display - Fixed project grouping to consolidate different formats pointing to the same file (e.g., [[project]] and [[project|alias]] now group together). Improved display formatting with clickable headers showing absolute paths without .md extensions and proper wikilink alias parsing. Task cards preserve original formats while grouping logic ignores display aliases. Fixes issues #448 reported by @minchinweb and #469 reported by @anareaty User Experience Improvements# Tag Input Sanitization - Added automatic sanitization to remove # prefixes from tag input, preventing duplicate tags like #tag1 and ##tag1. Applied to task creation, editing, and real-time input handling. Fixes issue #331 reported by @AndreMonthy Contributors# Special recognition goes to @renatomen for the extensive custom user fields system that forms the core of this release, including field mapping, filtering, grouping, and sorting capabilities. Thanks to @fastrick for implementing the configurable click behavior feature. Thanks to the following community members for their bug reports and feature requests: @23maverick23 - Reported API custom status configuration issues with detailed technical analysis @Crunchnuggetz - Identified ICS calendar event sorting problem in agenda view @minchinweb - Reported project consolidation issues with wikilink variations @anareaty - Identified project display formatting problems in kanban view @bepolymathe - Requested calendar event filename template functionality @AndreMonthy - Reported tag input sanitization issues with clear examples @nightroman - Reported API issues where defaults were not being applied"},{"title":"TaskNotes 3.22.0","url":"/obsidian/releases/3.22.0/","description":"Added modular properties system allowing users to control visibility of task properties (due date, scheduled date, priority, projects, contexts, tags, custom fields, and total t...","product":"obsidian","text":"Major Features# Modular Properties System# Added modular properties system allowing users to control visibility of task properties (due date, scheduled date, priority, projects, contexts, tags, custom fields, and total tracked time) both globally and per saved view. Properties can be configured through a new Properties dropdown in the filter bar, with settings automatically saved per view. Includes performance optimizations to render properties only when visible. Thanks to @renatomen for the initial implementation of this feature Task cards now dynamically render properties based on visibility settings with improved error handling and type safety. System supports both core properties and user-defined custom fields with proper fallback to default configurations for new users. Added total tracked time as a configurable property in the modular system, calculated from time entries and displayed consistently across all views when enabled. Bases-style Filter Bar Redesign# Complete filter bar redesign matching Obsidian's bases plugin styling with improved layout, spacing, and button appearance. Added text labels and chevron icons to all filter buttons (Sort, Filters, Properties, New) for better discoverability. Replaced dropdown menus with native Obsidian context menus featuring section headers and improved reliability. Sort/Group functionality now uses unified context menu system with better organization. Implemented intelligent filter popup positioning using boundary detection to prevent popups from hiding under adjacent panes. Increased default popup width from 300px to 500px for better usability. Moved expand/collapse controls from separate containers directly into filter headings across all views (TaskListView, AgendaView, subtask widget) for cleaner interface and consistent user experience. Added dedicated \"+ New\" task creation button to filter bar with neutral styling and proper view context awareness. Statistics view# Implement a new view to track statistics about projects and time tracking. UX# Task Interaction Improvements# Changed \"This Week\" grouping label to \"Next seven days\" for clearer, more specific language about the 7-day time period while maintaining identical underlying functionality. Fixes issue #516 reported by @anareaty External Contributions# Type-aware input fields in task modals now provide appropriate UI components based on field type (text/list with autosuggest, date with picker icon, boolean with toggle). Project autosuggest during task creation now supports multi-word project names without interrupting suggestions on spaces. Contributed by @renatomen Fixed subtask right-click context menus that were incorrectly showing parent task options instead of subtask-specific options. Enhanced inline task overlay cursor behavior with configurable timing settings (0-500ms) for predictable overlay hiding when cursor approaches link boundaries. Contributed by @renatomen Fixed project names containing commas (e.g., [[Money, Org & Adm]]) being incorrectly split, breaking selection and display across task modals, settings, and instant conversion. Now uses proper wikilink parsing to preserve comma-containing project names as single entities. Contributed by @renatomen Fixed date parsing errors caused by hardcoded field mapping not respecting user's custom field configurations. Plugin now properly uses field mapper for note date extraction with fallback to hardcoded fields for backward compatibility. Contributed by @renatomen Fixed User Fields column order in settings to match Field mapping configuration for consistency. Contributed by @renatomen Bug Fixes# Timezone and Date Handling# Fixed timezone-dependent \"Today\" identification issues across multiple views including MiniCalendarView tooltips, PomodoroService session categorization, PomodoroStatsView statistics, and StatsView date calculations. All date-sensitive components now use UTC-anchored dates for timezone-independent behavior. Fixes issue #452 reported by @MinchinWeb User Interface Fixes# Redesigned group counters with clean appearance (removed background, border, padding), positioned to far right of headers using muted text color for subtle display while maintaining left-aligned headings. Improved contrast for INTERRUPTED status badge in pomodoro statistics for better readability. Fixes issue #529 reported by @motusira Removed title length limits that were causing text truncation, allowing full title display. Fixes issue #378 reported by @nsstrickland Added all-day slot toggle to calendar view for better event organization. Fixes issue #242 requested by @Crunchnuggetz Added calendar locale configuration for international calendar support with proper localization. Contributed by @pixeler Fixed task states not refreshing when date changes at midnight, ensuring accurate daily task status updates. Fixes issue #527 reported by @jordandrako Fixed inline task overlay title wrapping using white-space: break-spaces for proper text display. Fixes issue #517 reported by @cathywu New Capabilities# Added weekday display and increment options to date picker with integration into task context menus for improved date selection experience. Fixes issue #238 requested by @girisumit Added tags to available sorting and grouping options for more flexible task organization. Fixes issue #169 requested by @bce283c Added create inline task command for quick task creation within notes with NLP project support for automatic project assignment based on context. Fixes issue #299 requested by @0dfa1bc Added filename template variables to folder templates including support for additional customization options. Fixes issue #473 requested by @oliverlalan Implemented status auto-suggestion with NLP integration for intelligent status recommendations during task creation and editing. Infrastructure Improvements# Development and Testing# Updated multiple npm dependencies including ical.js (1.5.0 → 2.2.1) and Jest (29.7.0 → 30.1.1) with compatibility fixes. Resolved all npm security vulnerabilities and updated ICS subscription service for ical.js v2.x compatibility. Fixed all test suite failures and infrastructure issues including Jest 30 compatibility, RRule mocking, TypeScript configuration, and CI environment setup. Removed coverage thresholds that were causing CI failures while maintaining test quality. Improved code quality throughout modular properties system with proper TypeScript compliance, error handling, performance optimizations, and memory cleanup functions. Replaced 'any' types with proper type guards and added comprehensive interface definitions. Contributors# Special recognition goes to @renatomen for multiple substantial contributions including type-aware custom field inputs, enhanced task interaction fixes, project name handling improvements, date parsing fixes, and settings alignment. Thanks to the following community members for their bug reports and feature requests: @anareaty - Reported grouping label confusion with clear examples @MinchinWeb - Identified timezone handling inconsistencies across multiple views @motusira - Reported contrast issues with INTERRUPTED status badge @nsstrickland - Identified title truncation problems @Crunchnuggetz - Requested all-day slot toggle for calendar views @jordandrako - Reported task state refresh issues at midnight @cathywu - Identified text wrapping problems in overlays @girisumit - Requested enhanced date picker functionality @oliverlalan - Requested template variable enhancements"},{"title":"TaskNotes 3.22.1","url":"/obsidian/releases/3.22.1/","description":"Thanks to @jhedlund for implementing the configurable recurring task due date feature.","product":"obsidian","text":"New Features# Configurable Recurring Task Due Date Behavior# Added optional due date advancement for recurring tasks. When enabled, maintains the time separation between scheduled and due dates when tasks are completed. The new \"Maintain due date offset in recurring tasks\" setting in Misc preferences controls this behavior and defaults to disabled to preserve existing behavior. Contributed by @jhedlund, fixes issue #470 Bug Fixes# Calendar and Task Display# Fixed calendar view issues where tasks were not displaying correctly due to empty status values causing infinite loops and TypeErrors. Resolved timeEntries.filter is not a function errors when loading calendar events and prevented Obsidian freezing during task creation with empty status text. Fixes issue #520 reported by @cathywu Saved Views and Property Management# Fixed property visibility settings not being preserved when saving filter views. View configurations now properly store and restore property display preferences. Fixes issue #545 reported by @anareaty Fixed saved view selection to prefer newly created views over older matching views, ensuring the correct view is activated after saving. Added proper null safety checks for FilterBar interactions to prevent errors during view save operations. User Interface Improvements# Added responsive behavior to filter bar buttons that automatically hide button text when pane width falls below 500px to prevent overflow in narrow sidebars. Uses container queries with media query fallback for broader browser support. Fixes issue #549 reported by @TonyAtlas Development Improvements# Reduced excessive console logging in TaskListView by removing 37+ debug statements while preserving essential error logging for troubleshooting. Contributors# Thanks to @jhedlund for implementing the configurable recurring task due date feature. Thanks to the following community members for their bug reports: @cathywu - Reported calendar view task display issues with detailed technical information @anareaty - Identified property visibility persistence problems in saved views @TonyAtlas - Reported filter bar overflow issues in narrow sidebars with helpful screenshots"},{"title":"TaskNotes 3.23.0","url":"/obsidian/releases/3.23.0/","description":"We extend special thanks to @renatomen for his exceptional contributions to this release:","product":"obsidian","text":"New Features# ICS Export and Calendar Integration# Added full ICS export functionality with proper RFC 5545 compliance for improved calendar application compatibility Implemented automatic ICS export with configurable interval updates (5-1440 minutes) for calendar subscription workflows Added manual \"Export all tasks as ICS file\" command for bulk export operations Thanks to @mdbraber for requesting this feature (#422) Status-Based Auto-Archive# Introduced configurable auto-archive system with per-status timeout settings (1-1440 minutes) Added persistent queue that survives plugin restarts for reliable task archiving Implemented settings UI for fine-grained control over auto-archive behavior Thanks to @TonyAtlas for requesting this feature (#547) and to @renatomen for design suggestions Multi-Language Natural Language Processing# Added NLP support for 12 languages: English, Spanish, French, German, Russian, Chinese, Japanese, Italian, Dutch, Portuguese, Swedish, Ukrainian Implemented locale-specific date parsing using chrono-node language support Enhanced pattern matching with proper handling for Latin, Cyrillic, Chinese, and Japanese scripts Thanks to @pschoenbach for requesting German language support (#563) Enhanced Project Autosuggest# Implemented configurable multi-row project cards with customizable display fields Added selective search functionality across chosen fields with simple flag system Introduced fuzzy search option for broader, multi-word matching capabilities Enhanced project selection with clear metadata display (title, aliases, path) Thanks to @renatomen for implementing this feature (#555) Bases Plugin Integration# Added experimental integration with the Bases plugin for enhanced task management workflows Implemented direct formula computation and custom property support Added clickable tags and contexts with accessibility support Created simplified kanban view integration with proper lifecycle management Thanks to @renatomen for his incredible work developing the proof-of-concept for this feature Settings UI Modernization# Complete redesign of settings interface with card-based design system Added collapsible functionality and live API documentation Enhanced calendar subscription interface with local file support Bug Fixes# Task Creation and File Handling# Fixed startup crash when templates contain empty reminders property (reported by @glpayson, #583) Implemented automatic sanitization of forbidden characters in task titles instead of blocking creation (reported by @glpayson, #590) Added support for platform-specific filename characters (hash, square brackets) Resolved inconsistent behavior between instant convert and manual task creation Project and Link Functionality# Added clickable project links in task edit modal for better navigation (requested by @anareaty, #432) Fixed completion date timezone handling to ensure consistent local time recording Corrected frontmatter property naming in Bases kanban drag-and-drop operations Property Display and Performance# Fixed custom property duplication when configured in both settings and filter bar Resolved unwanted total tracked time display showing zero values Standardized custom property identifiers with consistent prefix format Plugin Integration and Stability# Resolved Bases plugin integration issues and view switching problems Fixed kanban view loading with proper static imports and interface consistency Improved error handling and cleanup patterns for better stability Fixed API endpoints to respect custom status configurations (reported by @23maverick23, #487) Acknowledgments# Special Recognition# We extend special thanks to @renatomen for his exceptional contributions to this release: Created the enhanced project autosuggest system with configurable cards and selective search functionality (PR #555) Developed a proof-of-concept integration with the Bases plugin that demonstrated full compatibility and provided the technical foundation for our experimental Bases integration His innovative work on the Bases POC revealed that everything that I was hoping might be possible in a future integration with Bases was actually possible! Community Contributors# We're grateful to the community members whose issues were resolved in this release: @glpayson for providing detailed bug reports with reproduction steps that led to fixes for the startup crash with empty reminders (#583) and character handling improvements (#590) @mdbraber for requesting ICS export functionality that became a major feature in this release (#422) @TonyAtlas for the auto-archive feature request that resulted in the new status-based auto-archive system (#547) @anareaty for requesting clickable project links (#432) and reporting the \"This Week\" grouping label issue (#516) @pschoenbach for requesting multi-language NLP support, specifically German language support (#563) @23maverick23 for reporting API status configuration issues that improved custom status handling (#487) @Burrish for the documentation correction (#597) Full Changelog: 3.22.1...3.23.0"},{"title":"TaskNotes 3.23.1","url":"/obsidian/releases/3.23.1/","description":"Full Changelog: 3.23.0...3.23.1","product":"obsidian","text":"Bug Fixes# Bases Plugin Integration# Fixed Bases views not recognizing custom field mappings when using non-default property names. Status dots, priority colors, and dates now display correctly in Bases views when using custom field names, including Cyrillic and other localized property names. Thanks to @anareaty for reporting this issue (#607) Full Changelog: 3.23.0...3.23.1"},{"title":"TaskNotes v3.23.2 Release Notes","url":"/obsidian/releases/3.23.2/","description":"This release focusses on performance improvements. These improvements should be especially noticeable in vaults with a large number of tasks.","product":"obsidian","text":"This release focusses on performance improvements. These improvements should be especially noticeable in vaults with a large number of tasks. New Features# Added agenda/list view to Advanced Calendar New {{contexts}} template variable for joining multiple context values New {{projects}} template variable for joining multiple project values Thanks to @Mara-Li for these additions Time Format Consistency# Plugin-wide 12hr/24hr time format preference support Consistent time display across all calendar views and components Thanks to @anareaty and @Astrusia for this suggestion #431 Performance Architecture# Centralized ViewPerformanceService for all TaskNotes views Global task version cache with change detection Debounced updates with configurable batching View-specific update handlers with selective refresh logic Memory management and automatic cache cleanup Bug Fixes# Fixed cursor positioning issues when creating subtask widgets Thanks to @jhedlund for this fix! Contributors# Special thanks to contributors: @jhedlund for fixing cursor positioning with subtasks @Mara-Li for implementing context/project template variables and bracket fixes @anareaty for reporting time format inconsistencies"},{"title":"TaskNotes v3.23.3 Release Notes","url":"/obsidian/releases/3.23.3/","description":"This release addresses critical bugs with project and subtask functionality, ensuring proper field mapping support and expanding project filtering capabilities.","product":"obsidian","text":"This release addresses critical bugs with project and subtask functionality, ensuring proper field mapping support and expanding project filtering capabilities. New Features# Project Property Filter Support# Added property-based filtering for project picker dropdown Configure projects to appear in picker based on frontmatter properties (e.g., type: project) Complements existing folder and tag filtering options Thanks to @aubreyz for requesting this feature enhancement (#660) Bug Fixes# Project/Subtask Field Mapping# Fixed project and subtask functionality not working when users customize project field names ProjectSubtasksService and MinimalNativeCache now properly respect user field mapping configuration Resolves issue where hardcoded 'projects' field lookup ignored custom field mappings Thanks to @JD2026 (#674), @anareaty, (#674) and @Volker-brdb (#672) and for reporting these subtask display issues Test Infrastructure# Added missing test mocks for isTaskUsedAsProjectSync and formatDateForStorage functions Ensures test suite stability for project-related functionality"},{"title":"TaskNotes 3.23.4","url":"/obsidian/releases/3.23.4/","description":"Special thanks to contributors:","product":"obsidian","text":"Bug Fixes# Task Scheduling & Natural Language Processing# Fixed Russian weekday scheduling conflict where single weekdays (e.g., \"воскресенье\") were incorrectly interpreted as recurring tasks instead of single-day scheduling (#665, thanks to @anareaty for the report) Fixed issue where natural language processing failed to save parsed time estimates in task creation modal (#682, thanks to @RumiaKitinari for the detailed report) Fixed scheduled task grouping UTC anchor regression that caused today's tasks to appear under \"Past Scheduled\" instead of \"Today\" (#384, thanks to @jcromwell for the report) Settings & Configuration# Fixed plugin failure when excluded folders setting contains trailing commas - the parsing logic now properly filters empty strings (#664, thanks to @Yoav6 for identifying this issue) Calendar & Time Management# Fixed calendar not refreshing when task duration or time tracking changes (#382, thanks to @mdbraber) Fixed calendar not refreshing after task archive or move operations Fixed timeblock editing using stored date instead of current date for past day modifications (#647, thanks to @RumiaKitinari) Fixed Pomodoro timer not preserving task context when auto-starting sessions (#641, thanks to @RumiaKitinari) Fixed all-day tasks not rendering properly across multiple days in calendar view (thanks to Danny Talks Tech for reporting this in his video review) User Interface# Fixed mini calendar header overflow issue in sidebar view (#459, with CSS improvements suggested by @jsonshanks, thanks to @girisumit for the report) New Features & Enhancements# Visual Improvements# Added file-text icon to note cards in agenda view for better visual distinction from headers and consistency with task and calendar event icons (#662, thanks to @ras0q for the suggestion) Improved mini calendar styling, interactions, and legend display Enhanced task dot visualization to reflect accurate matching dates Settings Organization# Moved timeblocking settings to Features tab with improved usage instructions for better discoverability Documentation# Updated documentation to fix auto-archiving settings reference (#673, thanks to @antonio for pointing out the inconsistency) Contributors# Special thanks to contributors: @anareaty for reporting the Russian weekday scheduling conflict @RumiaKitinari for detailed reports on natural language processing, timeblock editing, and Pomodoro timer issues @jcromwell for reporting the scheduled task grouping UTC regression @Yoav6 for identifying the excluded folders trailing comma issue @mdbraber for reporting calendar refresh issues with time tracking changes @girisumit for reporting the mini calendar header overflow issue @jsonshanks for providing CSS improvement suggestions for the mini calendar @ras0q for suggesting the file-text icon addition to agenda view @antonio for pointing out the auto-archiving documentation inconsistency Danny Talks Tech for reporting the all-day task rendering issue in his video review This release focuses primarily on bug fixes and stability improvements, particularly around calendar functionality, natural language processing, and user interface polish."},{"title":"TaskNotes 3.24.0","url":"/obsidian/releases/3.24.0/","description":"Special thanks to all this release's contributors:","product":"obsidian","text":"New Features# Agenda View Overdue Section# Added separate \"Overdue\" section in Agenda view instead of mixing overdue tasks with today's tasks (#557, thanks to @backyardbiomech for the detailed report) Collapsible section with task completion statistics and proper internationalization support Includes overdue recurring tasks based on their scheduled dates Task Dependencies and Blocking Relationships# Implemented blocking/blocked task dependencies with persistent relationships (#701, thanks to @prayidae for the detailed feature request) Tasks can be marked as blocking other tasks or blocked by other tasks Dependency relationships persist in frontmatter as structural links Dynamic blocked state computed based on blocking task completion status Task Card Widget in Notes# Added configurable task card widget displaying at the top of task notes (#576, thanks to @jhedlund for the request) Provides immediate access to task actions and context menus without requiring command palette Uses CodeMirror widget system for integration Appears above project subtasks widget when both enabled Can be disabled via settings Hierarchical Subgrouping# Implemented hierarchical subgrouping functionality for TaskListView and AgendaView (thanks to @renatomen for this major feature contribution) Allows two-level task organization (e.g., Group by Status, Subgroup by Priority) Cross-view support with consistent behavior State persistence for expand/collapse preferences Custom user fields supported as subgroup options Internationalization Support# Added i18n framework with multi-language support Support for German, Spanish, French, Russian, Chinese, and Japanese Translation coverage for command palette entries and UI strings Localized agenda and filter interface elements Template Variables# Added {{hashtags}} template variable for space-separated hashtag rendering (#612, thanks to @strazto for the suggestion) Added {{currentNoteTitle}} template variable for note-specific folder organization (#637, thanks to @Mara-Li for the request) Added template variable support for archive folder paths (#677, thanks to @dsebastien for the request) Fixed {{project}} variables to properly extract basenames from wikilinks (#490, thanks to @nsstrickland for the detailed bug report) Project and Subtask Management# Enhanced task modals with project and subtask management capabilities Added \"Add to project\" and \"Add subtasks\" sections in task creation/edit modals Context menu options for assigning tasks to projects and adding subtasks Collapsible lists with visual separators between form sections View and Grouping Enhancements# Added \"Completed Date\" as grouping option for analyzing productivity (#430, thanks to @anareaty for the suggestion) Added \"Status\" as sorting option in Kanban and Task List views (#633, thanks to @mdbraber for the report) Implemented per-grouping column persistence for Kanban views Smart default ordering respecting StatusManager and PriorityManager configurations Bug Fixes# Calendar and Advanced Calendar# Fixed calendar not refreshing when task duration or time tracking changes Fixed calendar not refreshing after task archive or move operations Fixed agenda duplication for all-day ICS events (#695, thanks to @realJohnDoe for the report) Added configurable eventMinHeight for Advanced Calendar to make short duration tasks readable (#718, thanks to @Ruboks-Cube for the detailed report) Fixed multi-day task creation in month/year view to properly calculate time estimates (#564, thanks to @same774 for the report) Kanban View# Fixed kanban view losing columns after upgrades (#689, thanks to @mikesale for the report) Fixed clearing filters defaulting to \"none\" instead of \"status\" grouping (#679, thanks to @camara-tech-pro for the question) Fixed column order changes when switching between views (#710, thanks to @phortx for the report) Fixed kanban drag-and-drop for custom field grouping (#494, thanks to @anareaty for the report) Enhanced save view modal functionality with improved styling and accessibility Task Management# Fixed HTTP API task creation to return sanitized title matching stored content (#635, thanks to @nightroman for the detailed report) Fixed #task tag being incorrectly added when using property-based task identification (#570, thanks to @RobbK17 for the report) Fixed recurring task completion styling in Bases views (#669, thanks to @jordandrako for the report) Hierarchical Tag Support# Added hierarchical tag support with exclusion patterns for Obsidian nested tags (#584, thanks to @renatomen for the detailed feature request) Hierarchical matching allows searching for parent tags to match child tags (e.g., t/ef matches t/ef/project, t/ef/task) Exclusion patterns support using - prefix to exclude specific tags and their children Maintains backward compatibility with existing substring matching Natural Language Processing and Tags# Fixed nested tags losing slashes in agenda view rendering (#712, thanks to @antonio for the report and fix) Added support for hyphens in NLP tag parsing (#568, thanks to @jordandrako for the report) Settings and Configuration# Fixed property value truncation in project autosuggest settings by adding input debouncing (#705, thanks to @aubreyz for the report) Improved webhook transform error handling with detailed logging (#719, thanks to @stephen-netu for the detailed report) Added save button disable logic to prevent duplicate task creation (thanks to @hamlim for the report and implementation) Code Quality and Development# Configured Prettier formatter for consistent code formatting (#717, thanks to @ras0q for the request) Applied ESLint fixes reducing problems from 209 to 97 Added format and format:check scripts for development workflow Fixed browser extension repository URL in README (thanks to @elijahmanor for the correction) Enhancements# Performance and Reliability# Added debouncing to project autosuggest property inputs Improved error handling for webhook transform failures User Interface# Added time display based on timeEstimate property in task statistics (thanks to Sergen Aras for the implementation) Enhanced language selection display with native scripts Settings Organization# Reorganized settings with improved categorization Added collapsible functionality to various UI sections Enhanced accessibility with proper button labeling Documentation# Added documentation for task dependencies feature Updated comprehensive subgrouping feature documentation Enhanced template variable documentation Updated various view documentation for new features Contributors# Special thanks to all this release's contributors: Feature Contributors# @renatomen for implementing the major hierarchical subgrouping feature and hierarchical tag support feature request (#584) @antonio for implementing nested tag slash preservation and providing the fix @elijahmanor for fixing the browser extension repository URL @sergenaras for implementing time display based on timeEstimate property in task statistics @hamlim for implementing save button disable logic to prevent duplicate task creation Issue Reporters and Feature Requesters# @backyardbiomech for the detailed overdue recurring tasks report (#557) @prayidae for the detailed task dependencies feature request (#701) @jhedlund for requesting task context menu in notes (#576) @anareaty for requesting completed date grouping (#430) and reporting kanban custom field drag issues (#494) @mdbraber for reporting missing status sorting option (#633) @strazto for requesting hashtags template variable (#612) @Mara-Li for requesting currentNoteTitle template variable (#637) @dsebastien for requesting archive folder template support (#677) @nsstrickland for the detailed project variable bug report (#490) @realJohnDoe for reporting ICS all-day event duplication (#695) @Ruboks-Cube for reporting short duration task rendering issues (#718) @same774 for reporting multi-day task creation issues (#564) @mikesale for reporting kanban column loss (#689) @camara-tech-pro for the kanban grouping question (#679) @phortx for reporting column order changes (#710) @nightroman for the detailed HTTP API title sanitization report (#635) @RobbK17 for reporting property identification tag issue (#570) @jordandrako for reporting recurring task styling in Bases (#669) and NLP tag parsing with hyphens (#568) @aubreyz for reporting project autosuggest truncation issue (#705) @ras0q for requesting code formatting improvements (#717) @stephen-netu for the detailed webhook transform script loading report (#719)"},{"title":"TaskNotes 3.24.1","url":"/obsidian/releases/3.24.1/","description":"This patch release fixes the task card widget introduced in 3.24.0 to only display on actual task notes.","product":"obsidian","text":"Bug Fixes# Task Card Widget# Fixed task card widget appearing on all notes instead of only task notes Widget now properly respects task identification settings (tag or property-based) This patch release fixes the task card widget introduced in 3.24.0 to only display on actual task notes."},{"title":"TaskNotes 3.24.2","url":"/obsidian/releases/3.24.2/","description":"TaskNotes documentation.","product":"obsidian","text":"Fixed# (#766) Fixed tag parsing incorrectly identifying notes with tags containing \"task\" (like \"pkm-task\") as task notes Added exact hierarchical tag matching for task identification to prevent false positives Preserved substring matching behavior for filter bar searches where it's desired Only exact matches or hierarchical children (like \"task/work\") now identify notes as tasks Thanks to @anareaty and @fastrick for reporting this issue (#767) Fixed subgroups not rendering under the \"Overdue\" agenda group Thanks to @renatomen for reporting this issue (#768) Fixed calendar view appearing empty in week and day views due to invalid time configuration values Added time validation in settings UI with proper error messages and debouncing Added runtime sanitization in calendar with safe defaults (00:00:00, 24:00:00, 08:00:00) Prevents \"Cannot read properties of null (reading 'years')\" error from FullCalendar Thanks to @kmaustral for reporting (#769) Fixed NLP processor incorrectly assigning hardcoded \"waiting\" status when \"blocked\" appears in task titles NLP now only uses user-defined status configurations when available, ignoring hardcoded fallback patterns Prevents unexpected status assignments for users with custom status workflows Fallback patterns still work when no custom status configurations are defined Thanks to @renatomen for reporting this issue"},{"title":"TaskNotes 3.24.3","url":"/obsidian/releases/3.24.3/","description":"TaskNotes documentation.","product":"obsidian","text":"(#776) Fixed screens failing to load with \"toLowerCase is not a function\" error Issue occurred when frontmatter tags array contained non-string values (numbers, booleans, etc.) Added type validation to filter out non-string values before processing tags Valid string tags continue to work normally while invalid types are safely skipped Thanks to @kmf and @Andre-Ioda for help debugging this issue"},{"title":"TaskNotes 3.24.4","url":"/obsidian/releases/3.24.4/","description":"(#768) Fixed calendar view crashes when tasks contain null values in grouping fields","product":"obsidian","text":"Fixed# (#768) Fixed calendar view crashes when tasks contain null values in grouping fields Added null/undefined checks in sort comparisons to prevent localeCompare errors Calendar now handles null values in tags, contexts, and custom fields gracefully Thanks to @kmaustral for reporting (#601) Fixed Unicode characters not displaying in tags and contexts Unicode characters (Š, Ė, Ž, Ą, etc.) are now properly preserved in tags and contexts Affects Agenda View, Task List View, and all other views displaying tags Thanks to @Kapinekas for reporting (#778) Fixed cursor artifacts in CodeMirror widgets Thanks to @jhedlund for the fix Fixed task card widgets in note editor not updating for archive and time tracking changes Task card widgets now properly detect when tasks are archived/unarchived Task card widgets now properly detect when time tracking starts/stops Blue \"tracking\" border now appears/disappears correctly in live preview Archive styling now updates correctly in live preview Changed# (#751) Status bar tracked task click behavior now opens task notes directly Single tracked task: opens the task note immediately Multiple tracked tasks: shows selector modal to choose which task note to open Provides faster access to tracked tasks compared to previous task list view (#727) \"Create New Inline Task\" command now respects the \"Include Current Note in Project\" setting When enabled, the current note is automatically added as a project to inline tasks Provides consistency with instant convert functionality Thanks to @chrisfeagles for the suggestion Improved link handling throughout the plugin using Obsidian's native APIs Replaced manual wikilink generation with FileManager.generateMarkdownLink() Now respects user's link format settings (wikilink vs markdown, relative paths) Replaced manual link parsing with parseLinktext() for proper alias handling Better compatibility with future Obsidian updates Added centralized link utilities in linkUtils.ts Refactored widget cursor styles into reusable utility class Consolidated shared CSS into .cm-widget-cursor-fix utility Improved maintainability across widget components"},{"title":"TaskNotes 3.24.5","url":"/obsidian/releases/3.24.5/","description":"(#806) Fixed Bases views crashing on Obsidian 1.10.0 startup","product":"obsidian","text":"Fixed# (#806) Fixed Bases views crashing on Obsidian 1.10.0 startup TaskNotes Bases views (Task List and Kanban) now restore correctly when already open at startup Added defensive checks in setEphemeralState to handle early lifecycle calls Added focus() method to view objects for proper restoration Made root elements focusable to support Obsidian 1.10.0 view lifecycle (#792, #800) Fixed markdown-style project and dependency links not being recognized in frontmatter Added support for markdown link format [text](path) in projects and blockedBy fields Handles URL-encoded paths like [Car Maintenance](../../projects/Car%20Maintenance.md) Markdown links now render as clickable links showing display text instead of raw [text](path) format Links are properly resolved for grouping, filtering, and project-task associations Previously only wikilink format [[path]] was supported Prevents automatic removal of project assignments when editing tasks Thanks to @minchinweb for reporting (#780) Fixed \"Cannot Create Timeblocks\" error when daily notes folder doesn't exist Added proper error handling when createDailyNote fails due to missing folder Improved error messages to guide users to check Daily Notes plugin configuration Prevents uncaught errors from obsidian-daily-notes-interface package Thanks to @uberunix for reporting"},{"title":"TaskNotes 3.24.6","url":"/obsidian/releases/3.24.6/","description":"(#440) Fixed inline task replacement not working for links with relative paths","product":"obsidian","text":"Added# Added release notes viewer New view displays release notes in a dedicated tab when plugin updates Automatically opens after updating to a new version Access anytime via command palette \"TaskNotes: View release notes\" or Settings > General Release notes are rendered using native Obsidian markdown rendering Includes link to view all releases on GitHub Fully internationalized with i18n support Auto-generation system ensures correct version is loaded without manual updates Fixed# (#440) Fixed inline task replacement not working for links with relative paths Markdown links with relative paths like [task](../../../GTD/tasks/task.md) now display inline previews Wikilinks with relative paths now work correctly Removed overly aggressive path sanitization that was stripping .. from all link paths Works in both Live Preview and Reading Mode Thanks to @minchinweb for reporting (#814) Fixed markdown links in projects field not being recognized on Project notes Tasks with markdown-style project links [text](path) now appear in project's Subtasks section Updated project link detection to use parseLinkToPath utility which handles both wikilinks and markdown links Handles URL-encoded paths like [z Test Project](z%20Test%20Project.md) Thanks to @minchinweb for reporting (#827) Fixed project links being generated as markdown links for users with markdown links enabled in Obsidian settings Project links in frontmatter are now always generated as wikilinks [[link]] by default for Obsidian compatibility Obsidian does not support markdown links in frontmatter properties without third-party plugins Added optional setting to enable markdown links in frontmatter for users with obsidian-frontmatter-markdown-links plugin Setting only appears when user has markdown links enabled globally in Obsidian Thanks to @nightroman for reporting"},{"title":"TaskNotes 3.25.0","url":"/obsidian/releases/3.25.0/","description":"Added Calendar view for Bases plugin integration (requires Bases 1.10.0+)","product":"obsidian","text":"Added# Added Calendar view for Bases plugin integration (requires Bases 1.10.0+) Supports month, week, day, year, and list views Property-based events from note date properties (configurable start date, end date, and title properties) Custom card rendering in list view for tasks, timeblocks, ICS events, and property-based events Layout options: time format, weekend visibility, all-day slot, today highlight, scroll time, event height Visibility toggles for event types (scheduled, due, recurring, time entries, timeblocks, property-based) Date validation to handle invalid property values Drag-and-drop to update property-based event dates in frontmatter Full internationalization support for calendar features in 7 languages (English, French, Spanish, German, Japanese, Russian, Chinese) Added grouped rendering support for Bases integration list and kanban views List view displays collapsible groups with toggle controls Kanban view renders grouped columns with drag-drop support Automatically detects ungrouped views and renders as flat list (#842) Added keyboard navigation support for task forms Action bar icons now focusable with proper tab order and ARIA attributes Enter and Space keys trigger actions on focused elements Added submenu support for reminders button for better keyboard accessibility Improved focus indicators for better visual feedback Thanks to @maybetm for this excellent contribution! Changed# Migrated Bases integration to use public API (Bases 1.10.0+) with graceful fallback to internal API for older versions Fixed# (#789) Fixed folder path truncation in settings causing tasks to be created in wrong paths Changed debounce to trailing mode to ensure final value is saved instead of partial input Fixes issue where rapid typing, paste, or autocomplete would save incomplete folder paths Thanks to @sascha224 for reporting (#806) Fixed Bases views crashing on Obsidian 1.10.0 startup TaskNotes Bases views (Task List and Kanban) now restore correctly when already open at startup Added defensive checks in setEphemeralState to handle early lifecycle calls Added focus() method to view objects for proper restoration Made root elements focusable to support Obsidian 1.10.0 view lifecycle (#825) Fixed single/double click settings not applying to calendar views Shared click handling now works consistently across Advanced Calendar and Bases Calendar Ctrl/Cmd+click opens tasks in new tab as expected Single and double-click actions respect user settings (#699) Fixed Obsidian freezing when moving calendar tab to new window Skip calendar resize during window transfer to prevent freeze Calendar may display incorrectly after move but can be fixed by switching views Prevents complete UI lockup during tab transfer (#816) Fixed template variables not processing in ICS subscription note folder paths Template variables like {{year}}, {{month}}, {{date}} now work in ICS note folder settings Extracted folder template processing into shared utility for consistency Added support for ICS-specific variables: {{icsEventTitle}}, {{icsEventLocation}}, {{icsEventDescription}} Users can now organize ICS notes in date-based hierarchies (e.g., Daily/{{year}}/{{month}}/) Thanks to @j-peeters for reporting (#813) Fixed subscribed ICS calendars irregularly disappearing from calendar views Added 5-minute grace period after cache expiration to keep events visible during refresh Trigger automatic background refresh when cache is stale or missing Initialize ICS service instances early so views can register event listeners before data loads Prevents disappearance during network errors or when calendar opens at Obsidian startup Thanks to @j-peeters for reporting (#829) Fixed time estimates and recurrence patterns being lost during instant task conversion Added timeEstimate field to ParsedTaskData interface Time estimates from natural language parsing now properly transferred to task frontmatter Parsed values now take priority over default settings RRule strings passed directly without conversion (preferred format) Thanks to @Justin-Burg for reporting (#826) Fixed task card widget not appearing when Obsidian starts with task note open Deferred dispatch calls to avoid \"EditorView.update not allowed during update\" error Widget now renders correctly on startup without requiring workarounds Thanks to @nightroman for reporting (#781), (#841) Fixed ICS calendar events displaying incorrect times due to timezone conversion issues Events with non-IANA timezone identifiers (e.g., TZID=Zurich without VTIMEZONE) now display at correct local times Fixed Outlook/Exchange calendar events showing original timezone instead of user's local timezone Replaced unreliable toJSDate() conversion with toUnixTime() for accurate UTC timestamp handling Affects all ICS subscriptions including Infomaniak, Outlook, and other providers with non-standard timezone formats Thanks to @chrlaney for reporting and @wilf80 for detailed analysis (#810) Fixed recurring tasks with overdue due dates disappearing from agenda view Recurring tasks now check both due and scheduled dates for overdue status Previously only scheduled was checked for recurring tasks, causing tasks with overdue due dates to be hidden Ensures consistent overdue detection logic between recurring and non-recurring tasks Thanks to @skyrunner15 for reporting (#822) Fixed mini calendar showing incorrect dates in negative UTC offset timezones Calendar tooltips and month displays now show correct dates for users in Americas/Pacific timezones UTC-anchored dates are now converted to local calendar dates before formatting Fixes off-by-one day error that affected date selection and display Thanks to @kenhsmith for reporting"},{"title":"TaskNotes 3.25.1","url":"/obsidian/releases/3.25.1/","description":"(#854) (#695) Fixed all-day ICS calendar events displaying on wrong day and appearing twice","product":"obsidian","text":"Fixed# (#854) (#695) Fixed all-day ICS calendar events displaying on wrong day and appearing twice All-day events now stored as date-only strings (YYYY-MM-DD) instead of UTC timestamps Events display on correct calendar date regardless of user timezone (fixes issue in PST, EST, and other negative UTC offset timezones) All-day events no longer appear twice in Agenda view Updated all date parsing throughout the codebase to handle date-only format correctly Maintains compatibility with FullCalendar and preserves iCalendar RFC 5545 semantics for VALUE=DATE events Thanks to @needo37 for reporting #854 and @realJohnDoe for reporting #695 (#859) Fixed multi-day task creation in Bases calendar view Extracted shared task creation logic to calendar-core.ts for consistency between calendar views Multi-day all-day selections now correctly set time estimate based on number of days dragged Timed task selections (week view) now correctly calculate duration in minutes Single-day clicks no longer override default time estimate settings Both Bases calendar and AdvancedCalendarView now use same logic for consistent behavior Fixed all-day task rendering to use 24-hour days (1440 minutes = 1 day on calendar) Follows UTC Anchor principle for date-only strings Thanks to @anareaty for reporting"},{"title":"TaskNotes 3.25.2","url":"/obsidian/releases/3.25.2/","description":"(#857) Fixed Mini Calendar opening previous day's daily note when clicked","product":"obsidian","text":"Fixed# (#857) Fixed Mini Calendar opening previous day's daily note when clicked Affects users in negative UTC offset timezones (Americas, Pacific) Thanks to @tsweezy for reporting (#871) Fixed Bases Kanban drag-and-drop updating wrong property when grouped by custom fields Added support for both Bases 1.10.0+ format ({property: string, direction: string}) and legacy string format Note: GroupBy is not exposed in the Bases public API (config.get('groupBy') returns undefined) Known limitation: When grouping by projects, Bases groups by literal wikilink strings, not resolved file paths Tasks with different wikilink formats pointing to the same project file will appear in separate columns Example: [[Project]], [[path/to/Project]], and [[Project|Alias]] create separate columns This differs from native TaskNotes Kanban which resolves all wikilinks to absolute paths Thanks to @kmaustral for reporting Added# Added date navigation configuration for Bases calendar views Hardcoded date option: Set a specific date (YYYY-MM-DD format) for the calendar to display on load Property-based navigation: Automatically navigate to dates from filtered note properties Three navigation strategies: First result, Earliest date, or Latest date Changed# Release notes now bundle all versions from current and previous minor series with collapsible sections Added setting to disable automatic release notes display after updates"},{"title":"TaskNotes 3.25.3","url":"/obsidian/releases/3.25.3/","description":"(#899) Fixed \"Folder for converted tasks\" setting being hidden when convert button is disabled","product":"obsidian","text":"Added# (#877) Added standard Obsidian CSS classes to settings tab buttons for improved theme compatibility Fixes issue where themes like Retroma couldn't distinguish active tabs Thanks to @Bregor for the contribution Fixed# (#899) Fixed \"Folder for converted tasks\" setting being hidden when convert button is disabled Setting now always visible since it affects command palette task conversion Resolves confusion for users who convert tasks via command palette Thanks to @nnnell for the fix (#905), (#907) Fixed project filter incorrectly affecting custom field suggestions Custom field wikilink suggestions ([[) now show all vault files instead of only filtered projects Task Edit modal now uses consistent hierarchical tag matching with Task Creation modal Thanks to @renatomen for the thorough fix and tests"},{"title":"TaskNotes 3.25.4","url":"/obsidian/releases/3.25.4/","description":"(#937), (#956) Added optional setting to hide identification tags in task cards","product":"obsidian","text":"Added# (#937), (#956) Added optional setting to hide identification tags in task cards New \"Hide identification tags in task cards\" setting (only visible when using tag-based identification) Hides exact matches (e.g., #task) and hierarchical children (e.g., #task/project, #task/work/urgent) Reduces visual clutter while keeping tags in frontmatter for organizational purposes Backward compatible - disabled by default Thanks to @renatomen for implementing this feature and @edakimling for reporting (#911) Added custom field suggestion filtering New autosuggestFilter field to UserMappedField interface allows filtering suggestions by current filter context Added collapsible filter section in settings with visual indicator Comprehensive test coverage for custom field filtering feature Thanks to @renatomen for this enhancement Fixed# (#903) Fixed Edit Task modal not adding completedDate when marking tasks as done Edit Task modal now correctly adds completedDate when changing status to completed Fixed Edit Task modal adding empty contexts and projects arrays to frontmatter Behavior now consistent with other completion methods (Agenda view, widget context menu, quick actions) Thanks to @nightroman for reporting (#969), (#967) Fixed Bases Kanban layout not displaying correctly when no groupBy is configured All tasks were appearing in a single \"None\" column Columns now appear in the order defined in TaskNotes settings (not alphabetical) Detects invalid Bases grouping and falls back to status-based grouping Tasks are properly distributed across status columns Thanks to @mweichert for the fix and @PacoTaco2, @abuhammer for reporting"},{"title":"Tasknotes 3.25.6","url":"/obsidian/releases/3.25.6/","description":"(#1013) Fixed inability to subscribe to Apple iCloud calendars","product":"obsidian","text":"Fixed# (#1013) Fixed inability to subscribe to Apple iCloud calendars Calendar URLs copied from Apple Calendar (starting with webcal://) can now be pasted directly Previously required manually changing the URL format before it would be accepted Works with both standard and secure calendar URLs (webcal:// and webcals://) Thanks to @nickbirch51 for reporting (#1022) Fixed tasks randomly disappearing from views and not being recognized Tasks would appear initially but disappear after a few seconds, especially during long sessions Restarting Obsidian or using \"Refresh Cache\" would only temporarily fix the issue Thanks to @seepage87 for reporting and @alejandrospoz for help debugging (#968) Fixed timeEntries being duplicated when mapped to custom property name When timeEntries was configured to use a custom property name in Metadata settings (e.g., time_entries), saving tasks would create duplicate entries in both the custom property and the default timeEntries property FieldMapper now correctly uses only the configured property name for time tracking data Thanks to @minchinweb for reporting this issue (#953) Fixed non-task notes incorrectly appearing as subtasks in views Notes with Parent or project properties but no task tag/property no longer show up as tasks Views now update correctly when task tags are removed from files Improved performance for large vaults by optimizing cache invalidation Thanks to @renatomen for reporting and submitting PR #955"},{"title":"Untitled","url":"/obsidian/releases/3.3.0/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.1.1...3.3.0","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.1.1...3.3.0"},{"title":"Untitled","url":"/obsidian/releases/3.4.0/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.3.0...3.4.0","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.3.0...3.4.0"},{"title":"Untitled","url":"/obsidian/releases/3.4.1/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.0...3.4.1","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.0...3.4.1"},{"title":"Untitled","url":"/obsidian/releases/3.4.2/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.1...3.4.2","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.1...3.4.2"},{"title":"Untitled","url":"/obsidian/releases/3.5.1/","description":"This release focusses on significant performance improvements by migrating away from the baroque plugin caching system to Obsidian's native cache.","product":"obsidian","text":"This release focusses on significant performance improvements by migrating away from the baroque plugin caching system to Obsidian's native cache. Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.0...3.5.1"},{"title":"Untitled","url":"/obsidian/releases/3.6.0/","description":"Fix task tag check. Add optional timeblocking.","product":"obsidian","text":"Fix task tag check. Add optional timeblocking."},{"title":"TaskNotes v3.7.0 Release Notes","url":"/obsidian/releases/3.7.0/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.6.0...3.7.0","product":"obsidian","text":"Reading Mode Task Previews (thank you @amithkk)# Task link previews now work in Reading Mode in addition to Live Preview Consistent interactive experience across all Obsidian view modes Same functionality: click to edit, right-click for context menu, hover for file preview New ReadingModeTaskLinkProcessor.ts with dedicated CSS styling Task Action Palette# New quick-action command palette for rapid task management Access via command palette: \"TaskNotes: Open Task Action Palette\" Change status/priority with fuzzy search, set dates, start/stop timers, archive/delete tasks Handles recurring task instances vs. series intelligently Fully keyboard navigable with categorized actions Natural Language Task Input# Parse natural language when creating tasks: \"Buy groceries tomorrow 3pm high priority @home #errands\" Powered by chrono-node for robust date/time parsing Extracts dates, priorities, status, contexts (@), tags (#), recurrence, and time estimates Multi-line support: first line parsed, additional lines become task details Toggle in Settings → Basic Defaults UI/UX Improvements# Enhanced Task Creation Modal# Smart input mode with simplified interface when natural language is enabled Progressive disclosure to detailed form when needed Better conversion flow with pre-populated forms Live filename preview as you type Settings & Modal Improvements# Moved Natural Language Input to Basic Defaults section Updated task link overlay description to mention both view modes Reusable confirmation modal for consistent dialogs Better error handling and accessibility improvements Bug Fixes# Fixed: Inline Tasks Not Respecting Default Status & Priority (Issue #58)# Problem: Inline task conversion applied \"none\" instead of configured defaults Solution: Changed useDefaultsOnInstantConvert default from false to true Timer Function Standardization# Fixed browser compatibility by replacing Node.js timer types with browser-native timers Resolved timing issues across different environments Enhanced Task Link Overlays# Better path resolution with security enhancements Graceful fallbacks for invalid or missing task files Improved handling of rapid view changes Technical Improvements# Enhanced Date Support# Full due date and scheduled date support in task creation and filename generation New filename template variables: {dueDate} and {scheduledDate} (YYYY-MM-DD format) Support for ISO dates, relative dates, named dates, and natural language Performance & Code Quality# Improved event handling with better refresh logic Layout change listeners for immediate overlay updates Enhanced error handling with user-friendly messages Better TypeScript types and modular design New Files & Dependencies# New Files# src/editor/ReadingModeTaskLinkProcessor.ts src/modals/TaskActionPaletteModal.ts src/services/NaturalLanguageParser.ts src/modals/ConfirmationModal.ts styles/task-action-palette-modal.css New Dependency# chrono-node: Natural language date parsing library What's Changed# Feat/task previews in reading mode by @amithkk in https://github.com/callumalpass/tasknotes/pull/57 New Contributors# @amithkk made their first contribution in https://github.com/callumalpass/tasknotes/pull/57 Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.6.0...3.7.0"},{"title":"Version 3.7.1","url":"/obsidian/releases/3.7.1/","description":"Files with Major Changes:","product":"obsidian","text":"Major UI/UX Enhancements# Interactive Inline Task Previews# Clickable Status Dots: Status indicators in inline task previews are now interactive - click to cycle through task statuses directly from the preview Clickable Date Fields: Due and scheduled dates are now clickable and open dedicated modals for quick editing Enhanced Visual Design: Redesigned with minimal styling Improved spacing and vertical alignment between status dots, priority indicators, and task titles Better hover effects with brightness and subtle animations Status dots now use bordered design for better visibility Modernized Task Card Design# Interactive Status Cycling: Click status dots on task cards to quickly change task status Improved Mobile Support: Better touch targets and responsive behavior Enhanced Animations: Smooth hover effects, scaling, and transition animations Cleaner Layout: Streamlined design with better visual hierarchy Enhanced Natural Language Processing# Advanced Date Parsing# Explicit Trigger Recognition: Now recognizes specific phrases: Due dates: \"due on\", \"deadline\", \"must be done by\", \"needs to be completed\" Scheduled dates: \"scheduled for\", \"start on\", \"work on\", \"planned for\" Configurable Defaults: New setting to choose whether ambiguous dates default to \"due\" or \"scheduled\" Enhanced Recurrence Patterns: \"every [weekday]\" patterns (every monday, every friday) Plural day patterns (mondays, tuesdays, etc.) \"Every other\" interval patterns (every other week, every 2 days) Multiple days (\"every tuesday and thursday\") Improved Date/Time Handling# Better Time Component Support: Enhanced parsing of specific times with dates Robust Validation: Improved handling of edge cases and malformed input Smart Cleanup: Automatic removal of duplicate tags and contexts Performance & Developer Experience# Instant Task Conversion Improvements# Real-time Updates: Task link overlays refresh immediately after task conversion Smart Caching: Improved metadata cache management for newly created tasks Better Error Handling: Enhanced validation with user-friendly error messages Multi-line Support: Enhanced conversion of tasks with details from multiple selected lines Technical Improvements# Improved Event Handling: Fixed n.dispatch is not a function error with proper validation BEM CSS Methodology: Migrated to Block Element Modifier naming for better CSS organization Performance Optimizations: Reduced unnecessary re-renders and improved widget caching Enhanced State Management: Better synchronization between UI updates and task data Modal & Interface Enhancements# Enhanced Date/Time Modals# Better Keyboard Navigation: Enter to save, Escape to cancel Separate Time Inputs: Dedicated date and time fields for precision Quick Date Buttons: Common date selections for faster input Improved Accessibility: Proper ARIA labels and screen reader support Better User Experience# One-Click Status Changes: Direct status cycling from any task preview Direct Date Editing: Click any date to immediately edit it Enhanced Visual Feedback: Better hover states, transitions, and loading animations Accessibility Improvements: Enhanced keyboard navigation and screen reader support Bug Fixes & Stability# Fixed: Inline task widget dispatch errors that caused console warnings Fixed: Vertical alignment issues with different-sized status and priority indicators Fixed: Layout conflicts between flexbox and inline display properties Fixed: Spacing issues in inline task previews causing cramped appearance Fixed: Missing task link overlay refreshes after instant task conversion Configuration & Settings# New User Settings# Natural Language Default: Configure whether ambiguous dates default to \"due\" or \"scheduled\" Enhanced Task Creation: Improved default value application for instant task conversion Technical Details# Files with Major Changes: Enhanced inline task previews (TaskLinkWidget.ts, TaskLinkOverlay.ts) Modernized task card design (TaskCard.ts) Advanced natural language processing (NaturalLanguageParser.ts) Improved modal interfaces (DueDateModal.ts, ScheduledDateModal.ts) Comprehensive CSS overhaul with BEM methodology"},{"title":"Untitled","url":"/obsidian/releases/3.8.1/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.7.1...3.8.1","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.7.1...3.8.1"},{"title":"TaskNotes 3.8.5 Release Notes","url":"/obsidian/releases/3.8.5/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.1...3.8.5","product":"obsidian","text":"UI/UX Improvements# Compact Filter Bar (Special thanks to @amithkk :tada: )# Complete redesign of FilterBar component with compact, modern interface Native Obsidian dropdowns replace basic HTML select elements for better consistency Collapsible controls - settings are hidden by default with expandable controls via settings button Visual indicators showing active filter count on settings button Integrated search bar with search icon and improved visual hierarchy Right-aligned control buttons for better layout organization Advanced Calendar View Integration# Unified view options - calendar view toggles now integrated into FilterBar dropdown Streamlined interface - removed separate toggle controls in favor of FilterBar integration Consistent UX across different view types with shared filter/view controls Dynamic option management with real-time updates and state synchronization Enhanced Natural Language Processing# Improved Text Processing# Better whitespace handling with new cleanupWhitespace() function for consistent text normalization Enhanced priority detection with improved pattern matching and conflict resolution Completion status support - added isCompleted field to parsed task data More robust text extraction across tags, contexts, priorities, and dates Date and Time Handling Improvements# Enhanced date parsing with better timezone handling for date-only strings Improved date normalization with direct Date constructor to avoid timezone issues Better error handling for invalid date strings and edge cases More robust timestamp formatting with validation checks Testing Infrastructure# Comprehensive Test Suite# Complete testing infrastructure with Jest configuration for both unit and integration tests Enhanced mocking system with improved Obsidian API mocks and better type safety Integration test helpers with utilities for end-to-end workflow testing Improved test coverage across core components and services Mock Improvements# Updated mock factories with better type consistency and realistic data generation Enhanced DOM simulation for better UI component testing Improved date-fns mocking with support for \"MMM d, yyyy h:mm a\" format Better Obsidian API compatibility in test mocks Developer Experience# Type Safety Enhancements# Refactored type definitions for improved consistency across the codebase Better TypeScript integration with enhanced type checking and inference Improved callback types for better development experience Build and Deployment# Updated GitHub Actions with artifact uploader v4 for improved CI/CD Enhanced development workflow with better testing and build processes User Interface Polish# Task Creation Modal# Improved placeholder text with more natural language examples Better user guidance for natural language task input format Clearer instruction formatting for enhanced user experience Visual Consistency# Native Obsidian styling throughout filter and control components Consistent iconography using Obsidian's icon system Improved responsive design with better mobile and small screen support Bug Fixes and Stability# Error Handling# Improved error handling in date parsing and normalization functions Better validation for user input and edge cases Enhanced robustness in text processing and natural language parsing Code Quality# Refactored components for better maintainability and performance Simplified scheduled date logic with cleaner default handling Enhanced code organization with better separation of concerns What's Changed# Add compact filter bar by @amithkk in https://github.com/callumalpass/tasknotes/pull/73 Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.1...3.8.5"},{"title":"Untitled","url":"/obsidian/releases/3.8.6/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.5...3.8.6","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.5...3.8.6"},{"title":"Untitled","url":"/obsidian/releases/3.8.7/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.6...3.8.7","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.6...3.8.7"},{"title":"Release Notes v3.9.0","url":"/obsidian/releases/3.9.0/","description":"This release introduces a host of new features, bug fixes, and significant enhancements to improve your task and time management experience. Key updates include a more powerful...","product":"obsidian","text":"This release introduces a host of new features, bug fixes, and significant enhancements to improve your task and time management experience. Key updates include a more powerful and standards-compliant recurrence system, a streamlined user interface, and improved performance. A special thank you to amithkk (https://github.com/amithkk) for their contributions to this release! New Features# RRule-Based Recurrence: Task recurrence is now powered by the iCalendar standard (RFC 5545), allowing for more complex and flexible recurring task schedules. A migration assistant will help you update your existing tasks to the new format. Interactive Recurring Task Calendar: An interactive calendar has been added to the task edit modal, allowing you to visualize and manage individual completions of recurring tasks. \"Show\" Dropdown in Filter Bar: A unified \"Show\" dropdown has been added to the filter bar, providing enhanced filtering options for your tasks. Insert Tasknote Link Command: A new command has been added to insert a link to a tasknote, streamlining your workflow. Dedicated Inline Task Folder Setting: You can now specify a dedicated folder for inline tasks, with support for {{currentNotePath}} to save tasks in the same folder as the current note. \"Show Due Dates When Scheduled\" Setting: A new setting allows you to display due dates for scheduled tasks in the calendar view. Compact Filter Bar: A more compact filter bar option is now available for a cleaner interface. (Thanks, amithkk!) Multiple New Ribbon Icons: New ribbon icons have been added for extended views and actions, providing quicker access to features. \"Highlight Today\" in Calendar View: The calendar view now highlights the current day for better visibility. New Documentation Site: A new documentation site, built with MkDocs, is now available with improved structure and searchability. CI/CD and Testing: A comprehensive testing suite using Jest has been added to improve code quality and prevent regressions. GitHub Actions workflows have been implemented for automated testing, documentation deployment, and releases. Enhancements# UI/UX Improvements: The task edit and creation modals have been redesigned for a more minimalist and intuitive experience. Task-related icons have been updated for better clarity. Context menus have been added to task cards for quick actions. The agenda view sorting options have been fixed. The recurring calendar widget is now centered and on a separate line from its label. Dropdown menus now handle clicks on text labels more reliably. Performance and Reliability: The task link overlay has been refactored to use a ViewPlugin for better performance. The Advanced Calendar view now handles resizing and being moved to a new window more gracefully. The natural language processing for task creation has been improved with a fallback mechanism. Date parsing and handling have been made more robust, especially for UTC and different date formats. Development Workflow: ESLint configuration has been updated with new rules and plugins for better code consistency. The build process for CSS has been improved. The development guidelines have been updated to reflect the new architecture. Bug Fixes# Fixed an issue where agenda view sorting options were not working correctly. Fixed a bug that caused a forced reflow when moving the Advanced Calendar to a new window. Resolved a TypeError in the task modal's suggestion filtering. Fixed an issue where the Pomodoro task selector did not show all un-archived tasks. Corrected the filtering of daily notes in the getNotesForDate function. Fixed a bug where the underlying markdown of a task link was not revealed on hover. Removed misleading placeholder symbols from the settings. Addressed various linting issues and improved code quality. Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.7.1...3.9.0"},{"title":"Release Notes: 3.9.1","url":"/obsidian/releases/3.9.1/","description":"New Features","product":"obsidian","text":"New Features GitHub Issue Templates: Added templates for bug reports and feature requests to streamline issue submission and ensure all necessary information is provided. Bug Fixes Pomodoro Timer: Fixed an issue where a long break would incorrectly start after the first work session. The timer now correctly schedules a short break as intended. Task Creation: The \"Magic Wand\" (Natural Language Processing) now properly fills the context and tag fields in the task creation modal. Default contexts and tags are preserved if none are found in the natural language input. What's Changed# Add github issue templates by @amithkk in https://github.com/callumalpass/tasknotes/pull/101 Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.9.0...3.9.1"},{"title":"TaskNotes 4.0.0-beta.0","url":"/obsidian/releases/4.0.0-beta.0/","description":"Beta Release","product":"obsidian","text":"Beta Release You may encounter issues. Report problems on GitHub Issues. What's New in v4# TaskNotes v4 migrates all views to the Bases system. Breaking Changes# Minimum Obsidian version: 1.10.1 View commands now use Bases files - Ribbon icons and command palette commands (Calendar, Kanban, Tasks, Agenda, Project Subtasks) now open .base files created automatically in your vault Saved filter views - Custom saved views can be converted to .base files using a conversion button in settings Added# OAuth Calendar Integration# Google Calendar and Microsoft Outlook integration via OAuth 2.0 View and sync calendar events in Bases calendar Drag events in the TaskNotes bases calendar to change the event's time online Events sync every 15 minutes or upon local change Requires creating your own OAuth application (approximately 15 minutes) See Calendar Setup Guide Time Entry Editor Modal# Dedicated interface for managing time entries Alt-drag on Bases calendar to create time entries View total tracked time per task Edit and delete time entries Access via Task Action Palette (Alt/Opt + Enter) Kanban Swimlane Layout# Horizontal swimlane grouping option for Bases Kanban Group tasks by status, priority, or other fields Hide empty columns Configurable column widths Improved drag-and-drop in swimlane mode Saved View Converter# Conversion button in settings to convert saved filter views to .base files Original settings preserved Converted views created in TaskNotes/Views/ Changed# View System Architecture# All views now use Bases architecture Calendar, Kanban, Tasks, Agenda, and Project Subtasks are .base files Views stored in TaskNotes/Views/ Keyboard shortcuts and ribbon icons map to .base files Configure file paths in Settings → Integrations → Bases Integration Calendar# Control which calendar sources display Toggle Google Calendar, Microsoft Calendar, and ICS events independently Configurable list view with custom day count (2-10 days) Improved timezone handling for recurring events Settings# Reorganized settings tabs OAuth calendar settings in Integrations tab Updated help text Fixed# (#843) Fixed task tag being added when \"Identify tasks by\" is set to \"Property\" TaskCreationModal, TaskEditModal, and InstantTaskConvertService now respect taskIdentificationMethod setting Thanks to @jack2game Fixed dark mode calendar borders Fixed Bases Kanban column ordering - Thanks to @mweichert Fixed state management bug in FilterSettingsComponent Fixed timezone handling for recurring events Migration Guide# First Launch# Default view files are created automatically in TaskNotes/Views/ Ribbon and command palette commands now open .base files Review Settings → General to customize view file paths Converting Saved Filter Views# Go to Settings → General Click the conversion button to convert saved filter views to .base files Converted views appear in a file in TaskNotes/Views/ Calendar Integration (Optional)# Go to Settings → Integrations → OAuth Calendar Integration Follow the Calendar Setup Guide Create OAuth applications with Google and/or Microsoft (approximately 15 minutes) Enter Client ID and Secret in calendar cards Click Connect Known Limitations# Quick OAuth setup is disabled - only advanced setup (your own credentials) is available Saved filter views require manual conversion using the button in settings Migration is one-way - downgrading to v3 may require manual reconfiguration OAuth setup requires creating applications with Google/Microsoft Feedback# Report issues on GitHub. Include: Obsidian version Steps to reproduce Console errors (Ctrl/Cmd + Shift + I) Whether issue occurs after migration or fresh install"},{"title":"TaskNotes 4.0.0-beta.1","url":"/obsidian/releases/4.0.0-beta.1/","description":"Beta Release","product":"obsidian","text":"Beta Release You may encounter issues. Report problems on GitHub Issues. Added# Added context menus for time entries and ICS events in calendar Time entries: Right-click shows task context menu, left-click opens time entry editor modal ICS/Google/Microsoft Calendar events: Right-click shows ICS event context menu with options to show details, create task/note, link note, and copy info Added calendar icon to ICS event titles for better visual distinction Added hover tooltips for timeblocks in calendar views Added MiniCalendar view for Bases integration Monthly calendar grid with dot indicators on days with notes Configurable date property (file.ctime, note.dateCreated, etc.) Fuzzy selector modal for selecting notes on clicked days Ctrl+click (or Cmd+click on Mac) on any day opens/creates daily note Added virtual scrolling and lazy rendering to Bases views for high-performance handling of large datasets TaskListView: Virtual scrolling for 100+ tasks in flat and grouped views with collapsible groups KanbanView: Virtual scrolling for regular columns (30+ tasks) and swimlane cells (30+ tasks per cell) Tested with up to 30,000 notes with no performance degradation Thanks to @aubreyz and @turingexmachina for their reports of performance issues and diagnosis help Changed# Refactored Bases integration to use public API and trust pre-sorted data Migrated all three views (Task List, Kanban, Calendar) to clean class-based architecture Removed legacy view files and ~500 lines of redundant sorting/grouping logic Introduced BasesDataAdapter, PropertyMappingService, and BasesViewBase abstractions Trusts Bases plugin to provide pre-sorted and pre-grouped data via public API Reduced code duplication by 40% while maintaining full feature parity Refactored calendar modules to use ES6 imports instead of lazy require() calls Removed all dynamic require() calls from calendar-core.ts and calendar-view.ts Consolidated all imports at module top level Improves code maintainability, makes dependencies explicit, and follows modern TypeScript best practices Time entry events now show task context menu on right-click (previously had no context menu) Replaced MinimalNativeCache with just-in-time TaskManager for improved reliability Removed complex index synchronization in favor of direct MetadataCache queries Eliminated 7 internal indexes (tasksByDate, tasksByStatus, overdueTasks, etc.) Added minimal DependencyCache for task dependencies and project references only Zero startup time (no index building required) Always provides fresh, accurate task data from Obsidian's MetadataCache Completed internationalization with 100% translation coverage across all supported languages Added 90 missing translation keys to English base Completed 829 translations across 6 languages (German, Spanish, French, Japanese, Russian, Chinese) All locales now have complete coverage (1745/1745 keys) Improved translation quality for migration system, calendar settings, statistics, ICS events, and filter components Migrated to i18n-state-manager CLI tool for translation management Replaced custom scripts with more robust i18n-state-manager package Added i18n-state.config.json for project-specific patterns New features: find-unused, check-duplicates, improved stale detection Hash-based state tracking and ripgrep-based scanning for performance Bases view templates now generate dynamically based on user settings Task filters adapt to user's task identification method (tag or property) Property ordering reflects defaultVisibleProperties setting Uses correct YAML object notation for Bases filters Maintains backward compatibility with legacy static templates Updated Bases CalendarView to show TaskNotes in property-based events Tasks can now be visualized on calendar via any date property (dateCreated, scheduled, due, etc.) Previously all TaskNotes were filtered out from property-based events Fixed# (#1022, #684) Fixed tasks randomly disappearing when Smart Connections plugin is enabled Eliminated race condition caused by index synchronization delays TaskManager now reads directly from Obsidian's MetadataCache instead of maintaining separate indexes No more timing-sensitive code that could conflict with other plugins' metadata processing Tasks will always be visible regardless of other plugins' processing times Thanks to @alejandrospoz, @seepage87, @amarjt, @luckb0x, camara-tech for reporting and help debugging. (#992) Fixed \"Failed to resolve module specifier 'obsidian'\" error when moving recurring task instances in calendar Removed unnecessary dynamic imports that were causing module resolution failures Consolidated imports at top of calendar-core.ts module Thanks to @jalooc for reporting this issue Fixed task dependencies not displaying on task cards TaskManager now properly calculates isBlocked and isBlocking flags from dependency data Added missing property extractors and renderers in TaskCard for all dependency-related fields Dependency information now shows correctly in Bases views, task note widgets, and other views Shows \"Blocked (n)\" and \"Blocking (n)\" pills, plus detailed task links Fixed Bases property mapping for user-configured field names PropertyMappingService now correctly strips prefixes and applies FieldMapper transformations Example: User configures \"state\" → \"status\", Bases provides \"note.state\", now correctly maps to \"status\" Ensures TaskCard properly recognizes and renders user-configured properties Fixed Bases views not respecting user-configured visible properties Now prioritizes Bases 1.10.0+ public API config.getOrder() method Removed reliance on internal API paths that no longer work Filters out blocked/blocking properties when using defaults (only shown when explicitly requested via blockedBy) Fixed MiniCalendar UTC anchoring for consistent timezone-independent date handling Fixed DateValue conversion in BasesDataAdapter DateValue objects have {date: Date, time: boolean} structure Now properly checks for value.date instanceof Date before legacy conversion methods Fixes property-based events in CalendarView"},{"title":"TaskNotes 4.0.0-beta.2","url":"/obsidian/releases/4.0.0-beta.2/","description":"Beta Release","product":"obsidian","text":"Beta Release You may encounter issues. Report problems on GitHub Issues. Added# (#1090) Portuguese (Brazil) translation Full Portuguese (pt-BR) localization support A big thanks to @andysteel for the contribution Configurable task modal fields New \"Modal Fields\" settings tab for complete control over task creation and edit modals Configure which fields appear in creation vs edit modals independently Drag-and-drop reordering of fields within groups (metadata, organization, dependencies, custom) Enable/disable individual fields (including core fields like contexts, tags, time estimate) Organize fields into groups Automatic migration of existing user-defined fields Title and details fields support visibility toggling (ordering fixed for consistency) Rich markdown editor for NLP task creation Replaced plain textarea with full CodeMirror markdown editor Live preview, syntax highlighting, and wikilink support Ctrl/Cmd+Enter keyboard shortcut to save task Esc/Tab keyboard shortcuts for modal control Customizable NLP triggers with autocomplete Configure custom trigger characters/strings for each property type (tags, contexts, projects, status, priority) Supports user-defined field triggers CodeMirror-based autocomplete with keyboard navigation (arrow keys, Enter, Tab) Quote support for multi-word values in user fields Native tag suggester integration when using # trigger Inline task link overlay enhancements Configurable visible properties for inline task cards PropertySelectorModal for selecting which properties to display Improved layout: title prioritized, horizontal scrolling for metadata Real-time updates when task data changes New utility services TriggerConfigService - manages NLP trigger configurations PropertySelectorModal - reusable multi-select property picker Property helpers for consistent property handling across views Kanban column reordering via drag and drop Drag column headers to reorder columns Column order is saved per grouping property Visual feedback during drag operations Mini calendar enhancements (in progress) Week numbers column Heat map intensity visualization Note preview tooltips on hover Keyboard navigation Unified Relationships widget Consolidated project subtasks, task dependencies, and blocking relationships into a single dynamic widget Four automatic tabs: Subtasks (Kanban), Projects (List), Blocked By (List), Blocking (Kanban) Tabs automatically show/hide based on available relationship data Bases views handle all data updates reactively - no manual refresh needed Single configuration setting: show/hide and position (top/bottom) Significantly reduced code complexity (430 fewer lines) Fixed# (#1084) Fixed word wrapping in NLP preview items Thanks to @maybetm for the fix (#975) Fixed advanced calendar list headers not respecting theme colors Thanks to @hugohil for the fix (#1089) Fixed embedded task list bases growing unbounded and leaving large empty space Embedded bases now scroll internally instead of expanding to show all tasks Consistent behavior between task list and kanban embedded views Thanks to @same774 for reporting with screenshot Bases Calendar view options now working correctly Fixed \"Highlight today\" toggle not applying - now properly adds/removes CSS class when toggled Fixed calendar view type (month/week/day/etc) not being saved when changed via calendar buttons View type is now persisted when users click month/week/day buttons in the calendar UI (#1050) Task modal no longer adds unwanted empty contexts and projects arrays FieldMapper now checks if arrays are empty before writing to frontmatter Thanks to @nightroman for reporting this issue Inline task link overlay fixes Fixed layout prioritization: title now prioritized over metadata Added horizontal scrolling for metadata to prevent overflow Fixed real-time update listeners for task data changes Fixed group collapse/expand functionality in TaskListView Re-registered click event listener for group headers using Component API Groups can now be properly collapsed and expanded Fixed config loading race condition in KanbanView and CalendarView Config is now properly loaded in onload() lifecycle method Views wait for config before rendering options Fixed MiniCalendarView to use direct Bases API like other views Consistent use of Component lifecycle methods Proper cleanup in onunload() Changed# NLP system overhaul Replaced StatusSuggestionService wrapper with direct NaturalLanguageParser usage Consolidated trigger configuration into unified TriggerConfigService Enhanced NaturalLanguageParser with full trigger and user field support Removed custom # tag autocomplete in favor of Obsidian's native tag suggester (when using # trigger) Task card and editor improvements Simplified TaskCard interface - removed unused options (showCheckbox, showArchiveButton, groupByDate) Refactored TaskLinkWidget to use unified TaskCard component for consistency Added support for inline vs. block layout modes in task cards Improved task card BEM CSS with better styling for inline mode Settings UI enhancements NLP triggers now configurable through Settings > Features tab Added settings for inline task card visible properties Improved appearance tab with property selector integration Better organization of NLP-related settings Refactored Bases views to use Component lifecycle properly Views now extend Component and use onload()/onunload() Automatic cleanup of event listeners via Component.registerDomEvent() Improved state management and ephemeral state handling Improved development experience Converted ESLint errors to warnings for non-blocking development Fixed various linting issues and unused imports Removed# Removed StatusSuggestionService (functionality consolidated into NaturalLanguageParser) Breaking Changes# Relationships widget settings consolidated (automatic migration) Old settings removed: showProjectSubtasks, projectSubtasksPosition, showTaskDependencies, taskDependenciesPosition New unified settings: showRelationships, relationshipsPosition Widget now appears on ALL notes (tasks, projects, regular notes) - Bases filtering controls which tabs are visible Migration: Existing users will see the new unified widget automatically. If you had project subtasks enabled, relationships widget will be enabled by default Bases file change: The command mapping changed from 'project-subtasks': 'TaskNotes/Views/project-subtasks.base' to 'relationships': 'TaskNotes/Views/relationships.base' Run \"Create Default Files\" in Settings > General to create the new relationships.base file"},{"title":"TaskNotes 4.0.0-beta.3","url":"/obsidian/releases/4.0.0-beta.3/","description":"Beta Release","product":"obsidian","text":"Beta Release You may encounter issues. Report problems on GitHub Issues. Added# Updated task card styling Increased status dot size from 16px to 18px Added subtle shadows and transitions to card hover states Updated hover effects on status and priority dots with scaling and removed glow Modified metadata pills with backdrop blur and adjusted spacing Added box shadows to interactive elements (dates, projects, tags) on hover Updated animations to use cubic-bezier easing Added gradient accents to subtask and blocking task borders Fixed subtasks appearing behind parent card hover backgrounds Fixed subtask click and context menu events bubbling to parent cards Fixed subtasks inheriting parent priority and status colors (#361) Added completion-based recurrence support with recurrence_anchor field Tasks can now recur based on completion date instead of scheduled date Set recurrence_anchor: completion in task frontmatter to enable this behavior When completing a recurring task, the next occurrence will be scheduled relative to the completion date The DTSTART in the RRULE automatically updates to the completion date, ensuring calendar views show future occurrences at the correct dates Defaults to scheduled (original behavior) if not specified Useful for tasks like \"Exercise weekly\" where you want the next occurrence 7 days after you actually complete it, not 7 days after it was scheduled Example: Complete a weekly task 2 days late, and the next occurrence will be 7 days from the completion date (not the original scheduled date) Thanks to @luciolebrillante for the original feature request, and @jhedlund, @nschenone, @BryanWall, @realJohnDoe, and @kazerniel for additional input and interest (#416) Added support for skipped recurrence instances with skipped_instances field Recurring tasks can now have individual instances marked as \"skipped\" without completing them Skipped instances are stored in the skipped_instances frontmatter array (e.g., [\"2025-11-15\", \"2025-11-22\"]) Right-click on a recurring task instance in calendar views to skip/unskip it Visual styling differentiates skipped instances: Calendar views: Gray background with muted appearance Task cards: Strike-through text with gray styling Skipped instances don't affect the recurrence pattern - future instances continue as scheduled Useful for holidays, vacations, or other planned exceptions to recurring tasks Thanks to @mdbraber for the suggestion to use an array similar to complete_instances, and @jerzy-dudzic for reporting the issue Fixed# (#893) Fixed yearly recurring tasks not always updating scheduled date to next occurrence when completed Increased look-ahead period for yearly recurrence from 365 days to 800 days (~2.2 years) Also optimized look-ahead periods for other frequencies: daily (30 days), weekly (90 days), monthly (400 days) Ensures the next occurrence is always found when completing recurring task instances Thanks to @VenturaNotes for reporting (#951) Fixed yearly recurring tasks not showing up in calendar's weekly, 3-day, or day views Extended the look-ahead period for yearly recurring tasks when generating calendar instances Calendar views now look ahead ~2.2 years for yearly tasks to ensure occurrences appear even in short date ranges Only displays instances that fall within the actual visible calendar range Weekly recurring tasks were unaffected and continued to work correctly Thanks to @bespokecomp for reporting (#889) Fixed git merge conflicts in calendar subscription metadata Calendar subscription lastFetched and lastError fields are now stored in memory instead of being saved to disk Prevents git conflicts when syncing vaults across multiple computers that independently fetch calendar subscriptions The \"last synced\" timestamp in settings will reset on plugin reload, but subscriptions will re-fetch automatically Thanks to @karlfrohlich for reporting Fixed recurrence modal not loading DTSTART date/time when editing existing recurrence rules The custom recurrence modal now correctly parses and displays the start date and time fields Fixed parser that was splitting on = instead of : for DTSTART values (#1097) Fixed custom properties and formulas not displaying in Bases views Updated TaskCard to use Bases API's getValue() method for formulas and custom note properties Formulas now work correctly using formula.NAME syntax Custom note properties now work correctly using note.PROPERTY syntax Thanks to @cathywu for reporting (#1099) Fixed issues with default Bases file creation Fixed double-prefix bug in relationships template that generated invalid filter expressions like note.note.projects Fixed race condition where files created during plugin load wouldn't appear in file explorer Default Bases files now generate with correct property paths and appear reliably in the file explorer Thanks to @kmaustral for reporting (#1110) Fixed open recurring tasks appearing crossed out in Tasks view Removed stale selectedDate property that was never updated in v4 Tasks view now uses fresh UTC-anchored \"today\" for correct recurring task completion status Fixes issue where tasks completed yesterday would appear crossed out today for users in positive UTC offset timezones Also fixed KanbanView to use UTC-anchored dates for consistency Thanks to @kmaustral for reporting (#1118) Fixed user-defined fields not working in inline task conversion User-defined fields like >customfield value now properly convert to frontmatter when using the \"TaskNote: Convert task to TaskNote\" command Fixed fields appearing with internal IDs (e.g., field_1761435101864) instead of configured frontmatter key names Array values are now properly joined with commas Added userFields property to ParsedTaskData interface to support custom fields throughout the conversion flow Thanks to @guncav for reporting Fixed kanban column width CSS constraints not matching settings Updated CSS min-width from 280px to 200px and max-width from 350px to 500px to match slider range Column width slider now works correctly across the full 200-500px range Kanban view now shows empty columns for all user-defined statuses when grouping by status Empty columns appear for custom statuses defined in settings, even when no tasks have that status Allows users to drag tasks into empty status columns Works in both flat kanban view and swimlane mode Respects the existing \"Hide empty columns\" setting Thanks to @williamcheuk03 for reporting this issue"},{"title":"TaskNotes 4","url":"/obsidian/releases/4.0.1/","description":"TaskNotes 4.0.1 is a stability-focused major release that finishes the migration to Obsidian's Bases core plugin. Every task-facing view (Task List, Kanban, Calendar, Agenda...","product":"obsidian","text":"TaskNotes 4.0.1 is a stability-focused major release that finishes the migration to Obsidian's Bases core plugin. Every task-facing view (Task List, Kanban, Calendar, Agenda, Mini Calendar, and the embedded Relationships widget) now runs on .base files. This refactor simplifies the plugin codebase, removes bespoke UI logic, and lets workflows feel native to Obsidian—views are just files in your vault. Highlights# New features and improvements: Performance improvements Virtual scrolling in Task List and Kanban views handles 30,000+ tasks without performance degradation OAuth calendar integration Google Calendar and Microsoft Outlook bi-directional sync Drag calendar events in the TaskNotes calendar to update them online Configurable modals and NLP New Modal Fields settings tab for moving, hiding, or requiring fields in create/edit modals Rich markdown editor and customizable NLP triggers, including autocomplete for user fields Time management features Time Entry Editor Modal Improved Timeblock creation and management Completion-based recurrence with recurrence_anchor field Skippable recurrence instances Bases architecture changes: Bases-first architecture Task views ship as .base files inside TaskNotes/Views/ Commands and ribbon buttons now open files you control Filtering/grouping/sorting uses Bases YAML instead of TaskNotes-specific UI Agenda is a dedicated list-mode calendar .base file for fast daily/weekly reviews Inline workflows stay in sync Unified Relationships widget embeds a Bases view so project subtasks, dependencies, and blocking tasks stay in one place Task cards inside notes honor the same Bases filtering/grouping rules as standalone views Why Bases?# Moving everything to Bases allowed us to delete thousands of lines of bespoke filtering logic, state management, and widget code. The plugin now leans on Obsidian's supported API, which: Reduces maintenance overhead and improves reliability Lets advanced users version-control and audit their view definitions Makes saved views portable between vaults Keeps TaskNotes behavior consistent with other Obsidian-native workflows Upgrade Notes# Obsidian 1.10.1 or later is required (Bases public API with group-by support) Enable the Bases core plugin before opening TaskNotes views Run Settings → TaskNotes → General → Create Default Files if you need fresh .base files Use Export All Saved Views to Bases to convert any legacy FilterBar saved views into .base files The Relationships widget uses TaskNotes/Views/relationships.base; adjust that file to change what appears inside notes Breaking Changes# The old FilterBar UI has been removed—all filtering and saved views live in .base files Legacy widget settings (showProjectSubtasks, showTaskDependencies, etc.) were replaced with showRelationships and relationshipsPosition Task view commands now fail if their mapped .base file is missing; configure paths under Settings → TaskNotes → General → View Commands Priority sorting now uses alphabetical order instead of custom weights In v3, TaskNotes used priority \"weights\" to determine sort order (higher weight = higher priority) In v4, Obsidian's Bases plugin sorts priorities alphabetically by their value The weight field has been removed from the settings UI Workaround: Name your priority values to sort alphabetically in your desired order Example: 1-urgent, 2-high, 3-medium, 4-normal, 5-low Or: a-urgent, b-high, c-medium, d-normal, e-low Agenda view has been replaced by the list view in Calendar Grouping is not supported in this view, so the \"Overdue\" group is no longer provided A separate \"Overdue\" view is available in the \"Task List\" base file Known Issues# Users upgrading from versions prior to 3.x should export saved views to Bases before deleting old plugin data Embedded Bases views still require the Bases plugin to remain enabled; disabling Bases will hide TaskNotes task views Details# Added# Virtual scrolling and lazy rendering to Bases views for handling thousands of notes without performance degradation - Thanks to @aubreyz and @turingexmachina for reporting performance issues and help with diagnosis Google Calendar and Microsoft Outlook integration via OAuth 2.0 with automatic syncing Time Entry Editor Modal for managing time entries (Alt-drag on calendar to create) Kanban Swimlane Layout with horizontal grouping and configurable column widths Saved View Converter button in settings to convert v3 saved filter views to .base files Context menus for time entries and ICS events in calendar views Calendar icon to ICS event titles for better visual distinction Hover tooltips for timeblocks in calendar views MiniCalendar view for Bases integration with monthly grid and dot indicators - Thanks to @aubreyz and @turingexmachina for reporting performance issues and help with diagnosis (#1090) Portuguese (Brazil) translation - Thanks to @andysteel for the contribution Configurable task modal fields with drag-and-drop reordering in new \"Modal Fields\" settings tab Rich markdown editor for NLP task creation with syntax highlighting and wikilink support Customizable NLP triggers with autocomplete and keyboard navigation Inline task link overlay enhancements with configurable visible properties Kanban column reordering via drag and drop with saved order per grouping property Mini calendar enhancements including week numbers, heat map visualization, note preview tooltips, and keyboard navigation Unified Relationships widget consolidating project subtasks, dependencies, and blocking relationships with automatic tabs Updated task card styling with improved hover effects, shadows, and gradient accents (#361) Completion-based recurrence support with recurrence_anchor field for tasks that recur based on completion date - Thanks to @luciolebrillante for the original feature request, and @jhedlund, @nschenone, @BryanWall, @realJohnDoe, and @kazerniel for additional input and interest (#416) Support for skipped recurrence instances with skipped_instances field and right-click skip/unskip in calendar - Thanks to @mdbraber for suggesting the array approach and @jerzy-dudzic for reporting the issue Sub-grouping support to Bases Task List view with nested grouping by any property and collapsible groups Documentation for default Bases templates showing all default .base file templates with examples Changed# All views (Calendar, MiniCalendar, Kanban, Tasks, Agenda, Project Subtasks) now use Bases architecture with .base files Calendar sources (Google, Microsoft, ICS events) can be toggled independently with improved timezone handling Reorganized settings tabs with OAuth calendar settings in Integrations tab Refactored Bases integration to use public API and trust pre-sorted data Refactored calendar modules to use ES6 imports instead of lazy require() calls Time entry events now show task context menu on right-click Replaced MinimalNativeCache with just-in-time TaskManager for zero startup time and always-fresh task data Completed internationalization with 100% translation coverage across all 6 supported languages Migrated to i18n-state-manager CLI tool for improved translation management Bases view templates now generate dynamically based on user settings with adaptive task filters Updated Bases CalendarView to show TaskNotes in property-based events NLP system overhaul with consolidated trigger configuration and direct NaturalLanguageParser usage Simplified TaskCard interface and refactored TaskLinkWidget for consistency Settings UI enhancements with NLP triggers configurable through Features tab Refactored Bases views to use Component lifecycle properly with automatic cleanup Improved development experience by converting ESLint errors to warnings Renamed \"Advanced Calendar\" to \"Calendar\" throughout the UI Improved timeblock visual styling in calendar views with reduced border width and softer shadows Updated \"Export All Views\" button to \"Export V3 Views\" to clarify it migrates v3 saved views Improved internationalization (i18n) support in General settings tab with all Bases integration settings using translation keys Changed default Tasks List template view order with \"All Tasks\" first and added \"Unscheduled\" view Fixed# (#843) Fixed task tag being added when \"Identify tasks by\" is set to \"Property\" - Thanks to @jack2game for reporting Fixed dark mode calendar borders Fixed Bases Kanban column ordering - Thanks to @mweichert for reporting Fixed state management bug in FilterSettingsComponent Fixed timezone handling for recurring events (#1022, #684) Fixed tasks randomly disappearing when Smart Connections plugin is enabled by eliminating race condition - Thanks to @alejandrospoz, @seepage87, @amarjt, @luckb0x, and camara-tech for reporting and help debugging (#992) Fixed \"Failed to resolve module specifier 'obsidian'\" error when moving recurring task instances in calendar - Thanks to @jalooc for reporting Fixed task dependencies not displaying on task cards with proper isBlocked and isBlocking flags Fixed Bases property mapping for user-configured field names Fixed Bases views not respecting user-configured visible properties Fixed MiniCalendar UTC anchoring for consistent timezone-independent date handling Fixed DateValue conversion in BasesDataAdapter for property-based events in CalendarView (#1084) Fixed word wrapping in NLP preview items - Thanks to @maybetm for the fix (#975) Fixed advanced calendar list headers not respecting theme colors - Thanks to @hugohil for the fix (#1089) Fixed embedded task list bases growing unbounded and leaving large empty space - Thanks to @same774 for reporting with screenshot Fixed \"Highlight today\" toggle and calendar view type persistence in Bases Calendar view options (#1050) Fixed task modal adding unwanted empty contexts and projects arrays - Thanks to @nightroman for reporting Fixed inline task link overlay layout prioritization and horizontal scrolling for metadata Fixed group collapse/expand functionality in TaskListView Fixed config loading race condition in KanbanView and CalendarView Fixed MiniCalendarView to use direct Bases API like other views (#893) Fixed yearly recurring tasks not always updating scheduled date to next occurrence when completed - Thanks to @VenturaNotes for reporting (#951) Fixed yearly recurring tasks not showing up in calendar's weekly, 3-day, or day views - Thanks to @bespokecomp for reporting (#889) Fixed git merge conflicts in calendar subscription metadata by storing in memory instead of disk - Thanks to @karlfrohlich for reporting Fixed recurrence modal not loading DTSTART date/time when editing existing recurrence rules (#1097) Fixed custom properties and formulas not displaying in Bases views using getValue() method - Thanks to @cathywu for reporting (#1099) Fixed issues with default Bases file creation including double-prefix bug and race condition - Thanks to @kmaustral for reporting (#1110) Fixed open recurring tasks appearing crossed out in Tasks view by using UTC-anchored dates - Thanks to @kmaustral for reporting (#1118) Fixed user-defined fields not working in inline task conversion to TaskNote - Thanks to @guncav for reporting Fixed kanban column width CSS constraints not matching settings slider range Fixed Kanban view showing empty columns for all user-defined statuses when grouping by status - Thanks to @williamcheuk03 for reporting (#1103) Fixed TaskNotes/Views folder being created unnecessarily on startup - Thanks to @Wayment9504 for reporting (#1133) Fixed empty priority columns not showing in Kanban view when \"Hide empty columns\" is disabled - Thanks to @luckb0x for reporting Fixed OAuth calendar cards showing \"Unknown account\" by removing non-functional Account field - Thanks to @Oblique for reporting Fixed incorrect Bases syntax in default template files with correct parameter naming Fixed incorrect Bases syntax in \"Export V3 Views\" feature with correct YAML structure (#1127) Fixed custom priority colors not being respected in Task List and Subtasks sections - Thanks to @HPmattsloper for reporting (#1043) Fixed inability to set \"at time of event\" (0 offset) as default reminder in settings - Thanks to @dblinnikov for reporting (#1055) Fixed break sessions being logged as type: work when started via command/hotkey - Thanks to @0-BSCode for reporting and debugging (#1024) Fixed date/time picker immediately closing when selecting time on iPhone by refactoring to native Modal components - Thanks to @3zra47 for reporting (#1122) Fixed inline task titles being truncated too aggressively with increased max-width - Thanks to @jacorvillo for reporting Fixed Obsidian crashes when invalid time values entered in Bases calendar view configuration (#1120) Fixed custom field mappings not being respected throughout the application - Thanks to @kmaustral for reporting (#1121) Fixed custom user fields being saved with auto-generated IDs instead of user-defined property keys - Thanks to @guncav for reporting (#1123) Fixed relationships widget only displaying on task notes, now appears on both task and project notes - Thanks to @dblinnikov for reporting Fixed time entries not showing in calendar view for tasks without scheduled or due dates (#1091) Fixed task card and relationships widgets appearing inside footnote editors - Thanks to @3zra47 for reporting (#1086) Fixed calendar \"+more\" popover showing white text on white background in dark mode - Thanks to @same774 for reporting (#1076) Fixed inability to create timeblocks ending at midnight (00:00) - Thanks to @skoove for reporting (#958) Fixed cursor jumping and layout shifts when typing near task card or relationships widgets in live preview - Thanks to @thesmithmode for detailed debugging information (#513) Fixed task card and relationships widgets not appearing in reading mode and fixed critical memory leak - Thanks to @berzernberg for reporting Removed# Removed StatusSuggestionService (functionality consolidated into NaturalLanguageParser) Removed legacy FilterBar UI - all filtering now lives in .base files Removed legacy views"},{"title":"TaskNotes 4.0.2","url":"/obsidian/releases/4.0.2/","description":"This release fixes some of the more urgent (and easy-to-fix) bugs that were introduced in the v4 major release. Thanks to everyone for your patience, and to those who have repor...","product":"obsidian","text":"This release fixes some of the more urgent (and easy-to-fix) bugs that were introduced in the v4 major release. Thanks to everyone for your patience, and to those who have reported issues, for taking the time to do so. There will be more releases over the coming weeks to iron out some of v4's kinks. Added# Added \"Not Blocked\" view to default task list template Shows incomplete tasks that are ready to work on (not blocked by incomplete dependencies) Uses Bases list.filter() to check completion status of each blocking task This new view can be accessed by regenerating the Task List view, or by copying the filters from the default base templates documentation Fixed# (#1145, #1156) Fixed default Kanban view requiring manual 'Group by' configuration Default Kanban template now automatically includes groupBy property set to status Resolves \"Kanban requires a 'Group by' property to be configured\" error on first use Users no longer need to manually configure grouping through the Sort menu Thanks to @randomness42 and @seepage87 for reporting Fixed user-defined custom fields appearing as user:field_xxx in generated base templates Custom fields now use their actual property names (e.g., effort instead of user:field_1761435303709) Ensures Bases can properly query user-defined properties Also fixed totalTrackedTime to correctly map to the configured timeEntries property name (#1145) Improved Kanban error message when no 'Group by' property is configured Now includes instructions: \"Click the 'Sort' button and select a property under 'Group by'\" Thanks to @randomness42 for the suggestion (#1139, #1141) Fixed relationships widget not appearing in project notes Project references are now resolved to full file paths when indexing Uses Obsidian's link resolution API to handle wikilinks, markdown links, and relative paths Restores v3.x behavior where subtasks appear in parent project notes Thanks to @jhedlund, @n1njaznutz, and @luckb0x for reporting and testing Fixed dependency blocking status to be status-aware \"Blocked (x)\" pill now only appears when tasks have incomplete blocking dependencies Tasks with all completed blocking dependencies no longer show as blocked Fixed cache invalidation bug causing blocking/blocked pills to disappear when editing tasks When a task is modified, only forward dependencies are cleared (stored in its frontmatter) Reverse dependencies are preserved (stored in other tasks' frontmatter) Changed# Removed custom TaskNotes icon from task modals Task creation and edit modals now use Obsidian's standard title styling Thanks to @kepano for the suggestion Moved default base templates documentation to docs/views/ Location: docs/views/default-base-templates.md Added cross-references to official Obsidian Bases documentation Updated code comments to reference new documentation path Fixed incorrect quote escaping in default base templates documentation YAML examples now use proper single quotes for strings containing double quotes"},{"title":"TaskNotes 4.0.3","url":"/obsidian/releases/4.0.3/","description":"TaskNotes documentation.","product":"obsidian","text":"Fixed# (#1157) Fixed task embeds appearing on new line instead of inline with bullets in lists Changed inline task cards to use span elements instead of divs for proper inline flow Added max-width constraint to prevent wrapping when tasks are wider than editor Task embeds now display correctly inline with bullet points during live preview Thanks to @3zra47 for reporting (#1168) Fixed mini calendar stealing focus every few seconds when pinned to sidebar Thanks to @DearHaruHaru for reporting (#1161, #1162) Fixed \"unexpected scalar\" YAML parsing error in generated tasks-default.base template Changed nested quotes in \"Not Blocked\" filter from double to single quotes Thanks to @benschifman and @InterstellarRaccoon for reporting, @GarrettKaupp for identifying the fix Changed# Updated task modal UI to use native Obsidian patterns for better theme compatibility Thanks to @kepano for feedback"},{"title":"TaskNotes 4.0.4","url":"/obsidian/releases/4.0.4/","description":"TaskNotes documentation.","product":"obsidian","text":"Added# (#1134, #779) Added CMD+Enter (Mac) / Ctrl+Enter (Windows/Linux) keyboard shortcut support for saving in all modals Works from any input field in task creation, task edit, time entry, timeblock, and property selector modals Thanks to @luckb0x, @hamlim and @nightroman for the feature requests Fixed# (#1181) Fixed vertical overflow in Kanban view columns with fewer than 15 tasks Prevents cards from extending beyond column boundaries before virtualization activates Thanks to @lomarcanys for reporting (#1177) Bases views now anchor recurring completion and calendar navigation to the right date Recurring completion from Bases Task List/Kanban uses the task's scheduled/due date instead of \"today\" (fixes complete_instances) Bases calendar navigation and property-based events use UTC anchors to avoid previous-day jumps Thanks to @nslee123 for flagging the issue Bases calendar navigation now respects UTC-anchored dates to avoid landing on the previous day Corrected all-day end date calculation to prevent off-by-one spans Added regression test for the UTC anchor behavior Thanks to KaCii for flagging the issue Changed# Refactored plugin styling to better align with Obsidian's native UI conventions Replaced all cursor: pointer with cursor: var(--cursor) (100+ instances) to follow Obsidian's cursor convention Removed forced border: none; box-shadow: none rules that were fighting against Obsidian's native button styling Scoped custom .tn-btn button system to settings modal only (.mod-settings), allowing Obsidian's native button styles to work elsewhere Thanks to @kepano for guidance"},{"title":"TaskNotes 4.0.5","url":"/obsidian/releases/4.0.5/","description":"TaskNotes documentation.","product":"obsidian","text":"Changed# (#790) Task edit modal now shows unresolved project links with appropriate styling Similar to how dependencies are displayed, unresolved projects now appear with visual indication Hovering over an unresolved project shows a tooltip explaining it couldn't be resolved Thanks to @aubreyz for reporting Fixed# (#1011) Fixed chevrons incorrectly showing on tasks with no subtasks Project index was incorrectly adding all linked files instead of only files referenced in the projects field Now properly parses the projects field and only indexes those specific files as projects Also fixed alias handling in project and dependency links - aliases are now correctly stripped before link resolution Thanks to @craziedde for reporting (#1200) Fixed kanban drag & drop not updating task properties correctly Dragging tasks to different columns now properly triggers business logic (completedDate, auto-archive, webhooks) Previously, kanban updates bypassed updateProperty and directly modified frontmatter Thanks very much to @tvoklov for the PR (#1203) Fixed autocomplete dropdown being clipped inside NLP field boundaries Configure CodeMirror tooltips to render in document.body instead of constrained editor container Prevents suggestion dropdown from being hidden when it extends beyond the NLP field height Thanks to @Andrei-Ioda for reporting (#1172) Fixed task lists and checkboxes rendering incorrectly in task details editor Remove padding-left override on .cm-line to allow CodeMirror decorations (checkboxes, indentation) to render properly Content padding is now handled by .cm-content while .cm-line uses natural spacing Thanks to @nightroman for reporting Fixed relationships widget not appearing on project notes without frontmatter Widget now correctly shows on any note referenced as a project by tasks, regardless of whether the note has frontmatter Fixed task card and relationships widgets not appearing when opening notes in source mode Removed live preview mode restriction to allow widgets to render in both source and live preview modes (#901) Fixed calendar view toolbar buttons overflowing on narrow screens Added flex-wrap: wrap to calendar header toolbar to allow buttons to wrap to multiple lines Thanks to @RumiaKitinari for reporting (#1193), (#1194), (#1185) Fixed new calendar views not respecting user's default calendar settings Previously, new Bases calendar views used hardcoded inline defaults instead of user-configured preferences Calendar view initialization now correctly uses plugin.settings.calendarViewSettings as the fallback Thanks @ki5ck, @minchinweb and @ThamirysOlv for reporting Fixed calendar to ensure that it respects user's locale Tries to use calendar locale, then tries UI language, then system language, then falls back to English (#1043) Fixed default reminders with \"at time of event\" (0 offset) not being applied to tasks UI was displaying \"1\" instead of \"0\" for zero-offset reminders in settings Thanks to @dblinnikov for reporting (#1206) Fixed NLP status parsing regressions with trigger prefixes and temporal keywords Manually typing status trigger + label now correctly parses (e.g., *Done when label is Done) Status values containing temporal keywords no longer misparsed as dates (e.g., Expedite = Now) Thanks very much to @renatomen for the PR (#1212) Fixed \"Show release notes on update\" toggle not saving correctly Thanks to @Jon-dog for reporting (#1197) Add Portuguese language to list of translations in general tab settings Allows users to select the Portuguese translation option Thanks to @andysteel for the PR Fixed file properties displaying incorrectly in Bases views File properties like file.name, file.basename, file.size, etc. were showing as \"Title\" or returning null Now correctly extracts and displays all file properties from Obsidian's file metadata Supports both direct TFile properties (name, basename, extension, path, size, ctime, mtime) and computed properties (links, embeds, tags, backlinks, aliases)"},{"title":"TaskNotes 4.1.0","url":"/obsidian/releases/4.1.0/","description":"(#1245), (#793) Added custom icon support for task statuses","product":"obsidian","text":"Added# (#1245), (#793) Added custom icon support for task statuses Configure a Lucide icon name (e.g., check, circle, clock) per status in Settings → Task Properties → Task Statuses Icons display instead of the colored dot, inheriting the status color Browse available icons at lucide.dev Improves accessibility by allowing shape-based status differentiation Thanks to @3Fish for the feature request and @Raonmir2, @aubreyz, @prayidae, and @anareaty for the discussion on accessibility and icon-based indicators (#1259) Added Property Types Reference documentation Documents expected data types (text, list, date, number) for all frontmatter properties Includes format specifications, examples, and a complete YAML reference Thanks to @Oblique82 for the suggestion (#1248) Added formula property support for sub-grouping in Bases Task List view Formula properties (e.g., formula.myFormula) now appear in the Sub-group by dropdown Supports all Bases Value types including strings, numbers, booleans, dates, and lists Thanks to @prayidae for the feature request (#1070) Added formula property support for swimlanes in Bases Kanban view Formula properties now appear in the Swim Lane dropdown Fixed swimlanes displaying empty when grouping by formula properties Note: Dragging tasks between formula-based columns/swimlanes is disabled (formulas are computed values) Thanks to @cathywu for reporting (#1010), (#1126) Added batch task selection and editing in Task List and Kanban views Shift+click to select multiple tasks Right-click selected tasks to open batch context menu Batch operations: change status, priority, due date, scheduled date, archive, delete Drag multiple selected cards in Kanban to move them together Click the selection count indicator to clear selection Thanks to @jalooc and @solidabstract for the feature requests (#1207) Added inline search box to Bases views (Task List, Kanban, Calendar) Enable via \"Enable search box\" toggle in view settings Searches across title, status, priority, tags, contexts, projects, and visible custom properties Press Escape or click × to clear search Thanks to @renatomen for the PR (#363) Added \"Create or open task\" command with NLP-based quick task creation Open via command palette or assign a hotkey Search existing tasks or type natural language to create new tasks (e.g., \"Buy groceries tomorrow #shopping\") Press Enter to select an existing task, Shift+Enter to create a new task Real-time preview shows parsed title, due date, priority, tags, and other metadata Can be used when adding sub-tasks to create sub-tasks on-the-fly Thanks to @luciolebrillante for the feature request (#1044), (#1222) Added unsaved changes confirmation when closing task edit modal Detects modifications to any field (title, dates, priority, tags, etc.) Shows confirmation dialog with Save/Discard/Keep Editing options Prevents accidental data loss from clicking outside the modal or pressing Escape Thanks to @renatomen for the PR and @0-BSCode for the feature request (#904) Added visual highlighting for overdue and past dates on task cards Overdue due dates now display in red text Past scheduled dates now display in blue text Thanks to @ras0q for the suggestion (#1164) Added priorityWeight formula to all default Bases templates for priority-based sorting Formula maps each priority value to a numeric weight based on your custom priority configuration Sort by formula.priorityWeight in ascending order to get highest priority tasks first Example: if(priority==\"high\",0,if(priority==\"normal\",1,if(priority==\"low\",2,999))) Thanks to @jhedlund for the suggestion (#1257), (#1064) Added configurable event stacking options for Bases Calendar view Allow events to overlap: Toggle whether timed events visually overlap or display side-by-side in week/day views Max stacked events: Limit horizontal event stacking in week/day views (0 = unlimited) Max events per day: Limit events shown per day cell in month view (0 = auto based on cell height) Max event rows per day: Limit event rows per day cell in month view (0 = unlimited) Configure per-view in the Bases Calendar view settings under Layout Thanks to @3zra47 and @hasanyilmaz for the feature requests Changed# Improved inline task conversion to merge TasksPlugin and NLP parsing results Previously, if a task had hashtags (e.g., - [ ] Buy milk tomorrow #groceries), NLP parsing was skipped entirely Now NLP always parses the clean title to extract dates/times, then merges with TasksPlugin-extracted metadata TasksPlugin explicit values (emoji dates like 📅) take priority over NLP-inferred values Tags, contexts, and projects from both sources are combined and deduplicated Polished task card styling for a more native Obsidian look Simplified hover and focus states to use native Obsidian colors Removed blur filter and shadows from metadata pills Fixed subtask chevron vertical alignment with status dot Reduced swimlane label column width in Kanban view (#1151) Increased mini calendar heatmap color intensity for better visibility Days with notes now show more noticeable colors, especially with low note counts Intensity levels increased from 10/25/45/65% to 25/40/55/70% Thanks to @arreme for the suggestion Fixed# (#1271) Fixed custom user fields not appearing in task modals after creation New custom fields are now automatically added to both creation and edit modals Deleting a custom field also removes it from modal configuration Updating a field's display name syncs to the modal configuration Thanks to @craziedde for reporting (#1256) Fixed links in custom properties not rendering as clickable in task cards Wikilinks ([[Note]]) now render correctly in Bases views Markdown links ([text](url)) now render correctly in all views Links in list-type properties are also properly rendered Thanks to @3zra47 for reporting (#1157) Fixed inline task embeds breaking layout when placed in indented bullet lists Task titles now wrap naturally within line boundaries instead of forcing the entire card to a new line Metadata (dates, tags, etc.) stays inline when space permits, with horizontal scrolling on hover when needed Thanks to @3zra47 for reporting (#1241) Fixed deleting custom priorities in settings removing the wrong priority when multiple priorities exist Thanks to @Anthonyhunter100 for reporting (#1165) Fixed Kanban view grouping by list properties (contexts, tags, projects) treating multiple values as a single combined column Tasks with multiple values now appear in each individual column (e.g., a task with contexts: [work, call] appears in both \"work\" and \"call\" columns) Added \"Show items in multiple columns\" option (enabled by default) to control this behavior Fixed drag-and-drop to properly add/remove individual values instead of replacing the entire list Fixed swimlane mode to also respect list property explosion Thanks to @dictionarymouse for reporting (#1217) Fixed inconsistent Ctrl+Click/Cmd+Click behavior for opening notes in new tabs Note cards and internal links now properly support Ctrl/Cmd+Click to open in new tab Added middle-click support for opening in new tab Thanks to @diegomarzaa for reporting (#1265) Fixed task edit modal corrupting markdown-style project links on save Links like [Project Name](path.md) were being wrapped in extra brackets: [[[Project Name](path.md)]] Plain text project names are now preserved as-is instead of being converted to wikilinks Markdown-style project links now resolve properly and display as linked (not orange/unresolved) Thanks to @minchinweb for reporting (#1266) Fixed Kanban view scroll position resetting to top of column after any change Clicking status dots, priority, or other task properties no longer jumps the column back to top Scroll position is now preserved for both regular columns and swimlane cells Thanks to @essouflenfer for reporting (#485), (#1221), (#1262) Fixed NLP parser not recognizing non-ASCII characters in tags, contexts, and projects Tags like #investigación were being truncated at accented characters (e.g., #investigaci) Non-Latin scripts (Chinese, Cyrillic, Japanese, etc.) were not recognized at all (e.g., @家, #杂事, @ознакомиться) Parser now uses Unicode-aware regex patterns to support all languages and scripts Thanks to @Arachnidai, @fidelaznar, and @qian1ing for reporting (#1249) Fixed project preview in task creation modal showing quadruple brackets ([[[[Project]]]]) Projects selected from autocomplete were being wrapped in extra wikilink brackets in the preview display Thanks to @2vzqwz8tvg-png for reporting (#1249) Fixed custom priority ordering in settings being unclear and non-intuitive Priority cards are now draggable to reorder (like statuses) Priorities are displayed in weight order (lowest to highest priority) New priorities are added at the end (highest priority) instead of with a fixed weight Thanks to @2vzqwz8tvg-png for reporting (#1272) Fixed recurrence anchor not being saved when set to \"completion\" during task creation Selecting \"completion\" as the recurrence anchor now correctly persists to the task frontmatter Thanks to @blaxcky for reporting (#1128) Fixed NLP parser not allowing slashes in context names Contexts like @shopping/groceries were being split into @shopping and /groceries Hierarchical context names now work the same as tags and projects Thanks to @wealthychef1 for reporting (#1170) Fixed dateCreated and dateModified not using custom property names when creating notes from calendar events Notes created from ICS events now respect the field mapping configured in settings Thanks to @maddie-m for reporting (#1171) Fixed calendar event toggles not responding to changes after initial load Toggling \"Show scheduled tasks\", \"Show due tasks\", and other event filters now correctly updates the calendar Previously, changing these toggles had no effect until the view was reloaded Thanks to @hangryscribe3 for reporting (#1198) Fixed project links being created relative to the wrong file when editing from Bases views Relative paths in project links are now correctly resolved relative to the task note file Previously, editing a task from a Bases view would create project links relative to the .base file Thanks to @minchinweb for reporting"},{"title":"TaskNotes 4.1.1","url":"/obsidian/releases/4.1.1/","description":"TaskNotes documentation.","product":"obsidian","text":"Added# (#1277) Icon autosuggestion for custom status settings Type to search through all available Lucide icons Thanks to @Arachnidai for the suggestion New formula properties in default Base templates Date calculations: daysUntilDue, daysUntilScheduled, daysSinceCreated, daysSinceModified Boolean helpers: isOverdue, isDueToday, isDueThisWeek, isScheduledToday, isRecurring, hasTimeEstimate Time tracking: timeRemaining, efficiencyRatio, timeTrackedThisWeek, timeTrackedToday, timeTrackedFormatted Grouping: dueMonth, dueWeek, scheduledMonth, scheduledWeek, dueDateCategory, timeEstimateCategory, ageCategory, createdMonth, modifiedMonth, priorityCategory, projectCount, contextCount, trackingStatus Combined due/scheduled: nextDate, daysUntilNext, hasDate, isToday, isThisWeek, nextDateCategory, nextDateMonth, nextDateWeek - work with whichever date comes first Sorting: priorityWeight, urgencyScore (combines priority with date proximity) Display: dueDateDisplay (relative dates like \"Today\", \"Tomorrow\", \"3d ago\") Action-oriented views (Not Blocked, Today, Overdue, This Week) now sort by urgency score, showing most important tasks first See Default Base Templates documentation for full details Note: To get these new formulas, either copy them from the documentation, or delete your .base files in TaskNotes/Views/ and restart Obsidian to regenerate them Changed# (#1282) Added spacing between task title and metadata in inline task widgets for improved readability Thanks to @3zra47 for the suggestion Custom status icons now display in all context menus (task context menu, batch operations menu, and task creation/edit modals) Added embedded video guide for Google Calendar OAuth setup in documentation Thanks to @antoneheyward for the tutorial Fixed# (#1279) Fixed Kanban column width setting not being respected on mobile devices Thanks to @guncav for reporting (#1026), (#1177) Fixed recurring task completion from Base views recording the wrong date for users in negative UTC offset timezones (e.g., PST/PDT) when completing tasks in the evening The bug caused complete_instances to record the next day instead of the user's current calendar day Thanks to @3zra47 and @nslee123 for reporting and providing detailed reproduction steps"},{"title":"TaskNotes 4.1.2","url":"/obsidian/releases/4.1.2/","description":"TaskNotes documentation.","product":"obsidian","text":"Fixed# Significant performance improvements for Bases views (TaskList, Kanban, Calendar) Reduced extractDataItems time from ~4 seconds to ~5-10ms for large vaults (6000+ tasks) Computed file properties (file.backlinks, file.links, etc.) are now fetched lazily during render instead of upfront Only visible items (with virtualization) trigger expensive property computations Added debouncing to onDataUpdated to prevent UI freezes during typing Timeblock generation now uses Obsidian's metadataCache instead of file reads Added date range filtering for calendar events to skip events outside visible range (#1285) Calendar view uses 5-second debounce to prevent flickering while typing Thanks to @steven-murray for reporting Calendar view switching (month/week/day/list) is now much faster View type is now saved on unload instead of on every change Fixed task edit modal archive button being too narrow on mobile devices (#1319) Added missing properties to Field Mapping settings recurrence_anchor - now in Settings > Task Properties > Task Details skipped_instances - now in Settings > Task Properties > Metadata Properties Thanks to @kazerniel for reporting (#1310) Fixed inline task conversion deleting text when task title exceeds filename limits Text that cannot fit in the filename is now preserved in the task note's body Thanks to @prayidae for reporting (#1301) Fixed inline task wikilinks leaving blank space when no metadata properties are visible Thanks to @Richard-UMPV for reporting (#1317) Fixed project autosuggest filters not working correctly when only \"Required Property Key\" is configured NLP + trigger now properly filters by property existence when no property value is specified Modal \"Add to project\" button now shows consistent results with inline autosuggest Thanks to @JacksonMcDonaldDev for reporting (#1287), (#1307) The \"New\" button in Bases views now opens the TaskNotes creation modal Tasks created from Bases views now respect default properties (status, priority, etc.) Tasks are now created in the configured default folder instead of the views folder Thanks to @anareaty and @sylvainfct-dot for reporting (#1291) Fixed Microsoft Calendar OAuth documentation using wrong redirect URI Added instructions for configuring via Azure manifest editor Thanks to @PlecotusAustriacus for reporting Added# (#803) New command \"Convert current note to task\" to add task properties to an existing note Thanks to @GardarikanetS and @diegomarzaa for suggesting (#1080) Custom user fields now support default values Each field type has an appropriate input: text field, number input, toggle, date preset dropdown, or comma-separated list Defaults are applied when creating tasks via modal, instant conversion, \"Create or open task\" command, or HTTP API Thanks to @bradyrx for suggesting Changed# Added documentation link to settings panel (links to tasknotes.dev) Reorganized settings panel for improved discoverability Removed \"Defaults\" tab - default values are now configured alongside each property in the Task Properties tab Moved task filename format settings to the Title property section Moved project autosuggest settings to the Projects property section Body template setting moved to the Features tab Added descriptions to each property explaining its purpose Moved \"Folder for converted tasks\" setting to General tab under Task Storage for better discoverability Updated setting description to clarify that leaving empty uses the default tasks folder"},{"title":"TaskNotes 4.1.3","url":"/obsidian/releases/4.1.3/","description":"This patch fixes a critical performance issue affecting the Calendar views. As a bonus, it adds a configurable \"split\" view to the task creation/edit modals.","product":"obsidian","text":"This patch fixes a critical performance issue affecting the Calendar views. As a bonus, it adds a configurable \"split\" view to the task creation/edit modals. Added# Split layout for task modals on wide screens (900px+) Details editor appears in a dedicated right column when the modal is expanded New setting \"Split layout on wide screens\" in Modal Fields settings tab to toggle this behavior Improves usability by showing form fields and details side-by-side Fixed# (#1330) Fixed calendar view regression taking 5 seconds to load and respond to user interactions Initial calendar load is now immediate again User interactions (drag/drop, creating timeblocks, etc.) respond instantly Removed redundant date filtering (FullCalendar handles this more efficiently) Thanks to @ysafonov, @kmaustral, @sunjiawe, @Мизгирь, and @FiliusIcari for reporting"},{"title":"TaskNotes 4.10.0","url":"/obsidian/releases/4.10.0/","description":"TaskNotes documentation.","product":"obsidian","text":"Added# New companion plugin: TaskNotes Workflows adds Markdown-defined automation for TaskNotes tasks, events, schedules, and manual commands. It keeps automation workflows outside TaskNotes core while using the runtime API for safe task reads, writes, queries, events, and relationship resolution. See TaskNotes Workflows. (#1530) Auto-start time tracking starts a timer when a task moves into active work. Thanks to @Jendrik0 and @benmartinek for the request and follow-up. (#222, #184) Stop time tracking on complete stops active timers when a task is completed. Thanks to @bcohen44 and @cathywu for the requests, and @amarjt for the follow-up. (#265) Stamp started timestamp records a custom started timestamp when a task first moves into active work. Thanks to @cathywu, @digitaldoctors, and @Leo310 for the request and discussion. (#1703) Clear scheduled when started clears the scheduled date when a task moves into active work. Thanks to @kmaustral for the request. (#1293) Rollover overdue scheduled tasks moves incomplete tasks with past scheduled dates back to today. Thanks to @grosserfrank for the request. (#1896) Escalate upcoming due tasks raises priority as due dates approach. Thanks to @Neptune-Illusion for the request. (#214, #518, #1785, #1855) The subtask inheritance workflows can copy parent contexts, tags, priority, planning dates, and dependencies into new subtasks. Thanks to @timfidd, @bepolymathe, @AndyEveritt, @lindsaylearns, @tomsymonds, @wedgen, @poulpoulsen, and @misolex for the related requests and discussion. (#1166) Blocked task review provides a reminder-style review for blocked tasks without automatically deleting dependency links. Thanks to @jpmoo and @jortscity for the request and follow-up. Added a versioned TaskNotes JavaScript runtime API for companion plugins, with namespaced model validation, canonical task query validation/normalization/explain helpers, catalogs, query/support helpers, lifecycle events, typed errors/results, task, time-tracking, Pomodoro, recurring-task, settings, NLP, event, and extension-registry surfaces. Runtime API mutations carry source and correlation metadata so companion plugins can debug and coordinate workflow runs. See JavaScript API. Added documentation for the companion-plugin model. See Companion Plugins. (#288, #345, #361, #523, #573, #703, #925, #929, #1115, #1137, #1260, #1303, #1324, #1394, #1445, #1509, #1735, #1736, #1743, #1780, #1874, #1951, #1974) Added support for TaskNotes spec 0.2.0 materialized occurrences, including recurrence parent/date fields, generated mdbase schema roles, parent reconciliation when occurrence notes are completed, occurrence notes that inherit parent planning metadata without copying history, occurrence note controls in task, calendar, and edit-modal completion menus, and visible occurrence identity on task cards. This gives recurring tasks a concrete occurrence-note path for per-instance state, related notes, subtasks, templates, scheduling changes, completion history, and calendar behavior without forcing every recurring task to create files. See Recurring Tasks and Property Types Reference. Thanks to @LuxBetancourt, @jerzy-dudzic, @luciolebrillante, @BryanWall, @jhedlund, @kazerniel, @nschenone, @realJohnDoe, @cathywu, @Lorite, @EllenGYY, @JcMinarro, @gsssr, @slipstyle, @3zra47, @Leonard-44, @ak-42, @RumiaKitinari, @atos2212-blip, @kmaustral, @eugenedefox, @notDavid, @zitongcharliedeng, and @Jomo94 for the related recurrence, occurrence, completion, and calendar requests. (#1951) Added Calendar support for recurring tasks stretched between scheduled and due dates when the existing stretch option is enabled. Date-only ranges stay as all-day spans, and timed ranges render once per day in the range. Thanks to @atos2212-blip for the request. (#1751, #1792, #1969) Added a Task List and Kanban view option to hide top-level subtasks when their parent task is also in the filtered view, while still allowing inherited expanded relationships to show the subtasks under the parent. Thanks to @Glint-Eye and @Proxybat for the request and follow-up, and @stanley-910 and @Spencerduran for the earlier PRs. Changed# Moved core TaskNotes model behavior for field mapping, dates, recurrence, time-tracking, and adapter operation planning into a shared package used by the plugin and companion tooling. Calendar views now coalesce materialized occurrence notes with their matching virtual recurring instances. Dragging a materialized occurrence reschedules that occurrence note without changing the parent recurrence rule or the note's occurrence_date identity. See Recurring Tasks. Improved the Calendar Bases View Options menu by splitting settings into clearer groups and hiding view-specific controls until they apply to the selected calendar mode. Fixed# (#1976) Fixed embedded Calendar and Agenda Bases so \"Navigate to date from property\" can use the containing note's date property when the Base rows do not have that property. Thanks to @matesvecenik for reporting this. (#1977) Fixed Calendar and Agenda views showing duplicate all-day entries when a task's scheduled date and due date are the same day. Timed due dates on the same day still show as separate deadline markers. Thanks to @pdgBC for reporting this. Fixed the release notes view using cramped interface typography instead of regular reading typography. (#216) Improved inline conversion for Tasks plugin task lines, including Dataview-style fields, priority markers, recurrence text, date aliases, block links, and safer trailing-field parsing. Thanks to @ksdavidc for the request, @natleahh for the Dataview example, and @hangryscribe3 and @nayatiuh for the discussion. (#1974) Stopped Calendar and Agenda property-based events from logging date parse errors for entries that do not have the selected date property. Thanks to @Jomo94 for suggesting completed-date Agenda events. (#1973) Reduced unnecessary Calendar view recreations when external calendar providers are reported in a different order, and preserved Calendar scroll position when a config-driven refresh has to recreate the view. Thanks to @e-zz for reporting this. (#1972) Fixed ICS calendar event related notes so standalone events with similar numeric IDs no longer show unrelated notes or tasks on every event. Thanks to @ks-studio-net for reporting this. (#1970) Fixed generated default Base filters so updating default files applies configured excluded folders to TaskNotes task views. Thanks to @henrim01 for reporting that templates could still appear in regenerated views. (#1968) Fixed inline task link overlays collapsing on Obsidian mobile, which could hide the task title and leave a tall empty gap after the widget. Thanks to @renatomen for reporting and diagnosing the containment issue."},{"title":"TaskNotes 4.10.1","url":"/obsidian/releases/4.10.1/","description":"TaskNotes documentation.","product":"obsidian","text":"Added# Added a startup check for new compatible TaskNotes releases. When a new release is available, TaskNotes shows a notice that opens the TaskNotes entry in Obsidian's Community Plugins browser. (#1989) Added a command-palette action plus runtime and HTTP API actions for updating configured default .base files from the current TaskNotes templates. Thanks to @businessBoris for the request. (#1115) Added API and MCP support for creating materialized occurrence notes from recurring tasks, and made headless recurring-instance completion respect occurrence notes when the parent uses Create next after completion. Thanks to @gsssr for the original request, @slipstyle for the follow-up, and @martin-forge for identifying the API/MCP gap. Fixed# (#1985) Fixed embedded Calendar and Agenda time-grid views drifting out of alignment inside callouts and Reading mode. Thanks to @matesvecenik for reporting and sharing screenshots. (#1986) Fixed the local HTTP API rejecting requests from the TaskNotes browser extension's Chrome extension origin. Thanks to @n1njaznutz for reporting this. (#1980) Added mobile bottom spacing to Agenda Calendar views so the last visible tasks can scroll above Obsidian's bottom navigation bar. Thanks to @Jomo94 for reporting and sharing the screenshot. (#1984) Fixed mobile task link overlays hiding configured inline task card properties such as scheduled date, due date, contexts, and projects. Thanks to @stil-sudo for reporting. (#1979) Kept the left-positioned subtask chevron from overlapping the task status control on mobile task cards. Thanks to @Jomo94 for reporting and sharing the screenshot. (#1903) Reduced the Edit Task modal's mobile action-button footer so Open note, Archive, Delete, Save, and Cancel take two rows instead of three on iPhone-sized screens. Thanks to @3zra47 for the original report and @krzyfu for the follow-up about the button area crowding the editor. (#1982) Preserved scroll position in TaskNotes Bases after task edits and data refreshes, avoiding jumps back to the top on mobile. Thanks to @3zra47 for reporting. (#1978) Restored Obsidian editor shortcuts such as insert link, headings, and list toggles inside the Edit Task modal's Details editor. Thanks to @krzyfu for reporting this."},{"title":"TaskNotes 4.10.2","url":"/obsidian/releases/4.10.2/","description":"TaskNotes documentation.","product":"obsidian","text":"Fixed# (#1995) Fixed Bases Calendar views showing both a materialized occurrence note and its matching virtual recurring task instance. Thanks to @rdefaccio for reporting this. (Discussion #1994) Fixed timed recurring tasks failing to advance their due dates when due-date offset preservation is enabled. Thanks to @mgrecar for raising this."},{"title":"TaskNotes 4.11.0","url":"/obsidian/releases/4.11.0/","description":"TaskNotes documentation.","product":"obsidian","text":"Added# (#730, #1897, #1942, #1998) Added Canvas Bases, an optional companion plugin that turns Obsidian Bases views into canvas-style boards and reusable JSON Canvas snapshots, with TaskNotes badges, task menus, dependency and subtask edges, and assignment zones for supported TaskNotes actions. See Canvas Bases for setup details. Thanks to @DillPickle80, @BradGaddis, @Hyadhuad, and @AlinaWithAFace for the visual planning requests, and to @renatomen, @prayidae, and @maranqz for the related discussion. Added a TaskNotes starter note that is created and opened automatically on first install to introduce task creation, inline conversion, and embedded Bases views. Added a runtime API surface for companion plugins to show or populate the standard TaskNotes task context menu. (#2000) Added separate settings for using the active note as a project during normal task creation and during inline task creation or instant conversion. Thanks to @BlueScreen32 for suggesting the split. (#1303, #2001) Added separate templates for materialized occurrence notes, including parent-level occurrence_template support and a global fallback setting. Thanks to @BrucePlumb for suggesting a separate occurrence-note template and @ak-42 for the related per-recurrence template request. (#2006) Added the projected local finish time beside the remaining duration while a Pomodoro is running. See Pomodoro View for the timer behavior. Thanks to @abbiefalls90 for suggesting this. (#2016) Added a setting for recurring external calendar event related notes, so Google, Microsoft, and ICS recurrences can either share notes across the series or keep notes limited to the selected instance. See Integrations Settings for the setting. Thanks to @akhtsang for reporting this, and to @cathywu and @mdbraber for the earlier series-linking discussion. Changed# (#1737) Clarified that changing the task tag does not automatically update existing Base view filters. Thanks to @goldorak00 for reporting this, and to @Domcoppinger and @imsuck for the first-time setup feedback. (#2005) Excluded archived task notes and archived project-note references from Task & Project Statistics. Thanks to @Xiarno for suggesting this. Added a local review-type lint check that catches dependency-resolution warnings from Obsidian's online review before submission. Improved dependency and project relationship cache updates so ordinary note edits avoid unnecessary relationship recalculation, while blocked and blocking state stays current when dependency status changes. Improved filter and view query caching so filter options update immediately after relevant task-field changes while large Task List, Kanban, and Calendar queries avoid repeated vault scans. Extended the in-app release notes bundle to include the current major release, with collapsed versions rendered only when opened. Fixed# (#2015) Fixed Google Calendar events from the previous six months disappearing from Calendar and Mini Calendar views after a fresh sync. Thanks to @akhtsang for reporting this. (#2013) Fixed task-card status and priority dots becoming oversized on touch-capable desktop devices. Thanks to @RumiaKitinari for reporting this. (#2009) Restored Tab and Shift+Tab focus movement in the Create new task modal's natural language input instead of letting the markdown editor indent the title. Thanks to @prepare4robots for reporting this. (#2007) Fixed status autocomplete in the task creation modal leaving status value fragments in the task title when the editor auto-paired the status trigger. Thanks to @prepare4robots for reporting this. (#2004) Fixed the Pomodoro start command forgetting the selected task after it was completed, so reopening the task lets it be picked up again. Thanks to @MPourjam for reporting this. (#1996) Made Kanban card drag-and-drop show a clear drop slot marker while cards are being repositioned, so the landing position remains visible during sorting. Thanks to @phillipadsmith for reporting this. Fixed runtime API dependency removal so removing the last dependency from a task also clears the mapped blockedBy property from the note."},{"title":"TaskNotes 4.11.1","url":"/obsidian/releases/4.11.1/","description":"TaskNotes documentation.","product":"obsidian","text":"Added# (#2024) Added materialized occurrence notes to the Relationships widget, so recurring parent task notes can show their occurrence notes in an Occurrences tab. See Relationships Widget. Thanks to @3zra47 for requesting this. (#2022) Added a Skip instance / Unskip instance action to the recurring task edit modal's completion calendar, so skipped dates can be adjusted from the same date menu as completions. See Recurring Tasks. Thanks to @AmonAmarthFTW for requesting this. (#2048) Added current due and scheduled dates to the edit modal's task information. Thanks to @1activegeek for requesting this. (#2058, #2059) Added natural-language parsing and the full date picker to date-type custom fields. Thanks to @chmac for requesting this. (#2060) Added date-type custom fields to the task right-click menu under Custom dates. Thanks to @chmac for requesting this. (#2067) Added an Edit task action to the task card context menu, including inline task cards. Thanks to @DarkCellar for requesting this. (#2068) Added reminders input support to the MCP tasknotes_create_task and tasknotes_update_task tools. Thanks to @Spirit597 for requesting this. (#2069) Added an Add project action to the Quick Actions palette. Thanks to @chmac for requesting this. Fixed# (#2007) Fixed a remaining task creation autocomplete case where a status value containing another status label could leave status fragments in the task title. Thanks to @prepare4robots for the follow-up report. (#2031) Fixed quick task creation failing when natural language input created a recurring task with a scheduled time. Thanks to @rdefaccio for reporting this. (#2034) Fixed Advanced Calendar timed events switching to a high-contrast mobile fill when Obsidian is narrowed or split on desktop. Thanks to @RumiaKitinari for reporting this. (#2039) Fixed broken images on the Workflows and Calendar Setup documentation pages. Thanks to @chmac for reporting this. (#2045) Fixed custom modal fields assigned to Basic Information not appearing in task creation or edit modals. Thanks to @chmac for reporting this. (#2063) Fixed project autocomplete storing ambiguous project links without the selected note's folder path. Thanks to @chmac for reporting this. (#2072) Fixed inline task links to headings so they show both the task title and heading instead of only the heading. Thanks to @spasche for reporting this. (#2075) Fixed multiday Calendar events being clipped to one day when a Base is embedded in Reading view. Thanks to @ddevaal for reporting this. (#2079) Fixed the reminder modal's Absolute tab so it switches from relative fields to absolute date and time fields. Thanks to @JunwonYoon for reporting this and identifying the CSS specificity issue. Changed# Improved local review checks so unsafe direct Object.prototype method access is caught before submission."},{"title":"TaskNotes 4.12.0","url":"/obsidian/releases/4.12.0/","description":"[!info] TaskNotes v5 beta","product":"obsidian","text":"[!info] TaskNotes v5 beta TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release. The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface. TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand. TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter. Security# Calendar OAuth credentials and account tokens are now stored in Obsidian Secret Storage instead of TaskNotes' data.json, with automatic migration for existing connections. See Calendar Integration. Thanks to @mcuste for the contribution Updated bundled HTTP, address parsing, and schema validation dependencies to versions containing their current security fixes. Added# Added portable task attachment references. Attachments now round-trip as an ordered attachments link list in task frontmatter and are exposed through the TaskNotes model and runtime API. These are collection-file references only; attachment bytes and binary metadata remain owned by the host. (#2142) MCP tasknotes_create_task and tasknotes_update_task now accept customProperties for configured TaskNotes user fields. Thanks to @phillipadsmith for suggesting this. (#2126, #2134) Added optional filename templates for materialized recurring occurrence notes, with explicit date, ISO week, month, year, and month-name variables plus per-parent overrides. Existing naming remains unchanged until a template is configured. See Recurring Tasks. Thanks to @raphaelfaouakhiri for reporting and implementing this. (#2105) Added {{projectFolder}} and {{projectFolders}} folder template variables for storing tasks alongside linked project notes. See Template Variables. Thanks to @carypruitt for this contribution. Changed# Generated TaskNotes type contracts now include configured natural-language capture triggers, allowing compatible clients to offer the same field suggestions. Rebuilt the TaskNotes documentation with reorganized navigation, full-text search, mobile and accessibility improvements, and references generated from the current commands, settings, compatibility metadata, HTTP routes, and default Bases. Added practical guides for adopting TaskNotes in an existing vault, mobile use, custom Bases, and backup and recovery. See the TaskNotes documentation. (#2088) Convert current note to task now uses your default scheduled date when the note does not already have scheduled frontmatter, while the None default still leaves converted notes unscheduled. See Task Properties. Thanks to @e-zz for suggesting this. Fixed# Plugin settings now recover when Obsidian briefly returns no data while reloading an externally changed settings file, preventing a post-reload error without overwriting the existing settings. (#2194) Pomodoro task selection suggestions now keep rich task cards at the menu width, preventing task titles from wrapping one letter per line. Thanks to @Evilgenee for reporting this. (#2196) Drag-to-reorder now works for Task List Bases embedded in Live Preview notes, matching the behavior of directly opened Bases and Reading mode embeds. Thanks to @jimbo108108 for reporting this. (#2198) Agenda Bases can now show overdue scheduled or due tasks on today's row with showOverdueOnToday, and regenerated default Agenda files enable that behavior by default. Thanks to @vicrdguez for reporting this. (#2182) Checklist progress on task cards now excludes cancelled markdown checklist items such as [-] from the completed/total count. Thanks to @ctrl-q for reporting this. (#2180) Inline task cards in Live Preview now keep their click and context menu handlers active on Obsidian 1.13, so clicking a rendered task link opens the edit modal instead of revealing the raw wikilink. Thanks to @npondel for the detailed diagnosis and @minchinweb for confirming the issue. (#2171) Stopped recurring notification and status-bar scans from reading unindexed notes directly from disk while preserving the fallback for direct task lookups. Thanks to @tgrosinger for identifying and diagnosing the excessive vault reads. (#2174) Open or create occurrence note from Quick Actions now uses the recurring task's scheduled occurrence date, preventing duplicate occurrence notes keyed to the day the action was run. Thanks to @chmac for reporting this. (#2169) Regenerated default Base views now include tasks whose identifying property is stored as a list containing the configured task value. Thanks to @GlebYavorski for reporting this. (#2166) Fixed Task List views configured to start collapsed so the first chevron click expands only the selected group instead of expanding every other group. Thanks to @renatomen for reporting and fixing this. (#2165) Convert current note to task now reads configured field mappings, including list-valued title fields such as aliases, and preserves an existing aliases list when the title is unchanged. Thanks to @jkuball for reporting this. (#2164) Flat Kanban boards now clear stale swimlane layout state when they rerender, preventing columns from occasionally stacking into one vertical strip after switching tabs. Thanks to @brienna for reporting this. (#2160, #2161) Generated Kanban Bases now use the correct TaskNotes status property and configuration block. Rich Bases status values render as their configured labels, while pinned columns and saved column order are honored. Thanks to @kevin-4c for the detailed reports and diagnosis. (#2111, #2159) Recurring task instances now remain visible through the final day of Calendar and Agenda ranges in positive-offset time zones, regardless of the configured first day of the week. Thanks to @Arachnidai and @odxn0803 for reporting this. (#2155) Regenerated default Calendar Bases now inherit the app-level time slot duration instead of hardcoding 30 minutes. Existing per-Base time settings remain intentional overrides. Thanks to @SZZ504232 for reporting this. (#2154) Timed ICS events without a TZID now preserve their floating wall time in the user's local timezone instead of being interpreted as UTC. Thanks to @cloesophia for the reproducible calendar sample. (#2152) Fixed paginated Google Calendar refreshes for calendars with many events so secondary calendars do not disappear after Google returns a second page. Thanks to @wobafett for reporting and diagnosing this. (#2141) Fixed Task List groups for tasks without scheduled or due dates showing a raw Bases icon object instead of None. Thanks to @ks-studio-net for reporting this. (#2140) The edit task modal now shows saved task-identification tags when hiding identification tags is disabled. Thanks to @3zra47 for reporting this. (#2148) Empty list-like frontmatter values no longer become literal \"null\" entries when tasks are edited. Thanks to @minchinweb for reporting this. (#2120, #2135) Long all-day event titles in Calendar week and day views now truncate instead of stretching the all-day row. Thanks to @same774 and @ks-studio-net for reporting this. (#2124) Fixed a Kanban crash when opening or closing the edit modal immediately after moving a task between list-valued swimlanes such as contexts. Thanks to @Decia-C for reporting this. (#2114) Completing a rescheduled occurrence for a scheduled-anchored recurring task now advances the parent from the moved occurrence date instead of an earlier original occurrence date. Thanks to @chrabia for reporting this. (#2113) Failed Google Calendar manual refreshes no longer make the next immediate refresh show a misleading success notice. Thanks to @JohWQ for reporting this. (#2109) TaskNotes no longer injects instant-conversion controls into embedded or detached Markdown editors, preventing checkbox notes opened from unrelated Bases from freezing Obsidian on mobile. Thanks to @jmartinmcfly for the clear reproduction and recording. (#2107, #2108) Creating tasks with Store title in filename enabled now handles duplicate or case-variant titles without failing or replacing the task title with a suffixed filename. Thanks to @AdmiralClackington for reporting and diagnosing this. (#2106) Regenerated default Calendar Base files now use your configured first day of the week instead of forcing Sunday. Thanks to @atos2212-blip, @cweekly, @idontcode34, and @hikatamika for reporting this. (#2100) Tags added while creating a task now keep the same frontmatter order as tags added later from the task context menu. Thanks to @mgrecar for reporting this. (#2092) New non-recurring tasks created directly in a completed status now get a completed date, so completed-date views can find them immediately. Thanks to @Crell for reporting this. (#2096) Fixed TaskNotes Kanban swimlanes falling back to None when the swimlane used a Bases formula that was not already cached by Bases. Thanks to @ddevaal for reporting this. (#2093) TaskNotes now retries custom Bases view registration when the Bases core plugin is enabled after TaskNotes, preventing default views from showing Unknown view type until TaskNotes is reloaded. Thanks to @yaye-work for reporting this. (#2084) The Relationships widget no longer prevents editor text selection from autoscrolling when dragging below the bottom edge of a task note. Thanks to @lostwildland for reporting this. (#2081, #2103) Kept task card and relationships widgets visible in reading mode when Obsidian scroll or preview updates remove their DOM, and refreshed visible widgets promptly after metadata changes. Thanks to @mukhozhuk for reporting and debugging this and @martin-forge for fixing it. (#2064, #2066) Recurring tasks now advance correctly after their next scheduled date is manually adjusted, preserving due-date offsets and times without jumping back to an earlier occurrence. Thanks to @chmac for reporting and fixing this. (#2018) Fixed Hide empty columns in Kanban views with swimlanes so columns with no visible tasks are hidden while pinned columns remain. Thanks to @scottTomaszewski for reporting and fixing this. Fixed recurring all-day ICS subscription events keeping the original end date on later instances, which could cause calendar list views to show events under the wrong day. Thanks to @abbiefalls90. (#2033) Fixed the project folder badge on task cards so, when expandable subtasks are enabled, it expands or collapses inline subtasks instead of showing an unavailable-action notice. Thanks to @abbiefalls90 for the fix and @scottkodai for the follow-up feedback. (#2040, #2041) Stopped newly created tasks from filling the Google Calendar retry queue when calendar export is disabled. Thanks to @chmac for reporting and fixing this. (#2046, #2051) The date and time picker now focuses the natural-language input when it is enabled, making keyboard-driven quick actions ready for immediate typing. Thanks to @DevOps-Toast for reporting this and @ther12k for fixing it. (#2125, #2129) Materialized recurring occurrence notes now record the date they were actually completed, while the parent recurring task continues to track the occurrence date. Thanks to @raphaelfaouakhiri for reporting and fixing this. (#2173, #2175) Completion-anchored recurring tasks with materialized occurrence notes now schedule the next occurrence from the day the occurrence was actually completed. Thanks to @chmac for reporting and fixing this. (#1982) Preserved the Task List's own scroll position during Bases refreshes so long mobile lists do not jump back to the top after task updates. Thanks to @3zra47 for the follow-up report. (#1863) Microsoft Calendar event updates now accept opaque Exchange calendar IDs instead of failing local validation before contacting Microsoft Graph. Thanks to @fmacondray for reporting this and providing the follow-up stack trace."},{"title":"TaskNotes 4.12.1","url":"/obsidian/releases/4.12.1/","description":"[!info] TaskNotes v5 beta","product":"obsidian","text":"[!info] TaskNotes v5 beta TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release. The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface. TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand. TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter. Changed# (#2204) Public documentation is now published from the dedicated tasknotes.dev repository. Plugin release notes and internal documentation remain in this repository. Updated compatibility with Obsidian's current plugin review and settings search. Fixed# Fixed TaskNotes interface elements sometimes appearing in the wrong window when using Obsidian pop-out windows. Improved confirmation dialogs, icons, and modal styling to use Obsidian's current interface APIs."},{"title":"TaskNotes 4.12.2","url":"/obsidian/releases/4.12.2/","description":"[!info] TaskNotes v5 beta","product":"obsidian","text":"[!info] TaskNotes v5 beta TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release. The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface. TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand. TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter. Fixed# (#2212) Fixed TaskNotes settings sections appearing pushed across the Obsidian settings pane on desktop. Thanks to @RafaQNunes for reporting this."},{"title":"TaskNotes 4.12.3","url":"/obsidian/releases/4.12.3/","description":"[!info] TaskNotes v5 beta","product":"obsidian","text":"[!info] TaskNotes v5 beta TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release. The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface. TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand. TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter. Fixed# (#2212) Fixed TaskNotes settings sections appearing offscreen or blank on Obsidian 1.13 desktop. Thanks to @RafaQNunes for reporting this, and to @m4to-3pe and @matthewrishii for confirming it remained in 4.12.2. (#2213) Runtime plugin-data updates now avoid writing when Obsidian cannot safely read an existing TaskNotes data.json, preventing calendar sync, Pomodoro, ICS, or auto-archive state writes from replacing saved settings. Thanks to @3zra47 for the follow-up details and file-history evidence. (#2216) Fixed updated default Kanban Bases grouping every task into the None column when grouping by status. The generated Kanban templates now use the real status property, and existing Kanban files using task.status keep grouping from TaskNotes task data. Thanks to @Esvorst for reporting this. (#2120, #2135) Long all-day event titles in Calendar week and day views now truncate in the all-day row instead of stretching it vertically. Thanks to @same774 and @ks-studio-net for reporting this, and to @Admorei for confirming it remained in 4.12.2."},{"title":"TaskNotes 4.2.0","url":"/obsidian/releases/4.2.0/","description":"Added Korean (한국어) language support","product":"obsidian","text":"Added# Added Korean (한국어) language support Full translation of all 1911 localization keys Korean language option now available in Settings → General → Language Adopted Obsidian 1.11.0 API features with backwards compatibility Settings tab now displays TaskNotes icon in the sidebar (Obsidian 1.11.0+) Settings sections now use native SettingGroup for improved visual grouping (Obsidian 1.11.0+) Falls back gracefully to traditional section headers on older Obsidian versions (#59) Added shortYear template variable for custom filename and folder templates Use {shortYear} in filename templates (e.g., \"25\" for 2025) Use {{shortYear}} in folder templates Thanks to @Pixeltica for the feature request (#1393) Option to prevent auto-creation of default Base view files on startup New \"Auto-create default files\" toggle in Settings → Integrations → Bases Integration When disabled, deleted sample Base files will not be recreated on plugin load The manual \"Create Default Files\" button remains available for on-demand recreation Thanks to @wealthychef1 for the feature request (#1408) Shift+click on status icon to cycle backwards through statuses Normal click cycles forward through status order Shift+click cycles in reverse order Thanks to @JerryLu086 for the feature request (#1410) Task creation modal now starts in vim insert mode when vim keybindings are enabled Previously required pressing 'i' before typing when Obsidian vim mode was active The modal now automatically enters insert mode on focus, allowing immediate typing Thanks to @Leo310 for the feature request Added button tooltips to calendar view toolbar Hovering over navigation and view buttons now shows descriptive hints Buttons include: Today, Previous, Next, Month, Week, Day, Year, List Added tooltips to task modal action icons Icon buttons for status, date, project, priority, recurrence, and reminder now show tooltips on hover Improves discoverability for new users (#503) Settings now sync automatically across devices via Obsidian Sync Changes to custom statuses, priorities, and other settings apply immediately without restart Thanks to @jhedlund for the feature request and @l-mb for the implementation (#1403) Kanban view option to consolidate status icons in column headers New \"Show status icon in column header only\" toggle in Kanban view settings (disabled by default) When enabled and grouped by status, shows the icon in the column header and hides it on cards Reduces visual redundancy when the column already indicates the status Thanks to @l-mb for the feature request and implementation (#1401) Calendar view option to span tasks between scheduled and due dates New \"Span tasks between scheduled and due dates\" toggle in Calendar view Layout settings When enabled, tasks with both scheduled and due dates display as multi-day bars Provides Gantt chart-style visualization for project planning Thanks to @0atman for the feature request (#1334) {{currentNotePath}} now works for \"Create new inline task\" command The inline task folder setting with {{currentNotePath}} previously only worked for checkbox conversion Now also applies when using the \"Create new inline task\" command from the command palette Thanks to @kmaustral for the feature request (#1264) Option to open Pomodoro timer in mobile sidebar instead of note panel New \"Mobile sidebar\" setting in Settings → Features → Pomodoro Timer Choose between: Note panel (default tab behavior), Left sidebar, or Right sidebar Allows quick swipe access to the timer without switching notes on mobile devices Thanks to @Evthestrike for the feature request (#1220) Option to use ICS event end time as task due date New \"Use ICS event end time as task due date\" toggle in Settings → Integrations → Calendar Subscriptions When enabled, tasks created from calendar events will have their due date set to the event's end time For all-day events, uses the event date (not the ICS container end date which is the next day per ICS spec) For timed events, includes the exact end time Defaults to disabled to preserve existing behavior Thanks to @MiserMagus for the feature request (#1108) Option to use task duration instead of due date for ICS calendar export New \"Use task duration for event length\" toggle in Settings → Integrations → Automatic ICS Export When enabled, exported calendar events use scheduled date + time estimate as DTSTART/DTEND This aligns with GTD workflows where scheduled + duration represents work planning, while due date represents deadlines When disabled (default), preserves existing behavior using due date as DTEND Thanks to @bepolymathe for the feature request Fixed# (#1421) Fixed natural language parser only capturing one date when both scheduled and due dates are specified Input like \"Task scheduled for tomorrow due next week\" now correctly sets both scheduled and due dates Previously the parser would return early after finding the first date trigger, ignoring any subsequent triggers Thanks to @wealthychef1 for reporting (#1384) Fixed title being sanitized even when \"Store Task Title in Filename\" is disabled Characters like ?, <, >, :, etc. are now preserved in task titles when they won't be used in filenames When storeTitleInFilename is false, only minimal sanitization (whitespace normalization, control character removal) is applied Thanks to @allison-casey for reporting (#1028), (#1140), (#1152), (#1354), (#1362) Fixed duplicate task entries appearing in Agenda view Tasks were shown twice: once as TaskNotes events and again as property-based events with a file icon Changed default Agenda template to disable property-based events (showPropertyBasedEvents: false) Users can re-enable property-based events in view settings if needed for non-task date properties Thanks to @YIRU69, @jhedlund, @dblinnikov, @Snakiest, @WeiYiAcc, @JacksonMcDonaldDev, @jimbo108108, and @krelltunez for reporting (#1386) Fixed timeEstimateCategory formula showing \"Long (>2h)\" instead of \"No estimate\" for new tasks The condition didn't properly handle null values when timeEstimate property is unset Also fixed the same issue in trackingStatus formula Thanks to @nicou for reporting and @osxisl for the PR (#1397) Fixed Bases views (Kanban, Calendar, Task List) resetting to Calendar view after a few minutes Also fixed CalendarView corrupting other view files when saving state on unload Thanks to @music-soul1-1 for reporting (#1398) Fixed overdue strikethrough showing on completed tasks Completed tasks with past due dates no longer display overdue styling Respects the \"Hide completed from overdue\" setting which defaults to true (#1363) Fixed calendar view showing nothing when a task has an invalid date format Tasks with malformed dates (e.g., \"262025-12-16\" instead of \"2025-12-16\") no longer crash the entire calendar Invalid tasks are now skipped with a console warning, allowing other events to display normally Thanks to @Erelen for reporting Fixed today column in week/day calendar views using FullCalendar's default yellow instead of theme accent Today's column now uses a tint of the theme accent color for consistent styling (#1399) Fixed drag-and-drop not working in Kanban view on mobile Cards and columns can now be dragged using long-press gesture on touch devices Includes haptic feedback and auto-scroll when dragging near edges Thanks to @l-mb for reporting and the fix (#1381) Fixed Pomodoro \"Change Task\" menu not showing newly created tasks Tasks created while the Pomodoro view was open would not appear in the task selector Improved metadata cache synchronization to properly wait for new files to be indexed Thanks to @Ghosthael for reporting (#1344) Fixed \"Unsaved Changes\" popup appearing randomly when closing task edit modal The popup would appear even when no changes were made to the task Caused by inconsistent trailing whitespace normalization when comparing details content Thanks to @hasanyilmaz for reporting (#1402) Fixed Kanban swimlane view showing tasks in wrong column when grouped by formula After editing task metadata, cards would jump to \"None\" column until Obsidian reload Column assignment now uses Bases' computed grouping instead of cached formula outputs Thanks to @bailob for the fix (#1352) Fixed date context menu not preserving time when using increment options Using +1 day, -1 day, +1 week, or -1 week on a task with a time (e.g., 2025-12-10T16:00) now preserves the time Previously the time would be stripped, changing 2025-12-10T16:00 to 2025-12-11 instead of 2025-12-11T16:00 Thanks to @cathywu for the feature request Fixed v3 saved views exporting incorrectly to Bases format Title filters now correctly use file.name instead of note.title Archived filters now generate valid boolean expressions instead of malformed comparisons \"Is Blocked\" filters now generate correct expressions with proper operator precedence (#1036) Due dates can now be dragged in the calendar view Previously only scheduled dates were draggable; due dates were locked in place Dragging a due event now updates the task's due date property Thanks to @same774 for reporting Improved calendar view responsiveness for user interactions Task creation, editing, timeblock changes, and view option toggles now update immediately Previously these actions waited 5 seconds due to the debounce intended for external file changes The 5-second debounce is now bypassed for direct user actions while still preventing flicker during typing Improved visual affordance for Pomodoro timer duration adjustment buttons The +/- buttons below the timer now have visible backgrounds and borders Hover states show accent color border for clearer interactivity feedback Previously buttons were nearly invisible with transparent backgrounds (#1409), (#1214), (#979) Improved Calendar, Agenda, Kanban, and Stats views in pop-out windows Drag-and-drop in Kanban view now works correctly when the view is in a new window Context menus (status, priority, task) now work correctly in pop-out windows Stats view drill-down modal now appears in the correct window Search boxes, task cards, and grouped task lists render correctly Root cause: Code was using global document and standard instanceof checks which fail across windows Solution: Use ownerDocument for DOM operations and Obsidian's cross-window instanceOf() method Known limitation: Calendar event dragging does not work in pop-out windows due to FullCalendar library using global document for mouse event listeners. Use context menus or edit modals as a workaround. Updated FullCalendar to v6.1.20 Thanks to @Snakiest, @same774, and @3zra47 for reporting (#1337) Fixed \"Convert current note to task\" hotkey not applying default values from settings When user configured default status/priority as \"None\", the modal would show \"Open\" and \"Normal\" instead Root cause: Task edit modal was refreshing data from file and overwriting user-configured defaults Now preserves constructor-provided task data when converting non-task files Thanks to @guihasparyk for reporting (#1304) Fixed \"Cannot find function map on type Link\" error in Blocking view Error occurred when embedding the Relationships base and opening the Blocking view Root cause: When blockedBy contained a single dependency, Bases returned it as a Link object without a .map() method Fixed by wrapping blockedBy with list() before calling .map(), consistent with the Blocked By view Thanks to @prayidae for reporting (#1295) Fixed missing navigation link to Default Base Templates page on tasknotes.dev The page existed but was not accessible from the site navigation Thanks to @Arachnidai for reporting (#1223) Fixed \"Go to today's note\" command opening wrong date in positive UTC offset timezones In timezones like Japan (UTC+9), early morning use of this command opened yesterday's note Root cause: Incorrectly extracting UTC date components instead of local timezone date Thanks to @BrucePlumb for reporting"},{"title":"TaskNotes 4.2.1","url":"/obsidian/releases/4.2.1/","description":"(#1424) Fixed \"Create New Task\" command creating tasks in active folder instead of default folder","product":"obsidian","text":"Added# New Calendars API endpoint for access to calendar data Access calendar provider information and connection status Query events from Google Calendar, Microsoft Calendar, and ICS subscriptions Filter events by date range tasknotes-cli has been updated to make use of this endpoint Fixed# (#1424) Fixed \"Create New Task\" command creating tasks in active folder instead of default folder \"Create New Task\" now correctly uses the configured default task folder \"Create New Inline Task\" continues to use the inline task folder setting Thanks to @Gogo-XD for reporting and @TonyAtlas for confirming (#1421), (#1042) Fixed natural language parser only setting one date when both scheduled and due dates are specified Entering something like \"task due Jan 9 at Jan 9\" now correctly sets both the due date and scheduled date Thanks to @wealthychef1 and @dblinnikov for reporting (#1410) Fixed vim insert mode not activating in task creation modal The modal now correctly enters insert mode when vim keybindings are enabled Thanks to @Leo310 for the feature request (#1422) Fixed tags with dashes not being parsed correctly Tags like #my-tag were being truncated to #my Thanks to @JerryLu086 for reporting (#1419) Fixed custom statuses and priorities not saving in settings Values entered in text fields were sometimes lost when closing the settings modal Thanks to @s33a for reporting"},{"title":"TaskNotes 4.3.0","url":"/obsidian/releases/4.3.0/","description":"(#1361) Option to disable inline task overlay for aliased wikilinks","product":"obsidian","text":"Changed# (#1437) Unified template variable syntax and available variables across filename and body templates Both systems now use double-brace {{variable}} syntax consistently Single-brace {variable} syntax remains supported for backwards compatibility but is deprecated Settings UI shows a warning when deprecated single-brace syntax is detected Filename templates gain body template variables: {{contexts}}, {{tags}}, {{hashtags}}, {{timeEstimate}}, {{details}}, {{parentNote}} Body templates gain filename template variables: {{zettel}}, {{nano}}, and all extended date/time variables Thanks to @23maverick23 for reporting Added# (#1361) Option to disable inline task overlay for aliased wikilinks New setting in Features → Inline Tasks: \"Disable overlay for aliased links\" When enabled, links with aliases like [[Task|Check Status]] render as plain links Links without aliases continue to show the interactive task widget Useful when embedding tasks in prose where the widget would be disruptive Thanks to @diegomarzaa for the contribution and @jldiaz for proposing this feature in #1117 (#1199, #1205) Google Calendar export for tasks Sync tasks to Google Calendar based on scheduled or due dates Automatic sync on task create, update, complete, and delete Configurable event title templates with placeholders ({{title}}, {{status}}, {{priority}}, etc.) Event descriptions include task metadata and optional Obsidian deep link Support for all-day or timed events with customizable duration Event color customization using Google Calendar's color palette Default reminder setting for popup notifications Bulk sync and unlink actions in settings Task-event linking stored in frontmatter (googleCalendarEventId) Recurring tasks sync as Google Calendar recurring events Completed or skipped recurring instances are automatically excluded Thanks to @someromans and @Leonard-44 for requesting this feature, and @dmantisk, @farangkao, @rayvermey, and @rdpr for their input Fixed# (#1413) Fixed angle-bracket links and project title display Angle-bracket links like [Spec]() now resolve correctly Project links display frontmatter title instead of raw filename/path when available Dependency values normalize consistently across wikilinks, markdown links, and angle-bracket variants Many thanks to @normenmueller for the contribution (#1414) Kanban column headers now display configured priority labels instead of raw values Many thanks to @normenmueller for the contribution (#1416) Fixed property-based task identification mutating tags unexpectedly Tags are only written when explicitly changed by the user Task tag is only added in tag-based identification mode Fixes #1391 Thanks to @loukandr for reporting and @normenmueller for the fix (#1187) Fixed \"Unknown view types\" error when opening Bases views after upgrading from pre-V4 Users who had disabled Bases support in earlier versions could not open Bases views after upgrading Settings migration now automatically re-enables Bases support since the toggle was removed in V4 Thanks to @MiracleXYZ for reporting (#1144) Fixed relationships.base showing empty views for Projects, Blocked By, and Blocking tabs The top-level task filter was excluding non-task files from the Projects view Projects can be any file type (not just tasks), so the filter is now applied per-view Subtasks, Blocked By, and Blocking views retain the task filter; Projects view does not Users with existing relationships.base files should delete and regenerate them to get the fix Thanks to @needo37 for reporting, and @n1njaznutz, @nestor50, and @IvyDliu for investigating and confirming the solution Fixed calendar view type not persisting or applying when changed View type changes via header buttons (week/day/month) are now saved to the .base file View type changes via Bases settings panel now apply immediately without reload (#1441) Fixed task dragging broken with \"Span tasks between scheduled and due dates\" enabled Span events can now be dragged to move tasks in time Dragging shifts both scheduled and due dates proportionally, preserving the span duration Previously, dragging span events would cause a visual/data mismatch where the calendar showed the wrong position Thanks to @Peeeet for reporting"},{"title":"TaskNotes 4.3.1","url":"/obsidian/releases/4.3.1/","description":"(#1546) Added sticky kanban column headers that remain visible while scrolling","product":"obsidian","text":"Added# (#1546) Added sticky kanban column headers that remain visible while scrolling Thanks to @normenmueller for the contribution (#1458) Added CSS color classes to context tags for custom styling Each context tag now receives a unique CSS class based on its name (e.g., context-tag--color-0 through context-tag--color-19) Enables styling individual contexts via CSS snippets Thanks to @phortx for the contribution Added mdbase-spec type definition generation New setting in Integrations tab to generate mdbase-spec v0.2.0 type definition files (mdbase.yaml and _types/task.md) at the vault root Type definitions are derived from TaskNotes settings (statuses, priorities, field mappings, user fields) and regenerated automatically when settings change Enables interoperability with other tools that support the mdbase-spec format Fixed# (#1472) Fixed task dependencies not being stored as wikilinks in frontmatter Dependencies now retain their [[wikilink]] format when saved, preventing them from breaking on file rename Thanks to @renekalff for reporting (#1443) Fixed default status/priority not updating when the referenced custom value is deleted Deleting a custom status or priority that was set as the default now resets the default to the first available value Thanks to @l-mb for the contribution (#1448) Fixed project removals not persisting from the task edit modal Removing all projects from a task now correctly clears the projects field Different link formats (e.g., markdown links vs wikilinks) no longer cause false change detection Thanks to @normenmueller for the contribution (#1514), (#1517) Fixed task reminders not syncing to Google Calendar Task-specific reminders (both relative and absolute) now sync to Google Calendar Previously only the global default reminder setting was used, ignoring per-task reminders Thanks to @christenbc for the contribution (#1525), (#1531) Fixed subtask status dot not refreshing visually when clicked Status dot, checkbox, and card styling now update instantly when cycling status Thanks to @christenbc for the contribution (#1537) Fixed Google Calendar errors during bulk sync Added rate limiting to space out API calls, preventing errors when syncing many tasks at once Thanks to @Lorite for the contribution (#1515), (#1540) Fixed time loss when setting recurrence and recurrence not clearing from Google Calendar Setting recurrence on a task with a scheduled time now preserves the time, preventing Google Calendar events from appearing as all-day Clearing recurrence from a task now also removes it from the synced Google Calendar event Thanks to @christenbc for the contribution (#1428), (#1559) Fixed hierarchical tags with slashes (e.g., #project/sub-project) being truncated in link text Tags containing slashes, hyphens, and Unicode characters now render correctly Thanks to @normenmueller for the contribution and @ysafonov for reporting (#1565) Fixed Google Calendar target calendar dropdown appearing empty after app restart The dropdown now re-populates once calendars are fetched during startup Thanks to @N-HEDGER for reporting (#1567) Fixed inline task card widgets disappearing momentarily When the task cache is temporarily cleared (e.g., during Smart Connections processing), the previously-rendered widget is now preserved instead of reverting to a plain wiki link Thanks to @scztt for reporting (#1568) Fixed deleted tasks not being removed from Google Calendar When a task file is deleted outside of TaskNotes (e.g., via Obsidian's file manager), the synced Google Calendar event is now cleaned up automatically Thanks to @kmaustral for reporting Fixed Integrations tab spacing and layout issues Improved positioning of buttons and status indicators across Google Calendar, ICS, and Webhooks sections"},{"title":"TaskNotes 4.3.2","url":"/obsidian/releases/4.3.2/","description":"(#1520) Tag and Context fields in Edit Task modal now show all available suggestions immediately on focus","product":"obsidian","text":"Added# (#1520) Tag and Context fields in Edit Task modal now show all available suggestions immediately on focus Previously required typing at least one character before suggestions appeared Already-selected values are excluded from the suggestion list Thanks to @Glint-Eye for the suggestion (#1506) Added setting to configure the default color for new timeblocks New color picker in Settings > Features > Timeblocking Previously hardcoded to indigo; now user-configurable Thanks to @phillipadsmith for the suggestion Fixed# Fixed mdbase-spec type definition generation not triggering when settings change (#1456) Fixed inline tasks jumping visually when marked as completed Thanks to @3zra47 for reporting (#1364) Fixed auto-stop time tracking not triggering when completing recurring task instances Thanks to @slipstyle for reporting (#1465) Fixed all-day events synced to Google Calendar receiving wrong notification time All-day events now use Google Calendar's configured all-day notification defaults instead of a minutes-based reminder Thanks to @Jomo94 for reporting (#1470) Fixed cursor showing as default instead of pointer on interactive elements Thanks to @TheFrostedDev for reporting (#1491) Fixed boolean property values being quoted as strings in Bases filter generation When using a boolean property (e.g. tasknote: true) for task identification, the filter now correctly handles the value Thanks to @denisgorod for reporting (#1494) Fixed Kanban swimlane resetting to \"None\" on initial load and after navigation Thanks to @tnguyen2018 for reporting (#1555) Fixed \"Folder already exists\" error when creating tasks or converting inline tasks Thanks to @jkune5 for reporting (#1532) Fixed expanded task modal buttons being cut off when content exceeds viewport height Thanks to @willfanguy for reporting (#1542) Fixed declined and cancelled events from ICS calendar subscriptions appearing in calendar view Thanks to @karenchoe428 for reporting (#1556) Fixed completion-based recurring tasks not rescheduling when the recurrence interval is large Thanks to @kazerniel for reporting (#1492) Fixed hardcoded \"open\" status leaking into filenames, recurring task displays, and parsing fallbacks Users with custom default statuses (e.g. \"inbox\") no longer see \"open\" where their configured default should appear Recurring tasks now show their actual configured status instead of always displaying \"open\" when not completed Thanks to @macdrifter for reporting (#1501) Fixed Google/Microsoft Calendar event colors not showing in agenda/list view Per-event and calendar-level colors now display correctly in the list view, matching grid view behavior Added today indicator highlighting to list view day headers Thanks to @Robubble for the suggestion"},{"title":"TaskNotes 4.3.3","url":"/obsidian/releases/4.3.3/","description":"Published mdbase-tasknotes (mtn), a standalone CLI for managing tasks in markdown files via mdbase","product":"obsidian","text":"Changed# Published mdbase-tasknotes (mtn), a standalone CLI for managing tasks in markdown files via mdbase Works on the same vault and _types/task.md schema that TaskNotes generates, without requiring the plugin or HTTP API Preferable over tasknotes-cli as a lighter-weight alternative and when Obsidian is not running, on remote machines, or in scripts and CI environments Supports natural language task creation, time tracking, project aggregation, statistics, and an interactive REPL Extracted shared natural language parsing logic into the standalone npm package tasknotes-nlp-core The NLP parser and related language configuration are now shared through this package This keeps behavior consistent between the plugin and CLI tools Added# (#1549) Added setting to reset markdown checkboxes when recurring tasks are completed When enabled, all checked checkboxes (- [x]) in the task body are reset to unchecked when a recurring task instance is completed and rescheduled Useful for recurring tasks with subtask checklists that need to be repeated each instance Configurable via Settings > Features > Recurring Tasks > \"Reset checkboxes on recurrence\" Thanks to @phortx for the feature request (#1548) Added ability to create calendar events on connected external calendars directly from the calendar view When clicking or dragging to select a time slot, a new \"Create calendar event\" option appears in the context menu Opens a modal to enter event title, description, location, and select which calendar to create on Supports both Google Calendar and Microsoft Calendar providers Thanks to @Robubble for the feature request (#1597) Added MCP server for AI agent integration Exposes TaskNotes tools at /mcp endpoint, gated behind enableMCP setting Supports tasks (CRUD, query, toggle status/archive, parse from text), time tracking, pomodoro, calendar events, and task statistics Thanks to @dstotijn for the contribution Fixed# Fixed generated mdbase type definitions for task dependencies using the wrong field type In _types/task.md, blockedBy[].uid now uses type: link (was type: string) Better matches how dependency links are serialized in task frontmatter ([[...]]) Fixed generated mdbase reminder type definitions to better match TaskNotes reminder data In _types/task.md, reminders[].type now uses enum values absolute|relative reminders[].relatedTo now uses enum values due|scheduled reminders[].absoluteTime now uses type: datetime (was type: string) (#1597) Fixed webhook payloads for time tracking start-with-description containing stale data Thanks to @dstotijn for the fix (#1581) Fixed Pomodoro starting break instead of work session after app restart After completing a work session and restarting, pressing Start would incorrectly start a break Now properly resets nextSessionType when clearing stale sessions or stopping the timer Thanks to @Sirnii for the detailed bug report and root cause analysis (#1577) Fixed Edit Note/Task modal hiding action buttons when content exceeds viewport height Added vertical scroll to modal content area while keeping buttons pinned at bottom Thanks to @hossam-elshabory for reporting and @ivannin for helping in discussion (#1600) Fixed kanban view grouping not working when more than 20 views exist The getGroupByPropertyId() method had a hardcoded loop limit of 20 iterations Views at index 20 or higher would not be found, causing groupBy to return null Thanks to @IHaveNoShame for reporting (#1595) Fixed task modal floating buttons blocking content on mobile Added mobile-specific (body.is-mobile) CSS to ensure proper flex layout Button container now stays pinned at bottom without overlapping scrollable content Thanks to @Jomo94 for reporting (#1590) Fixed HTTP API not allowing blockedBy dependencies when creating tasks Added blockedBy field support to TaskService.createTask() Updated API documentation with blockedBy, recurrence, and reminders fields Thanks to @hGriff0n for reporting (#1582) Fixed recurring tasks not appearing at end of visible calendar range for non-UTC timezones Daily/weekly recurring tasks with times after ~1pm would disappear on the last day of the visible range for users in positive UTC offsets (e.g., UTC+11) Fixed date boundary comparisons in both generateRecurringInstances() and generateRecurringTaskInstances() to compare dates only, not timestamps Thanks to @benefitbug for reporting (#1580) Fixed Google Calendar sync failing after OAuth token expires with unhelpful error message When refresh tokens expire or are revoked (e.g., Google Cloud project in Testing mode, user revoked access), the error message was confusing: \"Failed to refresh google token: Request failed, status 400\" Now detects irrecoverable token errors (invalid_grant, invalid_client) and automatically disconnects the OAuth connection Shows actionable error message: \"Google Calendar connection expired. Please reconnect in Settings > Integrations.\" Prevents repeated failed refresh attempts and error message spam Thanks to @osxisl for reporting and @Naesue for helping in discussion (#1584) Fixed DOMTokenList error when task status values contain spaces Clicking the status ring on a task card threw an error when status contained spaces (e.g., \"In Progress\") Status and priority values are now sanitized before being used as CSS class names Thanks to @omber for reporting"},{"title":"TaskNotes 4.4.0","url":"/obsidian/releases/4.4.0/","description":"TaskNotes documentation.","product":"obsidian","text":"Added# Mdbase type generation now includes tn_role annotations so external tools can identify each field's role even when frontmatter names are customized (#1618) Mdbase type matching now follows your task identification settings (tag or frontmatter property), with fallback to tag matching when needed Thanks to @jimbo108108 for reporting Mdbase type status fields now include tn_completed_values so external tools can reliably identify which status values count as completed (#1576) Added an optional Checklist Progress task-card property that renders a compact progress bar and completed/total count from top-level markdown checkboxes Uses metadata cache list items and excludes nested checklist entries so progress reflects top-level task steps In Bases views, map tasks (file.tasks) to Checklist Progress Existing .base files need file.tasks added to the view order YAML manually Newly generated .base templates now include file.tasks in view order by default Thanks to @phortx for opening #1576 and for the earlier implementation PR, and @piyushaswani55 for feedback in the issue discussion Changed# Mdbase type generation no longer overwrites mdbase.yaml if the file already exists, preserving user customisations Webhooks now fire consistently regardless of whether updates come from the UI, HTTP API, or MCP Webhook runtime state now syncs automatically when plugin settings change Shared HTTP response/body parsing utilities are now consolidated in a dedicated httpUtils module Release notes now include a reminder on every release page that default generated .base template changes never overwrite existing user .base files, and that users can regenerate templates from Settings to pick up updates Fixed# (#1608) Fixed task title frontmatter being removed when storeTitleInFilename is enabled title is now retained in frontmatter while filename derivation from title remains unchanged Thanks to @victoraraujo105 for the PR (#1602) Fixed time tracking statistics showing incorrect or zero values for Today/Week/Month due to UTC-anchored date range boundaries in Stats View Updated range calculations to use local calendar-day boundaries consistently (#1602) Fixed inconsistent timeEntries timestamp formats across create/edit/drag/resize flows Time entry timestamps are now written in canonical UTC ISO format (toISOString() with Z) across all write paths (#1602) Fixed denormalized timeEntries.duration drift after edits Time tracking calculations now derive duration from startTime/endTime Time entry save paths now strip legacy duration values instead of persisting them Thanks to @dy66 for opening #1602"},{"title":"TaskNotes 4.5.0","url":"/obsidian/releases/4.5.0/","description":"TaskNotes documentation.","product":"obsidian","text":"Fixed# (#1652) Fixed API, MCP, and NLP task creation so it respects your configured filename format when title storage in filenames is disabled Thanks to @36mimu36 for reporting, and @rafavital and @warm-july for follow-up discussion and reports (#1601, #1709) Fixed reading-mode relationship widgets sometimes rendering multiple times during startup Applied the same protection to task cards so overlapping refreshes are coalesced there too Thanks to @wealthychef1 and @CarlJohnson99 for reporting, and @benmartinek for confirming the behavior (#1713) Fixed ICS export so date-only scheduled tasks are written as all-day events instead of midnight events Thanks to @bepolymathe for the request and interoperability details (#267, #948, #1682, #1717, #1725) Fixed expanded subtasks and dependency cards in Bases Task List and Kanban views so related items can inherit the current view's filters instead of always showing every linked task Added a per-view \"Expanded relationships\" option so you can switch between inherited filters and showing all related tasks Thanks to @mdbraber, @GardarikanetS, @Glint-Eye, @prepare4robots, and @robmcphers0n for the original reports and feature requests, and @marblebyte for follow-up discussion Improved custom view and search-pane activation when reopening deferred tabs (#1720) Fixed Bases Task List cards showing icon tokens such as clock instead of readable date-like values, and fixed property labels to use Bases display names instead of raw property IDs Thanks to @Sirnii for reporting (#1633) Fixed interactive task-card labels and ribbon labels so Bases-backed cards use translations and configured display names instead of hardcoded English or raw property IDs Thanks to @Sarryaz for reporting (#1651) Fixed date is query filtering so date-only searches also match timed scheduled and due values during prefiltering Thanks to @36mimu36 for reporting (#1644) Fixed generated default task views so recurring tasks without a complete_instances property still appear as incomplete where appropriate Thanks to @bkennedy-improving for reporting, and @SandroK for follow-up discussion on related default-view behavior (#1513, #1686) Fixed a calendar issue where creating or editing events and timeblocks could reset the visible date back to today In-place calendar recreation now preserves the visible date unless you explicitly navigate elsewhere Thanks to @owenoxen for opening #1513, and @Lorite for opening #1686 and contributing the fix Fixed documentation deployment CI failures caused by docs-builder/src/js/main.js being excluded by a broad .gitignore rule Reduced background calendar-sync overhead when persisting sync tokens Prevented duplicate auto-stop time-tracking listeners from accumulating after settings reloads Fixed a settings-lifecycle issue that could accumulate calendar update callbacks while the Integrations tab is repeatedly opened (#1630) Fixed TaskNote inline task cards ignoring centered \"Readable line length\" layout in the Minimal theme Thanks to @martin-forge for reporting Fixed a broken docs cross-reference from Property Types Reference to Task Properties settings Fixed docs site links so internal Markdown links resolve to app routes instead of broken .md paths Fixed docs release-note links by building Markdown pages even when they are not listed directly in the sidebar Added# (#1704) Added an option to widen the current day column in multi-day calendar time-grid views You can control the width multiplier and choose whether it applies to week view, custom multi-day view, or both Thanks to @dictionarymouse for the feature request Added TaskNotes Obsidian CLI commands for task creation, time tracking, and Pomodoro control Includes shared NLP-to-task conversion across the CLI, modal, and API capture flows, plus new user documentation for the built-in CLI commands (#1716) Added roomier subtask and dependency cards inside the task modal while keeping the task options menu available Thanks to @hokfujow for the feature request (#1619, #386, #621) Added drag-to-reorder for Kanban and Task List views Supports grouped Task List moves, manual ordering via the tasknotes_manual_order property, and improved drag/drop behavior for swimlanes, filtered views, and interactive task controls To use it, sort the view by the Manual Order field (tasknotes_manual_order by default), or regenerate the built-in .base templates from Settings → TaskNotes → General → Create Default Files Thanks to @ac8318740 for the original contribution in PR #1619, @iholston and @dsebastien for opening #386 and #621, and @mdbraber, @elvarb, @LucidToday, @craziedde, @kmaustral, @SKIERZZ, @sookochoff, and @kanzaki1201 for follow-up discussion and testing across the linked issues and PR Added a standalone TaskNotes Specification repo and docs section covering the data model, field mapping, recurrence behavior, validation rules, and conformance tests Added tasknotes-tui, a terminal UI for working with TaskNotes vaults Includes keyboard-driven views, date navigation, time tracking, recurring task support, and a command palette Changed# Refactored several internal modules to reduce coupling and make maintenance safer Updated generated _types/task.md output so dateCreated and dateModified include generated timestamp values, and recurrence_anchor defaults to scheduled Cleaned up API, webhook, NLP, privacy, settings, and view documentation for clarity and accuracy Expanded Task List and Kanban documentation for drag-to-reorder, including manual-order sorting, grouped and swimlane scope, and filtered-view limitations"},{"title":"TaskNotes 4.5.1","url":"/obsidian/releases/4.5.1/","description":"TaskNotes documentation.","product":"obsidian","text":"Fixed# (#1672) Fixed custom date ranges in the MCP time summary tool so from and to dates work as expected Thanks to @pib for the fix (#1742) Fixed calendar week and day views so the time scale stays aligned on the left instead of drifting inward Thanks to @ysafonov for the report and screenshot"},{"title":"TaskNotes 4.5.2","url":"/obsidian/releases/4.5.2/","description":"TaskNotes documentation.","product":"obsidian","text":"Added# (#1342, #1793) Added native tag autocomplete to time entry descriptions by using the embedded markdown editor in the time entry editor modal. Thanks to @fastrick for the request and @renatomen for the PR. (#1756, #1798) Added HTTP API support for configured custom user fields so task responses include them and create/update requests can round-trip their values. Thanks to @Treygec for the request and PR. (#1777) Added a Modal Fields setting to choose whether Tab/Shift+Tab move focus out of the task details editor or use the markdown editor's indentation behavior. Thanks to @P-Sc for the PR. Changed# Updated the Obsidian API dependency to 1.12.3 and switched the Bases integration to the official API type declarations. Bases task cards and property-event cards now render metadata values through Obsidian's native Bases value renderer so links, dates, lists, icons, and formula values display more faithfully. Fixed# (#1778) Fixed MCP initialize requests using newer protocol versions such as 2025-11-25 failing instead of negotiating down to TaskNotes' supported MCP version. Thanks to @SakulaPor for reporting. (#1781) Fixed duplicate metadata properties on Bases task cards when bare and note.-prefixed property IDs map to the same TaskNotes field. Thanks to @loukandr for reporting and tracing the issue. (#1787) Removed the \"(click to change)\" helper text from recurrence tooltips on task cards. Thanks to @kazerniel for reporting. (#1828) Fixed subtask creation from a task card dropping the parent task project when natural-language input also adds projects. Thanks to @prepare4robots for reporting. (#1786) Fixed TaskNotes task cards and relationships/subtasks widgets appearing inside embedded task-note heading or block sections. Skips note-level widget injection in detached or embedded Markdown editor contexts used by plugins such as Block Link Plus. Thanks to @3zra47 for reporting. (#1815) Fixed the Priority property settings so the NLP trigger character field is visible and editable even when priority NLP parsing is disabled. Thanks to @spiv for reporting. (#1035) Fixed the task modal title field causing the modal to jump to the bottom when focused on iPhone. Thanks to @3zra47 for reporting and following up. (#1045) Fixed inline linked recurring tasks keeping the previous day's completed state after the calendar day changes. Thanks to @3zra47 for reporting and following up. (#1788) Fixed Task List subgroup headers and cards rendering without clear indentation. Thanks to @renatomen for the PR. (#1810) Updated Japanese Kanban terminology to use the more natural katakana spelling. Thanks to @sigma7863 for the PR. (#1633) Fixed Bases task cards using fallback labels instead of Bases display names for mapped task fields and file properties. Thanks to @Sarryaz for reporting the Bases task card i18n and field-mapping issue. (#884) Fixed untranslated strings and English placeholder examples across non-English interface translations. Thanks to @berzernberg for reporting Russian translation gaps. (#1765, #1769) Fixed auto-archived tasks leaving stale Google Calendar events when cleanup runs before calendar sync is ready or after the task moves into the archive folder. Thanks to @martin-forge for reporting and the PR. (#1764) Fixed Google Calendar sync using stale task metadata after rapid task updates, and fixed late recurring completions/skips recording the completion day instead of the scheduled occurrence date. Thanks to @martin-forge for the PR and to @jpmoo for reporting the recurring completion issues. (#1782) Fixed CI test runs resolving the NLP parser package from a local sibling checkout instead of the published dependency. Thanks to @martin-forge for reporting. Published mdbase-tasknotes 0.1.3 with compatibility fixes for TaskNotes-generated mdbase schemas. Includes clearer create-path diagnostics, natural-language mtn list --due filters, timer log datetime filters, home-directory path expansion, project wikilink preservation, and correct mtn --version reporting. Thanks to @tparsons9, @anomatomato, @npondel, @plashal, and @waspeer for the reports and PR. (#1667) Fixed NLP scheduled-date parsing so standalone scheduled and start triggers can set scheduled dates alongside due dates. Thanks to @hokfujow for reporting and @UniqueClone for the NLP core PR. Fixed NLP parser title cleanup for explicit date triggers and Japanese/Chinese priority phrases. (#1658) Fixed Pomodoro stats date bucketing for sessions near local midnight. Pomodoro session stats now compare the recorded session calendar date against UTC-anchored target days without shifting through UTC or the reader's current timezone. Pomodoro daily-note storage now writes sessions to the daily note matching the recorded session date. Thanks to @ewgdg for reporting, @AntonIlinykh and @dkchacha for follow-up discussion, and @ITblacksheep for PR #1758. (#1813) Fixed Pomodoro timer UI stalls caused by refreshing session statistics on every timer tick. Pomodoro stats now refresh on initial render and session completion instead of once per second. Pomodoro daily-note stats now read the relevant date/range instead of routing through all history. Native Pomodoro notifications now respect the notification setting and granted permission before showing. Thanks to @Szu-Szu for reporting and @its-thex for confirming. (#1744) Fixed Bases Task List views so changing the per-view Expanded relationships option takes effect on re-render. Restores the expected show-all behavior for setups that hide subtasks at the top level with note.projects.isEmpty(). Thanks to @minol-dev for reporting, @Glint-Eye for follow-up discussion, and @stanley-910 for PR #1792 exploring the related standalone-subtask workflow. Fixed tag clicks in task cards opening the task edit modal in addition to the tag search panel, and kept rendered tag metadata on a single row inside task cards."},{"title":"TaskNotes 4.5.3","url":"/obsidian/releases/4.5.3/","description":"TaskNotes documentation.","product":"obsidian","text":"Fixed# (#1834, #1847) Fixed empty Bases formula and custom properties showing null or undefined on TaskNotes task cards. A big thanks to @Glint-Eye and @3zra47 for reporting. (#1836) Fixed TaskNotes Bases views not refreshing task cards after status, archive, and auto-archive updates. A big thanks to @kmaustral for reporting."},{"title":"TaskNotes 4.6.0","url":"/obsidian/releases/4.6.0/","description":"TaskNotes documentation.","product":"obsidian","text":"Changed# TaskNotes now requires Obsidian 1.12.2 or later, matching the Obsidian APIs used by the plugin. Improved internal code quality by resolving lint warnings, moving static inline styles into CSS utilities, and extending sentence-case lint coverage to English localization strings, with no intended behavior changes. Fixed# Fixed TaskNotes failing to load when Obsidian opened without an active Markdown file."},{"title":"TaskNotes 4.7.0","url":"/obsidian/releases/4.7.0/","description":"TaskNotes documentation.","product":"obsidian","text":"Changed# Enabled lint checks that mirror Obsidian community plugin review findings, including dynamic code execution, Promise handling, deprecated APIs, unsafe stringification, directive comments, Node built-in imports, and explicit any usage. Clarified privacy documentation for optional integrations that make periodic background network refreshes. Cleaned up internal Obsidian and Bases compatibility adapters used by search and grouped views. (#1839, #1881) Updated default Base urgency scoring so timed tasks earlier in the day sort above later tasks with the same priority and date Thanks to @loukandr for the contribution Fixed# Fixed project autocomplete searches so non-empty + queries only return files matching the query in the basename, title, aliases, or explicitly searchable metadata rows. (#1713) Fixed all-tasks ICS export when a task uses a space-separated scheduled datetime such as 2025-08-12 18:00 Thanks to @bepolymathe for requesting this and @m4to-3pe for following up Fixed Pomodoro stats reopening immediately after a plugin reload before the Pomodoro service has finished initializing. (#1872) Fixed unarchiving moved tasks so the destination task folder processes template variables such as {{project}} before moving the file Thanks to @OXI-717 for reporting (#1870) Fixed custom user field NLP triggers with file autosuggest so selecting a wikilink suggestion stores the link in the user field instead of leaving it in the task title Thanks to @Sineapple for reporting (#1878) Fixed completed tasks still appearing as active blockers for dependent tasks Thanks to @macbikegeek for reporting (#1880) Fixed the status bar time-tracking label for task titles that contain a dash Thanks to @ubidev for reporting (#1854) Fixed modal task completion so completed tasks receive a completed date consistently Thanks to @misolex for reporting (#1124, #1838, #1881) Fixed default Base views and formulas excluding tasks scheduled or due today at a non-midnight time from day-level comparisons Thanks to @kmaustral for reporting and @loukandr for the fix Removed# Removed JavaScript webhook transform support and examples. JSON webhook transform templates remain supported."},{"title":"TaskNotes 4.7.1","url":"/obsidian/releases/4.7.1/","description":"TaskNotes documentation.","product":"obsidian","text":"Changed# Release assets are now built with GitHub artifact attestations so users and reviewers can verify the provenance of main.js, manifest.json, and styles.css."},{"title":"TaskNotes 4.7.2","url":"/obsidian/releases/4.7.2/","description":"TaskNotes documentation.","product":"obsidian","text":"Changed# Improved local lint checks so package and CSS issues reported by Obsidian's online review can be caught before submission. Cleaned up stylesheet compatibility issues reported by Obsidian's online review without changing the intended TaskNotes appearance. Improved spacing and alignment in task, timeblock, and webhook modals after the stylesheet cleanup. Reworked optional calendar and ICS subscription refresh scheduling to avoid interval-based network polling while preserving the same refresh intervals. Cleaned up additional source patterns reported by Obsidian's online review, including unsafe default object stringification and redundant external type unions. Prevented a console error when plugin listeners are cleaned up after reloads. Added a local lint check to prevent interval-based polling in files that also perform network requests."},{"title":"TaskNotes 4.8.0","url":"/obsidian/releases/4.8.0/","description":"TaskNotes documentation.","product":"obsidian","text":"Added# (#353) Added a Has Subtasks filter for task queries, so views and API clients can show only project-style tasks or direct tasks. Thanks to @mdbraber for suggesting this. (#380) Added a test-reminder button in notification settings, so reminder setup can be checked without creating a real task reminder. Thanks to @mdbraber for suggesting this. (#711, #168) Added an optional task-creation setting to open the new task note after saving, either in the current tab or a new tab. Thanks to @phortx and @23426356587 for suggesting this, and to @edward-peters and @obsilover for the follow-up. (#1041, #1800) Added copy-drag support for timeblocks: hold Ctrl, Cmd, or Alt/Option while dragging an existing timeblock to duplicate it at the new date and time. Thanks to @0-BSCode and @cweekly for suggesting this. (#1052) Added a public JavaScript API for in-vault scripts at app.plugins.plugins.tasknotes.api.parseNaturalLanguage(text), so Templater, QuickAdd, and MetaBind workflows can use TaskNotes' natural-language parser without running the HTTP API. Thanks to @edakimling for suggesting this. (#1235) Added a task-card toggle for blocked tasks, so you can expand a blocked task to see the tasks it is waiting on. Thanks to @craziedde for suggesting this. (#1254) Added ../ and ./ normalization for folder templates after variables are expanded, so instant task conversion can target sibling folders such as {{currentNotePath}}/../Tasks. Thanks to @rdick for suggesting this. (#1267) Added Daily Notes-style date tokens such as YYYY, MM, DD, MMMM, and dddd to TaskNotes folder templates. Thanks to @paulsen-it for suggesting this. (#1380) Added tag actions to task context menus, including add/remove actions for individual tasks and batch-selected tasks. Thanks to @Chuhtra for suggesting this. (#1377) Added right-click Mini Calendar actions for opening daily notes from day cells and weekly notes from week numbers. Thanks to @hasanyilmaz for suggesting this. (#1151) Added a Mini Calendar max color note count option, so one-note days can use the strongest heatmap color when that better fits the view. Thanks to @arreme for suggesting this. (#1376) Added backslash escapes for NLP trigger tokens, so text like \\@context, \\*done, or \\tomorrow can stay in the task title. Thanks to @JerryLu086 for suggesting this. (#1366) Added CSS variables for compacting nested task-card indentation, with smaller defaults on mobile and documented snippets for tighter task-link lists. Thanks to @rk-kontur for suggesting this. (#1502, #603) Added calendar indicators for external events that have linked notes or tasks, and showed loaded event titles in task-card calendar metadata instead of only the linked event count. Thanks to @Robubble and @mdbraber for suggesting this, and to @ubidev for the follow-up. (#1522) Added a per-status option to skip rarely used statuses when cycling task-card status indicators. Thanks to @Glint-Eye for suggesting this. (#144) Added an \"Open note in new tab\" action to the task context menu. Thanks to @cathywu for suggesting this and @macbikegeek for the follow-up feedback. (#167) Added an optional next-status override for each status, so forward cycling can jump to a configured status instead of always following the status order. Thanks to @DanBrazelton for suggesting this, and to @michelebugio, @Moyf, @anareaty, and @vorrermid for the follow-up feedback. (#1520) Made tag and context fields show available suggestions as soon as the field is focused. Thanks to @Glint-Eye for suggesting this, and to @craziedde for the follow-up. (#1541) Added {{currentNotePath}} and {{currentNoteTitle}} support to the default tasks folder, so normal task creation can place new tasks beside the active note without creating an inline link. Thanks to @ChristianAnyanwu for suggesting this, and to @abbasou and @ttlaylor for the follow-up feedback. (#648, #1605) Added clickable links in task-card contexts for note links, markdown links, and web URLs while keeping plain contexts as tag-search buttons. Thanks to @trdischat and @Glint-Eye for suggesting this, and to @renatomen for the follow-up feedback. (#1482) Added clickable custom-field links on task cards for wikilinks, markdown links, autolinks, and bare web URLs. Thanks to @ptbosch-figueiredorj for suggesting this, and to @Soleone for the follow-up use case. (#1471) Added Kanban column and swimlane-cell add buttons that open the TaskNotes creation modal with the grouped values already filled in. Thanks to @byheaven for suggesting this and @Davincible for the project-board use case. (#933) Added non-Markdown vault files such as canvases to project suggestions, using extension-qualified link targets so those files can be selected as task projects. Thanks to @Alvin21Bon for suggesting this. (#1475, #725) Added quote/backtick escapes for NLP input, so literal course codes or date words can stay in task titles without being parsed as estimates or dates. Thanks to @RumiaKitinari and @gavingwebb for suggesting this. (#1462) Added natural-language date entry to the task date picker, so existing due and scheduled dates can be changed with phrases such as \"tomorrow at 3pm\" when NLP is enabled. Thanks to @Ruboks-Cube for suggesting this. (#1526) Added a native date field to the task date picker, so scheduled and due dates can be changed with the device date picker while keeping optional times visible. Thanks to @jmartinmcfly for suggesting this and @23426356587 for the follow-up feedback. (#1603) Added Calendar view toggles for hiding completed or skipped recurring task instances while keeping future outstanding instances visible. Thanks to @wandererovertheseaofpiss for suggesting this. (#287, #273, #274) Added linked hover highlighting for Calendar and Agenda events that come from the same task note, so scheduled, due, and recurring entries are easier to connect. Thanks to @girisumit for suggesting this. (#280) Added project-specific CSS hooks to task cards and Calendar events, so project-based visual styling can be handled with user snippets. Thanks to @girisumit for suggesting this. (#1625) Added Shift + Cmd/Ctrl + Enter in the Create Task modal to save the current task and reopen the modal for the next one. Thanks to @tcb678 for suggesting this. (#1353) Focused the Create Task modal's natural-language input when the modal opens, with a longer mobile delay so the keyboard can open after layout. Thanks to @GiovanH for suggesting this. (#1664) Added project-based custom filename template variables, including the first project, all projects, and a short projectId. Thanks to @bendavis987 for the contribution. (#923) Added {{projectFilePath}} and {{projectFilePaths}} folder template variables, so task folders can mirror project note locations in the vault. Thanks to @PacoTaco2 for suggesting this. (#1697) Added cached Google Calendar, Microsoft Calendar, and ICS events to Mini Calendar days, with compact colored dots and event details from the existing calendar connection. Thanks to @RPGArchivist for suggesting this. (#1754) Added optional icons for priority values, so task cards can show a configured priority icon instead of only a colored dot. Thanks to @BrucePlumb for suggesting this and @prepare4robots for the follow-up feedback. (#1761) Added TaskNotes edit and task-action submenu entries to Obsidian's native file context menu for recognized task notes. Thanks to @delzero for suggesting this. (#1771) Added mobile drag handles to manually sorted Task List Bases views, so dragging can start from the handle without disabling normal text interaction on the rest of the card. Thanks to @PatrickGolz for suggesting this. (#1776) Allowed calendar timeline end times after midnight, such as 26:00 for a 2 AM next-day end. Thanks to @chrabia for suggesting this. (#1784, #1833) Added a per-view pinnedColumns option for TaskNotes Kanban views, so selected empty columns can stay visible as drop targets while other empty columns remain hidden. Thanks to @loukandr for suggesting and prototyping this. (#1794) Added context updates to the task card context menu, so contexts can be added, toggled, or cleared without opening the task edit modal. Thanks to @m13ntrpn for suggesting this. (#315, #1356, #1748, #1809) Added a subtle task-card indicator and CSS hooks for tasks with note body details, including existing task bodies read through Obsidian's metadata cache. Thanks to @volodxyz, @Karut, @yeHHH1g, and @aliceinwaterdeep for suggesting this, and to @minchinweb for the follow-up. (#1808) Added advanced Kanban swimlane ordering through swimLaneOrder, so swimlane rows can stay in a stable configured order. Thanks to @rookledookle for suggesting this, and to @benmartinek and @chrabia for the follow-up feedback. (#1805) Added an ICS export option to omit completed tasks from generated calendar files. Thanks to @bepolymathe for suggesting this. (#659) Added Obsidian links to ICS export descriptions, so exported calendar events can open their source task notes. Thanks to @bepolymathe for suggesting this. (#589) Added an Appearance toggle to turn off strikethrough styling on completed task card titles. Thanks to @BrucePlumb for suggesting this. (#561) Added a \"Last day\" option to the custom recurrence month-day picker for month-end repeating tasks. Thanks to @TonyAtlas for suggesting this and @BrucePlumb for the follow-up. (#217) Added weekday selection to daily custom recurrence rules, so interval rules such as every three days can skip weekends from the recurrence modal. Thanks to @kmaustral for suggesting this. (#1818) Added an auto-height mode for TaskNotes Calendar Bases views so embedded agenda/list sections can size to their content instead of forcing an inner scroller. Thanks to @martin-forge for suggesting this. (#1201) Added a Calendar Bases toggle to hide the hourly breakdown in week, custom-days, and day views while keeping the all-day planning row visible. Thanks to @PacoTaco2 for suggesting this. (#1176) Added advanced Kanban WIP limits through wipLimits, so column headers can show (current/limit) counts and highlight exceeded limits. Thanks to @williamcheuk03 for suggesting this. (#914) Added a generated Due in countdown to the default Agenda Base and allowed Calendar Bases list agendas to span up to 365 days. Thanks to @williamcheuk03 for suggesting this. (#900) Added an instant-conversion setting to keep the original Markdown checkbox marker when converting a checkbox into a TaskNote link. Thanks to @dsebastien for suggesting this. (#898) Added a mobile-only calendar integration opt-out, so synced desktop calendar settings no longer have to trigger external calendar loading on Obsidian Mobile. Thanks to @cathywu for suggesting this. (#887) Added built-in scheduled and due date presets to the Quick actions palette for current tasks. Thanks to @willgraham345 for suggesting this and @anrie for the related preset feedback. (#819) Added a command to open Quick actions for the inline task link under the cursor. Thanks to @rlolingo for suggesting this. (#798, #1732, #1835) Added hotkeyable commands to edit the current task, add a project to the current task, and add an existing task as a subtask of the current note. Thanks to @xorander00 and @prepare4robots for requesting this, and to @musta-code and @ubidev for the follow-up suggestions. (#791) Added a UUID v4 task filename format and {{uuid}} custom filename template variable. Thanks to @bangbangbanggit for suggesting this. (#932) Added hotkeyable commands to cycle the current task's status and priority. Thanks to @rxunique for suggesting this and @luckb0x for the follow-up feedback. (#1655) Added live elapsed time to the optional active time tracking status bar item. Thanks to @connradolisboa for suggesting this. (#1622) Allowed multiple comma-separated default reminder offsets for timed Google Calendar task exports. Thanks to @solidabstract for suggesting this. (#706, #820, #1040) Added direct Pomodoro duration editing, hour-aware timer formatting, clearer one-minute controls, and an optional active Pomodoro status bar countdown. Thanks to @SublunarSage, @lj1446615403-cloud, @0-BSCode, and @thestrike72 for the suggestions and feedback. (#873) Added an optional built-in sound for task reminder notifications, with volume and preview controls in Settings. Thanks to @berzernberg for suggesting this. Added a generated Pomodoro statistics Base with daily and monthly summary views for Pomodoro history stored in daily notes. Changed# Expanded the bug report template to ask for Obsidian \"Show debug info\" output, affected task frontmatter, relevant Bases file contents, reproduction steps, and related logs or screenshots. Release notes now show the default .base file regeneration reminder only on the current version section, keeping older bundled sections focused on their own changes. Updated the release notes GitHub prompt to invite feedback while still asking satisfied users to star the project. (#239) Ordered Kanban status and priority columns by the configured status order and priority weights when no manual column order is saved. Thanks to @ScumbagScalawag for asking about this, and to @nightroman, @lavir, and @elvarb for the follow-up discussion. (#269) Marked Kanban status columns that come from values outside the configured TaskNotes statuses, so manually edited or external status values are visible as non-standard instead of blending into the board. Thanks to @cstelmach for suggesting this and @digitaldoctors for the follow-up. Refined Kanban empty columns, swimlane rows, and column drag handles, and added a per-view compact card layout option for denser boards. Kept Kanban swimlane rows from shrinking to share the viewport so the Max Swimlane Height setting is respected. Added guidance in Pomodoro statistics and Base file settings explaining that Pomodoro Base views require daily notes storage. (#323) Reordered task modal action buttons to match the right-click task menu order. Thanks to @23426356587 for suggesting this. (#1189) Made the Create/Edit Task modal priority picker follow the priority order configured in Settings. Thanks to @n1njaznutz for suggesting this. Made task-card priority dots and configured priority icons slightly larger for better visibility. (#1244) Clarified the Task Properties documentation for custom property keys and status values in Bases filters and sorting. Thanks to @Arachnidai for suggesting this. (#1234) Kept right-aligned subtask chevrons visible on task cards instead of only showing them on hover. Thanks to @n1njaznutz for suggesting this. (#1237) Made today's date more visible in the Mini Calendar view when another day is selected. Thanks to @riekusr for suggesting this. (#1348) Let long task titles wrap inside the Create/Edit Task modal title field while keeping saved titles single-line, and widened the contexts and tags fields in the modal details area. Thanks to @hasanyilmaz for suggesting this. (#1392) Made TaskNotes date fields accept compact YYYYMMDD typing and pasted dates. Thanks to @kazerniel for suggesting this. (#1431) Showed the year on task-card due and scheduled dates when the date is outside the current year. Thanks to @kazerniel for suggesting this. (#1429) Opened TaskNotes view commands in a new tab when they load configured Base files, so they do not replace the active note. Thanks to @Ruboks-Cube for suggesting this. (#1426) Added copy actions for TaskNotes Bases views, including current-view filenames, links, and titles from the result count menu, plus selected-task copy actions in the batch menu, while keeping the native Bases copy and CSV export actions available. Thanks to @kmaustral for suggesting this. Improved keyboard access, mobile layout, and theme color consistency across task cards, TaskNotes Kanban, Bases Kanban, calendar controls, stats, settings, and filter popovers. (#1526) Made the Create/Edit Task modal due and scheduled date buttons open a calendar-first "},{"title":"TaskNotes 4.8.1","url":"/obsidian/releases/4.8.1/","description":"TaskNotes documentation.","product":"obsidian","text":"Fixed# (#1903) Improved the Edit Task modal on iPhone-sized screens so opening a task no longer automatically focuses the title field, and the mobile layout gives the title, fields, and action buttons more usable space. Thanks to @3zra47 for reporting the issue and sharing the screen recording. (#1909) Fixed compact Kanban task cards showing oversized status and priority indicators on touch devices. Thanks to @pxxush for reporting the issue. (#1908) Restored newly generated Calendar Bases to show the full day by default and inherit the calendar start/end settings instead of hard-coding 06:00-22:00. Thanks to @AndreMonthy for the report. (#1907) Fixed calendar time labels drifting away from the left axis in narrow sidebar calendar views. Thanks to @kmaustral for reporting the issue. (#1906) Fixed NLP priority shortcuts leaving partial text in task titles when custom priority values include words like high or low. Thanks to @RumiaKitinari for reporting the issue. (#1904, #1905) Fixed long tags in task cards wrapping instead of forcing horizontal scrolling in TaskNotes Bases views and note cards. Long tag pills can now wrap across lines and break within very long tag names on narrow screens. Thanks to @3zra47 for reporting the issue and to @zhouzhou626 for the contribution. (#1901) Fixed the task context menu creating an undefined property when adding or removing tags. Hardened task property updates so invalid frontmatter property names are rejected instead of written. Thanks to @mgrecar for reporting the issue. (#1902) Fixed Markdown-style project links in task frontmatter not appearing as subtasks on project pages. Thanks to @minchinweb for reporting the issue. Changed# Improved the internal structure around service notifications, vault writes, and shared utilities to make future fixes easier to test and maintain."},{"title":"TaskNotes 4.9.0","url":"/obsidian/releases/4.9.0/","description":"TaskNotes documentation.","product":"obsidian","text":"Security# (#1923) Restricted the HTTP API server to loopback and limited browser CORS access to loopback origins. Thanks to @martin-forge for reporting. Added# (#1932) Added middle-click support for opening task cards in a new tab. Thanks to @imsuck for the request. Fixed# (#1934) Fixed custom priority colors being overridden by default task-card priority styles in views. Thanks to @KittehBit for reporting. (#1933) Added the note path to fallback frontmatter parse warnings so malformed task YAML is easier to find. Thanks to @rayvermey for reporting. (#1931) Made the Pomodoro task chooser open from cached task data and ignore repeated clicks while it is already opening. Thanks to @sumiyalairu03 for reporting. (#1930) Fixed starting the Pomodoro timer from its hotkey without starting time tracking for the selected Pomodoro task. Thanks to @sumiyalairu03 for reporting. (#1929) Fixed the bottom Relationships widget overlapping embedded content such as Bases/Kanban views in task notes. Thanks to @rchaklashiya for reporting and following up with the embed case. (#1922) Restored the native color picker alongside manual color text entry in Create/Edit Timeblock fields. Thanks to @AndreMonthy for reporting. (#1921) Fixed direct frontmatter edits to lifecycle-relevant task fields not triggering Google Calendar sync or auto-archive side effects. Thanks to @martin-forge for reporting and verifying the direct-edit reproduction. (#1919) Fixed the Pomodoro view rapidly resizing at certain sidebar sizes. Thanks to @RumiaKitinari for reporting. (#1898, #1907) Fixed Calendar time labels shifting into the middle of Day and sidebar calendar grids after switching views. Thanks to @ddevaal for reporting and confirming the regression, and to @kmaustral for confirming the sidebar case in 4.8.1. (#1936) Added a Calendar Base drag/drop resolution option so events can snap to smaller increments than the visible time slot grid. Thanks to @benmartinek for suggesting this. Improved mobile task cards, inline widgets, modals, and settings layouts so dense controls and long labels fit more comfortably on small screens. (#1916) Fixed Markdown task links using Obsidian's generated filename label instead of the TaskNote title in the task link overlay. Thanks to @minchinweb for reporting. (#1911) Fixed recurrence choices starting from today instead of the selected calendar date when creating a task from Calendar view. Thanks to @mikhailmarka for reporting. (#1912) Fixed \"Create subtask\" pre-filling the parent task's full folder path in the Projects field instead of using the normal Obsidian link text. Thanks to @pkuehne for reporting and @benmartinek for confirming."},{"title":"TaskNotes 4.9.1","url":"/obsidian/releases/4.9.1/","description":"TaskNotes documentation.","product":"obsidian","text":"Added# (#1885) Added Shift+arrow keyboard range selection while bulk task selection mode is active. Thanks to @chrabia for suggesting bulk selection improvements and @sumiyalairu03 for the keyboard selection idea. Fixed# (#781, #1085) Fixed Outlook-published ICS calendar events appearing at the wrong time when their feed used Windows timezone names without matching timezone definitions. Thanks to @chrlaney for reporting and @mjkrasny for confirming the Outlook timezone case. (#1696) Fixed Google Calendar export for scheduled recurring tasks when a single occurrence is moved to a different date. Keeps the recurring master event on its original rule, excludes the original occurrence date, and syncs the moved occurrence as a detached event. Thanks to @martin-forge for reporting and contributing the fix. (#1912) Fixed \"Create subtask\" inserting the full path of the parent task in the Projects field instead of using the normal Obsidian link text. Thanks to @pkuehne for reporting and @benmartinek for confirming. (#1921) Fixed Google Calendar and auto-archive updates not running after direct task file edits. TaskNotes now picks up status, completion, and date changes made directly in a task file without triggering a large one-time Google Calendar rewrite at startup. Recovery also removes stale Google Calendar links when task files were deleted or replaced outside TaskNotes. Thanks to @martin-forge for reporting and contributing the fix. (#1938) Fixed partial HTTP API task updates rewriting native tags with # prefixes or duplicate task tags. Thanks to @joseluisgonzalezdelgado-ctrl for reporting. (#1939) Fixed the task Details field rendering as a small nested textarea when the embedded editor falls back. Thanks to @g-arthurvanderbilt for reporting and @cookbr for confirming the desktop impact. Fixed tag and modal preview edge cases found during validation: double-hash tags no longer match the task tag, empty tag lists stay empty when read back, and natural-language previews remain visible when enabled. (#1941) Fixed mobile Kanban boards scrolling the whole board vertically instead of keeping each list independently scrollable. Thanks to @pxxush for reporting. (#1943) Fixed MCP task-query tool instructions so filter operators match the operators TaskNotes actually accepts. Thanks to @jordankbartos for reporting and proposing a fix in #1944. (#1945) Fixed Google Calendar export so overlapping sync services do not create duplicate events for the same task while the saved event ID is still catching up. Thanks to @martin-forge for reporting and contributing the fix. (#1946) Fixed the bottom task in virtualized Task List Bases being partially hidden behind Obsidian's mobile bottom bar. Thanks to @3zra47 for reporting. (#1947) Fixed mobile Task List cards with left-positioned subtask chevrons so the chevron remains visible and project/detail badges stay on the main row. Thanks to @Jomo94 for reporting. (#1948) Fixed Agenda Calendar Bases so completed recurring instances can appear on their recorded completion dates, even when recurring task projections are hidden or the completion date is outside the recurrence pattern. Thanks to @Jomo94 for reporting."},{"title":"TaskNotes 4.9.2","url":"/obsidian/releases/4.9.2/","description":"TaskNotes documentation.","product":"obsidian","text":"Added# (#1791) Added collapse and expand controls for grouped Bases Task List views, including a default collapsed state option. Thanks to @renatomen for the contribution. Fixed# Fixed Pomodoro storage migration so existing plugin-data history is written to daily notes before switching storage, and clarified that daily notes can come from either the core Daily Notes plugin or Periodic Notes. (#1964) Fixed Microsoft Calendar OAuth so connecting no longer forces a fresh consent prompt every time, and clarified the Microsoft desktop app setup steps. Thanks to @thechonta for reporting. (#1966) Fixed custom priority icons so they render as icons instead of filled squares on task cards. Thanks to @sruiz-savia for reporting. (#1963) Fixed Google Calendar sync so duplicate event ID fields are repaired when saving task calendar metadata. Thanks to @christenbc for reporting. (#1961) Fixed the default custom filename template so it uses the recommended double-brace syntax and no longer warns on first use. Thanks to @chmac for reporting. (#1962) Fixed task tag normalization so tags entered with spaces are saved with hyphens for Obsidian tag compatibility. Thanks to @christenbc for reporting. (#1959) Fixed the MCP tasknotes_list_tasks tool so circular internal task data and live Obsidian object references no longer break task-list responses. Thanks to @kmaustral for reporting. (#1957) Fixed the Pomodoro timer layout in vertically split panes so the timer header and progress circle remain reachable when the pane is short. Thanks to @sumiyalairu03 for reporting. (#1956) Fixed Google Calendar sync so completing a recurring task updates the linked event title with the completion checkmark. Thanks to @jacksoluke for reporting. (#1953) Fixed inline task conversion so source-line wikilinks no longer create nested wikilinks in the replacement link text. Thanks to @bgk0018 for reporting. (#1952) Fixed Pomodoro task picker search results so matching task titles are ranked and sorted ahead of due-date ordering. Thanks to @KFrancoD for reporting. (#1392, #1949) Fixed due and scheduled date picker fields so typed or pasted date edits stay open until you choose Select, including compact YYYYMMDD entry when a date is already set. Thanks to @kazerniel for reporting and following up. (#982, #1947) Restored larger mobile task-card typography and let secondary card icons wrap below the task details when they no longer fit comfortably on mobile. Thanks to @3zra47 for reporting the font-size regression, @chrsdk and @scottaltham-payroc for confirming the mobile font-size issue, and @Jomo94 for reporting the mobile card layout problem."},{"title":"TaskNotes - Unreleased","url":"/obsidian/releases/unreleased/","description":"TaskNotes documentation.","product":"obsidian","text":""},{"title":"Settings","url":"/obsidian/settings/","description":"TaskNotes settings are organized into tabs. Each tab controls a different part of plugin behavior.","product":"obsidian","text":"TaskNotes settings are organized into tabs. Each tab controls a different part of plugin behavior. General# The General tab controls task identification, storage locations, and task-card click behavior. Use this tab when your vault already has conventions such as custom tags, property-based identification, or specific folder structures. For more information, see the General Settings documentation. Task Properties# Task Properties defines the schema TaskNotes writes to frontmatter, including status, priority, dates, reminders, projects, and user fields. Each property card lets you remap key names and behavior so TaskNotes can match existing metadata rather than forcing a migration. For more detailed information, see the Task Properties Settings documentation. Modal Fields# Modal Fields controls the task create/edit experience by deciding which fields are visible and in what order. If your workflow depends on a handful of fields, you can surface only those and reduce form noise. For more information, see the Modal Fields Settings documentation. Appearance & UI# Appearance & UI handles task card density, calendar defaults, time formatting, and visual toggles for supporting widgets. Use this tab to tune how much information is visible at a glance. For more detailed information, see the Appearance & UI Settings documentation. Features# Features groups behavior toggles for inline tasks, natural language input, Pomodoro, reminders, and performance-related options. It is where you enable advanced workflow capabilities and then refine defaults. For more information, see the Features Settings documentation. Integrations# Integrations covers external connectivity: Bases view wiring, Google/Microsoft OAuth calendar sync, ICS subscriptions, automatic ICS export, HTTP API settings, and webhook endpoints. For more detailed information, see the Integrations Settings documentation."},{"title":"Appearance & UI Settings","url":"/obsidian/settings/appearance/","description":"These settings control the visual appearance of the plugin, including the calendar, task cards, and other UI elements.","product":"obsidian","text":"These settings control the visual appearance of the plugin, including the calendar, task cards, and other UI elements. Task Cards# Use Default visible properties to decide what metadata appears on task cards without opening each task. This is the primary control for card density. Checklist progress is available as a visible property in task cards. In Bases view order arrays, the corresponding source property is file.tasks (shown as tasks in Bases property pickers once present in the view order list). Nested task cards use CSS variables for their indentation. Add a CSS snippet if you want a denser hierarchy than the default: .tasknotes-plugin { --tn-nested-task-indent: 12px; --tn-nested-task-padding: 8px; } body.is-mobile .tasknotes-plugin { --tn-nested-task-indent: 8px; --tn-nested-task-padding: 6px; } If task links inside normal markdown lists feel visually doubled with both a list marker and the task status indicator, a CSS snippet can hide those markers for task-link lines: .markdown-reading-view li:has(.task-inline-preview--reading-mode)::marker { content: \"\"; } .markdown-source-view.mod-cm6 .cm-line:has(.tasknotes-inline-widget) .cm-formatting-list { display: none; } Display Formatting# Use Time format to switch between 12-hour and 24-hour display across all TaskNotes surfaces. Calendar View# Calendar view settings determine the default landing mode, day/week framing, and timeline affordances. You can choose the default view, custom day span, first day of week, weekend visibility, week numbers, and whether today/current-time markers are shown. Selection mirror controls whether drag selections show a visual preview before committing. Use Calendar locale for region-specific formatting and calendar systems (for example en, de, or fa). Leave it empty to use automatic detection. Default Event Visibility# This section controls which event layers are enabled when a calendar view opens. You can independently toggle scheduled tasks, due dates, due dates for already-scheduled tasks, time entries, recurring tasks, and ICS events. Time Settings# Time settings define the structure of timeline views: slot duration, earliest visible time, latest visible time, and initial scroll position. Use these together to match your workday shape. UI Elements# UI element toggles control auxiliary surfaces such as the tracked-task status bar entry, the project subtasks widget and its placement, expandable subtasks in cards, chevron position, and the alignment of the views/filters button. Related Settings# Some appearance-related settings are configured elsewhere: Task filename format: Configured in Task Properties → Title card Project autosuggest display: Configured in Task Properties → Projects card"},{"title":"Features Settings","url":"/obsidian/settings/features/","description":"These settings allow you to enable, disable, and configure the various features of the plugin, such as inline tasks, natural language processing, the Pomodoro timer, and notific...","product":"obsidian","text":"These settings allow you to enable, disable, and configure the various features of the plugin, such as inline tasks, natural language processing, the Pomodoro timer, and notifications. Inline Tasks# Inline task settings control how aggressively TaskNotes turns plain note content into structured task interactions. Task link overlay enables the Live Preview card behavior for task links, while Instant task convert surfaces conversion buttons next to list items and checkboxes. Keep checkbox when converting leaves the original Markdown checkbox marker in the source note when a checkbox becomes a TaskNote link. For conversion output, Inline task convert folder sets destination behavior and supports {{currentNotePath}}, and Use task defaults on instant convert applies your default task values at conversion time. The separate Convert current note to task command keeps the current note body as the task details. If the note has no scheduled frontmatter, the command uses the Scheduled Date default from Task Properties; it does not apply body templates. Body Template# Body template settings let you scaffold newly created tasks with consistent note content. When enabled, TaskNotes reads the configured template file and expands variables like {{title}}, {{date}}, {{time}}, {{priority}}, {{status}}, {{contexts}}, {{tags}}, and {{projects}}. Materialized occurrence notes can use a separate template. Set Occurrence note template file to provide a global fallback for occurrence notes; a recurring task's occurrence_template frontmatter field takes priority when it is set. If neither occurrence-specific template is configured, occurrence notes continue through the normal body template behavior. Natural Language Processing# NLP settings define how text input is interpreted during task capture. Enable natural language task input activates date and metadata parsing, Default to scheduled changes ambiguous date handling, NLP language selects parsing patterns, and Status suggestion trigger controls optional status autocomplete activation. Wrap text in double quotes, single quotes, or backticks to keep it as literal title text during NLP parsing. For example, BIO \"123H\" - HW1 keeps 123H in the title instead of treating it as a 123-hour estimate, while Review \"Today\" notes keeps Today as text instead of parsing it as a date. Pomodoro Timer# Pomodoro settings control interval lengths, long-break cadence, optional auto-start behavior, and end-of-session notifications/sound. Pomodoro data storage chooses whether history is kept in plugin data or daily notes. Notifications# Use this section to enable reminders globally, choose whether notices are shown in-app or through system notifications, and optionally play a built-in reminder sound with its own volume control. Performance & Behavior# Performance and behavior toggles let you refine overhead and interaction feel: exclude completed tasks from overdue calculations, disable indexing for very large vaults, and tune suggestion debounce timing. Time Tracking# Time tracking options handle completion behavior. You can automatically stop running timers when a task is completed and optionally show a confirmation notification. Recurring Tasks# Use Maintain due date offset in recurring tasks to keep due/scheduled spacing consistent when recurring tasks roll forward. Occurrence note behavior is configured per recurring task from the task context menu: open Recurrence → Occurrence notes to choose manual creation or automatic creation of the next materialized occurrence after completion. See Recurring Tasks for the workflow and storage model. Timeblocking# Timeblocking enables lightweight daily-note scheduling blocks and controls whether those blocks are visible by default in calendar views. Usage# In the calendar view, click and drag on a time slot to select a time range. A context menu will appear—select \"Create timeblock\" to create a timeblock (this option only appears if timeblocking is enabled in settings). Drag existing timeblocks to move them. Resize edges to adjust duration."},{"title":"General Settings","url":"/obsidian/settings/general/","description":"These settings control the foundational aspects of the plugin, such as task identification, file storage, and click behavior.","product":"obsidian","text":"These settings control the foundational aspects of the plugin, such as task identification, file storage, and click behavior. Task Storage# Task storage settings define where new and inline-created task files are created and how archived tasks are relocated. Default tasks folder sets the base location and supports folder template variables, including {{currentNotePath}} and {{currentNoteTitle}} for creating command-palette or ribbon tasks beside the active note. It also supports date variables such as {{year}} and Daily Notes-style date tokens such as YYYY/MM/DD. Folder for inline-created tasks controls the Create Inline Task command and instant conversion output. Leave it empty to use the default tasks folder, set a fixed folder path to centralize inline tasks, or use {{currentNotePath}} and {{currentNoteTitle}} placeholders for contextual routing. Relative path segments such as ../ are normalized after variables are expanded. If archive moves are enabled, completed archived tasks are moved automatically to your configured archive folder. Task Identification# TaskNotes can identify task notes using either a tag or a frontmatter property. Use Identify tasks by to select a strategy. Tag mode uses a configured task tag (for example task) and can optionally hide that identifying tag in card displays. Property mode matches a property/value pair (for example isTask: true or category: task) and is useful when you avoid tag-based identification. If you change the task tag after creating default Base views, existing .base filters will still point at the old tag until you update the default Base files or edit those filters. Hide Identification Tags# When using tag-based identification, you may want to keep your task identification tags in the frontmatter for organizational purposes, but hide them from the visual display in task cards to reduce clutter. The Hide identification tags in task cards setting allows you to do this. When enabled: Tags that exactly match your task identification tag (e.g., #task) will be hidden Hierarchical child tags (e.g., #task/project, #task/work/urgent) will also be hidden Other tags that don't match the identification pattern will still be displayed The setting only affects the visual display—tags remain in the frontmatter Example: If your task identification tag is task and a task has the tags #task, #task/project, #important, and #review: With the setting disabled (default): All tags are shown: #task, #task/project, #important, #review With the setting enabled: Only non-identifying tags are shown: #important, #review Folder Management# Use Excluded folders to omit paths from Notes tab indexing and keep large archive areas out of regular task browsing. Views & Base Files# TaskNotes uses Obsidian Bases files (.base) to power its task views. By default, missing view files are created automatically on startup. Use Create files to generate missing default files in TaskNotes/Views/ without overwriting existing files. Use Update files to overwrite the configured default files with templates generated from your current TaskNotes settings. Frontmatter# This section only appears when you have markdown links enabled globally in Obsidian settings. Use markdown links in frontmatter switches project/dependency serialization from wikilinks ([[path]]) to markdown links ([text](path)). This requires the obsidian-frontmatter-markdown-links plugin. Task Interaction# Task interaction settings define default click behavior on task cards. You can independently choose single-click and double-click actions (edit task, open note, or no action for double click). Release Notes# View release notes opens the release notes view for the current version. Notes also open automatically after updates and remain available from the command palette."},{"title":"Integrations Settings","url":"/obsidian/settings/integrations/","description":"These settings control the integration with other plugins and services, such as Bases and external calendars.","product":"obsidian","text":"These settings control the integration with other plugins and services, such as Bases and external calendars. Bases# TaskNotes v4 uses Obsidian's Bases core plugin for its main views. For setup instructions, see Core Concepts. View Commands Configuration# View command settings map TaskNotes commands and ribbon actions to specific .base files. This is useful when you maintain custom variants of the default views and want first-class command access to those files. Access these settings in Settings → TaskNotes → General → Views & base files. Default mappings: Open Mini Calendar View → TaskNotes/Views/mini-calendar-default.base Open Kanban View → TaskNotes/Views/kanban-default.base Open Tasks View → TaskNotes/Views/tasks-default.base Open Calendar View → TaskNotes/Views/calendar-default.base Open Agenda View → TaskNotes/Views/agenda-default.base Pomodoro Statistics Base → TaskNotes/Views/pomodoro-stats.base Relationships Widget → TaskNotes/Views/relationships.base Each command allows you to specify a custom .base file path and includes a reset button to restore the default path. Auto-create default files: When enabled, TaskNotes creates missing default .base files automatically on startup. Create files: Button to generate all default .base files in the TaskNotes/Views/ directory. Existing files are not overwritten. The generated Pomodoro statistics Base reads Pomodoro sessions from daily notes frontmatter. If your Pomodoro history is still stored in plugin data, migrate it from Settings → TaskNotes → Features before using that Base file. OAuth Calendar Integration# Connect Google Calendar or Microsoft Outlook to sync events bidirectionally with TaskNotes. Events automatically refresh every 15 minutes and sync when local changes are made (such as dragging events to reschedule). Enable Disable calendar integrations on mobile when you sync TaskNotes settings between desktop and mobile but do not want Obsidian Mobile to load external calendars on startup. The setting only affects mobile devices; desktop calendar integrations continue to run normally. Setup Requirements# OAuth integration requires creating your own OAuth application with Google and/or Microsoft. Initial setup takes approximately 15 minutes per provider. Setup Guide: See Calendar Integration Setup for detailed instructions on creating OAuth credentials with Google Cloud Console and Azure Portal. Google Calendar# Provide Client ID and Client Secret from Google Cloud Console, then use Connect Google Calendar to complete OAuth loopback authentication. Disconnect revokes account tokens while retaining the OAuth app credentials for reconnection. Use Forget saved credentials to remove the client ID and client secret. The Target calendar setting used for exporting tasks to Google Calendar is also used as the default selection when creating a manual external calendar event from the calendar view. If the target calendar is unavailable, TaskNotes falls back to the provider's primary calendar. For timed task exports, Default reminder accepts one or more minute offsets separated by commas, such as 60, 1440. All-day task exports use the target Google Calendar's default reminder settings. When connected, displays: Connected account email Connection time Last sync time Manual refresh button Microsoft Outlook Calendar# Provide Client ID and Client Secret from Azure App Registration, then use Connect Microsoft Calendar to authenticate. Disconnect revokes account tokens while retaining the OAuth app credentials for reconnection. Use Forget saved credentials to remove the client ID and client secret. When connected, displays: Connected account email Connection time Last sync time Security# OAuth client credentials and account tokens are stored in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system OAuth credentials and account tokens are not written to TaskNotes' data.json Access tokens refresh automatically Calendar data syncs directly between Obsidian and the calendar provider (no intermediary servers) Disconnect at any time to revoke account access; use Forget saved credentials to remove the OAuth app credentials Calendar subscriptions (ICS)# ICS settings define how subscribed calendar events are represented in your vault. You can set a default template, destination folder, filename strategy, and custom filename template for generated notes. Use Add Calendar Subscription to register URLs or local files, and Refresh all subscriptions for manual synchronization. Recurring event related notes controls how notes linked from recurring external calendar events are matched. Series-wide keeps the current behavior: a note linked to one loaded recurrence can appear on the other loaded recurrences from the same Google, Microsoft, or ICS event series. Selected instance only limits related notes and counts to the exact recurrence instance that was linked. Automatic ICS export# Automatic export keeps an ICS feed of your tasks updated on a schedule. Configure whether it is enabled, where the file is written (vault-relative path), the refresh interval, and use Export now for immediate output. Export filters can omit archived tasks, completed tasks, tasks without due dates, or tasks without scheduled dates. When both due-date and scheduled-date requirements are enabled, exported tasks must have both dates. HTTP API# HTTP API settings control the local server lifecycle, listening port, and request authentication token. Changes to API enablement or port require an Obsidian restart to take effect. WarningThe HTTP API binds to loopback only and browser CORS is limited to loopback origins. If the authentication token is empty, local API requests are still unauthenticated. Set a token unless your local environment is fully trusted. Webhooks# Add Webhook: Register a new webhook endpoint."},{"title":"Modal Fields Settings","url":"/obsidian/settings/modal-fields/","description":"The Modal Fields tab lets you decide exactly which fields appear in the task creation and edit modals. Open Settings → TaskNotes → Modal Fields to manage the configuration.","product":"obsidian","text":"The Modal Fields tab lets you decide exactly which fields appear in the task creation and edit modals. Open Settings → TaskNotes → Modal Fields to manage the configuration. Field Groups# Fields are organized into draggable groups: Basic Information – Title and Details Metadata – Contexts, Tags, Time Estimate Organization – Projects and Subtasks Dependencies – Blocked By and Blocking Custom Fields – Any user-defined fields that you add through Task Properties Each group can be collapsed, and their order in the manager matches the order shown in the modal. Managing Fields# Every field entry includes: Visibility toggles for creation and edit modals Enable/disable checkbox Drag handle for ordering within its group Required toggle (where applicable, e.g., Title) Changes are saved automatically. Use this to hide fields you never touch, ensure required metadata appears up front, or reorder fields to match your workflow. Syncing User Fields# The Sync User Fields button pulls the latest user-defined fields from the Task Properties tab into the Custom Fields group. New user fields are appended, renamed fields update in place, and removed fields drop out of the configuration. Re-run the sync whenever you add or rename custom fields. Resetting to Defaults# Select Reset to Defaults to restore the stock configuration (all built-in fields enabled plus empty custom slots). The reset keeps your existing user field definitions; it only reverts modal layout and visibility."},{"title":"Property-based Task Identification","url":"/obsidian/settings/property-identification/","description":"When you choose to identify task files by a frontmatter property (instead of a tag), TaskNotes will match notes whose frontmatter property equals the configured value.","product":"obsidian","text":"When you choose to identify task files by a frontmatter property (instead of a tag), TaskNotes will match notes whose frontmatter property equals the configured value. Boolean values# Enter the setting value as true or false (without quotes) in the settings UI. Obsidian stores checkbox properties as real booleans, not strings. The plugin compares booleans correctly: \"true\" in settings matches frontmatter boolean true \"false\" in settings matches frontmatter boolean false Arrays are supported (e.g., property: [false, true]) Tip: You don’t need to quote boolean values in frontmatter. Use plain true/false to keep Obsidian’s property types consistent. Examples# Setting: Property Name = isTask, Property Value = true Matches: isTask: true Does not match: isTask: false Setting: Property Name = isTask, Property Value = false Matches: isTask: false Does not match: isTask: true For related configuration details, see Task Properties."},{"title":"Property Types Reference","url":"/obsidian/settings/property-types-reference/","description":"This reference documents the expected data types for each frontmatter property that TaskNotes uses.","product":"obsidian","text":"This reference documents the expected data types for each frontmatter property that TaskNotes uses. Quick Reference# Property Type Example title text \"My Task\" status text \"open\", \"in-progress\", \"done\" priority text \"low\", \"normal\", \"high\" due text (date) \"2025-01-15\" scheduled text (date) \"2025-01-10\" completedDate text (date) \"2025-01-20\" dateCreated text (datetime) \"2025-01-01T08:00:00Z\" dateModified text (datetime) \"2025-01-15T10:30:00Z\" tags list [\"work\", \"urgent\"] contexts list [\"office\", \"home\"] projects list [\"[[Project A]]\"] timeEstimate number 120 (minutes) recurrence text \"FREQ=WEEKLY;BYDAY=MO\" recurrence_anchor text \"scheduled\" or \"completion\" timeEntries list (objects) See Time Entries blockedBy list (objects) See Dependencies reminders list (objects) See Reminders complete_instances list [\"2025-01-08\", \"2025-01-15\"] skipped_instances list [\"2025-01-22\"] recurrence_parent text (link/path) \"[[Tasks/Weekly review]]\" occurrence_date text (date) \"2025-01-15\" occurrence_materialization text \"manual\" or \"on_completion\" occurrence_next_trigger text \"completion\" or \"completion_or_skip\" occurrence_template text (link/path) \"[[Templates/Occurrence]]\" occurrence_past_horizon text (duration) \"P7D\" occurrence_future_horizon text (duration) \"P14D\" icsEventId list [\"event-abc123\"] Use this table for fast validation when a field is not behaving as expected in views or API calls. Most parsing issues come from shape mismatches (for example scalar vs list) rather than missing values. Property Details# The sections below describe storage formats, but there is flexibility in authoring style. TaskNotes normalizes many equivalent YAML representations as long as the resulting data type is correct. Text Properties# title# Type: text (string) Description: The task's title or name Example: title: \"Complete project documentation\" status# Type: text (string) Description: The task's current status. Must match one of the status values configured in your settings. Default values: \"open\", \"in-progress\", \"done\" Example: status: \"in-progress\" Note: Also supports boolean values (true/false) for Obsidian checkbox compatibility. See Boolean Status Values. priority# Type: text (string) Description: The task's priority level. Must match one of the priority values configured in your settings. Default values: \"low\", \"normal\", \"high\" Example: priority: \"high\" Date Properties# All date properties are stored as text strings in your frontmatter. TaskNotes expects specific formats: When in doubt, prefer ISO-style values. They sort correctly as text, travel well through APIs, and are easiest to parse consistently. due# Type: text (date string) Format: YYYY-MM-DD or ISO 8601 timestamp Description: The task's due date Examples: due: \"2025-01-15\" due: \"2025-01-15T17:00:00\" scheduled# Type: text (date string) Format: YYYY-MM-DD or ISO 8601 timestamp Description: When the task is scheduled to be worked on Examples: scheduled: \"2025-01-10\" scheduled: \"2025-01-10T09:00:00\" completedDate# Type: text (date string) Format: YYYY-MM-DD Description: The date when the task was completed Example: completedDate: \"2025-01-20\" dateCreated# Type: text (datetime string) Format: ISO 8601 timestamp Description: When the task was created Example: dateCreated: \"2025-01-01T08:00:00Z\" dateModified# Type: text (datetime string) Format: ISO 8601 timestamp Description: When the task was last modified Example: dateModified: \"2025-01-15T10:30:00Z\" List Properties# List properties must be arrays, even when containing a single value. Single-item arrays may look verbose, but they prevent edge cases when filters and formulas assume list semantics. tags# Type: list (array of strings) Description: Tags associated with the task Examples: tags: [\"work\", \"documentation\"] tags: - work - documentation contexts# Type: list (array of strings) Description: Context labels for the task Examples: contexts: [\"office\", \"computer\"] contexts: - \"office\" - \"computer\" projects# Type: list (array of strings) Description: Project references (typically wiki-links) Examples: projects: [\"[[Website Redesign]]\", \"[[Q1 Planning]]\"] projects: - \"[[Website Redesign]]\" - \"[[Q1 Planning]]\" Numeric Properties# timeEstimate# Type: number Unit: minutes Description: Estimated time to complete the task Example: timeEstimate: 120 (2 hours) Recurrence Properties# recurrence# Type: text (string) Format: RFC 5545 RRULE format Description: Defines how the task repeats Examples: recurrence: \"FREQ=DAILY\" recurrence: \"FREQ=WEEKLY;BYDAY=MO,WE,FR\" recurrence: \"FREQ=MONTHLY;BYMONTHDAY=1\" recurrence_anchor# Type: text (string) Valid values: \"scheduled\" or \"completion\" Description: Determines whether the next occurrence is calculated from the scheduled date or when the task was completed Example: recurrence_anchor: \"scheduled\" complete_instances# Type: list (array of date strings) Format: YYYY-MM-DD Description: Dates when recurring task instances were completed Example: complete_instances: - \"2025-01-08\" - \"2025-01-15\" skipped_instances# Type: list (array of date strings) Format: YYYY-MM-DD Description: Dates when recurring task instances were skipped Example: skipped_instances: - \"2025-01-22\" Materialized Occurrence Properties# Materialized occurrence notes are ordinary task notes created for one date in a recurring series. The parent recurring task owns the recurrence rule; the occurrence note owns date-specific state such as status, completed date, body content, time entries, reminders, and comments. When an occurrence note is created, TaskNotes inherits parent planning metadata such as scheduled time, due offset, priority, tags, contexts, projects, reminders, dependencies, details, custom properties, and time estimate. It does not copy parent recurrence/history/runtime fields such as recurrence, complete_instances, skipped_instances, completedDate, provider event IDs, or timeEntries. recurrence_parent# Type: text (link or path string) Description: Parent recurring task for a materialized occurrence note Example: recurrence_parent: \"[[Tasks/Weekly review]]\" occurrence_date# Type: text (date string) Format: YYYY-MM-DD Description: Target recurrence date represented by a materialized occurrence note Example: occurrence_date: \"2025-01-15\" occurrence_materialization# Type: text (string) Valid values: \"manual\", \"on_completion\", \"rolling\" Description: Parent task policy for creating occurrence notes. The plugin currently supports manual creation and creating the next note after completion; rolling windows are defined by the spec but are not automated yet. Example: occurrence_materialization: \"on_completion\" occurrence_next_trigger# Type: text (string) Valid values: \"completion\" or \"completion_or_skip\" Description: Parent task policy for whether skip actions should also create the next occurrence note when occurrence materialization is set to on_completion Example: occurrence_next_trigger: \"completion_or_skip\" occurrence_template# Type: text (link or path string) Description: Optional template reference used when creating materialized occurrence notes. This parent-level template takes priority over the global occurrence note template fallback in Features settings. Example: occurrence_template: \"[[Templates/Weekly occurrence]]\" occurrence_past_horizon and occurrence_future_horizon# Type: text (ISO 8601 duration string) Description: Optional rolling-window bounds for occurrence materialization. These fields are part of the TaskNotes spec; automated rolling materialization is not currently enabled in the plugin. Examples: occurrence_past_horizon: \"P7D\" occurrence_future_horizon: \"P14D\" Complex Properties# These properties contain structured data with multiple fields. For these fields, copy known-good examples before editing manually. Minor schema deviations can break downstream features such as reminders, recurrence, or dependency checks. Time Entries# Type: list (array of objects) Description: Time tracking entries for the task Structure: timeEntries: - startTime: \"2025-01-15T10:30:00Z\" # Required: ISO 8601 timestamp endTime: \"2025-01-15T11:15:00Z\" # Optional: ISO 8601 timestamp description: \"Initial work\" # Optional: text Dependencies (blockedBy)# Type: list (array of objects) Description: Tasks that must be completed before this task can start Structure: blockedBy: - uid: \"path/to/blocking-task.md\" # Required: path to blocking task reltype: \"FINISHTOSTART\" # Required: relationship type gap: \"P1D\" # Optional: ISO 8601 duration offset Relationship types accepted in stored data: FINISHTOSTART, STARTTOSTART, FINISHTOFINISH, STARTTOFINISH Current behavior: Dependencies created from the UI use FINISHTOSTART. Blocking evaluation is based on dependency presence/completion state and does not currently apply distinct scheduling semantics for different reltype values or gap. Reminders# Type: list (array of objects) Description: Reminder notifications for the task Structure for relative reminders: reminders: - id: \"rem_1\" # Required: unique identifier type: \"relative\" # Required: \"relative\" or \"absolute\" relatedTo: \"due\" # Required for relative: \"due\" or \"scheduled\" offset: \"-PT1H\" # Required for relative: ISO 8601 duration description: \"1 hour before due\" # Optional: description Structure for absolute reminders: reminders: - id: \"rem_2\" type: \"absolute\" absoluteTime: \"2025-01-15T09:00:00Z\" # Required for absolute: ISO 8601 timestamp description: \"Morning reminder\" icsEventId# Type: list (array of strings) Description: ICS calendar event IDs linked to this task Example: icsEventId: - \"event-abc123\" - \"event-def456\" Complete Example# Here's a complete task with all property types: --- title: \"Complete quarterly report\" status: \"in-progress\" priority: \"high\" due: \"2025-01-31\" scheduled: \"2025-01-25\" tags: - work - reports contexts: - office projects: - \"[[Q1 Planning]]\" timeEstimate: 240 dateCreated: \"2025-01-01T08:00:00Z\" dateModified: \"2025-01-20T14:30:00Z\" timeEntries: - startTime: \"2025-01-20T10:00:00Z\" endTime: \"2025-01-20T11:30:00Z\" blockedBy: - uid: \"tasks/gather-data.md\" reltype: \"FINISHTOSTART\" reminders: - id: \"rem_1\" type: \"relative\" relatedTo: \"due\" offset: \"-P1D\" description: \"Due tomorrow\" --- Field Mapping# All property names can be customized via Settings → Task Properties → Field Mapping. If you change a field mapping, TaskNotes will read and write using your custom property name. Custom property names are frontmatter keys, so names with spaces or punctuation are valid in task files. When you write your own Bases filters or formulas for those keys, use bracket notation such as note[\"TN-status\"] or note[\"Task Type\"] instead of dot notation. Dot notation only works reliably for simple identifier-style names. For example, if you map due to dueDate, TaskNotes will expect: dueDate: \"2025-01-15\" See Task Properties settings for configuration details. Custom User Fields# You can define additional properties with these types: text - Single text value number - Numeric value date - Date string (YYYY-MM-DD) boolean - true/false list - Array of values See Custom User Fields for configuration details."},{"title":"Task Properties Settings","url":"/obsidian/settings/task-properties/","description":"This tab configures all task properties. Each property is displayed as a card containing its configuration options.","product":"obsidian","text":"This tab configures all task properties. Each property is displayed as a card containing its configuration options. Looking for property type documentation?See the Property Types Reference for detailed documentation on the expected data types (text, list, date, etc.) for each frontmatter property. Property Card Structure# Each property card contains: Property key: The frontmatter field name used to store this property Default: The default value applied to new tasks (where applicable) NLP trigger: Toggle and character configuration for natural language parsing (where applicable) Property-specific settings: Additional configuration options specific to that property This tab defines the task schema used by creation flows, NLP parsing, views, and API payloads. Property keys are YAML/frontmatter keys. TaskNotes can read and write keys that contain spaces or punctuation, but hand-written Bases filters and formulas must reference those keys with bracket syntax, for example note[\"TN-status\"], rather than dot syntax such as note.TN-status. Core Properties# Title# The task title property. Configuration options: Property key: Frontmatter field name (default: title) Store title in filename: When enabled, the task title is stored in the filename instead of frontmatter. The filename updates when the title changes. Filename format: When \"Store title in filename\" is disabled, choose how filenames are generated: Title-based Zettelkasten-style Timestamp-based UUID v4 Custom template Custom template: Define a custom filename pattern using variables (shown when \"custom\" format is selected) Status# Task completion state. Configuration options: Property key: Frontmatter field name (default: status) Default: Default status for new tasks NLP trigger: Character that triggers status parsing (default: *) Status Values: Expandable section containing individual status cards Each status value has: Value: Internal identifier stored in frontmatter (e.g., \"in-progress\") Label: Display name shown in the interface (e.g., \"In Progress\") Color: Visual indicator color Icon: Optional icon identifier Completed: Whether this status represents a finished task Skip when cycling: Exclude this status from the click-to-cycle order on task cards while keeping it available in menus, suggestions, and direct edits Next status: Optional override for the status used when cycling forward from this status; leave it set to the status order to use the normal sequence Auto-archive: Automatically archive tasks after a delay (1-1440 minutes) Status cards support drag-and-drop reordering. Use the Value field as the stable stored identifier and the Label field for display text with spaces or title casing. TaskNotes status menus and cycling use the configured order, and TaskNotes Kanban views can preserve dragged column order. Native Bases grouping/sorting may still order status values alphabetically by their stored Value, so use prefixes such as 1-open, 2-doing, 3-done if you need predictable native Bases order. Boolean Status Values# TaskNotes supports using boolean values (true and false) as status values, which integrates with Obsidian's native checkbox property format: When you set a task's status to \"true\" or \"false\" (case-insensitive), TaskNotes automatically converts it to a boolean in frontmatter When reading tasks with boolean status values from frontmatter, they are converted back to the strings \"true\" or \"false\" This allows you to use Obsidian's native checkbox property toggles in the Properties panel while maintaining compatibility with TaskNotes Example: --- status: true # Boolean checkbox in Obsidian --- Priority# Task priority level. Configuration options: Property key: Frontmatter field name (default: priority) Default: Default priority for new tasks (can be set to \"No default\") NLP trigger: Character that triggers priority parsing (default: !, disabled by default) Priority Values: Expandable section containing individual priority cards Each priority value has: Value: Internal identifier stored in frontmatter (e.g., \"high\") Label: Display name shown in the interface (e.g., \"High Priority\") Color: Visual indicator color Priority cards support drag-and-drop reordering. Status and priority values are stored in frontmatter; renaming them later may require migration of existing task files. Note for Bases plugin users: Obsidian's Bases plugin sorts priorities alphabetically by their Value. To control sort order, name values to sort alphabetically in the desired order: Example: 1-urgent, 2-high, 3-medium, 4-normal, 5-low Or: a-urgent, b-high, c-medium, d-normal, e-low Date Properties# Due Date# When the task must be completed. Configuration options: Property key: Frontmatter field name (default: due) Default: Default due date for new tasks (None, Today, Tomorrow, Next Week) Scheduled Date# When to work on the task. Configuration options: Property key: Frontmatter field name (default: scheduled) Default: Default scheduled date for new tasks (None, Today, Tomorrow, Next Week) When you use Convert current note to task, this default is also applied if the source note does not already have scheduled frontmatter. Choose None to keep converted notes unscheduled by default. due tracks commitment deadlines, while scheduled tracks intended execution time. Organization Properties# Contexts# Where or how the task can be done. Configuration options: Property key: Frontmatter field name (default: contexts) Default: Comma-separated list of default contexts (e.g., @home, @work) NLP trigger: Character that triggers context parsing (default: @) Projects# Projects the task belongs to. Configuration options: Property key: Frontmatter field name (default: projects) Default projects: Select project notes to automatically link to new tasks Use active note for new tasks: Automatically link the active note as a project when opening task creation from the command palette or ribbon Use parent note for inline/instant conversion: Automatically link the source note as a project when using inline task creation or instant task conversion NLP trigger: Character that triggers project parsing (default: +) Autosuggest Filters: Expandable section to filter which notes appear in project suggestions Customize Display: Expandable section to configure how project suggestions appear Autosuggest Filters# Control which notes appear when selecting projects: Required tags: Comma-separated list of tags (shows notes with ANY of these tags) Include folders: Comma-separated list of folder paths (shows notes in ANY of these folders) Required property key: Frontmatter property that must exist Required property value: Expected value for the property (optional) These filters reduce suggestion noise in large vaults. A \"Filters On\" badge appears when any filters are configured. Customize Display# Configure project suggestion appearance: Enable fuzzy matching: Allow typos and partial matches in project search Row 1, 2, 3: Configure up to 3 lines of information for each project suggestion Tags# Obsidian tags for categorization. Configuration options: Default: Comma-separated list of default tags (without #) NLP trigger: Character that triggers tag parsing (default: #) Note: Tags use native Obsidian tags and do not have a separate property key setting. Task Details# Time Estimate# Estimated time to complete the task. Configuration options: Property key: Frontmatter field name (default: timeEstimate) Default: Default time estimate in minutes (0 = no default) Recurrence# Pattern for repeating tasks. Configuration options: Property key: Frontmatter field name (default: recurrence) Default: Default recurrence pattern (None, Daily, Weekly, Monthly, Yearly) Recurring tasks also use the Recurrence anchor metadata property to decide whether the series advances from the scheduled date or the completion date. Materialized occurrence note controls live on each recurring task's context menu under Recurrence → Occurrence notes rather than as a global default. Reminders# Notifications before task deadlines. Configuration options: Property key: Frontmatter field name (default: reminders) Default Reminders: Expandable section containing default reminder cards Each default reminder can be: Relative reminders (triggered relative to due or scheduled date): Anchor date (due date or scheduled date) Offset amount and unit (minutes, hours, days) Direction (before or after) Description Absolute reminders (triggered at specific times): Date Time Description Metadata Properties# These properties are system-managed and typically only require property key configuration: Date Created: When the task was created Date Modified: When the task was last modified Completed Date: When the task was completed Archive Tag: Tag used to mark archived tasks Time Entries: Time tracking entries for the task Complete Instances: Completion history for recurring tasks Skipped Instances: Skip history for recurring tasks Recurrence Anchor: Whether recurring progression is based on scheduled date or completion date Blocked By: Tasks that must be completed first Materialized occurrence notes also use system-managed frontmatter fields such as recurrence_parent, occurrence_date, occurrence_materialization, occurrence_next_trigger, and optional occurrence template/horizon fields. Occurrence notes inherit parent planning metadata when they are created, but keep their own status, completion date, and time entries. These fields are documented in the Property Types Reference and are normally changed through recurrence and occurrence-note controls instead of by hand. Feature Properties# These properties are used by specific TaskNotes features and are not stored in task frontmatter: Pomodoros: Property key for Pomodoro session counts. When Pomodoro data storage is set to \"Daily notes\", this property is written to daily notes rather than task files. ICS Event ID: Property key for calendar event identifiers. Added to notes created from ICS calendar events to link them back to the source event. ICS Event Tag: Property key for calendar event tags. Added to notes created from ICS calendar events for identification. Custom User Fields# Define custom frontmatter properties to appear as filter options across views. Configuration options for each field: Display Name: How the field appears in the UI Property Key: The frontmatter property name Type: Data type (text, number, boolean, date, or list) Default Value: Pre-fill value for new tasks (format varies by type) NLP trigger: Toggle and character for natural language parsing Autosuggest Filters: Filter which files appear when using [[ wikilink autocomplete Custom fields are most maintainable when they map to repeated workflow decisions (for example effort, owner, or client). Link Values# Use a Text custom field for a single link and a List custom field for multiple links. Task cards render [[wikilinks]], [label](https://example.com), , and bare https://example.com values as clickable links. Autosuggest filters work with text and list fields when entering [[ wikilinks, so a field such as Related Note can suggest only files from a chosen folder or tag. Default Values# Each field type has a different input format for default values: Text: Enter the default text value Number: Enter the default number Boolean: Toggle switch to set default checked/unchecked state Date: Select from presets (None, Today, Tomorrow, Next Week) List: Enter comma-separated default values Default values are applied when creating tasks via: Task creation modal Instant task conversion \"Create or open task\" command HTTP API (when using task creation defaults) Autosuggestion Filters# Each custom field can configure filters to control which files appear in wikilink suggestions: Required tags: Comma-separated list of tags (shows files with ANY of these tags) Include folders: Comma-separated list of folder paths (shows files in ANY of these folders) Required property key: Frontmatter property that must exist Required property value: Expected value for the property (optional) A \"Filters On\" badge appears when filters are configured. See User Fields Feature Documentation for detailed examples."},{"title":"Troubleshooting","url":"/obsidian/troubleshooting/","description":"Common issues and solutions for TaskNotes.","product":"obsidian","text":"Common issues and solutions for TaskNotes. When debugging, start with one affected task and one affected view. Record the TaskNotes version from the plugin list, the Obsidian version from About, the operating system, and whether the problem also occurs in a fresh default Base. First checks# Confirm Obsidian meets the current version requirement and Bases is enabled. Open the affected task as Markdown and validate the --- frontmatter delimiters and indentation. Confirm the task matches Settings → TaskNotes → General → Task identification and is not in an excluded folder. Run TaskNotes: Refresh cache from the command palette. Close and reopen the affected .base file. Restart Obsidian only after the targeted checks above. If the issue remains, enable Settings → TaskNotes → Features → Debug logging, reproduce it once, and inspect the developer console with Ctrl/Cmd + Shift + I. Disable debug logging after collecting the relevant entries. Bases and Views (v4)# Views Not Loading# Symptoms: TaskNotes views show errors or don't display tasks First confirm Bases is enabled (Settings -> Core Plugins -> Bases), then restart Obsidian once. If views are still missing, verify .base files exist in TaskNotes/Views/. If needed, regenerate defaults from Settings -> TaskNotes -> General -> Views & base files (Create files). Commands Open Wrong Files# Symptoms: Ribbon icons or commands open unexpected files Check command mappings in Settings -> TaskNotes -> General (View Commands). Reset mappings that were changed unintentionally, then verify each referenced .base file exists at the configured path. Common Issues# Tasks Not Appearing in Views# Symptoms: Tasks you've created don't show up in TaskNotes views Follow this decision tree: Does Quick actions for current task work on the note? No: compare its tag or identification property with General → Task identification. Yes: task recognition works; continue to the Base filter. Is the note inside an excluded folder? Yes: move it or update Excluded folders. No: continue. Does a newly generated default task Base show it? Yes: the custom Base has a stale property name or filter. No: run TaskNotes: Refresh cache and validate the frontmatter. Did identification or field mapping change recently? Yes: update the default Base files or edit their filters and columns. Generated files do not update automatically when settings change. Task Link Widgets Not Working# Symptoms: Links to task files appear as normal wikilinks instead of interactive widgets Check that Task link overlay is enabled, then verify linked files are actually recognized as tasks (matching tag/property configuration). Links to normal notes will render as normal links by design. Instant Conversion Buttons Missing# Symptoms: Convert buttons don't appear next to checkbox tasks Instant convert buttons only appear when the feature is enabled, in edit mode, and with cursor proximity to list items. Enable the feature, switch from reading mode to edit mode, and place the cursor near the target checkbox. Calendar View Performance Issues# Symptoms: Calendar views are slow or unresponsive Reduce visible event layers first (scheduled/due/recurring/time entries), then increase ICS refresh intervals and shorten displayed date ranges. If slowness persists, apply the general performance guidance below. Natural Language Parsing Not Working# Symptoms: Natural language input doesn't extract expected task properties Enable NLP in Settings -> TaskNotes -> Features, then verify your trigger characters (@, #, ! by default) and any custom status/priority mappings. If parsing still seems inconsistent, compare input against the syntax in NLP API. Time Tracking Issues# Symptoms: Time tracking doesn't start/stop properly or data is lost Most tracking issues come from overlapping sessions, interrupted shutdowns, or save failures. Stop active sessions before starting new ones, confirm files are writable, and restart interrupted sessions. If needed, repair malformed time entries directly in frontmatter. Data Issues# Corrupted Task Files# Symptoms: Tasks appear broken or cause errors in views Open the task file directly and validate frontmatter syntax. Quote values that include special characters, validate YAML if necessary, and restore from backup for severe corruption. Missing Task Properties# Symptoms: Tasks missing expected properties or using default values unexpectedly Check field mappings first, then confirm Task Defaults. If properties are absent on older notes, add them manually or re-save through TaskNotes so current mapping rules are applied. Date Format Issues# Symptoms: Dates not displaying correctly or causing parse errors Use supported formats (YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS), quote where needed, and re-enter problematic dates via TaskNotes date pickers to normalize formatting and timezone handling. Performance Troubleshooting# Slow View Loading# To improve loading times, reduce external calendar subscriptions, increase ICS refresh intervals, exclude large folders, and disable event types you do not use. External Calendar Issues# OAuth Calendar Not Connecting# Symptoms: Google Calendar or Microsoft Outlook won't connect Verify credentials and loopback redirect configuration (127.0.0.1 with dynamic local port), ensure app publication/test-user access is correct, and retry after disconnecting. Also check popup blockers. For provider-specific setup details, use Calendar Setup. OAuth Calendar Not Syncing# Symptoms: Connected calendar shows old events or doesn't update Run manual refresh, check last-sync timestamps, reconnect if needed, and verify events exist in the source provider before debugging TaskNotes behavior. ICS Subscriptions Not Loading# Symptoms: ICS calendar events don't appear in calendar views Confirm the ICS URL/file is reachable, run manual refresh, validate the feed format, and inspect subscription status errors for provider-side failures. Calendar Sync Problems# Symptoms: External calendar changes not reflected in TaskNotes Check refresh intervals and force a manual refresh first. If source data is current but TaskNotes remains stale, remove and re-add the subscription to clear cached state. Getting Help# Reporting Issues# Report bugs on GitHub Issues. Include: Exact TaskNotes and Obsidian versions Operating system The smallest affected task frontmatter with private values removed The .base path and whether a regenerated default has the same problem Steps to reproduce from a fresh Obsidian start Relevant console errors and TaskNotes debug entries Screenshots if relevant Configuration Reset# Use a reversible reset only after the checks above: Close Obsidian Navigate to .obsidian/plugins/tasknotes/ Copy data.json to a backup outside the plugin directory Rename the original to data.json.backup-YYYY-MM-DD Restart Obsidian WarningA reset affects settings, status and priority configurations, integration state, saved views, and plugin-stored Pomodoro history. Keep the backup until the problem is resolved. Restore it only while Obsidian is closed. For full restore and uninstall guidance, see Backup, restore, and removal."},{"title":"Views","url":"/obsidian/views/","description":"TaskNotes provides multiple views for managing tasks and tracking productivity. All task-focused views operate as .base files located in the TaskNotes/Views/ directory and requi...","product":"obsidian","text":"TaskNotes provides multiple views for managing tasks and tracking productivity. All task-focused views operate as .base files located in the TaskNotes/Views/ directory and require Obsidian's Bases core plugin to be enabled. For details on Bases integration and how to enable it, see Core Concepts. For view templates and configuration examples, see Default Base Templates. Task-Focused Views# Task-focused views are different entry points into the same underlying task notes. The Task List View is a common starting view for day-to-day planning because it exposes filters, sorting, and grouping in list format. When you want workflow by status, Kanban View organizes cards into columns and can optionally add swimlanes for an extra organizational layer. Calendar Views are useful when schedule and timing matter more than backlog shape, with month/week/day/year/list modes plus drag-and-drop scheduling and time-block support. Agenda View is a preconfigured list-oriented calendar layout designed for short-horizon planning, while MiniCalendar View gives a compact month heatmap and fast keyboard navigation. Productivity-Focused Views# These views support time management and work tracking. Pomodoro View supports focused intervals directly inside Obsidian, and Pomodoro Stats View summarizes completed sessions so you can see pace and consistency over time. Screenshots in this section are captured via the Playwright docs suite (npm run e2e:docs)."},{"title":"Agenda View","url":"/obsidian/views/agenda-view/","description":"The Agenda view is a dedicated .base file that opens the calendar in list mode. It provides a scrollable agenda of upcoming tasks, notes, and external calendar events without ne...","product":"obsidian","text":"The Agenda view is a dedicated .base file that opens the calendar in list mode. It provides a scrollable agenda of upcoming tasks, notes, and external calendar events without needing to switch the primary calendar into list view manually. File Location# Default file: TaskNotes/Views/agenda-default.base Command: Open Agenda View (ribbon icon and command palette) Configure the file path in Settings → TaskNotes → General → View Commands TaskNotes creates missing default .base files automatically on startup when Auto-create default files is enabled. You can replace the command path with your own .base file if you maintain multiple agendas. Default Configuration# The stock agenda file renders the calendar in listWeek mode: views: - type: tasknotesCalendar name: \"Agenda\" calendarView: \"listWeek\" listDayCount: 7 startDateProperty: file.ctime titleProperty: file.basename order: - note.status - note.priority - note.due - formula.dueIn - note.scheduled This configuration displays seven days at a time, derives entries from file.ctime/file.basename, shows the generated Due in countdown next to due dates, and inherits the same display options (show scheduled/due/recurring/timeblocks/time entries/ICS events) as the primary calendar view. Customization# Edit the .base file to tailor the agenda: Change calendarView to listDay or listMonth for different spans Adjust listDayCount for shorter or longer agendas; the Bases option supports up to 365 days Add filters to focus on specific projects, tags, or statuses Modify order to control which task properties appear in the row layout Because the view runs inside Bases, any YAML changes are applied immediately after saving the file. Usage Tips# Use the calendar toolbar arrows (Previous/Next) to move the agenda window forward or backward, or simply scroll the list to review upcoming entries Saved views within Bases let you maintain multiple agenda variants (e.g., \"Work Week\" vs. \"Personal\") Calendar display options (show due, show scheduled, etc.) persist when you save the .base file, so you can maintain one agenda that includes external events and another that focuses strictly on TaskNotes tasks"},{"title":"Calendar Views","url":"/obsidian/views/calendar-views/","description":"TaskNotes provides two calendar-based views: the Mini Calendar and the Calendar View. Both operate as Bases views (.base files) and require the Bases core plugin to be enabled i...","product":"obsidian","text":"TaskNotes provides two calendar-based views: the Mini Calendar and the Calendar View. Both operate as Bases views (.base files) and require the Bases core plugin to be enabled in Obsidian. Mini Calendar is date-density and navigation focused, while Calendar View is scheduling focused. Bases View Architecture# Calendar views in TaskNotes v4 are implemented as Bases views, which means: Calendar views are created as .base files in your vault Configuration is controlled through YAML frontmatter in the base file The Bases plugin is an official Obsidian core plugin and must be enabled Views can be opened in tabs, pinned, and managed like other Obsidian views This architecture makes calendar behavior auditable. Filters, formulas, and display options are stored with the view file, so they are versionable and easy to share across vault setups. Mini Calendar View# The Mini Calendar displays a month-based view that shows which days contain tasks or other dated notes. It provides navigation and an overview of your task distribution across time. Features# Date Navigation: Click any date to open a fuzzy selector modal showing all notes associated with that date Keyboard Navigation: Navigate the calendar using arrow keys and select dates with Enter Heatmap Styling: Visual indicators show the density of tasks or notes on each day Configurable Date Property: Set which date property to track (not limited to tasks - can display any dated notes based on configured property) Month Navigation: Browse forward and backward through months to view historical and future task distribution Mini Calendar is commonly used as an entry view: select a date, then open Task List, Agenda, or Calendar for execution. Calendar View# The Calendar View provides multiple view modes (month, week, day, year, list, and custom days) with drag-and-drop scheduling and time-blocking capabilities. Tasks can be created by clicking on dates or time slots, and rescheduled by dragging them to new dates or times. View Modes# The Calendar View supports the following view modes: Month: Month grid showing all-day and timed events Week: Week view with hourly time slots for detailed scheduling Day: Single day view with hourly breakdown Year: Annual overview showing event distribution across months List: Chronological list of events. TaskNotes also includes a dedicated Agenda command that opens this mode via its own .base file for quick reviews. Custom Days: Configurable multi-day view (2-10 days) View modes can be switched within a single .base file based on planning horizon (day, week, month, year, or custom range). Week View Day View Year View Performance Improvements# The Calendar View uses virtual scrolling to maintain performance when displaying large numbers of events. This allows the calendar to handle extensive task lists and long time ranges without degradation in responsiveness. Custom Days View# The Custom Days view provides a configurable multi-day calendar that displays between 2-10 days at once. This view addresses screen space utilization by offering a middle ground between the single-day view and the full week view. Key Features# Configurable Duration: Set the number of days to display (2-10 days) via Settings > Calendar > Custom view day count TimeGrid Format: Uses the same hourly time slots and time-based event layout as Week and Day views Real-time Updates: The view updates immediately when the day count setting is changed Default Configuration: Ships with 3 days displayed by default for optimal space utilization Use Cases# The Custom Days view is particularly useful for: Users who find the single-day view too wide and wasteful of screen space Planning workflows that require seeing a few days at a glance without the full week Detailed scheduling tasks that benefit from the time-grid format Customizing the viewing window to match personal preference and screen size Configuration# Select the View: Choose \"Custom Days\" from the calendar toolbar alongside Month, Week, Day, and Year views Adjust Day Count: Navigate to Settings > Calendar > Custom view day count and use the slider to select 2-10 days Set as Default: Optionally set \"Custom Days\" as your default view in Settings > Calendar > Default view Recurring Task Support# The Calendar View provides recurring task management with visual hierarchy and drag-and-drop behavior. Visual Hierarchy# Recurring tasks are displayed with distinct visual styling: Next Scheduled Occurrence: Solid border with full opacity, representing the specific date/time when you plan to work on the next instance Pattern Instances: Dashed border with reduced opacity (70%), showing preview of when future recurring instances will appear based on the DTSTART and recurrence rule Drag and Drop Behavior# The calendar provides different behaviors depending on which type of recurring event you drag: Dragging Next Scheduled Occurrence (Solid Border): Updates only the scheduled field in the task Reschedules just that specific occurrence to the new date/time Leaves the recurrence pattern unchanged Notice: \"Rescheduled next occurrence. This does not change the recurrence pattern.\" Dragging Pattern Instances (Dashed Border): Updates the DTSTART time in the recurrence rule Changes when all future pattern instances appear Does not affect the independently scheduled next occurrence Notice: \"Updated recurring pattern time. All future instances now appear at this time.\" Flexible Scheduling# The next scheduled occurrence can appear on any date, even: Before the DTSTART date On days that don't match the recurring pattern (e.g., Tuesday for a weekly Monday pattern) At different times than the pattern instances This flexibility allows for complete control over both the recurring pattern and individual occurrence scheduling. View Options# The Calendar View provides several display options that control what types of events appear on the calendar: Show scheduled: Display tasks with scheduled dates Show due: Display tasks with due dates Show timeblocks: Display time-blocking entries Show recurring: Display recurring task events Show ICS events: Display events from imported ICS calendars Show time entries: Display time tracking entries All-day slot: Show or hide the all-day event area at the top of time grid views (Week, Day, and Custom views) Create daily notes from date links: Let date header links create a missing daily note before opening it. Turn this off if date links should only open existing daily notes. Drag/drop resolution: Set snapDuration when you want events to drag or resize in smaller increments than the visible slotDuration, such as 5-minute dragging on a 30-minute grid. Span tasks between scheduled and due dates: Display tasks as multi-day bars spanning from their scheduled date to their due date (see below) Multiple saved calendar views can store different option sets (for example planning vs focus), avoiding repeated manual toggles. The All-day slot option is particularly useful when you have many all-day tasks on a single date, as hiding it can resolve scrolling issues and make the hourly time slots more accessible. When disabled, all-day events will not be displayed in time grid views, but they will still appear in month view. Multi-Day Task Spans# The Span tasks between scheduled and due dates option provides a visual representation of task duration on the calendar. When enabled: Tasks with both a scheduled date and a due date display as a single bar spanning across all days from the scheduled date to the due date This replaces the separate scheduled and due markers for qualifying tasks Tasks with only a scheduled date or only a due date continue to display as single-day events Span events are shown as all-day bars with the task's priority color Span events are read-only on the calendar (edit the underlying scheduled/due dates to modify) This option is useful for project planning and visualizing how long tasks are expected to take, similar to Gantt chart-style views. These display options are preserved when you save a view, allowing you to create specialized calendar views that show only specific types of events and maintain those preferences across sessions. OAuth Calendar Integration# The Calendar View supports bidirectional synchronization with external calendar services through OAuth authentication: Google Calendar: Connect to Google Calendar accounts to display and sync events Microsoft Outlook: Connect to Microsoft Outlook accounts for calendar integration Synchronization Behavior# External calendar events appear alongside TaskNotes tasks in all calendar views Drag and drop events to reschedule them - changes sync back to the external calendar service Events from external calendars respect the same view options and display settings as native TaskNotes tasks Configuration# OAuth calendar connections are configured through the TaskNotes settings panel. Authentication uses standard OAuth flows to securely connect to external services. Time Entry Editor Modal# The Calendar View includes a Time Entry Editor Modal for creating time tracking entries directly from the calendar interface. Creating Time Entries# Drag on the calendar to select a time range When the selection menu appears, choose Create time entry The modal opens with the start and end times pre-populated based on the selection, and the entry can be linked to a task or left standalone Editing Time Entries# Time entries displayed on the calendar can be selected to open the Time Entry Editor Modal for modification. The modal provides fields for adjusting start time, end time, associated task, and other time entry metadata. Filtering and View Configuration# Calendar filtering is configured through the Bases YAML frontmatter in the .base file. This allows you to define which tasks and events appear in each calendar view. Filtering options include task properties, date ranges, tags, and other criteria supported by the Bases plugin. Saved calendar views retain their filter configuration, display options, and view mode, allowing you to create specialized calendar views for different purposes."},{"title":"Kanban View","url":"/obsidian/views/kanban-view/","description":"The Kanban View displays tasks as cards organized in columns, where each column represents a distinct value of a grouped property. Kanban emphasizes state transitions and drag o...","product":"obsidian","text":"The Kanban View displays tasks as cards organized in columns, where each column represents a distinct value of a grouped property. Kanban emphasizes state transitions and drag operations over dense list scanning. Configuration# Kanban views are stored as .base files in TaskNotes/Views/. The groupBy property determines the column structure—each unique value becomes a column in the board. Open a .base file and access the view settings panel to configure options. Core Settings (Bases)# Data source: Select which files or folders to include in the view Filter: Define criteria to include or exclude specific tasks Sort: Specify the order of tasks within each column Group by: Required. Defines the property that creates columns (e.g., status, priority) Choosing a stable groupBy field is the most important design decision. Frequent changes to this field create column churn and make historical comparisons harder. Kanban-Specific Options# Access these options through the Bases view settings panel: Swim Lane: Optional property for horizontal grouping. Creates a two-dimensional layout where tasks are organized by both column (groupBy) and row (swimLane) Column Width: Controls the width of columns in pixels. Range: 200-500px. Default: 280px Max Swimlane Height: Caps each swimlane row before the task area scrolls. Range: 300-1200px. Default: 600px Hide Empty Columns: When enabled, columns containing no tasks are hidden from the view Pinned Columns: Optional comma-separated list of column values that should stay visible even when empty. This is useful with Hide Empty Columns when each board needs a small stable subset of shared statuses or categories WIP Limits: Advanced JSON configuration for showing per-column work-in-progress limits in column headers Hide Empty Swimlanes: When enabled, ordered swimlanes with no tasks are hidden from the view Card Layout: Chooses the task card density for this board. Default uses the standard TaskNotes card layout. Compact uses a tighter card layout for denser boards Show items in multiple columns: When enabled (default), tasks with multiple values in list properties (contexts, tags, projects) appear in each individual column. For example, a task with contexts: [work, call] appears in both the \"work\" and \"call\" columns. When disabled, tasks appear in a single combined column (e.g., \"work, call\") Hide top-level subtasks: When enabled, tasks whose Projects field links to another task in the current filtered board are hidden as standalone cards and remain available through the parent task's expanded subtasks Column Order: Managed automatically when dragging column headers. Stores custom column ordering Swim Lane Order: Advanced JSON configuration for pinning swimlane rows in a stable order A common setup is to keep one board grouped by status and another grouped by project or context, each in a separate .base file. Interface Layout# Standard Layout# In standard mode, the Kanban board displays a horizontal row of columns. Each column corresponds to a unique value of the groupBy property. Each column includes: A header showing the property value and task count A scrollable area containing task cards An add button that opens the TaskNotes creation modal with the column value filled in Drag-and-drop functionality for reordering columns or moving tasks between columns Swimlane Layout# When a swimLane property is configured, the board displays a grid layout. The horizontal axis represents columns (groupBy values), and the vertical axis represents swimlanes. Each swimlane row includes: A label cell showing the swimlane property value and total task count Multiple cells, each representing a column within that swimlane Scrollable cells containing task cards Add buttons inside cells that fill in both the column value and swimlane value To pin swimlanes in a stable order, set the advanced swimLaneOrder option to a JSON object keyed by the swimlane property: config: swimLane: note.contexts swimLaneOrder: '{\"note.contexts\":[\"transitcal\",\"bill\",\"cycles-research\",\"astrolabe\"]}' Listed swimlane values render first in the configured order. Values not listed in swimLaneOrder render below them using the default order for status and priority swimlanes, or alphabetically for other properties. If hideEmptySwimLanes is disabled, listed values can remain visible even when no matching tasks are currently present. To show WIP limits in column headers, set the advanced wipLimits option to a JSON object keyed by column value: config: wipLimits: '{\"in-progress\":5,\"review\":2}' Columns with limits display counts as (current/limit). When the current count is above the configured limit, the count uses the error color. In swimlane boards, the column header count is the total for that column across all swimlanes. Task Cards# Each task card displays information based on the visible properties configured in the Bases view. Standard task information includes title, priority, due date, and scheduled date. Use the Card Layout setting when a board needs a different density from other task views. Existing boards use Default unless cardLayout: compact is set in the view options. To show checklist progress on cards, include file.tasks in the view order array. For existing .base files, add this in YAML manually first; after it is in order, it appears in the Bases picker as tasks. Click a card to open the task file for editing. Right-click to access the context menu for task actions. Drag cards between columns or swimlane cells to update the task's properties. Column Operations# Reordering Columns# Drag column headers to reorder columns. The new order persists across sessions and is stored in the columnOrder configuration. Drag-and-Drop Tasks# Drag task cards between columns to update the groupBy property value. In swimlane mode, dragging a task to a different cell updates both the groupBy and swimLane properties. When grouping by a list property (contexts, tags, projects) with \"Show items in multiple columns\" enabled, dragging a task between columns modifies the list rather than replacing it. The source column's value is removed and the target column's value is added. For example, dragging a task from the \"work\" column to the \"home\" column changes contexts: [work, call] to contexts: [call, home]. Drag operations write directly to task metadata, so consistent grouping values reduce ambiguity. The add button at the bottom of a column or swimlane cell keeps deterministic view filter defaults and fills in the grouped values for that location. Manual Reordering Within Columns# Kanban also supports drag-to-reorder within a column or swimlane cell when the view is sorted by the manual-order property. With the default field mapping, that property is tasknotes_manual_order. To enable persistent manual ordering within Kanban columns: sort: - column: tasknotes_manual_order direction: DESC Once the first sort criterion is the manual-order property, dragging a card within the same column updates stored frontmatter values so the new order persists across refreshes and sessions. In swimlane mode, the reorder scope is a single cell, not the entire board. A reorder inside the \"In Progress\" column for the \"High\" swimlane only adjusts the tasks in that cell. Important constraints: Manual drag-to-reorder only works when the view sort includes the manual-order property. Moving a card to a different column or swimlane still updates the grouped property values as usual. In filtered or partially visible columns, TaskNotes may also update hidden or filtered notes in the same reorder scope to preserve a stable persistent order. Large reorder operations may show a confirmation dialog before writing changes. The default generated TaskNotes templates use manual-order sorting in places where drag-to-reorder should work immediately, such as relationship views and manual-order task lists. Performance Optimization# The Kanban view implements virtual scrolling for columns or swimlane cells containing 30 or more tasks. This optimization reduces memory usage by approximately 85% and maintains 60fps scrolling performance for columns with 200+ tasks. Virtual scrolling activates automatically based on task count. No configuration is required. Example Configuration# A typical Kanban view .base file includes: --- type: query source: TaskNotes view: TaskNotes Kanban views: - name: TaskNotes Kanban type: tasknotesKanban groupBy: property: task.status config: swimLane: task.priority swimLaneOrder: '{\"task.priority\":[\"high\",\"normal\",\"low\"]}' columnWidth: 300 hideEmptyColumns: true pinnedColumns: to-do, in-progress, done wipLimits: '{\"in-progress\":5}' --- This configuration creates a Kanban board with: Columns based on task status Swimlanes based on task priority Priority swimlanes pinned in high, normal, low order 300px column width Empty unpinned columns hidden, while the to-do, in-progress, and done columns stay visible as drop targets A WIP limit of 5 tasks on the in-progress column Filtering and Sorting# Filtering and sorting are configured through the Bases view settings, not through a separate FilterBar component. Use the Bases filter editor to define conditions based on task properties. Use the Bases sort editor to specify the order of tasks within each column."},{"title":"Pomodoro View","url":"/obsidian/views/pomodoro-view/","description":"The Pomodoro View provides a timer for working in focused intervals, based on the Pomodoro Technique.","product":"obsidian","text":"The Pomodoro View provides a timer for working in focused intervals, based on the Pomodoro Technique. Timer Interface# The Pomodoro View includes a timer with controls to start, stop, and reset the timer. While a timer is running, the view shows both the remaining duration and the projected local finish time. You can also associate a task with the timer, and the time will be automatically recorded in the task's time tracking data when the session is complete. Pomodoro Stats View# The Pomodoro Stats View provides analytics and historical data about your Pomodoro sessions. This includes a history of completed sessions, as well as metrics like completion rates and total time spent on tasks."},{"title":"Task List View","url":"/obsidian/views/task-list/","description":"The Task List View displays tasks in a scrollable list format with filtering, sorting, and grouping capabilities. In TaskNotes v4, this view operates as a Bases view configured...","product":"obsidian","text":"The Task List View displays tasks in a scrollable list format with filtering, sorting, and grouping capabilities. In TaskNotes v4, this view operates as a Bases view configured through YAML. This view is optimized for high task volume and explicit filter definitions. Bases Architecture# Task List is implemented as a .base file located in TaskNotes/Views/tasks-default.base by default. It requires the Bases core plugin to be enabled. What is Bases?# Bases is an official Obsidian core plugin built directly into Obsidian (not a community plugin). It provides a framework for creating database views of notes and tasks. To enable Bases: Open Settings -> Core Plugins Enable \"Bases\" TaskNotes view commands will now open .base files from TaskNotes/Views/ If commands open empty or unexpected views, first confirm Bases is enabled and the command path points to the intended .base file. View File Location# When you use the \"Open Tasks View\" command or ribbon icon, TaskNotes opens the .base file configured under Settings -> TaskNotes -> General -> Views & base files (initially TaskNotes/Views/tasks-default.base). TaskNotes creates missing default .base files automatically on startup when Auto-create default files is enabled, and you can point the command to any other .base file if you maintain multiple task-list layouts. Configuration# Task List views are configured through YAML frontmatter in the .base file. The YAML defines which tasks to show, how to sort them, and how to group them. Basic Structure# # All Tasks views: - type: tasknotesTaskList name: \"All Tasks\" order: - note.status - note.priority - note.due - note.scheduled - note.projects - note.contexts - file.tags sort: - column: due direction: ASC Configuration Options# type: Must be tasknotesTaskList for Task List views name: Display name shown in the view header order: Array of property names that control which task properties are visible in the task cards. Properties are referenced using their Bases property paths (e.g., note.status, note.priority, note.due, file.tasks). For existing .base files, add file.tasks in YAML manually; once present in order, it appears in the Bases picker as tasks. sort: Array of sort criteria. Tasks are sorted by the first criterion, with ties broken by subsequent criteria. column: Property to sort by (e.g., due, scheduled, priority, title) direction: ASC (ascending) or DESC (descending) groupBy: Optional grouping configuration property: Property to group by (e.g., note.status, note.priority) direction: Sort direction for group headers hideTopLevelSubtasks: Optional boolean. When true, tasks whose Projects field links to another task in the current filtered result set are hidden as top-level rows and remain available through the parent task's expanded subtasks. filters: Optional filter conditions using Bases query syntax filters: and: - note.status == \"Open\" - note.priority == \"High\" Start with one or two simple filters, verify results, then layer complexity. Incremental edits are much easier to debug than large one-shot query rewrites. Property Mapping# TaskNotes properties are accessed in Bases YAML using these paths: TaskNotes Property Bases Property Path Description Status note.status Task status value Priority note.priority Priority level Due date note.due Due date/time Scheduled date note.scheduled Scheduled date/time Projects note.projects Associated projects Contexts note.contexts Task contexts Tags file.tags File tags Checklist progress file.tasks First-level markdown checkbox progress shown as the TaskNotes checklist progress bar Time estimate note.timeEstimate Estimated duration Recurrence note.recurrence Recurrence pattern Blocked by note.blockedBy Blocking dependencies Title file.name Task title (file name) Created file.ctime File creation date Modified file.mtime File modification date The exact property names depend on your TaskNotes field mapping settings (Settings -> TaskNotes -> Task Properties). The table above shows default mappings. Filtering and Sorting# Adding Filters# Edit the .base file to add filter conditions using Bases query syntax: views: - type: tasknotesTaskList name: \"High Priority Tasks\" filters: and: - note.priority == \"High\" - note.status != \"Completed\" order: - note.status - note.priority - note.due Filter Operators# Bases supports standard comparison operators: == (equals), != (not equals) >, <, >=, <= (comparison) contains() (substring/array membership) Boolean logic: and, or For detailed filter syntax, see the Bases documentation. Sorting Examples# Single sort criterion: sort: - column: due direction: ASC Multiple sort criteria: sort: - column: priority direction: DESC - column: due direction: ASC - column: title direction: ASC Drag-to-Reorder# Task List supports drag-to-reorder when the view is sorted by the manual-order property. With the default field mapping, that property is tasknotes_manual_order. To enable persistent manual ordering in a Task List view: sort: - column: tasknotes_manual_order direction: DESC Once the first sort criterion is the manual-order property, you can drag task cards to reorder them. TaskNotes writes updated LexoRank-style values into task frontmatter so the order persists across refreshes and sessions. If your field mapping changes the sort-order property name, use that mapped property name instead of tasknotes_manual_order. Drag-to-Reorder with Grouping# Grouped Task List views can also be reordered, but the reorder scope is the current group. For example, when grouping by status, dragging within the \"In Progress\" group updates the manual order for tasks in that group. Important constraints: Drag-to-reorder only works when the view sort includes the manual-order property. Reordering in formula-based groups is blocked because formula values are computed and cannot be edited directly. In filtered or partially visible lists, TaskNotes may also update hidden or filtered notes in the same reorder scope to preserve a stable persistent order. Large reorder operations may show a confirmation dialog before writing changes. The default generated TaskNotes task-list templates include a Manual Order view that is already configured for this behavior. Grouping# Groups organize tasks under collapsible headers based on a property value. Enable Grouping# Add groupBy configuration to your view: views: - type: tasknotesTaskList name: \"Tasks by Status\" groupBy: property: note.status direction: ASC order: - note.status - note.priority - note.due Available Grouping Properties# Common grouping properties: note.status - Group by task status note.priority - Group by priority level note.contexts - Group by first context note.projects - Group by project (tasks can appear in multiple groups) Interactive Group Headers# Group headers support interaction: Click to expand/collapse the group Click on project links in headers to navigate to project notes Hover over project links with Ctrl to preview project notes Collapsed State Persistence# Collapsed/expanded state for each group is preserved across sessions. Creating Multiple Views# You can create multiple .base files for different task perspectives: Duplicate an existing .base file in TaskNotes/Views/ Rename it (e.g., High Priority.base) Edit the YAML configuration for that view Open the file to see the customized view Example: Context-Specific View# # Work Tasks views: - type: tasknotesTaskList name: \"Work Context\" filters: and: - note.contexts.contains(\"work\") groupBy: property: note.priority direction: DESC order: - note.status - note.priority - note.due Migrating from v3 Saved Views# TaskNotes v3 stored filter configurations in plugin settings. These saved views are not automatically migrated to v4. To recreate a v3 saved view: Create a new .base file in TaskNotes/Views/ Translate your v3 filter conditions to Bases YAML syntax Configure sorting and grouping through YAML Save the file The v3 FilterBar UI component no longer exists - all configuration is done through YAML editing. Task Actions# The Task List View provides interaction with tasks through clicking and context menus: Click on a task: Opens the task for editing or navigates to the task note (behavior configured in Settings -> TaskNotes -> General in click-action controls) Right-click on a task: Opens a context menu with actions: Mark as complete Change priority Change status Edit dates Delete task And more Context menu availability depends on your TaskNotes settings and task properties. Virtual Scrolling# The Task List View automatically enables virtual scrolling when displaying 100 or more items (tasks + group headers). Virtual scrolling provides: Approximately 90% memory reduction for large lists Elimination of UI lag when scrolling through hundreds of tasks Smooth performance with unlimited task counts Virtual scrolling activates automatically and requires no configuration. When active, only visible tasks are rendered to the DOM, with off-screen tasks rendered on-demand as you scroll. Further Reading# Default Base Templates - Complete templates for all TaskNotes views Bases Plugin Documentation - Official Obsidian documentation for Bases syntax and features Kanban View - Alternative board-based task visualization Calendar Views - Time-based task visualization Views Overview - All available TaskNotes views"},{"title":"TaskNotes Webhooks","url":"/obsidian/webhooks/","description":"TaskNotes webhooks send HTTP POST requests when selected events occur.","product":"obsidian","text":"TaskNotes webhooks send HTTP POST requests when selected events occur. Prerequisites# Enable HTTP API in Settings -> TaskNotes -> Integrations -> HTTP API. Create at least one webhook (settings UI or API). Subscribe it to one or more events. Event Types# Task events: task.created task.updated task.deleted task.completed task.archived task.unarchived Time events: time.started time.stopped Pomodoro events: pomodoro.started pomodoro.completed pomodoro.interrupted Recurring events: recurring.instance.completed recurring.instance.skipped Completing a materialized occurrence note emits recurring.instance.completed with the reconciled parent task plus the completed occurrence and date in the event data. Skipping virtual recurring instances emits recurring.instance.skipped; materialized occurrence skip currently reconciles the parent and occurrence note without emitting a separate skip webhook. Reminder events: reminder.triggered Payload Shape# All webhook payloads use the same top-level envelope: { \"event\": \"task.created\", \"timestamp\": \"2026-02-21T10:30:00.000Z\", \"vault\": { \"name\": \"My Vault\", \"path\": \"/path/to/vault\" }, \"data\": {} } data is event-specific. Register and Manage Webhooks via API# Create# POST /api/webhooks Required fields: url (string) events (non-empty array) Optional fields: id secret (auto-generated if omitted) active (default true) transformFile corsHeaders (default true) Example: curl -X POST http://localhost:8080/api/webhooks \\ -H \"Content-Type: application/json\" \\ -d '{ \"url\": \"https://example.com/tasknotes\", \"events\": [\"task.completed\", \"task.created\"], \"transformFile\": \"TaskNotes/webhooks/slack.json\" }' List# GET /api/webhooks Returns registered hooks. Secrets are not returned. Delete# DELETE /api/webhooks/:id Delivery History# GET /api/webhooks/deliveries Returns last 100 in-memory deliveries. Delivery Behavior# Current implementation behavior: Webhook processing is asynchronous (fire-and-forget from task operation). Each delivery starts with one attempt. Failed deliveries retry with exponential backoff: 1s, 2s, 4s. Maximum retries: 3 retries after initial attempt (up to 4 attempts total). If cumulative failureCount for a webhook exceeds 10, webhook is auto-disabled. No explicit request timeout is set in delivery fetch. Because retries and duplicates are possible, handlers should be idempotent. Signature Verification# When corsHeaders is enabled (default), delivery includes: X-TaskNotes-Event X-TaskNotes-Signature X-TaskNotes-Delivery-ID Signature is HMAC-SHA256 over JSON.stringify(payload) using webhook secret. Node.js example: const crypto = require(\"crypto\"); function verifyWebhook(payload, signature, secret) { const expected = crypto .createHmac(\"sha256\", secret) .update(JSON.stringify(payload)) .digest(\"hex\"); return signature === expected; } Payload Transformations# A webhook can specify transformFile pointing to a file in your vault. Supported file types: .json: event template map with variable interpolation If transform execution fails, TaskNotes falls back to original payload. JavaScript transform files are no longer supported. JSON Transform Files# Structure: { \"task.completed\": { \"text\": \"Task completed: ${data.task.title}\", \"vault\": \"${vault.name}\" }, \"default\": { \"text\": \"TaskNotes event: ${event}\" } } Rules: Matching order: exact event key, then default. Variables use ${path.to.value}. Missing variables are left unchanged. CORS and Headers# Webhook delivery requests are outbound server-side requests from TaskNotes. corsHeaders behavior: true (default): sends TaskNotes custom headers including signature. false: only sends Content-Type: application/json. Disable custom headers for endpoints that reject non-standard headers. Testing# Local Test Server# Use repository script: node test-webhook.js Optional custom port: node test-webhook.js 8080 Default server values: URL: http://localhost:3000/webhook Test secret: test-secret-key-for-tasknotes-webhooks External Inspection# For quick inspection, use a request-bin tool such as webhook.site. Troubleshooting# No deliveries# Confirm HTTP API is enabled. Confirm webhook is active. Confirm event is subscribed. Signature mismatch# Confirm secret matches webhook config. Verify your verifier hashes the exact JSON body. Verify hex digest comparison. Webhook disabled automatically# If failures continue and failureCount exceeds 10, webhook is disabled. Fix endpoint availability or response handling. Re-enable webhook in TaskNotes settings, or recreate it via POST /api/webhooks. Transform errors# Confirm transformFile exists in vault. Confirm the file is a .json transform template. Check Obsidian console logs for transform exceptions."},{"title":"Workflows","url":"/obsidian/workflows/","description":"This page describes practical ways to combine TaskNotes features into repeatable workflows. The goal is to show how recurring tasks, projects, filtering, and scheduling fit toge...","product":"obsidian","text":"This page describes practical ways to combine TaskNotes features into repeatable workflows. The goal is to show how recurring tasks, projects, filtering, and scheduling fit together in everyday use. Habit Tracking with Recurring Tasks# Habit tracking in TaskNotes is built on recurring task notes. You can create a recurring task from natural language (for example, \"Exercise daily\" or \"Gym every Monday and Wednesday\") or configure recurrence explicitly in the task modal. The modal recurrence controls support frequency, interval, weekday selection, and end conditions. Once a task has a recurrence rule, its edit modal shows a recurrence calendar. That calendar is where you mark completion per occurrence. Completion history is stored in complete_instances, so a recurring task can remain open while still recording daily/weekly completion behavior. title: Morning Exercise recurrence: \"FREQ=DAILY\" scheduled: \"07:00\" complete_instances: - \"2025-01-01\" - \"2025-01-02\" - \"2025-01-04\" Use Calendar and Agenda views to review upcoming occurrences, and use recurring-task filters when you want a habit-only planning view. For richer recurring work, such as a weekly review or maintenance visit, right-click the recurrence in a task card, calendar view, or the edit modal's completion calendar and choose Open or create occurrence note. The occurrence note inherits planning metadata such as scheduled time, due offset, projects, tags, reminders, details, and time estimate, then keeps its own checklist, completion state, and time entries while the parent recurring task keeps the long-term rule. On the calendar, the note-backed occurrence replaces the matching virtual parent occurrence; dragging it reschedules that note without rewriting the recurrence pattern. Project-Centered Planning# Projects in TaskNotes can be plain text values or wikilinks to project notes. Wikilinks are usually the better long-term option because they connect task execution to project context, backlinks, and graph navigation. title: \"Research competitors\" projects: [\"[[Market Research]]\", \"[[Q1 Strategy]]\"] During task creation, use the project picker to search and assign one or more projects. In day-to-day planning, open Task List or Kanban, then filter on note.projects contains [[Project Name]] to isolate one initiative. Save that filter as a Bases saved view if you revisit it regularly. When work spans initiatives, assign multiple projects and combine with contexts or tags for secondary organization. title: \"Prepare presentation slides\" projects: [\"[[Q4 Planning]]\"] contexts: [\"computer\", \"office\"] tags: [\"review\"] Execution Workflow (Daily)# A typical daily flow is to start in Task List for prioritization, move to Calendar for schedule placement, and finish in Agenda for near-term sequencing. This keeps backlog management, time allocation, and short-horizon execution in one system. If you use timeboxing, drag-select on calendar timeline views and create timeblocks directly from the context menu. If you use Pomodoro, run sessions against active tasks so completion and timing data stay attached to task notes. Maintenance Workflow (Weekly)# A weekly review usually includes three steps: clean up completed/archived tasks, verify recurring-task completion patterns, and rebalance project filters/views. If calendar integrations are enabled, this is also a good point to refresh subscriptions and confirm sync health. For teams or complex personal systems, keep project notes as source-of-truth documents and use TaskNotes views as execution dashboards derived from those notes."},{"title":"TaskNotes privacy overview","url":"/privacy/","description":"How the TaskNotes app and Obsidian plugin store data and when optional services are involved.","product":"shared","text":"Last updated: August 6, 2026 TaskNotes products are built around portable Markdown records. The storage and network boundaries depend on the client and collection you choose. TaskNotes app# The TaskNotes app opens every collection through mdbase and requires a connection to read or change it. A hosted collection stores the authoritative Markdown with the hosted provider. A computer collection keeps the authoritative Markdown on that computer. TaskNotes reaches it through an end-to-end encrypted relay that cannot read record contents; the computer must remain reachable and run mdbase Connect. TaskNotes keeps only a temporary in-memory session cache. It does not retain a separate offline collection after the app or page closes. Reminder notifications for mdbase collections require explicit permission and use content-free event payloads. Task content is refreshed through the authorized collection connection. Obsidian plugin# The plugin keeps task and note content in the local Obsidian vault. Plugin settings live in Obsidian's plugin configuration. Network access occurs only for enabled features that require it, including release checks, calendar providers, ICS subscriptions, webhooks, and remotely loaded API documentation assets. Analytics# TaskNotes does not include a product telemetry or analytics pipeline. Services you choose to connect may keep their own operational, account, security, or billing records under their respective policies. Removal# Removing a client does not necessarily remove its authoritative collection. Use the hosted provider's controls for a hosted collection, or manage the Markdown folder on the computer that owns a computer collection. Back up records before removing an authoritative copy. Questions and source code# Use the relevant TaskNotes GitHub repository to report a privacy problem or inspect the implementation: TaskNotes app TaskNotes Obsidian plugin"}] +[{"title":"TaskNotes documentation","url":"/","description":"Guides and reference material for the TaskNotes app, the Obsidian plugin, and the portable task format they share.","product":"shared","text":"TaskNotes keeps structured task information in portable Markdown records. Use the dedicated app on the web, Android, or iOS, or work inside Obsidian with the TaskNotes plugin. Beta · Web · Android · iOS TaskNotes app Manage portable TaskNotes v5 collections on the web, Android, and iOS through mdbase. Open the app guide → Obsidian TaskNotes plugin Task and note management inside an Obsidian vault using Bases and Markdown. Open the plugin guide → One portable task model# Both clients understand the same TaskNotes concepts: status, priority, dates, projects, contexts, recurrence, reminders, relationships, and custom fields. The interface and available integrations differ, but your task records are not locked to one screen or application. Start with portable task records if you want to understand what the products share. Read the formal specification when implementing or integrating with TaskNotes. Review the privacy overview before choosing a hosted or computer-connected collection."},{"title":"TaskNotes app","url":"/app/","description":"Use TaskNotes on the web, Android, and iOS with portable Markdown through mdbase.","product":"app","text":"The TaskNotes app is currently in beta. It is a web-first client packaged for Android and iOS, designed for quick capture, daily review, editing, and completion while keeping task records portable. The app is compatible with TaskNotes v5 collections, which use the mdbase 0.3.0 specification. The same collection can be used by other compatible TaskNotes and mdbase tools. Every TaskNotes session opens an mdbase collection. You can use a collection hosted online or connect to a Markdown collection on your computer through the encrypted mdbase relay. TaskNotes reads and writes that collection directly, so changes require a connection. The Today workspace in the desktop layout. Disposable sample collection Try TaskNotes before connecting your own collection. Explore Today, Scratchpad, search, and saved views with sample tasks. Your changes disappear when the demo resets. Open the interactive demo → Begin here# Try TaskNotes with sample tasks or open or install TaskNotes. Learn how mdbase supports TaskNotes. Choose where your collection lives, then follow the connection walkthrough with video and written steps. Create a task and open Today. Turn on reminders only if the collection and platform support delivery. What the app includes# Today, Upcoming, Projects, lists, boards, and calendars Capture, editing, completion, archive, and search Projects, contexts, tags, priorities, relationships, and custom fields Recurrence, materialized occurrence notes, reminders, and time tracking Hosted mdbase and end-to-end encrypted relay connections Browser, Android, and iOS packaging from the same application Plugin-only functionality such as inline Obsidian widgets, the command palette, external calendar integrations, HTTP APIs, and companion plugins is documented under the Obsidian plugin."},{"title":"Choose a collection","url":"/app/collections/","description":"Compare hosted mdbase with a collection connected from your own computer.","product":"app","text":"TaskNotes opens every collection through mdbase. The choice is where the main copy of your Markdown lives: hosted online or on your own computer. If mdbase is new to you, start with mdbase and TaskNotes for a plain-language explanation of the format, Connect desktop app, and hosting choices. For a video and written setup steps, follow Connect TaskNotes to mdbase. Hosted mdbase# Hosted mdbase is the recommended choice for convenient access across the web, Android, and iOS. The provider keeps the main collection online, so it is available from any TaskNotes device with a network connection and can deliver reminders while TaskNotes is closed. TaskNotes reads and writes the hosted collection directly. It does not keep a separate offline copy, so you need a network connection to open the collection or make changes. Connect to a computer# mdbase Connect can make a Markdown collection on your computer available to TaskNotes. Requests and responses travel through an end-to-end encrypted relay; the relay cannot read your task contents and you do not need to open a port on your router. The computer holds the main copy, so it must be awake, online, and running the mdbase Connect background service whenever you use TaskNotes. See how to install mdbase Connect and use a computer collection. Change collections later# Open Settings and choose Change collection. Opening another collection does not copy or move records from the collection you were using."},{"title":"Connect TaskNotes to mdbase","url":"/app/connect-mdbase/","description":"Watch how to connect hosted mdbase collections and existing local folders to the TaskNotes app, with written steps and a transcript.","product":"app","text":"Your browser cannot play this video. Download the MP4 or read the written steps and transcript below. 3 minutes 53 seconds · Silent walkthrough with on-screen instructions and visible cursors. Use the player’s fullscreen control for a closer view. Download the video · Read the transcript These instructions are for the web, Android, and iOS app, not the Obsidian plugin. The recording uses disposable demo data in the LAB test environment. Account sign-in and OS-specific installer dialogs are omitted. The folder chooser and Markdown editor shown are Linux examples; the connection steps apply across platforms. TaskNotes is in beta, so some labels may change. Choose where your collection lives# Hosted by mdbase: available online even when your computer is off. You need an internet connection, but not the desktop Connector to use TaskNotes. On your computer: files stay in a local folder. Keep that computer reachable and mdbase Connect running while other devices use the collection. Hosted collections can also be mirrored to your computer, so you can work with local Markdown files. Mirror setup is outside this walkthrough. The same TaskNotes app works with either. Read What is mdbase? for more background or Choose a collection for a fuller comparison. Connect a hosted collection# Open TaskNotes or its Android or iOS app and choose a collection. Sign in to mdbase if asked. Select a collection labelled Hosted by mdbase, then choose Review access. Review the named application, collection, requested actions, and setup changes. Approve only if you agree. For a collection needing TaskNotes definitions, the button reads Set up and allow access. Return to TaskNotes and add a task. It is saved in the hosted collection. If you do not have a hosted collection, expand Add or connect another collection → Create hosted collection in mdbase. Creating a collection and approving TaskNotes access are separate steps. Connect an existing local folder# Visit the mdbase Connect download page and choose the desktop app for your operating system and processor. Follow the current platform installation and beta security guidance, then open mdbase Connect. The standalone CLI download does not include the desktop interface. Name your computer and choose Continue in browser. Sign in if asked, approve the computer, then return to the desktop app and wait for it to connect. Open Collections → Add existing. Select the collection root containing mdbase.yaml, not just its tasks subfolder. Adding the folder validates it in place; it does not move or upload its files. Open the collection chooser in TaskNotes and select the collection listed under your connected computer. If TaskNotes already has a collection open, use Settings → Change collection → Connect another collection. Review and approve the requested access and setup changes if you agree. If TaskNotes subsequently asks, review Apply reviewed setup as well. Add a task and inspect its Markdown file in the collection. Completing the task updates that file’s status to done. You can use any Markdown editor; the video uses VS Code. TaskNotes does not open the folder directly or maintain a durable offline copy. Your computer remains the main copy and must be reachable for remote access. See Connection and availability if the collection cannot be reached. Switch an existing connection# Open Settings → Change collection and select a collection you have already approved. Connect another collection returns to mdbase to approve access to another one. Switching collections does not copy or move their records. Transcript# Read the full video transcript 00:00 — This video shows how to connect mdbase collections to the TaskNotes app. We’ll start with a hosted collection, then connect an existing folder on your computer. 00:08 — Hosted by mdbase: available online, even when your computer is off. No desktop Connector needed for TaskNotes. 00:14 — Hosted collections can also be mirrored to your computer, so you can work with local Markdown files. 00:21 — On your computer: files stay in an existing folder. Keep mdbase Connect running and the computer reachable. The same TaskNotes app works with either. 00:29 — Start with hosted: open app.tasknotes.dev and choose a collection. 00:37 — Select a collection labelled Hosted by mdbase, then review access. 00:50 — Review the permissions, then approve access if you agree. 01:00 — Add a task. It is saved in your hosted collection; no local computer is needed. 01:14 — Already have an mdbase collection on your computer? Connect that folder to TaskNotes without moving its files. 01:22 — For a local folder, first get the desktop app at mdbase.dev/downloads. 01:35 — Install and open mdbase Connect. 01:39 — Name this computer, then choose Continue in browser. 01:49 — Sign in if asked, then approve this computer. 02:00 — In Collections, choose Add existing and select your collection folder. 02:09 — Choose the folder containing mdbase.yaml. Its files stay where they are. 02:15 — Back in TaskNotes, open the mdbase collection chooser. 02:21 — Select the collection listed under your connected computer. 02:35 — Review the requested access and setup changes, then approve if you agree. 02:44 — Add a task to the local collection. 02:59 — Each task is a Markdown file. Changes you make in TaskNotes are saved back to the collection. 03:06 — The task is now a Markdown file in your existing folder. 03:11 — Keep mdbase Connect running while other devices use this folder. 03:15 — Once both are connected, switch collections in Settings → Change collection. 03:24 — Choose a collection you have already approved. 03:37 — In the local collection, complete the task. 03:46 — The same Markdown file now says status: done."},{"title":"Connection and availability","url":"/app/connection/","description":"Understand when TaskNotes can reach hosted and computer-connected mdbase collections.","product":"app","text":"TaskNotes reads and writes the selected mdbase collection directly. It does not keep a separate offline collection or a queue of changes waiting to sync. What each status means# Status Meaning Connected TaskNotes can read and change the selected collection Connecting TaskNotes is checking the collection connection Collection unavailable The hosted service or connected computer cannot be reached Open More to see the current status and use Refresh now to read the latest collection state. Hosted collections# A hosted collection needs a network connection and an available hosted mdbase service. If either is unavailable, TaskNotes cannot open the collection or save changes. Reconnect the collection if its authorization has expired. Collections on your computer# A computer collection also needs the computer holding the Markdown to be awake, online, and running the mdbase Connect background service. TaskNotes reaches it through the end-to-end encrypted relay. If the computer becomes unavailable, access returns when the computer and connector return. During a connection problem# Tasks already visible in the current session may remain on screen during a short interruption, but TaskNotes cannot safely save new changes until mdbase is reachable. A failed action is not silently queued for later. If the problem continues, open More and choose Change collection to use another mdbase collection."},{"title":"Interactive demo","url":"/app/demo/","description":"Explore the TaskNotes app with disposable sample tasks before connecting a collection.","product":"app","text":"Explore the TaskNotes app using a disposable collection of sample tasks. You can complete and edit tasks, use Scratchpad, search, and move between views without signing in or connecting a collection. The demo keeps changes only for the current session. Reloading or resetting it starts again with the original sample data."},{"title":"Get started with the TaskNotes app","url":"/app/getting-started/","description":"Open TaskNotes, connect an mdbase collection, create a task, and find your way around the app.","product":"app","text":"TaskNotes app is currently in beta. Features, availability, and setup steps may change before the stable release. The app supports TaskNotes v5 collections based on the mdbase 0.3.0 specification. 1. Open TaskNotes# Use app.tasknotes.dev in a supported browser or install the Android or iOS application when it is available through its store. The web and native applications use the same task interface. 2. Choose a collection# TaskNotes opens every collection through mdbase. In the collection chooser, select one labelled Hosted by mdbase or one listed under your connected computer. Read What is mdbase? if this is new to you, then Choose a collection to compare the two options. Follow Connect TaskNotes to mdbase for a short video, written steps, and a transcript covering hosted collections first, then existing local folders. 3. Create a task# Use Add task, enter a title, and save. Capture understands the collection's configured status, priority, project, context, and tag values. 4. Review the starter views# Open Today for current work, Upcoming for scheduled tasks, and Views for the complete collection of lists, boards, calendars, and project views. Navigation belongs to the current collection and can be reordered from Views. 5. Check collection status# Open Settings to see the collection location, connection state, last refresh, notification access, task model settings, and appearance preference."},{"title":"mdbase and TaskNotes","url":"/app/mdbase/","description":"Understand how TaskNotes uses hosted mdbase or the encrypted relay to reach a collection on your computer.","product":"app","text":"mdbase lets TaskNotes work with a portable Markdown collection instead of hiding your tasks in a TaskNotes-only database. Every TaskNotes session opens one mdbase collection: either a collection hosted online or one kept on your computer and reached through the encrypted relay. What is mdbase?# Two related names appear in TaskNotes: mdbase is the open collection format and specification. A collection is a folder of Markdown files plus a small description of what those files mean. mdbase Connect is the access service TaskNotes uses to ask for permission and connect to a hosted collection or a collection on your computer. Read the mdbase introduction for a visual explanation of the wider ecosystem. What it gives TaskNotes# TaskNotes understands what a task looks like inside an mdbase collection. That compatibility is defined by the TaskNotes v5 collection format and its mdbase 0.3.0 binding. That means TaskNotes can: use the same task fields, projects, tags, saved views, and settings on the web, Android, and iOS; ask for access to one collection without seeing your other folders; and keep reminders running while TaskNotes is closed when your collection supports them. Behind the scenes, mdbase checks that each change is valid and writes it to the main collection. You still own readable Markdown files rather than a database that only TaskNotes can open. How the connection works# The mdbase collection is the source of truth. TaskNotes reads and writes it directly and does not keep a separate offline collection, so opening tasks and saving changes require a connection. Choice Where the Markdown lives What must be available Hosted mdbase With the hosted provider Your device must have a network connection Connect to your computer In a folder on your computer Both devices must be online, and your computer must be running mdbase Connect Choose a collection compares the TaskNotes behavior of these options in more detail. Connect TaskNotes to mdbase shows both connection flows in a short video, with written steps and a transcript. Use a collection on your computer# Install the Electron-based mdbase Connect desktop app to make a folder on your computer available to TaskNotes. It runs a small background service that keeps TaskNotes connected to the Markdown folder. The download also includes command line tools. The mdbase editor is online and is not part of the desktop app. Open the mdbase Connect download page and choose the package for macOS, Windows, or Linux. Install and open mdbase Connect. Follow any platform-specific beta installation notes shown on the download page. Add an existing mdbase folder on the computer, or create a collection. In TaskNotes, choose Connect to a computer and select that collection. Review the requested actions and approve the connection. TaskNotes requests and responses travel through an end-to-end encrypted relay. The relay passes the encrypted data along but cannot read your task contents. You do not need to open an inbound port on your router. The background service on your computer checks that TaskNotes has permission, then reads or changes the Markdown files. It does not create another hosted or offline copy of the collection. Do I need to leave my computer on?# Yes. Your computer holds the main copy, so it is part of the connection: It must be awake, connected to the internet, and running the mdbase Connect background service whenever TaskNotes needs remote access. Sleep, shutdown, a network outage, or a stopped connector makes the collection unavailable until the computer returns. Reminder delivery also depends on the computer remaining available. You are responsible for the computer's security, disk health, and backups. This works well for an always-on desktop or home server. It is less convenient for a laptop that sleeps or travels regularly. Hosted mdbase removes the always-on-computer requirement, but it moves the main copy to a provider you must trust. Both choices require a network connection while you use TaskNotes. For more detail about how Connect protects and routes your data, read How mdbase Connect works. A practical recommendation# Choose Hosted mdbase if dependable access across several devices and reminder delivery matter most. Choose Connect to a computer if keeping the main Markdown folder on your own machine matters more and that machine can remain available."},{"title":"App integration manifest","url":"/app/reference/manifest/","description":"Generated reference for the TaskNotes app's mdbase integration requirements and capabilities.","product":"app","text":"This page is generated from the integration manifest shipped by TaskNotes app 1.0.3. Field Value Application ID dev.tasknotes.app Manifest version 1 Homepage http://127.0.0.1:4173/ Collection access full_collection Required contracts# tasknotes.task version 0.3.0-rc.3 File capabilities# list read add replace move delete Notification criteria# task.reminder listens for mdbase.runtime.timer.fired version 1.0.0."},{"title":"Reminders in the TaskNotes app","url":"/app/reminders/","description":"Understand reminder data, notification delivery, permissions, and collection requirements.","product":"app","text":"Task records can contain relative reminders anchored to scheduled or due dates, or absolute reminders fixed to a particular time. Saving reminder data does not by itself guarantee notification delivery. Delivery by collection# Collection Reminder data Notification delivery Hosted mdbase Saved in the collection Available after opt-in Computer through the relay Saved in the collection Available while the computer and connector remain available For mdbase collections, the authority schedules reminder events so delivery does not depend on one TaskNotes screen remaining open. Notification payloads are content-free; selecting one refreshes authorized collection state in the app. Turn on reminders# Open More, select Turn on reminders, and approve the browser or operating system permission. Some existing mdbase grants require Review notification access before the channel can be enabled. An unsupported or insecure browser reports that notification delivery is not available. The reminder definitions remain in the task record."},{"title":"Work with tasks","url":"/app/tasks/","description":"Capture, edit, organize, complete, archive, and search tasks in the TaskNotes app.","product":"app","text":"A task opens beside its source view on wider screens. Capture# Use Add task from navigation or from a saved view. When a view has safe creation defaults, TaskNotes applies them automatically so the new task remains in that view. Edit# A task can contain: Status and priority Scheduled and due dates Markdown notes Projects, contexts, and tags Dependencies and subtasks Collection-defined custom properties Time estimates and tracked sessions Recurrence and occurrence-note policies Relative and absolute reminder definitions Background saves remain ordered if you navigate away while a write is still in progress. Complete, archive, and delete# Complete a task from its row or detail screen. Archive retains the record and may move its Markdown file according to collection settings. Delete offers a short undo period before committing the removal. Search# Search runs across the current collection and matches titles, notes, projects, contexts, and tags. Use Refresh now under More if a change made by another tool does not appear yet."},{"title":"Troubleshoot the TaskNotes app","url":"/app/troubleshooting/","description":"Diagnose mdbase connection, authorization, refresh, and notification problems in the app.","product":"app","text":"Start by recording the app version, platform, collection type, collection status shown under More, and the smallest sequence that reproduces the problem. The collection is unavailable# For a hosted collection, confirm that the device is online and try Reconnect this collection. For a computer collection, also confirm that the computer holding the Markdown is awake, online, and running mdbase Connect. An authorization error appears# Use the reconnect action for the current collection and review the access that mdbase requests. If you no longer want to use that collection, open More and choose Change collection. A change did not save# TaskNotes writes directly to mdbase and does not queue failed changes for later. Restore the connection, then retry the action. Capture and editing screens keep recoverable input visible when they can do so safely. A change from another tool is missing# Open More and choose Refresh now. If the record still does not appear, confirm that the other tool wrote to the same mdbase collection and that the record uses a compatible TaskNotes task definition. Notifications do not arrive# Confirm that the current collection is an mdbase collection, reminders are enabled in More, the browser or operating system permission is granted, and the task contains a valid future reminder. For a computer collection, the computer and mdbase Connect must remain available."},{"title":"Views and navigation","url":"/app/views/","description":"Use and arrange lists, boards, calendars, projects, and saved views in the TaskNotes app.","product":"app","text":"Views are saved ways of selecting, sorting, grouping, and presenting records in a collection. They travel with the collection; the set pinned to navigation is a preference on each device. The Views manager controls navigation order and saved view definitions. Starter views# TaskNotes creates managed starter views such as Today, Upcoming, Calendar, and Projects. They use the same saved-view catalog as user-created views while providing focused presentations for common work. Presentations# Task list supports grouping, visible properties, section moves, and manual ordering. Kanban groups tasks into columns and can update the grouped property when a task moves. Calendar shows task dates in month, week, day, and list layouts. Mini calendar combines a month picker with tasks for the selected day. Projects finds project records referenced by active tasks. Navigation# Open Views to add or remove a view from navigation and to change its order. The first navigation item is the collection's home. Mobile displays the first three views directly and keeps the rest in the Views destination. Create and edit views# The view editor controls the name, presentation, query, grouping, sort order, visible properties, and safe defaults for tasks created from the view. View documents remain ordinary collection resources rather than being stored only inside the TaskNotes app."},{"title":"Portable task records","url":"/concepts/task-records/","description":"The Markdown records, collection configuration, and task concepts shared by TaskNotes clients.","product":"shared","text":"A TaskNotes task is an ordinary Markdown record with structured properties. Those properties describe the task; the Markdown body remains available for notes, checklists, links, and supporting detail. Collections# A collection is a group of records plus the configuration that explains how to interpret them. The configuration defines field names, statuses, priorities, custom properties, record locations, and saved views. The TaskNotes app uses collection throughout. The Obsidian plugin usually describes the containing folder as a vault and presents saved views through Obsidian Bases. Source of truth# Where the authoritative copy lives depends on the client and connection: Client and collection Source of truth Availability TaskNotes app · hosted mdbase Hosted collection Requires a network connection TaskNotes app · computer through relay Collection on that computer Requires the network, computer, and connector Obsidian vault Markdown files in the vault Controlled by Obsidian and your sync choice Portability and compatibility# Portable does not mean every client exposes every feature. Inline task widgets, Obsidian commands, external calendar integrations, and companion plugins belong to the Obsidian client. mdbase collection access and background reminder delivery belong to the TaskNotes app. Use the client-specific guide for interface instructions and the specification for normative data semantics."},{"title":"0. Overview","url":"/developers/specification/","description":"TaskNotes is an Obsidian plugin that stores tasks as individual markdown files with YAML frontmatter in a user's vault. Each task is a first-class file: readable and editabl...","product":"specification","text":"0.0 About tasknotes# TaskNotes is an Obsidian plugin that stores tasks as individual markdown files with YAML frontmatter in a user's vault. Each task is a first-class file: readable and editable with any text editor, version-controllable, and searchable without special tooling. A minimal task file looks like this: --- title: Buy groceries status: open priority: normal due: 2026-02-21 tags: [task] dateCreated: 2026-02-20T11:15:00Z dateModified: 2026-02-20T11:15:00Z --- Buy fruit and cleaning supplies. Tasks are identified within the vault by a configurable detection method — by default, by the presence of a specific tag (e.g. #task in body or frontmatter). The plugin stores its configuration in .obsidian/plugins/tasknotes/data.json within the vault root. This specification was derived from the behavior of the tasknotes plugin and is intended to serve as a stable, testable contract for: CLI tools and scripts that process task files outside Obsidian, any application that wants to interoperate with a tasknotes vault. The spec is deliberately language-agnostic. It does not require any particular runtime, and the executable conformance suite (in conformance/) can be driven by an adapter written in any language. The tasknotes plugin is the primary reference for how this spec was derived, but the specification is normative — where the spec and the plugin behavior differ, the spec defines the intended behavior. Known deviations are disclosed via conformance claims (§7.5). 0.1 Status and authority# This document is part of tasknotes-spec version 0.3.0-rc.3. This specification is normative for implementations that claim conformance. No single implementation is normative; implementations are expected to conform to the specification. 0.2 Motivation# TaskNotes-style systems store tasks as markdown files with YAML frontmatter. This model has practical advantages: Task records are plain files that can be inspected and edited without proprietary tooling. Data remains portable across environments. Files are suitable for version control and collaboration workflows. As soon as more than one tool reads and writes the same task files, implicit assumptions become an interoperability risk. In practice, these risks appear in three areas: Field semantics and naming drift. Date and timezone interpretation differences. Recurring-task state transitions that are handled differently by different clients. When these rules are not explicit, users can get inconsistent results from equivalent operations. A shared specification reduces that risk by making behavior testable and versioned. 0.3 Objectives# This specification defines a stable contract for: Representing task records in markdown frontmatter. Mapping storage keys to canonical semantic roles. Defining effective collection configuration via provider model (for example tasknotes.yaml and/or TaskNotes data.json). Interpreting date and datetime values consistently. Applying recurrence, per-instance completion/skip behavior, and optional materialized occurrence notes. Managing time tracking sessions and time_entries lifecycle behavior. Parsing and resolving links consistently across task fields. Defining dependency and reminder behavior. Optionally applying deterministic create-time templating behavior. Executing write operations with predictable side-effects. Validating task records and reporting issues. 0.4 Non-objectives# This specification does not standardize: UI layout, styling, command palettes, or interaction design. Internal caching architecture or rendering pipelines. Transport protocols (HTTP, IPC, etc.) except where they affect persisted task semantics. Rich template-language features beyond the portable create-time templating contract in §5/§7/§9. 0.5 Scope# This specification is standalone. It does not require conformance to any other specification. Implementations MAY internally reuse other libraries or specifications, but conformance claims under tasknotes-spec are evaluated only against this document. Templating is optional and profile-gated; implementations that do not claim the templating profile remain conformant without template support. References to TaskNotes plugin behavior, Obsidian behavior, or external specifications are informative context only unless this specification explicitly marks a requirement as normative. 0.6 Design principles# 0.6.1 File-first persistence# Task state is represented in user-visible files. Derived indexes and caches are non-canonical. 0.6.2 Deterministic semantics# Equivalent inputs MUST produce equivalent persisted outputs under the same configuration and active runtime timezone. 0.6.3 Explicit mapping# Semantic roles are canonical. Storage key names are configurable and therefore must be mapped explicitly. 0.6.4 Backward evolution# The specification supports migration from legacy keys and historical behaviors through explicit compatibility rules. 0.7 Conformance# Conformance is profile-based (see §7). A minimal implementation can conform to a narrow profile while remaining interoperable for core operations. 0.8 Normative language# The key words MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY are to be interpreted as described in RFC 2119. 0.9 Example collection# A default tasknotes vault looks like this: MyVault/ ├── TaskNotes/ │ ├── Tasks/ │ │ ├── buy-groceries.md ← task file (title-derived filename by default) │ │ └── weekly-review.md │ └── Archive/ ← archive folder (if moveArchivedTasks=true) ├── .obsidian/ │ └── plugins/ │ └── tasknotes/ │ └── data.json ← plugin settings (primary config provider) └── tasknotes.yaml ← optional spec-level config (secondary provider) Task files are identified by the #task tag by default (configurable). The full default collection state is described in §9.21. Configuration provider semantics and effective configuration rules are defined in §9. An implementation MAY use either provider, both, or additional providers, based on its documented precedence policy. A task file example (using default field mapping): --- title: Buy groceries status: open priority: normal due: 2026-02-21 tags: [task, errands] contexts: [\"town\"] dateCreated: 2026-02-20T11:15:00Z dateModified: 2026-02-20T11:15:00Z --- Buy fruit and cleaning supplies. 0.10 Versioning policy# This specification uses semantic versioning. A major version introduces breaking semantic changes. A minor version introduces additive behavior or optional features. A patch version clarifies wording or fixes non-breaking defects. Implementations MUST reject unsupported major versions when strict mode is enabled. 0.11 Change governance# Specification changes SHOULD be accompanied by: a motivation statement, precise normative edits, migration notes when behavior changes, updated examples."},{"title":"1. Terminology","url":"/developers/specification/01-terminology/","description":"This section defines terms used normatively in this specification.","product":"specification","text":"This section defines terms used normatively in this specification. 1.1 Collection# A collection is a filesystem scope within which task files are discovered and managed under a single TaskNotes configuration. 1.2 Task file# A task file is a markdown file identified as a task record by collection rules. 1.3 Frontmatter# Frontmatter is the YAML block at the start of a markdown file delimited by --- markers. 1.4 Task record# A task record is the semantic task object obtained from parsing a task file frontmatter (plus optional derived metadata). 1.5 Semantic role# A semantic role is a canonical meaning defined by this specification, independent of storage key names. Examples: title, status, date_created, complete_instances. 1.6 Storage key# A storage key is the YAML property name used in frontmatter. Examples: dateCreated, date_created, completedDate. 1.7 Field mapping# Field mapping is the configuration that maps semantic roles to storage keys for reads and writes. 1.8 Alias# An alias is a non-canonical storage key accepted for compatibility during reads. 1.9 Canonical write key# The canonical write key is the configured storage key that conforming writers use for persisted output. 1.10 Date value# A date value represents a calendar day with no time-of-day and no timezone. Canonical form: YYYY-MM-DD. 1.11 Datetime value# A datetime value represents an instant in time. Canonical form: ISO 8601 UTC with trailing Z. 1.12 Target date# A target date is the calendar date to which a recurrence instance operation applies (for example complete instance on 2026-02-20). 1.13 Recurrence rule# A recurrence rule is a tasknotes recurrence string stored in the recurrence semantic role. It uses RFC 5545 RRULE-style parameters inside a single semicolon-delimited field value and MAY include an explicit inline DTSTART prefix segment as defined in §4.3. 1.14 Recurrence anchor# Recurrence anchor defines how next-instance progression is computed. Allowed values: scheduled completion 1.15 Complete instances# Complete instances is the set/list of target dates marked completed for a recurring task. 1.16 Skipped instances# Skipped instances is the set/list of target dates marked skipped for a recurring task. 1.17 Materialized occurrence note# A materialized occurrence note is a task file created for one target date of a recurring parent task. It stores user-authored per-occurrence content and, when supported by the implementation, owns the authoritative task state for that occurrence date. 1.18 Recurrence parent# A recurrence parent is the recurring task record referenced by a materialized occurrence note. The reference is stored in semantic role recurrence_parent and resolved as a link according to §11. 1.19 Occurrence materialization# Occurrence materialization is the creation and reconciliation of materialized occurrence notes from a recurring parent task according to §4.18 and §5.20. 1.20 Effective status# Effective status is the status presented for a given date context after applying recurrence instance state. 1.21 Completed-status list# The completed-status list is the configured ordered list of status values treated as completed for non-recurring completion semantics. When a single value must be chosen deterministically, the first list entry is used unless explicit operation input overrides it. 1.22 Idempotent operation# An operation is idempotent if applying it multiple times with the same input produces the same persisted state as applying it once. 1.23 Unknown field# An unknown field is a frontmatter property not mapped to a semantic role in current configuration. 1.24 Validation issue# A validation issue is a structured report containing at least: machine-readable code, severity, optional path/field context, human-readable message. 1.25 Strict validation mode# Strict validation mode is a mode where invalid required semantics are treated as hard errors and write operations fail. 1.26 Legacy compatibility mode# Legacy compatibility mode is a mode where specific historical behaviors or aliases are accepted for migration but are not canonical for new writes. 1.27 Configuration provider# A configuration provider is an adapter that loads configuration from a source (for example tasknotes.yaml or .obsidian/plugins/tasknotes/data.json) and normalizes it to the schema in §9. 1.28 Effective configuration# The effective configuration is the final resolved configuration after applying provider precedence and fallback rules. 1.29 Template file# A template file is a markdown document used at create time to generate frontmatter and/or body content through variable expansion. When templating is enabled, template behavior is defined by §5.3.5 and §9.14. 1.30 Template expansion# Template expansion is deterministic replacement of template variables with create-time task data and runtime date/time values, followed by template merge rules. 1.31 Time entry# A time entry is a structured record in time_entries containing startTime, optional endTime, and optional description. 1.32 Active time entry# An active time entry is a time entry with startTime present and endTime absent. 1.33 Time tracking management# Time tracking management is the set of operations that start, stop, edit, and remove time_entries, including completion-triggered auto-stop behavior when configured."},{"title":"2. Model and Field Mapping","url":"/developers/specification/02-model-and-mapping/","description":"A task record consists of:","product":"specification","text":"2.1 Task record model# A task record consists of: frontmatter object (structured fields), markdown body (freeform text), file metadata (path, created/modified time) where available. Frontmatter is normative for task semantics. Body content is non-normative except where an implementation exposes body search or body-derived features. 2.2 Required semantic roles# Conforming implementations MUST support these semantic roles: Semantic role Type Required title string support required (value required via configured title source, see §2.2.2) status string/enum yes completed_date date support required (conditionally required, see §2.2.1) date_created datetime yes date_modified datetime yes If storage omits a role marked yes, validation MUST report an error (see §6). For operation-required roles, validation and operation rules in §5 and §6 apply. 2.2.1 Conditional requiredness (completed_date)# completed_date support is mandatory, but presence is conditional: For non-recurring tasks with status in configured status.completed_values, completed_date MUST be present. For non-recurring tasks with non-completed status, completed_date MAY be absent. For recurring tasks, completed_date is not required by recurrence completion semantics and MAY be absent. Validators MUST apply this conditional rule and MUST NOT treat completed_date as unconditionally required. 2.2.2 Conditional requiredness (title)# Semantic title is always required, with deterministic read resolution and storage-mode-dependent read/write behavior: Readers MUST resolve semantic title using storage-mode-aware precedence (§9.13): when title.storage=frontmatter: mapped title key when present and non-empty, then file basename fallback; when title.storage=filename: file basename first, then mapped title fallback when basename is unavailable. If mapped title and filename-derived title both exist and differ, the source authoritative for active title.storage MUST win and implementations SHOULD emit title_source_conflict. When title.storage=filename, implementations MAY keep mapped title as a synchronized compatibility mirror, but filename-derived title remains authoritative. Title storage mode controls canonical writes (§9.13): frontmatter favors mapped-key writes; filename favors filename-derived title with rename-on-title-change behavior. Validators MUST enforce semantic title presence using the active title-resolution policy (§9.13), not frontmatter key presence alone. 2.3 Common semantic roles# Implementations conforming beyond minimal scope SHOULD support: Semantic role Type Notes id string stable task identity token; see §2.6.5 priority string/enum configurable values due date or datetime see §3 scheduled date or datetime see §3 tags list free tags contexts list commonly prefixed with @ projects list project references, see §11 attachments list ordered file references owned by the task, see §2.6.7 and §11.8.3 time_estimate integer >= 0 minutes time_entries list see §2.6 recurrence string tasknotes recurrence string; see §4 recurrence_anchor enum scheduled or completion complete_instances list recurring completion state skipped_instances list recurring skip state recurrence_parent link-or-string parent recurring task reference for materialized occurrence notes; see §4.18 occurrence_date date target date represented by a materialized occurrence note occurrence_materialization enum parent task materialization mode: manual, on_completion, or rolling occurrence_next_trigger enum parent task next-note trigger: completion or completion_or_skip occurrence_template link-or-string optional template used when creating materialized occurrence notes occurrence_past_horizon duration optional rolling materialization lookbehind bound occurrence_future_horizon duration optional rolling materialization lookahead bound blocked_by list dependency records, see §10 and §11 reminders list reminder records, see §10 Optional extended roles are defined in §7 profiles. 2.4 Field mapping requirements# 2.4.1 Mapping presence# An implementation MUST have an effective mapping from each supported semantic role to a canonical write key. Mapping configuration is defined in §9. If semantic role id is supported, it MUST also have a canonical write key. 2.4.2 Read behavior# Readers MUST: Read the canonical mapped key if present. Support configured aliases where enabled. Resolve conflicts deterministically when canonical and alias keys coexist. When canonical and alias keys both exist for the same semantic role, canonical key value MUST win. When canonical key wins over alias, validator/loader SHOULD emit warning alias_conflict_ignored. 2.4.3 Write behavior# Writers MUST: write only canonical keys, avoid introducing alias keys in new writes, preserve unknown fields unless the operation explicitly opts into normalization. 2.5 Legacy alias compatibility# Implementations SHOULD accept these aliases on read for interoperability: Semantic role Canonical example Alias examples recurrence_anchor recurrence_anchor recurrenceAnchor complete_instances complete_instances completeInstances skipped_instances skipped_instances skippedInstances recurrence_parent recurrence_parent recurrenceParent occurrence_date occurrence_date occurrenceDate occurrence_materialization occurrence_materialization occurrenceMaterialization occurrence_next_trigger occurrence_next_trigger occurrenceNextTrigger occurrence_template occurrence_template occurrenceTemplate occurrence_past_horizon occurrence_past_horizon occurrencePastHorizon occurrence_future_horizon occurrence_future_horizon occurrenceFutureHorizon date_created dateCreated date_created date_modified dateModified date_modified completed_date completedDate completed_date time_entries timeEntries time_entries time_estimate timeEstimate time_estimate blocked_by blockedBy blocked_by attachments attachments — This table is compatibility guidance, not a requirement to choose camelCase or snake_case as canonical. 2.6 Structured role schemas# 2.6.1 time_entries# time_entries items MUST be objects with: startTime datetime (required) endTime datetime (optional) description string (optional) Additional constraints: a task MUST NOT contain more than one active time entry (entry with startTime and no endTime) at commit time. an entry with missing endTime is interpreted as an active/running session. an implementation MAY accept duration on read for backward compatibility, but canonical duration is derived from start/end and SHOULD NOT be persisted on canonical writes. Nested key names in time_entries are fixed by this specification and are not independently configurable in mapping. 2.6.2 projects# projects SHOULD be represented as links when link semantics are supported, but plain strings MAY be accepted. When interpreted as links, parsing and resolution MUST follow §11. 2.6.3 blocked_by# blocked_by items MUST be objects with: uid link-or-string task reference (required) reltype enum (required; default allowed by §10 when omitted) gap ISO 8601 duration string (optional) Detailed semantics are defined in §10. uid parsing and resolution MUST follow §11. 2.6.4 reminders# reminders items MUST be objects with: id string (required) type enum absolute|relative (required) relative-only fields: relatedTo, offset absolute-only fields: absoluteTime description string (optional) Detailed semantics are defined in §10. 2.6.5 id (stable task identity)# When semantic role id is present: value MUST be a non-empty string. value MUST be treated as stable identity metadata and MUST NOT be rewritten by rename, move, or title-change operations. readers and link resolution MAY use it as an identity lookup key (see §11.4 Step 3). implementations SHOULD keep id unique within a collection; duplicate IDs SHOULD produce a validation issue. 2.6.6 Materialized occurrence roles# The roles in this subsection are required only for implementations claiming profile materialized-occurrences (§7.3.4). Parent recurring task roles: occurrence_materialization: enum manual|on_completion|rolling; controls when occurrence notes are created (§4.18.5). occurrence_next_trigger: enum completion|completion_or_skip; controls whether skip/cancel transitions advance creation of the next occurrence note (§4.18.6). occurrence_template: link-or-string reference to a template file used when creating occurrence notes. Link parsing/resolution follows §11 when supported. occurrence_past_horizon and occurrence_future_horizon: ISO 8601 durations used by rolling materialization (§4.18.7). Materialized occurrence note roles: recurrence_parent: link-or-string reference to the parent recurring task. Wikilinks are the default interoperable representation in Obsidian-oriented collections. occurrence_date: date value identifying the target date this occurrence note represents. Implementations claiming materialized-occurrences MUST treat recurrence_parent and occurrence_date together as the occurrence identity key. Within a resolved parent task, at most one materialized occurrence note SHOULD exist for each occurrence_date; duplicate notes MUST be reported when detected (§6.4). Materialized occurrence notes MAY also use normal task roles such as status, completed_date, scheduled, due, time_entries, reminders, contexts, projects, and body content. For dates where a materialized occurrence note exists, its own task state is authoritative as defined in §4.18.3. 2.6.7 attachments# attachments is the authoritative task-membership list for files associated with a task. It MUST be represented as an ordered list of non-empty link-or-string values. Each value MUST identify one collection file and MUST follow the parsing, resolution, and canonical-write rules in §11.8.3. The list itself intentionally contains references only. MIME type, byte size, content digest, storage revision, timestamps, and other binary metadata belong to the collection's file descriptor or filesystem metadata and MUST NOT be duplicated into canonical task frontmatter. The Markdown body MAY embed or link an attached file for inline presentation, but body links and embeds do not add or remove task membership. A file is a task attachment if and only if it appears in the mapped attachments list. Readers MAY accept a single scalar reference as compatibility input and normalize it to a one-item list. Canonical writes MUST use a list, preserve its order, and MUST NOT contain empty or duplicate normalized targets. 2.7 Unknown fields# Unknown frontmatter keys MUST be preserved by default during updates, complete/uncomplete, skip/unskip, dependency mutations, reminder mutations, and archive operations. Unknown fields MAY be removed only when: explicit normalization/migration is requested, or strict schema replacement is explicitly requested. 2.8 Example mapping# Example effective mapping: mapping: id: id title: title status: status date_created: dateCreated date_modified: dateModified completed_date: completedDate recurrence: recurrence recurrence_anchor: recurrence_anchor complete_instances: complete_instances skipped_instances: skipped_instances recurrence_parent: recurrence_parent occurrence_date: occurrence_date occurrence_materialization: occurrence_materialization occurrence_next_trigger: occurrence_next_trigger occurrence_template: occurrence_template occurrence_past_horizon: occurrence_past_horizon occurrence_future_horizon: occurrence_future_horizon time_estimate: timeEstimate time_entries: timeEntries blocked_by: blockedBy reminders: reminders 2.9 Example task record# --- id: task-2026-01-10-weekly-review title: Weekly review status: open priority: high scheduled: 2026-02-20 recurrence: FREQ=WEEKLY;BYDAY=FR recurrence_anchor: scheduled complete_instances: [2026-02-13] skipped_instances: [] blockedBy: - uid: \"[[prepare-metrics]]\" reltype: FINISHTOSTART gap: P1D reminders: - id: rem_day_before type: relative relatedTo: due offset: -P1D - id: rem_start type: absolute absoluteTime: 2026-02-20T09:00:00Z dateCreated: 2026-01-10T09:30:00Z dateModified: 2026-02-20T08:02:11Z --- Review completed work and plan next week. 2.10 Deterministic load example# Given frontmatter: recurrence_anchor: scheduled recurrenceAnchor: completion If canonical key is recurrence_anchor, a conforming loader using canonical-precedence policy MUST resolve semantic recurrence_anchor as scheduled and SHOULD emit a compatibility warning."},{"title":"3. Temporal Semantics","url":"/developers/specification/03-temporal-semantics/","description":"This section defines how implementations MUST interpret, compare, and serialize task-related date and datetime values.","product":"specification","text":"3.1 Purpose# This section defines how implementations MUST interpret, compare, and serialize task-related date and datetime values. 3.2 Supported temporal value classes# Implementations MUST support: Date values: calendar day without time or timezone. Datetime values: instant in time. 3.3 Canonical serialization# 3.3.1 Date# Canonical date serialization is: YYYY-MM-DD 3.3.2 Datetime# Canonical datetime serialization is UTC ISO 8601 with Z, for example: 2026-02-20T13:45:00Z Canonical datetime writes MUST use second precision (YYYY-MM-DDTHH:MM:SSZ) and MUST NOT include fractional seconds. Implementations MAY accept alternative inbound datetime forms but MUST normalize outbound canonical writes. If an accepted inbound datetime includes fractional seconds, writers MUST normalize deterministically by truncating fractional precision to whole seconds. 3.4 Parsing requirements# 3.4.1 Date parsing# Date parsing MUST reject invalid calendar dates. valid: 2026-02-28 invalid: 2026-02-30 3.4.2 Datetime parsing# Datetime parsing MUST reject malformed values. In strict mode, datetime parsing MUST reject ambiguous local datetimes without offset (for example 2026-02-20T09:00:00 with no timezone offset). In permissive mode, implementations MAY accept such values only under an explicitly documented compatibility policy and SHOULD emit a warning. 3.4.3 Mixed input tolerance# Implementations MAY accept both date and datetime values for roles like due and scheduled if configured to do so. The accepted form MUST be documented. 3.4.4 Inbound acceptance matrix# To avoid ambiguity, conforming parsers MUST follow this matrix. Date forms: Form Example Strict Permissive Canonical date 2026-02-20 accept accept Basic date (no separators) 20260220 reject (invalid_date_value) MAY accept only under documented compatibility policy; SHOULD emit warning Datetime forms: Form Example Strict Permissive Canonical UTC 2026-02-20T09:00:00Z accept accept ISO with explicit offset 2026-02-20T09:00:00+10:00 accept accept ISO with fractional seconds 2026-02-20T09:00:00.250Z accept (normalize to second precision on write) accept (normalize to second precision on write) Offset-less local datetime 2026-02-20T09:00:00 reject (invalid_datetime_value) MAY accept only under documented compatibility policy; SHOULD emit warning Space-separated datetime 2026-02-20 09:00:00 reject (invalid_datetime_value) MAY accept only under documented compatibility policy; SHOULD emit warning Basic datetime (no separators) 20260220T090000Z reject (invalid_datetime_value) MAY accept only under documented compatibility policy; SHOULD emit warning When permissive-mode compatibility accepts a non-canonical form, canonical writes MUST still follow §3.3. 3.5 Day semantics vs instant semantics# 3.5.1 Date roles# Date roles represent days, not instants, and MUST NOT be timezone-shifted. 3.5.2 Datetime roles# Datetime roles represent instants and MUST preserve instant equality through normalization. Example: input 2026-02-20T08:00:00-05:00 canonical write 2026-02-20T13:00:00Z 3.5.3 Implementation guidance: UTC-anchor strategy (non-normative)# Because date-only fields are human-readable (YYYY-MM-DD) while implementations often compute using datetime objects, a common strategy is to use a UTC-midnight anchor for date-only internals. Recommended approach: Parse date-only values to a UTC-midnight anchor instant for internal computations. Format date-only values from UTC calendar components when writing YYYY-MM-DD. Keep date-only roles as date-only on write unless an explicit conversion operation is requested. Evaluate user-facing day semantics (today, overdue, day grouping) using local calendar-day boundaries per §3.6. Implementations MAY use different internal representations as long as all normative requirements in this section are preserved. 3.6 Local calendar-day evaluation# 3.6.1 Active runtime timezone# For day-level semantics, the active runtime timezone is: the caller-provided temporal execution context, when present the collection authority's configured timezone the process/system local timezone. The timezone is runtime context, not TaskNotes type-binding configuration. A remote caller SHOULD send its current IANA timezone for interactive operations; a headless authority SHOULD use its durable collection timezone. Every operation MUST resolve this precedence once and use one effective timezone for all day-level semantics in that operation. Implementations MUST make the effective timezone discoverable. 3.6.2 Local calendar-day rules# When calculating day-level concepts (for example overdue/day grouping/calendar day cells), implementations MUST evaluate against local calendar-day boundaries of the active runtime timezone. This requirement prevents off-by-one day drift in positive and negative UTC offsets. 3.7 Comparison rules# 3.7.1 Date-to-date# Compare by calendar day ordering. 3.7.2 Datetime-to-datetime# Compare by instant ordering. 3.7.3 Date-to-datetime# If compared, implementations MUST document coercion policy. Recommended policy: convert date to local start-of-day for day-level comparisons, avoid implicit coercion for instant-level comparisons. 3.8 due and scheduled semantics# due and scheduled MAY be either date or datetime by configuration. Implementations MUST: preserve stored granularity unless explicit conversion is requested, avoid silently converting date to datetime during unrelated writes, require documented explicit policy for date-to-datetime conversion operations, apply consistent coercion policy in filters and status calculations. 3.9 Completion date semantics# completed_date is a date role. For non-recurring completion, writers MUST set completed_date using §5 semantics: explicit completion-day input when provided, otherwise current local day in active runtime timezone. 3.10 Created/modified timestamps# date_created and date_modified are datetime roles. Writers MUST: set both on create, update date_modified on successful mutating operations that change persisted state, preserve date_created unless explicit migration/edit operation changes it. 3.11 time_entries semantics# 3.11.1 Timestamp format# time_entries.startTime and time_entries.endTime MUST be datetime instants in canonical form on write. 3.11.2 Range validity# If both times exist, endTime MUST be greater than or equal to startTime. 3.11.3 Duration handling# If duration is present, implementations SHOULD treat it as derived and MAY rewrite or remove stale duration values during normalization. 3.11.4 Active session semantics# An entry with startTime and no endTime represents an active/running session. Implementations that support time-tracking management operations (§5.19) MUST enforce at most one active session per task at commit time. 3.11.5 Derived time calculations# For interoperability, implementations SHOULD expose both derived views when reporting tracked time: closed_minutes: sum of entries where both startTime and endTime exist. live_minutes: closed_minutes plus elapsed minutes of active entries (if any). Implementations MUST document which derived view is used by each reporting surface (for example task cards, stats, APIs). 3.12 reminder temporal semantics# Reminder time fields are governed by §10.3 and MUST follow canonical datetime and duration formats from this section. Rules: reminders[].absoluteTime MUST be a canonical datetime on write. reminders[].offset MUST be a valid ISO 8601 duration string. relative reminder base conversion for date-only values MUST use reminders.date_only_anchor_time from §9, or 00:00 local time if unset. 3.13 Example: local-day overdue evaluation# Assume local timezone America/Los_Angeles and local date 2026-02-20. Task A: due: 2026-02-19 status: open Task A is overdue. Task B: due: 2026-02-20 status: open Task B is not overdue at start of day; it becomes overdue on 2026-02-21 local day. 3.14 Example: preserving granularity# Before update: due: 2026-02-20 priority: normal Operation: update priority only. After update (conforming): due: 2026-02-20 priority: high Non-conforming behavior would silently rewrite due to a datetime. 3.15 Example: canonical datetime write# Input: timeEntries: - startTime: 2026-02-20T09:30:00+01:00 endTime: 2026-02-20T10:00:00+01:00 Canonical write: timeEntries: - startTime: 2026-02-20T08:30:00Z endTime: 2026-02-20T09:00:00Z 3.16 Example: UTC-anchor roundtrip for date-only field# Input: due: 2026-02-20 Internal computation anchor: 2026-02-20T00:00:00Z After unrelated update, conforming write: due: 2026-02-20 Non-conforming behavior would rewrite due as a datetime or shift it to another day based on local offset."},{"title":"4. Recurrence","url":"/developers/specification/04-recurrence/","description":"This section defines recurrence semantics, including rule representation, anchor behavior, and per-instance completion/skip state.","product":"specification","text":"4.1 Purpose# This section defines recurrence semantics, including rule representation, anchor behavior, and per-instance completion/skip state. 4.2 Recurrence applicability# A task is recurring when semantic role recurrence contains a valid tasknotes recurrence string. If recurrence is absent or empty, the task is non-recurring. 4.3 Rule format# 4.3.1 Required format# recurrence MUST be a tasknotes recurrence string. This syntax is RRULE-derived but is not a full RFC 5545 content line or multi-line iCalendar fragment. The RRULE parameter portion MUST use RFC 5545 RRULE property syntax. It MAY include a leading inline DTSTART segment. If DTSTART is present, it MUST use one of: DTSTART:YYYYMMDD (date-only) DTSTART:YYYYMMDDTHHMMSSZ (UTC datetime) Canonical combined form is: DTSTART:...;FREQ=... Implementations MAY accept inbound RRULE: prefixes or multi-line iCalendar-like inputs for compatibility, but canonical writes SHOULD use the combined single-field form above. Examples: FREQ=DAILY FREQ=WEEKLY;BYDAY=MO,WE,FR FREQ=MONTHLY;BYMONTHDAY=1 DTSTART:20260220;FREQ=WEEKLY;BYDAY=FR 4.3.2 Invalid rule handling# Invalid recurrence rules MUST produce a validation error in strict mode and SHOULD produce at least a warning in permissive mode. 4.4 Recurrence anchor# recurrence_anchor controls progression semantics and MUST be one of: scheduled completion If missing, implementations SHOULD default to scheduled unless collection configuration defines another default. 4.4.1 Recurrence seed precedence# When recurrence generation requires a seed/start date, implementations MUST resolve it in this order: DTSTART embedded in recurrence, semantic scheduled, semantic date_created. If no seed can be resolved, recurrence materialization MUST fail deterministically and validation MUST report an error. 4.4.2 Anchor progression behavior# For recurrence_anchor=scheduled, progression is based on the scheduled chain and DTSTART MUST remain fixed after it is set. For recurrence_anchor=completion, complete-instance operations MUST advance progression by updating DTSTART to the completion target (date or datetime per §4.4.3). 4.4.3 DTSTART update semantics# When recurrence_anchor=completion and instance completion succeeds for resolved target day D: Instance-list state (complete_instances, skipped_instances) MUST always use day D. If the caller provided an explicit datetime target, DTSTART MUST be rewritten as DTSTART:YYYYMMDDTHHMMSSZ using that target instant normalized to UTC. Otherwise, DTSTART MUST be rewritten as DTSTART:YYYYMMDD for day D. RRULE components other than DTSTART MUST be preserved unless an explicit recurrence-edit operation changes them. If DTSTART is absent, completion-anchor progression MUST insert it before RRULE parameters. 4.4.4 Recalculation semantics for recurrence_anchor=completion# When calculating the next candidate occurrence for recurrence_anchor=completion: Implementations MUST treat DTSTART progression as the consumed-history mechanism. complete_instances MUST NOT be used as an exclusion set for future occurrence selection in this mode. skipped_instances MUST still exclude matching candidate dates. Candidate selection MUST choose the first RRULE occurrence strictly after the current DTSTART anchor (or resolved seed if DTSTART is absent). This matches the completion-anchor progression model where each completion advances the chain by rewriting DTSTART. This model is intentionally not fully reversible via ordinary uncomplete instance; progression history lives in DTSTART, not only in complete_instances. 4.4.5 DTSTART canonicalization on recurring writes# To ensure stable recurrence materialization across implementations, writers that persist recurring tasks MUST ensure DTSTART is present after create or successful recurring-instance completion. Rules: If persisted recurrence already contains DTSTART, keep it unless an explicit operation updates it per §4.4.3. If persisted recurrence omits DTSTART, writers MUST resolve a seed using §4.4.1 and insert DTSTART before RRULE parameters. For recurrence_anchor=scheduled, inserted DTSTART becomes the fixed progression baseline and MUST NOT be rewritten by later scheduled-anchor completions. If seed resolution fails, operation MUST fail deterministically and emit missing_recurrence_seed. 4.5 Instance state fields# Per-instance state is represented by: complete_instances: list of date values skipped_instances: list of date values These lists represent day-level instance outcomes. 4.6 Invariants# Implementations MUST enforce: Items in instance lists are valid date values. No date appears in both lists simultaneously. Duplicate dates are normalized (set semantics) or rejected deterministically. Validators MUST NOT reject an instance date solely because it is not an RRULE-generated occurrence. 4.7 Instance completion semantics# Operation: complete instance for target date D. Conforming behavior: Add D to complete_instances. Remove D from skipped_instances if present. Leave base task status unchanged unless explicit policy states otherwise. Update date_modified when state changes. Operation MUST be idempotent. 4.8 Instance uncompletion semantics# Operation: uncomplete instance for target date D. Conforming behavior: Remove D from complete_instances if present. Do not add D to skipped_instances implicitly. For recurrence_anchor=completion, uncomplete MUST NOT rewrite or roll back DTSTART; restoring prior progression requires an explicit recurrence edit or implementation-specific rewind operation. Update date_modified when state changes. Operation MUST be idempotent. 4.9 Instance skip semantics# Operation: skip instance for target date D. Conforming behavior: Add D to skipped_instances. Remove D from complete_instances if present. Update date_modified when state changes. Operation MUST be idempotent. 4.10 Instance unskip semantics# Operation: unskip instance for target date D. Conforming behavior: Remove D from skipped_instances if present. Do not add to complete_instances implicitly. Update date_modified when state changes. Operation MUST be idempotent. 4.11 Effective instance state# For target date D, effective state MUST be resolved in this order: If D in complete_instances: state is completed. Else if D in skipped_instances: state is skipped. Else: state is unresolved/default for that instance. Because overlap is invalid, this ordering is deterministic. 4.12 Interaction with base status# For recurring tasks: Base status is task-level metadata and MUST NOT be forcibly rewritten to a completed status on instance completion unless explicitly configured. Instance state determines completion for recurrence-aware views and operations. Dependency blocked/unblocked evaluation for v0.1 follows §10.2.5 and is not recurrence-instance-aware unless explicitly extended by implementation policy. For non-recurring tasks, completion uses base status semantics (§5). 4.13 Completed-status configuration# Implementations MUST define which status values are treated as complete for non-recurring tasks. The completed-status list MUST be configurable or schema-driven and MUST NOT rely on a hardcoded single literal. 4.14 Example: complete then skip same day# Initial: recurrence: FREQ=DAILY completeInstances: [2026-02-20] skippedInstances: [] Skip target date 2026-02-20: recurrence: FREQ=DAILY completeInstances: [] skippedInstances: [2026-02-20] 4.15 Example: idempotent complete# Initial: completeInstances: [2026-02-20] skippedInstances: [] Complete 2026-02-20 again: persisted instance lists remain unchanged, operation succeeds without duplicate entries. 4.16 Example: anchor semantics# Task: recurrence: FREQ=WEEKLY;BYDAY=FR recurrenceAnchor: completion If implementation supports next-occurrence materialization, it MUST compute next occurrence relative to completion progression when anchor is completion, not solely by scheduled chain. Implementations using DTSTART progression MUST update DTSTART to the completion date for this mode. Worked example (recurrence_anchor=completion): recurrence: DTSTART:20260220;FREQ=DAILY recurrence_anchor: completion complete_instances: [2026-02-20, 2026-02-21] skipped_instances: [2026-02-23] Conforming recalculation: does not exclude 2026-02-22 because it is absent from skipped_instances, does exclude 2026-02-23 because it is skipped, ignores complete_instances for future exclusion in this mode (§4.4.4). 4.17 Validation examples# Invalid overlap: completeInstances: [2026-02-20] skippedInstances: [2026-02-20] Result: validation error instance_state_overlap. Invalid date in list: completeInstances: [2026-02-30] Result: validation error invalid_date_value. 4.18 Recurrence materialization# This subsection is required only for implementations claiming profile materialized-occurrences (§7.3.4). Recurrence materialization creates ordinary task files for specific target dates of a recurring parent task. It is additive behavior: implementations that do not claim materialized-occurrences continue to use the instance-list model in §4.5-§4.12. Materialized occurrence notes MUST be task files according to the collection's task-detection rules (§9.7). 4.18.1 Parent and occurrence ownership# The parent recurring task owns series-level semantics: recurrence recurrence_anchor recurrence generation and DTSTART progression parent instance-list compatibility state (complete_instances, skipped_instances) materialization policy fields (occurrence_materialization, occurrence_next_trigger, occurrence_template, occurrence_past_horizon, occurrence_future_horizon) A materialized occurrence note owns per-date task semantics for its occurrence_date, including: status completed_date body content and checklists time_entries per-occurrence due, scheduled, reminders, contexts, projects, and unknown fields 4.18.2 Occurrence identity and parent reference# A materialized occurrence note MUST store: recurrence_parent: a link-or-string reference to the parent recurring task occurrence_date: the target date represented by the occurrence note The preferred Obsidian-compatible representation for recurrence_parent is a wikilink, for example: recurrence_parent: \"[[Weekly Review]]\" occurrence_date: 2026-02-27 Implementations claiming materialized-occurrences MUST resolve recurrence_parent using §11 link semantics for this role, even if they do not claim full extended. If the parent cannot be resolved, validation SHOULD report invalid_recurrence_parent. For one resolved parent, there SHOULD be at most one materialized occurrence note per occurrence_date. Duplicate detected occurrence notes SHOULD report duplicate_occurrence_note and MUST NOT be chosen nondeterministically for writes. 4.18.3 Effective state precedence# For target date D, recurrence-aware effective state MUST be resolved in this order: If a materialized occurrence note exists for (parent, D), derive state from that note's own task state: completed when its status is in status.completed_values; skipped when its status is in status.skipped_values; otherwise unresolved/default for that instance. Else if D is in parent complete_instances: state is completed. Else if D is in parent skipped_instances: state is skipped. Else: state is unresolved/default for that instance. If a materialized occurrence note disagrees with the parent instance lists, the materialized occurrence note wins for D. Validators SHOULD report occurrence_state_conflict, and repair/normalization operations MAY update parent lists to match occurrence notes. 4.18.4 Parent instance lists as compatibility state# When materialized occurrence notes are supported, parent complete_instances and skipped_instances remain part of canonical persisted state. They serve as interoperability state for unmaterialized occurrences and as a compatibility index for clients that do not read occurrence notes. Conforming writers SHOULD reconcile parent lists after materialized occurrence completion, skip, uncompletion, or unskip: completed child state: add D to complete_instances, remove D from skipped_instances; skipped child state: add D to skipped_instances, remove D from complete_instances; active/unresolved child state after uncompletion/unskip: remove D from the relevant parent list. Reconciliation failure MUST NOT silently change the occurrence note state. Implementations SHOULD surface a recoverable error or warning. 4.18.5 Materialization modes# occurrence_materialization controls when materialized occurrence notes are created. Allowed values: manual: occurrence notes are created only by explicit user or API action. on_completion: completing a materialized occurrence note creates the next occurrence note. rolling: the implementation maintains a bounded materialized window, such as today through the next 14 days. If absent, occurrence_materialization MUST default to manual. on_completion does not by itself create the first occurrence note in a series. The first materialized occurrence MUST be created by explicit materialization, rolling materialization, or a documented create-time option. Conforming implementations MUST NOT create occurrence notes merely as a side effect of read-only browsing. 4.18.6 Next-occurrence trigger# occurrence_next_trigger controls whether skip/cancel transitions also create the next occurrence note when occurrence_materialization=on_completion. Allowed values: completion: only completion creates the next occurrence note. completion_or_skip: completion and skip/cancel create the next occurrence note. If absent, occurrence_next_trigger MUST default to completion. The next occurrence MUST be computed from the parent recurring task after applying the triggering state transition and §4.4 anchor semantics. Materializing the next occurrence MUST be idempotent: if the next occurrence note already exists, the operation MUST return or reuse it rather than creating a duplicate. 4.18.7 Rolling materialization bounds# For occurrence_materialization=rolling, implementations MUST enforce finite bounds. Unbounded future materialization is non-conformant. Bounds SHOULD be expressed with ISO 8601 durations such as: occurrence_past_horizon: P0D occurrence_future_horizon: P14D If bounds are absent and rolling mode is enabled, implementations MUST use documented finite defaults. 4.18.8 Recurrence edits and historical notes# Materialized occurrence notes are durable task files. Editing the parent recurrence rule MUST NOT silently delete, rewrite, or move existing materialized occurrence notes. If an existing occurrence note's occurrence_date is no longer generated by the current parent recurrence rule, validators MAY report materialization_target_not_generated as a warning. This condition MUST NOT be treated as an error by default because recurrence edits can make historical notes intentionally non-generated."},{"title":"5. Operations","url":"/developers/specification/05-operations/","description":"This section defines normative behavior for task mutations and read-facing resolution concerns that affect persisted state.","product":"specification","text":"5.1 Purpose# This section defines normative behavior for task mutations and read-facing resolution concerns that affect persisted state. 5.2 General operation rules# For all mutating operations: Validation MUST run before commit in strict mode. Writes MUST be atomic at file level (all-or-nothing per file). date_modified MUST be updated on successful state change. Unknown fields MUST be preserved unless explicit normalization is requested. This applies to every operation in this section: create, update, complete, uncomplete, skip, unskip, dependency mutations, reminder mutations, archive, and time-tracking operations. Operations identified as idempotent MUST remain safe under repetition. 5.2.1 Target day/date resolution# Recurring instance operations act on a target day/date (complete instance, uncomplete instance, skip, unskip). Non-recurring complete uses completion-day semantics for completed_date. Resolution MUST be deterministic: If caller provides an explicit target date/datetime, that value is authoritative. If caller omits target for recurring instance operations, implementations MUST resolve in this order: task scheduled, if present and target-day-resolvable, else task due, if present and target-day-resolvable, else current local day in active runtime timezone (§3.6). Target-day resolution for fallback task fields (scheduled / due) MUST use this extraction policy: if stored value is canonical date (YYYY-MM-DD), use it as-is; if stored value is datetime, use the literal date token before T (YYYY-MM-DD) without timezone shifting; if stored value is non-canonical but accepted by compatibility policy, implementations MAY normalize to a date token and SHOULD emit a warning; if a candidate value is unusable, continue to the next fallback source. For non-recurring complete, if caller omits explicit completion-day input, implementations MUST use current local day in active runtime timezone. When an explicit target is datetime: operations that require day semantics MUST use its calendar date part in active runtime timezone, for recurring complete instance with recurrence_anchor=completion, the same explicit datetime target MUST also drive DTSTART rewrite semantics in §4.4.3. This explicit-target datetime rule is intentionally distinct from persisted-field fallback extraction above. 5.2.2 Idempotency and date_modified# For operations marked idempotent: first application MAY change state and date_modified, repeated application with semantically equivalent input MUST leave persisted state unchanged. When a repeated idempotent operation is a no-op, date_modified MUST remain unchanged. 5.3 Create# 5.3.1 Input requirements# Create MUST provide at minimum semantic roles required by §2, directly or via defaults. 5.3.2 Required behavior# Create MUST: apply default values, generate date_created and date_modified when absent, resolve semantic title and filename/path behavior according to §9.13, apply create-time templating when enabled and supported (§5.3.5, §9.14, §7), serialize canonical keys and canonical temporal formats, when recurrence is present, canonicalize DTSTART per §4.4.5, preserve caller-provided semantic id when present, fail with validation errors if required constraints are unmet, apply default reminders according to §10.3.9 when configured. 5.3.3 Title and filename resolution on create# Create MUST produce a deterministic initial filename/path. Rules: Generated filenames MUST use filename-safe sanitization and MUST avoid invalid/empty basenames. If title.storage=filename: basename MUST derive from semantic title, title changes after create are handled by update semantics (§5.4.4), implementations MAY also persist mapped title as a synchronized compatibility mirror, title.filename_format and title.custom_filename_template MUST be ignored. If title.storage=frontmatter, create-time basename MUST follow title.filename_format: title: sanitized semantic title, zettel: implementation-defined zettel pattern (MUST be documented), timestamp: implementation-defined timestamp pattern (MUST be documented), custom: title.custom_filename_template expansion. If generated path already exists, implementation MUST resolve collision deterministically (for example numeric suffixing). 5.3.4 Example# Input intent: title: \"Pay electricity bill\" Assume defaults: status default open priority default normal Persisted frontmatter (example): title: Pay electricity bill status: open priority: normal dateCreated: 2026-02-20T14:00:00Z dateModified: 2026-02-20T14:00:00Z 5.3.5 Optional create-time templating# This subsection is required only for implementations claiming profile templating (§7.3.3). Create-time templating pipeline MUST be deterministic: Compute base create payload from explicit input, defaults (§9.8), and generated/system values (date_created, date_modified, resolved title policy). Expand template variables using that base payload and active runtime date/time context. Merge template frontmatter into base frontmatter with base payload precedence (base keys MUST win on conflict). Resolve body output: if expanded template body is non-empty, use it; otherwise use caller-provided body/details (if any). Template parse rules: If template content begins with ---, implementations MUST treat the first --- ... --- block as template frontmatter and the remainder as template body. Frontmatter variable expansion MUST run before YAML parsing of template frontmatter. Portable variable support: Implementations claiming templating MUST support all variables in the Required column of the table below. Implementations MAY support any variable in the Extended column. Required task-data variables: Variable Value Format / separator {{title}} Semantic title string; YAML-quoted if needed {{status}} Task status value string {{priority}} Task priority value string {{dueDate}} Due date if set YYYY-MM-DD or empty {{scheduledDate}} Scheduled date if set YYYY-MM-DD or empty {{details}} Caller-provided body/description string {{contexts}} Contexts list comma-separated, e.g. \"work, home\" {{tags}} Tags list comma-separated, e.g. \"task, errands\" {{hashtags}} Tags list as hashtags space-separated, e.g. \"#task #errands\" {{timeEstimate}} Time estimate in minutes integer string or empty {{parentNote}} Parent note name/path string; YAML-quoted if needed Required date/time variables (expansion time): Variable Value Format {{date}} Current date yyyy-MM-dd {{time}} Current time (24h) HH:mm {{year}} Full year yyyy {{month}} Month number MM {{day}} Day of month dd Extended variables (optional): Variable Value Format {{dateTime}} Date + time yyyy-MM-dd-HHmm {{timestamp}} Full timestamp yyyy-MM-dd-HHmmss {{shortDate}} Short date yyMMdd {{shortYear}} Two-digit year yy {{monthName}} Month full name e.g. February {{monthNameShort}} Month short name e.g. Feb {{dayName}} Weekday full name e.g. Monday {{dayNameShort}} Weekday short name e.g. Mon {{week}} ISO week number ww {{quarter}} Quarter number 1–4 {{hour}} Hour (24h) HH {{minute}} Minute mm {{second}} Second ss {{time12}} Time with AM/PM hh:mm a {{time24}} Time (24h) HH:mm {{timezone}} UTC offset long e.g. +05:30 {{utcOffset}} UTC offset long e.g. +05:30 {{unix}} Unix timestamp (seconds) integer string {{unixMs}} Unix timestamp (ms) integer string {{zettel}} Zettelkasten ID date + seconds-since-midnight base-36 {{titleLower}} Title lowercase string {{titleUpper}} Title uppercase string {{titleSnake}} Title snake_case string {{titleKebab}} Title kebab-case string {{titleCamel}} Title camelCase string {{titlePascal}} Title PascalCase string {{priorityShort}} First letter of priority uppercase char {{statusShort}} First letter of status uppercase char Unknown variables (not in the above lists) MUST be handled per templating.unknown_variable_policy (§9.14): preserve: leave the {{...}} placeholder as-is. empty: replace with an empty string. Deterministic expansion context: date/time variable expansion MUST use the active runtime timezone from §3.6. locale-sensitive variables (monthName, monthNameShort, dayName, dayNameShort, time12) MUST use English locale outputs for portability (January, Jan, Monday, Mon, AM/PM). template-generated datetime-like outputs used in frontmatter MUST normalize to second precision when written as canonical datetime roles (§3.3.2). Failure behavior: templating.failure_mode=error: template read/parse failures MUST abort create. templating.failure_mode=warning_fallback: template read/parse failures MUST continue create using non-templated behavior (base frontmatter + caller body/details) and SHOULD emit warnings (template_missing or template_parse_failed). 5.3.6 Identity handling on create# If semantic id is provided on create, writers MUST preserve it. If implementation supports auto-generation of semantic id, generation policy MUST be documented and resulting id MUST remain stable after create. 5.4 Update# 5.4.1 Patch semantics# Update MUST be patch-by-default: only targeted semantic roles are changed. 5.4.2 Preservation rules# Update MUST preserve: unrelated known roles, unknown fields, original date/datetime granularity for untouched fields. 5.4.3 Example# Before: title: Weekly review scheduled: 2026-02-20 priority: normal customClient: ACME Operation: set priority to high. After: title: Weekly review scheduled: 2026-02-20 priority: high customClient: ACME 5.4.4 Title updates and filename updates# If an update changes semantic title, behavior MUST follow title.storage: title.storage=filename: implementation MUST rename file basename to match updated title (with sanitization and deterministic collision handling), preserving parent folder unless caller requested a move. title.storage=frontmatter: implementation MUST update mapped title field and MUST NOT rename file unless an explicit rename operation is requested. If implementation keeps frontmatter title for compatibility while title.storage=filename, it MUST keep stored title synchronized with effective filename-derived title. 5.5 Complete (non-recurring)# For non-recurring tasks, complete MUST: Set status to a configured completed value, unless already completed. If multiple completed values are configured, implementation MUST choose deterministically (default: first entry in status.completed_values). Set completed_date to completion day: explicit completion-day input when provided, otherwise current local day in active runtime timezone (§5.2.1). Apply overwrite policy deterministically (overwrite or preserve_if_present). Update date_modified on state change. Implementations MUST document completion-day input handling and completed_date overwrite policy. Operation MUST be idempotent. 5.6 Uncomplete (non-recurring)# For non-recurring tasks, uncomplete MUST: Set status to configured active/default status according to policy (default: status.default). Clear or retain completed_date according to policy. Update date_modified on state change. Policy MUST be documented and deterministic. Operation MUST be idempotent. 5.7 Complete instance (recurring)# For recurring tasks, complete with resolved target date D (§5.2.1) MUST follow §4.7. Writers MUST NOT convert recurring completion into a base status rewrite unless explicit configuration requires it. When recurrence_anchor=completion and caller supplies an explicit datetime target, implementations MUST apply §4.4.3 datetime DTSTART rewrite behavior. When recurrence_anchor=scheduled and DTSTART is absent, implementations MUST insert DTSTART deterministically per §4.4.5. Next-occurrence recalculation in this mode MUST follow §4.4.4. 5.8 Uncomplete instance (recurring)# For recurring tasks, uncomplete with resolved target date D (§5.2.1) MUST follow §4.8. For recurrence_anchor=completion, ordinary uncomplete is intentionally non-reversible and MUST NOT roll back DTSTART. 5.9 Skip and unskip instance# Skip/unskip for recurring tasks with resolved target date D (§5.2.1) MUST follow §4.9 and §4.10. 5.10 Dependency operations# Dependency operations MUST follow §10.2. 5.10.1 Add dependency# Add dependency MUST: validate dependency entry schema, parse and resolve uid per §11, enforce duplicate and self-reference rules, preserve existing non-target dependency entries, update date_modified on change. 5.10.2 Remove dependency# Remove dependency by uid MUST be idempotent. 5.10.3 Replace dependency list# Replace dependency list MUST be explicit (not default patch behavior). 5.11 Reminder operations# Reminder operations MUST follow §10.3. 5.11.1 Add reminder# Add reminder MUST: validate reminder schema, enforce unique id within task, update date_modified on change. 5.11.2 Update reminder# Update reminder MUST target a reminder by id and be patch-by-default. 5.11.3 Remove reminder# Remove reminder by id MUST be idempotent. 5.12 Archive# Implementations MAY support archive semantics through: archive tag, archive status, dedicated boolean/archive field. Archive behavior MUST be documented. Archive MUST NOT implicitly delete the task. 5.13 Delete# Delete MUST remove the task file. Delete MUST NOT implicitly delete files referenced by attachments. An implementation MAY offer a separate, explicit cleanup action subject to §5.21.4. Optional safety behavior: Implementations MAY perform backlink/dependency checks. If checks are enabled, implementation MUST provide a bypass option for explicit force delete. 5.14 Rename# Rename operation changes file path/filename while preserving semantic record identity. 5.14.1 Rename interaction with title storage mode# If title.storage=filename, basename changes from rename MUST update effective semantic title. If title.storage=frontmatter, rename MUST NOT implicitly rewrite mapped title unless explicitly requested. Implementations that persist frontmatter title in title.storage=filename mode MUST either update that field on rename or remove it to prevent divergence. If semantic id is present, rename/move MUST preserve its value unchanged. If implementation supports link/reference updating, it MUST: update resolvable references deterministically, report unresolved or ambiguous updates, update dependency uid and projects references consistently with normal links. If implementation does not support reference updates, this limitation MUST be disclosed in conformance claim. 5.15 Batch operations# Batch operations MAY be supported. If supported, implementation MUST report per-item outcomes and summary counts: total succeeded failed Partial success behavior MUST be documented. 5.16 Concurrency# Implementations SHOULD provide write-conflict detection (for example based on modified timestamp or file hash). When conflict is detected, operation MUST fail safely unless explicit overwrite is requested. 5.17 Dry run# If dry run mode is supported, operation MUST: execute validation and transformation logic, report intended changes, perform no file write. 5.18 Error model# Implementation-native operation failures MUST provide structured error information with: operation name, error code, message, optional field/path context. For conformance adapter envelopes (§5.23), failures MAY be represented as a compact error string for transport compatibility, but implementations SHOULD also expose the structured fields (for example via error_details). 5.19 Time tracking management# This subsection applies to implementations that support time_entries. 5.19.1 Start time tracking# Start on task T MUST: fail when T already has an active time entry, append a new entry with canonical startTime and no endTime, MAY set a default description, update date_modified, persist canonical time_entries shape (including removal of legacy/stale duration fields when normalizing). Recommended error code when already active: time_tracking_already_active. 5.19.2 Stop time tracking# Stop on task T MUST: fail when T has no active time entry, set endTime on the active entry to canonical current datetime, update date_modified, preserve non-target entries and unknown frontmatter fields. Recommended error code when no active"},{"title":"6. Validation","url":"/developers/specification/06-validation/","description":"Validation ensures persisted task records conform to this specification and collection configuration.","product":"specification","text":"6.1 Purpose# Validation ensures persisted task records conform to this specification and collection configuration. 6.2 Validation phases# Implementations SHOULD validate in these phases: Parse validation (YAML/frontmatter structure) Schema validation (types and role constraints) Semantic validation (cross-field invariants) 6.3 Validation modes# Conforming implementations MUST support: strict: errors block writes. Implementations MAY additionally support: permissive: writes may continue with warnings. Current mode MUST be discoverable. 6.4 Required checks# A conforming validator MUST implement checks required by the claimed profile(s): Check ID Requirement Required for 1 Unconditionally required semantic roles are present (status, date_created, date_modified). core-lite and above 1a completed_date conditional requiredness is enforced per §2.2.1. core-lite and above 1b title resolves via active title policy (§2.2.2 and §9.13): storage-mode-aware precedence and fallback. core-lite and above 2 Field values match role type requirements. core-lite and above 3 Temporal values conform to §3. core-lite and above 4 Recurrence values conform to §4 (including tasknotes recurrence-string syntax and anchor-seed resolution rules). recurrence and above 5 Per-instance lists contain valid dates with no overlap. recurrence and above 6 date_modified is not earlier than date_created when both exist. core-lite and above 7 time_estimate is non-negative when present. any profile that supports time_estimate 8 time_entries entries include required startTime, ranges are valid when endTime exists, and at most one active entry exists per task. any profile that supports time_entries 9 blocked_by entries conform to §10.2 (shape, enum, duplicates, self-reference). extended 10 reminders entries conform to §10.3 (shape, type-specific fields, unique ids). extended 11 relative reminders have resolvable base fields or produce configured error/warning behavior. extended 12 link-bearing fields (projects, blocked_by.uid, and supported attachments) conform to §11 parsing/resolution and traversal safety. extended, or any implementation supporting attachments 13 templating configuration is valid when provided (templating schema and enums). templating 14 create-time template failures obey configured failure mode (error vs fallback). templating 15 semantic id (when present) is a non-empty string; duplicate collection-level IDs SHOULD be reported when detectable. any profile that supports semantic id 16 materialized occurrence notes contain valid recurrence_parent and occurrence_date roles. materialized-occurrences 17 no duplicate materialized occurrence notes exist for the same resolved (recurrence_parent, occurrence_date) pair. materialized-occurrences 18 materialization policy values and rolling horizons conform to §4.18 and §9.17. materialized-occurrences 19 attachments is a list of non-empty, unique normalized file references with explicit extensions. any implementation supporting attachments 6.5 Unknown field policy# Unknown fields: MUST NOT fail validation by default unless collection is configured for strict schema closure. SHOULD generate informational warnings when strict schema closure is desired but not enabled. 6.6 Issue structure# Validation issues MUST include: code (machine-readable) severity (error, warning, or info) message (human-readable) Issues SHOULD include: field or path expected and actual details where useful 6.7 Recommended issue codes# Code Severity (default) Meaning missing_required error required role missing invalid_type error value type mismatch invalid_enum_value error value not in configured set invalid_date_value error malformed or impossible date invalid_datetime_value error malformed datetime invalid_recurrence_rule error recurrence not valid tasknotes recurrence syntax missing_recurrence_seed error recurrence has no resolvable seed/start date invalid_recurrence_anchor error anchor not allowed instance_state_overlap error same date in complete and skipped lists invalid_time_range error end before start in time entry missing_time_entry_start error time entry is missing required startTime multiple_active_time_entries error more than one active time entry exists in one task invalid_dependency_entry error dependency object missing required fields invalid_dependency_reltype error dependency reltype not allowed invalid_dependency_gap error dependency gap not valid ISO 8601 duration duplicate_dependency_uid error in strict mode when dependencies.enforce_unique_uid=true; warning otherwise by policy repeated dependency uid in task self_dependency error task depends on itself unresolved_dependency_target warning dependency target not resolvable invalid_reminder_entry error reminder object missing required fields duplicate_reminder_id error repeated reminder id in task invalid_reminder_type error reminder type not allowed invalid_reminder_offset error relative reminder offset not valid duration invalid_reminder_related_to error relatedTo must be due or scheduled invalid_reminder_absolute_time error absoluteTime invalid datetime unresolvable_reminder_base error relative reminder base field missing/unusable invalid_link_format error link value cannot be parsed as supported format ambiguous_link warning link resolves to multiple candidates path_traversal error resolved path escapes collection root unresolved_link_target warning link target cannot be resolved invalid_attachment_reference error attachment reference is empty, lacks an explicit extension, or targets a directory duplicate_attachment_reference error attachment list repeats the same normalized target invalid_task_id error semantic id is empty or invalid type duplicate_task_id warning duplicate semantic id detected in collection scope alias_conflict_ignored warning alias key ignored due to canonical conflict unresolvable_title error title cannot be resolved from title resolution policy title_source_conflict warning mapped title and filename title differ; active title-storage policy selected authoritative source template_missing warning configured template file cannot be read/found template_parse_failed warning template frontmatter/body parsing or expansion failed missing_recurrence_parent error materialized occurrence note omits recurrence_parent invalid_recurrence_parent warning occurrence note parent reference cannot be resolved or does not reference a recurring task missing_occurrence_date error materialized occurrence note omits occurrence_date duplicate_occurrence_note warning more than one materialized occurrence note exists for the same parent/date occurrence_state_conflict warning materialized occurrence state disagrees with parent instance lists materialization_target_not_generated warning occurrence date is not generated by current parent recurrence rule missing_skipped_status error skip of materialized occurrence requires configured skipped status next_occurrence_materialization_failed warning triggering operation succeeded but next occurrence note could not be created orphan_occurrence_note warning materialized occurrence note has no resolvable recurring parent or parent state references a deleted occurrence note unknown_field info unmapped field encountered Implementations MAY extend this code set but SHOULD preserve existing meanings. 6.8 Write-time validation behavior# In strict mode, mutating operations MUST fail if any error-severity issue is present after applying intended changes. Warnings SHOULD NOT block writes unless explicitly configured. Datetime/date acceptance and rejection in validation MUST follow the normative matrix in §3.4.4. 6.9 Validation examples# 6.9.1 Missing required role# Input: title: Plan workshop status: open dateCreated: 2026-02-20T09:00:00Z Issue: code: missing_required severity: error field: dateModified message: Required field 'dateModified' is missing. 6.9.2 Invalid recurrence anchor# Input: recurrence: FREQ=DAILY recurrenceAnchor: due Issue: code: invalid_recurrence_anchor severity: error field: recurrenceAnchor message: recurrence anchor must be 'scheduled' or 'completion'. 6.9.3 Overlap in instance state# Input: completeInstances: [2026-02-20] skippedInstances: [2026-02-20] Issue: code: instance_state_overlap severity: error message: same date exists in complete and skipped instance lists. 6.9.4 Invalid dependency reltype# Input: blockedBy: - uid: \"[[task-a]]\" reltype: BLOCKS Issue: code: invalid_dependency_reltype severity: error field: blockedBy[0].reltype message: reltype must be one of FINISHTOSTART, STARTTOSTART, FINISHTOFINISH, STARTTOFINISH. 6.9.5 Unresolvable reminder base# Input: reminders: - id: due_minus_1d type: relative relatedTo: due offset: -P1D Issue when due missing: code: unresolvable_reminder_base severity: error field: reminders[0] message: relative reminder references due but no due value exists. 6.9.6 Unknown field in permissive mode# Input: title: Plan workshop status: open vendorPriority: p1 Issue example: code: unknown_field severity: info field: vendorPriority message: field is not mapped to a known semantic role. 6.9.7 Multiple active time entries# Input: timeEntries: - startTime: 2026-02-20T10:00:00Z - startTime: 2026-02-20T11:00:00Z Issue: code: multiple_active_time_entries severity: error field: timeEntries message: task contains more than one active time entry."},{"title":"7. Conformance","url":"/developers/specification/07-conformance/","description":"This section defines conformance profiles and claim requirements for implementations.","product":"specification","text":"7.1 Purpose# This section defines conformance profiles and claim requirements for implementations. 7.2 Conformance principles# An implementation MUST NOT claim conformance to a profile unless all required capabilities of that profile are implemented. Implementations MAY implement additional behavior beyond a profile, but extra behavior MUST NOT violate profile requirements. 7.3 Profile model# Profiles are cumulative unless explicitly marked otherwise. 7.3.1 Profile: core-lite# Required capabilities: task identification and loading semantic-role mapping and canonical writes (§2) required role support (title, status, completed_date, date_created, date_modified) create, update, delete operations (§5) non-recurring complete/uncomplete (§5) temporal parsing/canonical serialization basics (§3) strict validation mode support (§6.3) validation core checks (§6.4 items 1,1a,1b,2,3,6) 7.3.2 Profile: recurrence# Additional required capabilities: tasknotes recurrence-string parsing/validation, including RRULE parameter syntax and inline DTSTART handling recurrence anchor semantics, including seed precedence and completion-anchor progression complete/uncomplete instance skip/unskip instance instance-list invariants and effective state resolution validation checks for recurrence and instance overlap 7.3.3 Profile: templating (non-cumulative extension)# This profile is not cumulative; it MAY be claimed alongside core-lite, recurrence, materialized-occurrences, and/or extended. templating MUST NOT be claimed alone. Required capabilities: create-time template processing semantics per §5.3.5 templating configuration support per §9.14 deterministic template/frontmatter/body merge behavior deterministic failure-mode behavior for template read/parse failures support for portable double-brace template variables defined in §5.3.5 7.3.4 Profile: materialized-occurrences (non-cumulative extension)# This profile is not cumulative; it MUST be claimed alongside recurrence. It MAY be claimed alongside extended and/or templating, but it does not require either. Required capabilities: materialized occurrence roles and identity semantics (§2.6.6) recurrence materialization semantics (§4.18) materialize/complete/skip/uncomplete/unskip materialized occurrence operations (§5.20) occurrences configuration defaults (§9.17) parent-reference link parsing/resolution for recurrence_parent (§11), without requiring full extended validation checks for materialized occurrence identity, duplicates, and state conflicts (§6.4 items 16-18) Claiming materialized-occurrences also has required capability-token implications: meta.claim.capabilities MUST include materialized-occurrences. meta.claim.profiles MUST also include recurrence. Omitting either token while claiming materialized-occurrences is a non-conformant claim. 7.3.5 Profile: extended# Additional required capabilities: dependency schema support (blocked_by) reminder schema support (reminders) link parsing/resolution semantics for link-bearing fields (§11) time-tracking management semantics for time_entries (§5.19), including per-task active-session constraints dependency operations and validation per §10.2 reminder operations and validation per §10.3 If extended is claimed, all of the above baseline capabilities MUST conform to documented semantics. Claiming extended also has required capability-token implications: meta.claim.capabilities MUST include dependencies, reminders, links, and time-tracking. Omitting any of these tokens while claiming extended is a non-conformant claim (even if capability-gated fixtures are skipped by a runner). Optional capability extensions within extended: rename capability: reference-aware rename behavior (including dependency UID references) archive capability: archive semantics (§5.12) batch capability: batch operations with per-item outcomes (§5.15) concurrency capability: write-conflict detection semantics (§5.16) dry-run capability: dry-run semantics (§5.17) When an optional capability token is claimed, corresponding behavior MUST conform to documented semantics. 7.4 Conformance claim format# A conformance claim MUST include: implementation name and version, tasknotes-spec version, claimed profile list, validation mode support (strict required; permissive optional), known deviations, compatibility mode status (if any), configuration provider status (active provider chain, precedence policy, and fallback state). Example: Implementation: example-task-cli v1.4.0 Spec: tasknotes-spec 0.3.0-rc.3 Profiles: core-lite, recurrence, templating Validation modes: strict, permissive Known deviations: none Compatibility mode: disabled Configuration providers: tasknotes_plugin_data_json > built_in_defaults Configuration fallback: none 7.5 Deviation disclosure# Any known deviation from normative text MUST be explicitly disclosed in conformance output/documentation. A deviation entry SHOULD include: affected section, deviation summary, impact, planned resolution version. 7.6 Feature detection# Implementations SHOULD expose machine-readable capability metadata, including: profiles effective runtime timezone active configuration providers and precedence chain enabled compatibility modes configurable status sets supported mapping aliases templating support flags and effective templating failure mode dependency and reminder support flags attachment membership, reference normalization, and host-provided binary operation flags (including whether physical deletion is available) time-tracking support flags, including active-session policy and auto-stop-on-complete behavior materialized occurrence support flags, including materialization mode, next trigger, and rolling bounds configured natural-language capture triggers when the optional nlp block is present 7.7 Strictness disclosure# Conformance requires strict validation mode support (§6.3). Conformance claims MUST indicate whether permissive mode is also supported. 7.8 Example profile matrix# Capability core-lite recurrence templating materialized-occurrences extended create/update/delete required required companion-profile required companion-profile required required non-recurring complete required required companion-profile required companion-profile required required recurring instance complete/skip - required optional required via companion recurrence claim required materialize occurrence notes (§4.18, §5.20) - - optional required optional recurrence parent link resolution - - optional required for recurrence_parent only required template expansion/merge (§5.3.5) - - required optional optional double-brace portable variable support - - required optional optional recurrence-string validation - required optional required via companion recurrence claim required link parsing/resolution (§11) - - optional required for recurrence_parent only required attachment membership and ops (§5.21) optional via attachments capability optional via attachments capability optional via attachments capability optional via attachments capability optional via attachments capability dependency schema and ops - - optional optional required reminder schema and ops - - optional optional required time tracking start/stop/edit semantics (§5.19) - - optional optional required rename updates dependency/project links - - optional optional optional via rename capability archive semantics (§5.12) - - optional optional optional via archive capability batch per-item outcomes (§5.15) - - optional optional optional via batch capability write-conflict detection (§5.16) - - optional optional optional via concurrency capability dry-run reporting (§5.17) - - optional optional optional via dry-run capability 7.9 Executable fixture suite# This specification includes an executable fixture suite in conformance/. language-neutral fixtures are stored in conformance/fixtures/*.json section/profile/operation coverage is tracked in conformance/manifest.json coverage guard tests MUST enforce both section representation and minimum-depth thresholds for key sections/operations. adapters execute fixture operations per conformance/docs/ADAPTER_CONTRACT.md runners MUST execute fixtures only when both conditions hold: fixture profile is satisfied by claimed adapter profiles under cumulative profile rules (§7.3), all fixture requires capability tokens are present. Fixture expectations MUST be profile-modular: they MUST NOT assume capability values or profile memberships beyond what the fixture's own profile/requires gating guarantees. Fixtures for optional extension capabilities (rename, archive, batch, concurrency, dry-run) MUST be capability-gated via requires and MUST NOT rely on extended profile membership alone. Conformance claims SHOULD report fixture pass/fail results against the claimed profiles. 7.10 Meta operations# The following operations are part of the conformance interface and MUST be supported by any adapter that participates in the conformance suite, regardless of claimed profile. These meta operations MUST be callable without requiring any capability token. meta.claim# Returns the adapter's self-reported metadata. Input: {} (empty object) Output: { \"ok\": true, \"result\": { \"implementation\": \"my-tool\", \"version\": \"1.0.0\", \"spec_version\": \"0.3.0-rc.3\", \"validation_modes\": [\"strict\"], \"profiles\": [\"core-lite\", \"recurrence\"], \"capabilities\": [\"dependencies\", \"links\"] } } Fields: Field Type Required Description implementation string yes Human-readable implementation name version string yes Implementation version string spec_version string yes tasknotes-spec version targeted by this adapter validation_modes string[] yes Supported validation modes; MUST include strict profiles string[] yes Claimed conformance profiles; valid values: core-lite, recurrence, extended, templating, materialized-occurrences capabilities string[] yes Optional capability tokens; known tokens listed in §7.11 profiles lists explicitly claimed profiles. Cumulative profile expansion is applied by runners for fixture selection (§7.3, §7.9), but does not change literal membership semantics of meta.has_profile. Profile-token consistency rules: If profiles contains extended, capabilities MUST include dependencies, reminders, links, and time-tracking. If profiles contains templating, capabilities MUST include templating. If profiles contains materialized-occurrences, profiles MUST also contain recurrence and capabilities MUST include materialized-occurrences. Runners and fixture suites SHOULD validate these claim-consistency rules directly from meta.claim, not only by capability-gating feature fixtures. meta.has_capability# Tests whether the adapter claims a specific capability. Input: { \"capability\": \"dependencies\" } Output: { \"ok\": true, \"result\": { \"value\": true } } result.value MUST be true if the capability is in the capabilities array returned by meta.claim, and false otherwise. meta.has_profile# Tests whether the adapter claims a specific conformance profile. Input: { \"profile\": \"recurrence\" } Output: { \"ok\": true, \"result\": { \"value\": true } } result.value MUST be true if the profile is in the profiles array returned by meta.claim, and false otherwise. 7.11 Known capability tokens# The following capability tokens are defined by this specification. Implementations MAY define additional tokens. Token Required by profile Meaning dependencies extended Supports blocked_by, dependency operations, and dependency validation reminders extended Supports reminders, reminder operations, and reminder validation attachments optional extension under any profile Treats the mapped attachments list as authoritative membership; validates and normalizes its collection-file references; and implements §5.21 attachment operations using host-owned binary storage. A claim MUST separately disclose which host file actions are available; it does not by itself promise physical deletion where the host cannot perform an authoritative reference check. links extended Supports link parsing and resolution (§11) time-tracking extended Supports time-tracking management operations (§5.19) materialized-occurrences materialized-occurrences Supports recurrence materialization and materialized occurrence operations (§4.18, §5.20) rename optional extension under extended Supports file rename with reference updates archive optional extension under extended Supports archive semantics (§5.12) batch optional extension under extended Supports batch operations with per-item outcomes (§5.15) concurrency optional extension under extended Supports write-conflict detection (§5.16) dry-run optional extension under extended Supports dry-run mode (§5.17) migration — Supports migration operations (§8) templating templating Supports create-time templating (§5.3.5)"},{"title":"8. Compatibility and Migrations","url":"/developers/specification/08-compatibility-and-migrations/","description":"This section defines how implementations transition from historical behavior to canonical specification behavior without silent data breakage.","product":"specification","text":"8.1 Purpose# This section defines how implementations transition from historical behavior to canonical specification behavior without silent data breakage. 8.2 Compatibility modes# Implementations MAY support compatibility modes for legacy behavior. If supported, compatibility modes MUST: be explicitly enabled or disabled, be discoverable through configuration or capability metadata, not be silently enabled by default in new collections. 8.3 Migration expectations# When canonical behavior differs from historical behavior, implementations SHOULD provide: deterministic migration rules, dry-run preview support, rollback-safe workflow guidance. 8.4 Alias normalization migration# For legacy key aliases, a migration SHOULD: read both canonical and alias keys, choose canonical value deterministically (recommended: canonical key precedence), rewrite persisted file using canonical keys, preserve unrelated unknown fields. 8.4.1 Example# Before: recurrenceAnchor: scheduled recurrence_anchor: completion After normalization: recurrenceAnchor: scheduled With warning: alias_conflict_ignored: alias value ignored because canonical key present. 8.5 Temporal normalization migration# If historical writes include mixed datetime styles, migration SHOULD normalize to canonical UTC ISO Z for datetime roles while preserving date-only roles as dates. Example: Before: dateCreated: 2026-02-20 10:00:00+00:00 After: dateCreated: 2026-02-20T10:00:00Z 8.6 Recurrence state migration# If historical data allows overlapping complete/skip dates, migration MUST resolve overlap deterministically. Recommended resolution policy: if overlap exists, prefer most recent user action where recoverable, otherwise prefer complete_instances and remove overlapping skip entries, emit migration report for affected dates. Policy choice MUST be documented. 8.7 Materialized occurrence migration# When introducing materialized occurrence notes into an existing collection, implementations SHOULD avoid automatic bulk creation. Recommended migration behavior: do not materialize historical or future occurrence notes unless explicitly requested; preserve existing parent complete_instances and skipped_instances; when importing existing per-occurrence task files, require deterministic parent/date matching before adding recurrence_parent and occurrence_date; when materialized occurrence state conflicts with parent instance lists, prefer the occurrence note for that date and report occurrence_state_conflict; provide a dry-run report before converting existing task files into materialized occurrence notes. Migration tooling MUST NOT silently delete occurrence notes or parent recurring tasks. 8.8 Dependency migration# When migrating legacy dependency data, implementations SHOULD: normalize dependency key names to mapped canonical key, ensure each entry has uid and canonical reltype, normalize legacy string/path references into configured canonical reference style, remove duplicate dependency entries by policy. If historical data omits reltype, migration MAY apply dependencies.default_reltype and SHOULD report count of inferred values. 8.9 Reminder migration# When migrating legacy reminder data, implementations SHOULD: normalize reminder key names, normalize type values to canonical enum (absolute or relative), normalize relatedTo values to canonical enum (due or scheduled), normalize absoluteTime to canonical UTC ISO Z, validate and normalize offsets to ISO 8601 duration syntax. If reminder id values are missing, migration MAY generate IDs and MUST report generated count. 8.10 Link migration# When migrating legacy link values, implementations SHOULD: normalize supported link syntaxes according to §11 parsing rules, preserve alias and anchor components where possible, normalize resolved targets into canonical write format by policy, detect and report ambiguous links instead of silently choosing non-deterministically. 8.11 Divergence register# Implementations SHOULD maintain a divergence register with columns: section current behavior target canonical behavior migration strategy deprecation timeline 8.12 Deprecation policy# For any behavior deprecated by the specification: announce deprecation in release notes, provide warning period, provide migration tooling where feasible, remove deprecated behavior only in a version aligned with compatibility commitments. 8.13 Data safety requirements# Migrations MUST NOT: silently drop unknown fields, silently convert valid date-only fields to datetime, silently rewrite recurrence semantics without explicit policy, silently materialize occurrence notes outside explicit user/configured materialization policy, silently delete materialized occurrence notes during recurrence edits, silently drop unresolved dependency entries, silently rewrite link targets to different destinations without explicit policy, silently delete reminders unless explicitly requested. 8.14 Suggested migration report format# spec_version_from: 0.1.0-draft spec_version_to: 0.3.0-rc.3 files_scanned: 214 files_changed: 67 warnings: alias_conflict_ignored: 3 instance_state_overlap_resolved: 2 occurrence_state_conflict: 1 unresolved_dependency_target: 4 changes: normalized_datetime_fields: 41 alias_keys_removed: 29 instance_overlaps_fixed: 2 occurrence_state_conflicts: 1 inferred_dependency_reltype: 5 generated_reminder_ids: 8 normalized_link_targets: 14 8.15 Compatibility statement example# Compatibility mode: legacy-aliases=true, legacy-timeentry-duration=true Planned removal: v2.0.0 Migration command: tasknotes migrate --normalize-frontmatter"},{"title":"9. Configuration","url":"/developers/specification/09-configuration/","description":"This section defines the normative configuration model for collections using tasknotes-spec.","product":"specification","text":"9.1 Purpose# This section defines the normative configuration model for collections using tasknotes-spec. 9.2 Configuration provider model# Implementations MUST derive an effective configuration from one or more configuration providers. A provider is a source adapter that returns a partial configuration normalized to this section's schema. Implementations MUST: support at least one provider, document supported providers, document provider precedence order, disclose active providers and fallback behavior in conformance output (§7). 9.2.1 Common provider types# Common providers include: yaml_file: a tasknotes.yaml document at collection root, tasknotes_plugin_data_json: .obsidian/plugins/tasknotes/data.json, built_in_defaults: implementation defaults, optional runtime/CLI/env overrides. This list is not exhaustive. 9.2.2 Deterministic precedence and merge# Provider precedence MUST be deterministic. Unless explicitly documented otherwise, implementations MUST resolve configuration per top-level key: for each key in §9.3/§9.4, the highest-precedence provider that supplies that key wins, winning object values replace lower-precedence object values as whole objects (no implicit deep merge), after top-level selection, implementations MUST apply documented schema defaults for missing nested keys before exposing effective configuration. If an implementation supports deep-merge behavior, it MUST be explicitly documented and deterministic. 9.2.3 Strict vs permissive provider behavior# In strict mode: failure to resolve required effective keys (spec_version, mapping) MUST be a configuration error. If permissive mode is implemented, then in permissive mode: implementations MAY continue with defaults when providers are missing/unreadable, implementations MUST emit configuration warnings, implementations MUST disclose that effective configuration is partial/default-derived. 9.2.4 TaskNotes plugin provider (data.json)# The TaskNotes plugin stores settings in .obsidian/plugins/tasknotes/data.json within the vault root. When using this file as a configuration provider, normalization MUST apply the field mapping in the table below. Key mapping table (data.json key → spec effective config): data.json key Spec key Notes fieldMapping mapping Normalize role names: dateCreated→date_created, completedDate→completed_date, recurrenceAnchor→recurrence_anchor, completeInstances→complete_instances, skippedInstances→skipped_instances, recurrenceParent→recurrence_parent, occurrenceDate→occurrence_date, occurrenceMaterialization→occurrence_materialization, occurrenceNextTrigger→occurrence_next_trigger, occurrenceTemplate→occurrence_template, occurrencePastHorizon→occurrence_past_horizon, occurrenceFutureHorizon→occurrence_future_horizon, blockedBy→blocked_by, timeEntries→time_entries, timeEstimate→time_estimate storeTitleInFilename title.storage true → \"filename\", false → \"frontmatter\" taskFilenameFormat title.filename_format Values: \"title\", \"zettel\", \"timestamp\", \"custom\"; used only when title.storage=frontmatter for canonical writes, but preserved as compatibility input when present customFilenameTemplate title.custom_filename_template Template string, e.g. \"{title}\"; used only when title.storage=frontmatter and filename_format=custom taskCreationDefaults.useBodyTemplate templating.enabled boolean taskCreationDefaults.bodyTemplate templating.template_path Path to template file customStatuses[*].value status.values Ordered array of status value strings defaultTaskStatus status.default Default status string customStatuses[isCompleted=true][*].value status.completed_values Statuses where isCompleted: true defaultTaskPriority defaults.priority Default priority string autoStopTimeTrackingOnComplete time_tracking.auto_stop_on_complete boolean autoStopTimeTrackingNotification time_tracking.auto_stop_notification boolean taskIdentificationMethod task_detection.method \"tag\" or \"property\" taskTag task_detection.tag Tag string used when method=\"tag\" taskPropertyName task_detection.property_name Frontmatter key used when method=\"property\" taskPropertyValue task_detection.property_value Expected value; empty means key must exist tasksFolder task_detection.default_folder Default folder for new tasks excludedFolders task_detection.excluded_folders Comma-separated folder paths to exclude moveArchivedTasks archive.move_on_archive boolean archiveFolder archive.folder Archive destination folder useFrontmatterMarkdownLinks links.use_markdown_format boolean; see §11 Key data.json fields with defaults (for cold-start reading of a vault with no tasknotes.yaml): Field Type Default Meaning tasksFolder string \"TaskNotes/Tasks\" Default folder for new task files taskIdentificationMethod \"tag\" | \"property\" \"tag\" How task files are identified taskTag string \"task\" Tag that identifies task files (when method=\"tag\") taskPropertyName string \"\" Frontmatter key for property-based identification taskPropertyValue string \"\" Expected value for property-based identification (empty = key presence) storeTitleInFilename boolean true Title storage mode taskFilenameFormat \"title\" | \"zettel\" | \"timestamp\" | \"custom\" \"title\" Filename generation format customFilenameTemplate string \"{title}\" Template for \"custom\" filename format defaultTaskStatus string \"open\" Default status on create defaultTaskPriority string \"normal\" Default priority on create customStatuses StatusConfig[] see object shape below Ordered status definitions autoStopTimeTrackingOnComplete boolean true Auto-stop active session on completion autoStopTimeTrackingNotification boolean false Show notification when auto-stopping useFrontmatterMarkdownLinks boolean false Use markdown links in frontmatter (requires obsidian-frontmatter-markdown-links plugin) moveArchivedTasks boolean false Move task file to archive folder on archive archiveFolder string \"TaskNotes/Archive\" Archive destination folder excludedFolders string \"\" Comma-separated folders to exclude from task indexing StatusConfig object shape: { \"id\": \"done\", \"value\": \"done\", \"label\": \"Done\", \"color\": \"#00aa00\", \"isCompleted\": true, \"order\": 3, \"autoArchive\": false, \"autoArchiveDelay\": 5 } spec_version is not present in data.json. Implementations MUST synthesize an effective spec_version as described in §9.5. Provider keys not listed above MAY be ignored by tasknotes-spec consumers. 9.3 Required top-level keys# Required keys apply to the effective configuration after provider resolution. Key Type Required Description spec_version string yes target spec version (provider-supplied or synthesized per §9.5) mapping object yes semantic role to storage key mapping 9.4 Recommended top-level keys# Key Type Description task_detection object task file identification rules defaults object role defaults used during create status object status set and completed-value semantics validation object validation behavior (strict required, permissive optional) links object link parsing/resolution behavior title object title source and filename behavior policy templating object optional create-time templating behavior policy dependencies object dependency behavior policy reminders object reminder behavior policy time_tracking object time-tracking management behavior policy occurrences object recurrence materialization defaults and bounds compatibility object legacy alias/behavior switches 9.5 spec_version behavior# spec_version MUST be a semantic version string. Pre-release identifiers are valid (for example 0.3.0-rc.3). Implementations in strict mode MUST reject unsupported major versions. If permissive mode is implemented, permissive mode MAY proceed with warning when major version differs. If a provider does not supply spec_version (for example TaskNotes data.json), implementations MUST synthesize an effective spec_version matching their target tasknotes-spec version and SHOULD disclose that it was synthesized. 9.6 mapping schema# mapping MUST map semantic roles (from §2) to string storage keys. Minimum required roles in mapping: title status completed_date date_created date_modified If semantic role id is supported (§2.6.5), mapping SHOULD include id. If profile materialized-occurrences is claimed, mapping MUST include recurrence_parent and occurrence_date, and SHOULD include parent policy roles (occurrence_materialization, occurrence_next_trigger, occurrence_template, occurrence_past_horizon, occurrence_future_horizon). Example: mapping: title: title status: status date_created: dateCreated date_modified: dateModified completed_date: completedDate recurrence: recurrence recurrence_anchor: recurrenceAnchor complete_instances: completeInstances skipped_instances: skippedInstances recurrence_parent: recurrence_parent occurrence_date: occurrence_date occurrence_materialization: occurrence_materialization occurrence_next_trigger: occurrence_next_trigger occurrence_template: occurrence_template occurrence_past_horizon: occurrence_past_horizon occurrence_future_horizon: occurrence_future_horizon time_entries: timeEntries blocked_by: blockedBy reminders: reminders attachments: attachments 9.7 task_detection schema# task_detection controls how task files are identified within the vault. Detection methods# The tasknotes plugin natively supports two identification methods, controlled by taskIdentificationMethod in data.json (mapped to task_detection.method): tag (default) — A markdown file is a task if it contains the configured tag (default #task) in its frontmatter tags array or inline in the body. Configured by task_detection.tag. property — A markdown file is a task if a specified frontmatter property has a specified value (or exists, if value is empty). Configured by task_detection.property_name and task_detection.property_value. Schema and selection rules: task_detection MAY specify either: method (single-method form), or methods (multi-method form; non-empty list). If both are present, methods MUST take precedence and implementations SHOULD emit a configuration warning. If neither is present, effective detection method MUST default to tag. method MUST be tag or property. methods entries MUST be unique and MUST be from: tag property field_presence field_match Method-specific required keys: when tag is enabled, effective task_detection.tag MUST be non-empty (default task when absent); when property is enabled, task_detection.property_name MUST be provided and non-empty; task_detection.property_value MAY be empty (empty means key-exists semantics). If methods has more than one entry, task_detection.combine controls combination semantics (§9.7.3). If omitted, it MUST default to or. 9.7.1 Tag matching semantics# When task_detection.method=tag, matching MUST follow these rules: Normalize configured task_detection.tag by stripping one leading # when present. Compare tag names case-insensitively after normalization. Frontmatter matching: tags MAY be a list of strings or a single string. each tag value is normalized by trimming surrounding whitespace and stripping one leading #. match requires exact normalized equality (for example task matches #task; task does not match tasking). Body matching: only markdown text outside fenced code blocks and inline code spans is considered, a match requires a hashtag token with exact normalized name (for example #task), partial-word matches MUST NOT count (for example #tasking does not match configured task). If either frontmatter or body matches, the file is identified as a task. 9.7.2 Property matching semantics# When property detection is enabled (method=property or methods includes property): task_detection.property_name MUST name the frontmatter key to inspect. If task_detection.property_value is non-empty, match requires semantic equality with the configured value. If task_detection.property_value is empty or absent, match requires key presence only. 9.7.3 Multi-method extension semantics# tasknotes.yaml-level providers MAY additionally support: field_presence (example: required key status) field_match (example: type == \"task\") Extension-key shape: field_presence: string or list of required frontmatter keys. field_match: object map of key -> expected scalar value for exact semantic equality checks. If multiple methods are configured in tasknotes.yaml, task_detection.combine MUST define combinator semantics: or (default): file is a task if any enabled method matches. and: file is a task only if all enabled methods match. If task_detection.combine is absent, implementations MUST default to or. Implementations MUST exclude folders listed in task_detection.excluded_folders from task indexing. Executable conformance: adapters participating in the fixture suite SHOULD expose config.detect_task_file to evaluate these detection semantics against fixture inputs. Example (tasknotes.yaml, equivalent to tag-based default): task_detection: method: tag tag: task default_folder: TaskNotes/Tasks Example (property-based): task_detection: method: property property_name: type property_value: task 9.8 defaults schema# defaults defines values used at create time when caller input omits a role. Defaults MUST NOT override explicit user input. Example: defaults: status: open priority: normal recurrence_anchor: scheduled reminders: - id: due_minus_1d type: relative relatedTo: due offset: -P1D defaults.reminders behavior is defined in §10.3.9. 9.9 status schema# status defines known status values and completion semantics. Example: status: values: [open, in-progress, done, cancelled] default: open completed_values: [done] skipped_values: [cancelled] default_skipped: cancelled Rules: default MUST be one of values. completed_values MUST be a non-empty list. Each completed_values entry MUST be in values. skipped_values, when present, MUST be a list whose entries are in values. default_skipped, when present, MUST be in skipped_values. For implementations claiming materialized-occurrences, skipped_values MUST NOT overlap completed_values. Implementations claiming materialized-occurrences MUST provide at least one skipped value or fail skip of materialized occurrence notes deterministically (§5.20.3). Non-recurring completion MUST use this list, not hardcoded literals. When a complete operation does not provide an explicit target status, writers MUST use the first entry of completed_values. When a materialized occurrence skip operation does not provide an explicit skipped status, writers MUST use default_skipped when present, otherwise the first entry of skipped_values. 9.10 validation schema# Example: validation: mode: strict reject_unknown_fields: false Rules: mode MUST be strict or permissive when present. If mode is absent, effective mode MUST default to strict. Conforming implementations MUST support strict. Implementations MAY support permissive. If mode=permissive is configured but not implemented, configuration MUST fail in strict mode and SHOULD emit warning/fallback in permissive mode. reject_unknown_fields=true enforces closed-schema behavior for mapped roles. 9.11 dependencies schema# Example: dependencies: default_reltype: FINISHTOSTART treat_missing_target_as_blocked: true enforce_unique_uid: true unresolved_target_severity: warning require_resolved_uid_on_write: false Rules: default_reltype MUST be one of the allowed reltype values in §10.2. treat_missing_target_as_blocked controls whether missing/unresolvable dependency targets contribute to blocked-state evaluation (§10.2.5). If treat_missing_target_as_blocked is absent, effective value MUST default to true. enforce_unique_uid=true enforces uniqueness at validation/write time. If enforce_unique_uid is absent, effective value MUST default to true. unresolved_target_severity MUST be warning or error. require_resolved_uid_on_write=true requires dependency UID resolution success for add/update operations. 9.12 links schema# Example: links: extensions: [\".md\"] unresolved_default_severity: warning update_references_on_rename: true Rules: extensions defines extension trial order for extensionless targets"},{"title":"10. Dependencies and Reminders","url":"/developers/specification/10-dependencies-and-reminders/","description":"This section defines canonical semantics for task dependencies (blocked_by) and task reminders (reminders).","product":"specification","text":"10.1 Purpose# This section defines canonical semantics for task dependencies (blocked_by) and task reminders (reminders). 10.2 Dependencies (blocked_by)# 10.2.1 Data shape# blocked_by MUST be a list of dependency entries. Each entry MUST be an object with: uid (required): reference to a blocking task (link or string) reltype (required): one of FINISHTOSTART STARTTOSTART FINISHTOFINISH STARTTOFINISH gap (optional): ISO 8601 duration string If reltype is omitted on read in compatibility mode, implementations MAY treat it as FINISHTOSTART and SHOULD emit a warning. 10.2.2 UID normalization# Implementations SHOULD normalize uid values to a canonical reference representation on write. If link formats are supported, both wikilink and markdown-link forms MAY be read. Canonical write form MUST be documented. Link parsing and resolution MUST follow §11. 10.2.3 Dependency uniqueness# Within a task, dependency entries are keyed by normalized uid. Policy is configuration-driven and MUST be deterministic: when dependencies.enforce_unique_uid=true (default), duplicate normalized uid values MUST NOT be accepted as canonical persisted state: strict mode: duplicates MUST fail validation/write with duplicate_dependency_uid; permissive mode: implementations MAY either fail or normalize to one entry, but MUST emit duplicate_dependency_uid. when dependencies.enforce_unique_uid=false, duplicates MAY be preserved as compatibility behavior. The active policy MUST be documented in conformance claims. 10.2.4 Self-dependency# A task MUST NOT depend on itself. Self-dependency is a validation error. 10.2.5 Blocking semantics (v0.1)# For v0.1, blocking evaluation MUST be status-presence based: A task is blocked if it has at least one unresolved dependency. A dependency on a resolvable task is unresolved when the referenced task is not in a completed status. Completed status MUST be determined from configured status.completed_values. For recurring referenced tasks in v0.1, unresolved/resolved evaluation MUST use base status only; complete_instances/skipped_instances are not consulted. When a referenced task is missing/unresolvable, whether that missing target contributes to blocked-state evaluation MUST follow dependencies.treat_missing_target_as_blocked (§9.11, default true). For v0.1, reltype and gap are preserved and validated but MUST NOT change the unresolved/resolved decision. 10.2.6 Missing referenced task# When uid cannot be resolved: implementations SHOULD emit unresolved_dependency_target. blocked-state contribution for this missing target MUST follow dependencies.treat_missing_target_as_blocked (§9.11). issue severity SHOULD follow dependencies.unresolved_target_severity (default: warning). for blocked_by.uid, this dependency-specific severity policy MUST take precedence over links.unresolved_default_severity. parse failures that produce invalid_link_format and containment violations that produce path_traversal remain error-severity conditions from §11. if dependencies.require_resolved_uid_on_write=true, add/update MUST fail with error. 10.2.7 Cycles# Implementations MUST reject direct self-cycles. Detection of multi-hop dependency cycles is RECOMMENDED but not required for core-lite or recurrence profiles. 10.2.8 Reverse relation field# Some implementations maintain reverse relationships (for example blocking). Such fields are derived and non-canonical in this spec unless explicitly mapped. If maintained, reverse updates SHOULD remain consistent with blocked_by edits. 10.2.9 Dependency operation semantics# Add dependency# Add dependency MUST: validate entry shape, handle duplicates by policy (preserve, normalize, or reject), preserve unrelated dependency entries, update date_modified on change. Remove dependency# Remove dependency MUST remove by normalized uid and be idempotent. Replace dependencies# Replace behavior MUST be explicit operation mode (not default for patch update). 10.2.10 Dependency examples# Example entry: blockedBy: - uid: \"[[prepare-metrics]]\" reltype: FINISHTOSTART gap: PT4H Example unresolved dependency (target missing): blockedBy: - uid: \"[[non-existent-task]]\" reltype: FINISHTOSTART 10.3 Reminders (reminders)# 10.3.1 Data shape# reminders MUST be a list of reminder entries. Each reminder MUST include: id (required): unique string within the task type (required): absolute or relative Optional field: description string Type-specific fields: absolute: requires absoluteTime datetime relative: requires relatedTo (due or scheduled) and offset (ISO 8601 duration) 10.3.2 Reminder uniqueness# Reminder id values MUST be unique within the task. If duplicates occur: strict mode: MUST raise duplicate_reminder_id. permissive mode: MAY normalize deterministically and emit warning. 10.3.3 Relative reminder base# relatedTo MUST reference semantic role due or scheduled. If the referenced role is absent, the reminder is unresolved. 10.3.4 Trigger instant computation# Trigger instant MUST be computed as follows: If type=absolute, trigger = absoluteTime instant. If type=relative, resolve base field from relatedTo, if base is datetime: use that instant, if base is date: convert to local datetime at configured reminders.date_only_anchor_time, trigger = base + offset. If reminders.date_only_anchor_time is not configured, implementations MUST use 00:00 local time. 10.3.5 Offset semantics# offset MUST be a valid ISO 8601 duration with optional sign. negative offset = before base positive offset = after base zero offset = at base instant 10.3.6 Invalid mixed fields# Entries with incompatible field combinations MUST fail validation in strict mode. Examples: type=absolute with relatedTo and no absoluteTime type=relative with absoluteTime and missing offset 10.3.7 Reminder ordering# When computing reminder schedules, implementations MUST sort by trigger instant ascending. For identical trigger instants, implementations MUST use stable tie-break ordering by id ascending. 10.3.8 Reminder operation semantics# Add reminder# Add reminder MUST validate shape and unique id, then update date_modified. If id is omitted by caller and implementation supports auto-ID generation, generated IDs MUST be unique within the task. Update reminder# Update reminder MUST address reminders by id and be patch-by-default. Remove reminder# Remove reminder by id MUST be idempotent. 10.3.9 Default reminders# If defaults.reminders is configured (see §9): create without explicit reminders MUST apply defaults. create with explicit reminders MUST follow reminders.apply_defaults_when_explicit (§9.15): false (default): explicit reminders replace defaults. true: explicit reminders are merged with defaults. Deterministic merge rules when apply_defaults_when_explicit=true: Start with explicit reminders in caller order. Append each default reminder whose id is not already present. If explicit and default reminders share an id, explicit reminder MUST win. 10.3.10 Reminder examples# Relative reminder: reminders: - id: due_minus_15m type: relative relatedTo: due offset: -PT15M Absolute reminder: reminders: - id: call_now type: absolute absoluteTime: 2026-02-20T09:00:00Z 10.3.11 Reminder resolution error handling# If relative reminder base is unavailable (relatedTo=due but no due field): strict mode: validation error unresolvable_reminder_base. permissive mode: warning and reminder excluded from trigger computation. 10.4 Interactions# 10.4.1 Rename interaction# If implementation supports rename/reference updates, dependency uid references SHOULD be updated consistently with other link references. 10.4.2 Completion interaction# Changing task completion state does not automatically remove dependencies or reminders unless explicitly configured. 10.4.3 Archive interaction# Archive operations MAY suppress reminder delivery in runtime systems, but archive MUST NOT silently delete reminder records from persisted frontmatter unless explicitly requested."},{"title":"11. Links","url":"/developers/specification/11-links/","description":"This section defines link syntax, parsing, resolution, and write-format semantics for link-bearing task fields — primarily projects, blocked_by.uid, and attachments. Alignment w...","product":"specification","text":"11.1 Purpose# This section defines link syntax, parsing, resolution, and write-format semantics for link-bearing task fields — primarily projects, blocked_by.uid, and attachments. Alignment with Obsidian and other ecosystems is informative context only; normative conformance is defined entirely by this section. Applicability: Implementations claiming profile extended (§7.3.5) MUST conform to this section for supported link-bearing roles. Implementations claiming profile materialized-occurrences (§7.3.4) MUST conform to this section for recurrence_parent links, but are not required to support unrelated extended link-bearing roles solely because of that profile. Implementations supporting the attachments role MUST conform to this section for attachment references regardless of profile. Implementations that claim neither extended nor materialized-occurrences MAY treat link-shaped strings as opaque data and are not required to implement §11 behavior. 11.2 Link formats# Implementations that conform to §11 (see §11.1 applicability) MUST support three link formats. 11.2.1 Wikilinks# [[target]] [[target|alias]] [[target#anchor]] [[target#anchor|alias]] [[folder/target]] [[./relative]] [[../parent/target]] Components: target: The file being linked to (without extension by default) alias: Display text; does not affect resolution anchor: A heading or block reference within the target path: May be absolute (from collection root) or relative (from current file) Examples in frontmatter: projects: - \"[[home-project]]\" - \"[[projects/alpha|Alpha Project]]\" blockedBy: - uid: \"[[prepare-metrics]]\" reltype: FINISHTOSTART 11.2.2 Markdown links# [text](path.md) [text](./relative.md) [text](../other/file.md) [text](path.md#anchor) The text portion is treated as an alias and does not affect resolution. Markdown links in frontmatter require the obsidian-frontmatter-markdown-links Obsidian plugin. Implementations MUST NOT write markdown-format links by default unless links.use_markdown_format=true is configured (§11.7). 11.2.3 Bare paths# ./sibling.md ../other/file.md folder/file.md Bare paths follow the same resolution rules as markdown links (relative to containing file's directory unless starting with /). 11.3 Link parsing# When a link value is read, implementations MUST parse it into a structured representation: Component Type Description raw string Original string value exactly as written target string File path or identifier (without anchor or alias) alias string? Display text if provided, otherwise null anchor string? Heading or block reference if provided, otherwise null format enum One of: wikilink, markdown, path is_relative boolean Whether target begins with ./ or ../ Parsing examples: Input target alias anchor format is_relative [[task-001]] task-001 null null wikilink false [[task-001|My Task]] task-001 My Task null wikilink false [[docs/api#auth]] docs/api null auth wikilink false [[./sibling]] ./sibling null null wikilink true [Link](file.md) file.md Link null markdown false ./other.md ./other.md null null path true 11.4 Resolution algorithm# Resolution transforms a parsed link into an absolute path (relative to collection root) pointing to the target file. Given a parsed link and the path of the source file containing it: Step 1: Parse the link into components (target, format, is_relative)# Step 2: Route by format# If format is markdown or path: If target starts with /, resolve from collection root (strip the leading /) Otherwise, resolve relative to the source file's directory (standard markdown behavior) Example: link [Docs](docs/api.md) in notes/meeting.md resolves to notes/docs/api.md If format is wikilink: If target starts with ./ or ../, resolve relative to the source file's directory If target starts with /, resolve from collection root (strip the leading /) If target contains / (and is not relative), resolve from collection root Example: [[docs/api]] resolves to docs/api If simple name (no /, no ./ or ../): proceed to Step 3 Step 3: Simple-name resolution (wikilinks only)# For simple wikilink names (no path separator): Define the search scope: For blocked_by.uid: scope to files matching task_detection (task files only) For projects: scope to all markdown files in the collection unless narrowed by explicit configuration For attachments: scope to all non-directory files in the collection ID match pass: search scoped files for semantic role id (§2.6.5) equal to the name. Implementations MAY treat literal frontmatter key id as compatibility input when semantic mapping for id is unavailable. Equality MUST be exact string equality. If exactly one match: resolve to that file If multiple matches: fail with ambiguous_link Filename match pass: if no ID match, search scoped markdown files by filename (without extension). Implementations MUST deduplicate normalized candidate paths before final selection. If exactly one filename candidate remains after normalization and extension handling, resolve to that file. If multiple filename candidates remain, resolve to null and emit ambiguous_link. Callers SHOULD use a path-qualified or relative target to disambiguate. Step 4: Extension handling# If the target has no extension, implementations SHOULD try configured extensions in order. Default extension order: [\".md\"]. Example: [[readme]] tries readme.md, readme.mdx, etc. Step 5: Path traversal check# After resolution and normalization, if the resolved path would escape the collection root, abort with path_traversal. See §11.5. Step 6: Return result# The normalized collection-relative path if found null if no matching file exists Resolution examples# Given collection structure: / ├── TaskNotes/ │ ├── Tasks/ │ │ ├── task-001.md │ │ └── subtasks/ │ │ └── task-002.md ├── notes/ │ └── meeting.md └── projects/ └── alpha.md Resolution from TaskNotes/Tasks/subtasks/task-002.md: Link value Resolved path Notes [[task-001]] TaskNotes/Tasks/task-001.md Simple-name search [[../task-001]] TaskNotes/Tasks/task-001.md Relative wikilink [[./task-003]] TaskNotes/Tasks/subtasks/task-003.md Relative (may not exist) [[notes/meeting]] notes/meeting.md Absolute from root [[alpha]] projects/alpha.md Simple-name search (projects scope) [link](../task-001.md) TaskNotes/Tasks/task-001.md Markdown, relative ../task-001.md TaskNotes/Tasks/task-001.md Bare path, relative 11.5 Path sandboxing# Link resolution MUST NOT produce paths outside the collection root. Rules: After resolving relative paths (applying ../ segments), the resulting path MUST be within the collection root directory If resolution would escape the collection root, the link MUST resolve to null and implementations MUST emit a path_traversal error This applies to all link formats: wikilinks, markdown links, and bare paths Implementations MUST normalize paths (resolve . and .. segments) before checking containment Examples (collection rooted at /home/user/MyVault/): Link From file Result [[../../../etc/passwd]] TaskNotes/Tasks/task.md null + path_traversal [[../../secrets/key]] deep/nested/file.md null + path_traversal [[../task-001]] TaskNotes/Tasks/subtasks/t.md Resolves normally 11.6 Canonical write format# When creating new link values or changing a link target, implementations MUST use a deterministic canonical form. Default (wikilink format)# By default (links.use_markdown_format=false), the canonical write format is a simple wikilink: blockedBy: - uid: \"[[task-001]]\" reltype: FINISHTOSTART projects: - \"[[projects/alpha]]\" Rules: Use the filename without extension as the target when the file can be identified by simple-name resolution within the appropriate scope. Use a path-qualified target (folder/name) when the simple name would be ambiguous. Do NOT include the alias component in dependency uid writes. Do NOT include the anchor component in dependency uid writes. Preserve the alias component in projects entries when the alias was provided by the user. For attachments, always write a path-qualified collection-relative target with its file extension, for example [[Attachments/01K1-photo.jpg]]. Attachment writes MUST NOT include an alias or anchor. Markdown link format (links.use_markdown_format=true)# When links.use_markdown_format=true is configured (requires the obsidian-frontmatter-markdown-links Obsidian plugin), the canonical write format for link-bearing fields is a markdown link using the collection-relative path: blockedBy: - uid: \"[task-001](TaskNotes/Tasks/task-001.md)\" reltype: FINISHTOSTART Round-trip preservation# When writing an existing link field and the resolved target is unchanged, implementations MUST preserve the original format when possible: If the user wrote [[task-001|My Task]], preserve alias for projects entries. If the user wrote a relative path, preserve relativity when possible. For blocked_by.uid, alias and anchor components MUST still be removed on canonical writes. If preservation is not possible (for example unresolved/ambiguous reconstruction), implementations MUST fall back to canonical write rules in this section. 11.7 Configuration# links configuration keys (see §9.12): links: extensions: [\".md\"] # Extension trial order for extensionless targets use_markdown_format: false # Write markdown links instead of wikilinks unresolved_default_severity: warning # \"warning\" or \"error\" update_references_on_rename: true # Update link targets when files are renamed Rules: extensions MUST be a non-empty list when present unresolved_default_severity MUST be \"warning\" or \"error\" update_references_on_rename=true enables rename-time link rewrite behavior (§11.9) use_markdown_format=true requires the obsidian-frontmatter-markdown-links plugin in Obsidian deployments 11.8 Role-specific rules# 11.8.1 projects# projects entries SHOULD be interpreted with this section's parsing/resolution rules. If a projects entry is a plain string (not a wikilink or markdown link), implementations SHOULD treat it as a bare filename or path and attempt resolution. If unresolved: links.unresolved_default_severity=error: validation error otherwise: SHOULD emit unresolved_link_target warning 11.8.2 blocked_by.uid# blocked_by.uid values MUST use this section's parsing/resolution rules. For dependency semantics, unresolved uid handling follows §10.2.6. For unresolved-target severity, dependencies.unresolved_target_severity controls and takes precedence over links.unresolved_default_severity. The canonical write form for uid values is specified in §11.6. 11.8.3 attachments# Attachment references MUST resolve to files, not directories. Canonical attachment targets MUST be collection-relative, path-qualified, and retain an explicit file extension. This avoids ambiguous simple-name lookup, makes the frontmatter portable without a media-specific extension search policy, and preserves the actual filename. Readers MUST accept wikilinks, Markdown links, and bare paths. They MAY accept simple-name or extensionless values as non-canonical compatibility input, but canonical writes MUST resolve and replace them with an explicit path and extension. Aliases and anchors are not part of attachment identity and MUST be removed on canonical writes. The normalized resolved collection path defines attachment identity for duplicate detection. Implementations MUST preserve list order and MUST reject duplicates after path normalization. Unresolved attachment targets use the configured unresolved_link_target severity; offline-capable clients SHOULD distinguish a known-but-not-locally-cached file from a genuinely unresolved target. 11.9 Rename and reference updates# If an implementation supports reference updates on rename (i.e. claims the rename capability): It MUST update resolvable references in blocked_by.uid, projects, and attachments link fields. It SHOULD update links in body content. It SHOULD preserve the original link format when possible. It MUST preserve alias and anchor components where valid for the target field. For blocked_by.uid, alias and anchor are non-canonical and MUST be removed on write (§11.6). It MUST report unresolved or ambiguous rewrite cases. If reference updates are not supported, this limitation MUST be disclosed in conformance claims. 11.10 Validation# Link validation issues: Code Severity Trigger invalid_link_format error Link value cannot be parsed as any supported format ambiguous_link warning Simple-name resolution found multiple candidates after normalization unresolved_link_target warning Link target cannot be resolved to an existing file path_traversal error Resolved path escapes collection root unresolved_link_target severity may be promoted to error via links.unresolved_default_severity=error. For blocked_by.uid, use unresolved_dependency_target severity policy from §10.2.6 instead of unresolved_link_target. 11.11 Examples# Dependency with wikilink (default)# --- title: Implement API status: open tags: [task] blockedBy: - uid: \"[[design-api]]\" reltype: FINISHTOSTART - uid: \"[[projects/infra/setup-server]]\" reltype: FINISHTOSTART gap: P1D projects: - \"[[projects/alpha]]\" dateCreated: 2026-02-20T10:00:00Z dateModified: 2026-02-20T10:00:00Z --- Dependency with markdown links (links.use_markdown_format=true)# --- title: Implement API status: open tags: [task] blockedBy: - uid: \"[design-api](TaskNotes/Tasks/design-api.md)\" reltype: FINISHTOSTART --- Relative links from nested task# # TaskNotes/Tasks/subtasks/task-002.md --- title: Sub-task status: open tags: [task] blockedBy: - uid: \"[[../task-001]]\" # resolves to TaskNotes/Tasks/task-001.md reltype: FINISHTOSTART projects: - \"[[projects/alpha]]\" # resolves from collection root ---"},{"title":"12. mdbase v0.3 Data-Contract Binding","url":"/developers/specification/12-mdbase-v0.3-binding/","description":"Status: Draft","product":"specification","text":"Status: Draft Record contract: tasknotes.task 0.3.0-rc.3 Event contract: tasknotes.task.completed 1.0.0 Target: mdbase 0.3.x 12.1 Purpose# This chapter defines how a TaskNotes task model is exposed through mdbase without coupling TaskNotes to one record type or one application's private extension. The binding has three deliberately separate parts: the tasknotes.task data contract defines the portable task view; an mdbase type's implements entry maps that view to its own frontmatter fields and supplies TaskNotes behavior; and the rest of the type file continues to define that type's storage, matching, defaults, lifecycle, links, and paths. The normative artifacts are: mdbase/tasknotes.task.md, the record contract; schemas/tasknotes-task.schema.json, the projected task-view schema; and schemas/tasknotes-task-binding.schema.json, the implementation binding schema. The optional event-interoperability artifacts are: mdbase/tasknotes.task.completed.md, the event contract; and schemas/tasknotes-task-completed.schema.json, its event-data schema. 12.2 The mental model# A contract is not another record type. It is a view that several record types can implement and several applications can consume. personal_task ─┐ work_task ─────┼─ implements tasknotes.task 0.3.0-rc.3 ── TaskNotes issue_task ────┘ ├─ automation └─ another task app Reading or listing through the contract uses the union of all implementing types. Creating a task is different: the caller MUST choose one exact target type because the contract does not choose storage, paths, or lifecycle policy. The contract version is an exact semantic version. For this draft it is also the tasknotes-spec version whose task semantics the contract exposes. There is no independent x-tasknotes.version or spec_version mirror. Record types use implements because they adapt persisted fields and semantic bindings to the tasknotes.task record contract. Event sources do not use a type file. A TaskNotes application instead registers an event-source declaration for tasknotes.task.completed with an active mdbase interoperability bridge. 12.3 Layering# An implementing type MUST keep these responsibilities in their canonical locations: Information mdbase v0.3 location Persisted frontmatter shape, required fields, enum values, formats schema Type identification match Display field, defaults, links, uniqueness, and path generation collection Managed create/update values lifecycle Contract identity and custom field names implements[].contract, version, and fields TaskNotes semantic behavior implements[].binding TaskNotes metadata MUST NOT be encoded as custom JSON Schema keywords. x-tasknotes MUST NOT be used for contract discovery, field mapping, conformance, or authorization. 12.4 Declaring an implementation# An mdbase TaskNotes type declares one implementation: implements: - contract: tasknotes.task version: 0.3.0-rc.3 fields: title: summary status: state priority: importance dateCreated: created_at binding: # TaskNotes behavior; abbreviated here profiles: [core-lite] capabilities: [] title: storage: frontmatter filename_format: title status: values: [todo, doing, done] default: todo completed_values: [done] definitions: [] priority: values: [normal] default: normal definitions: [] The contract file identified by the exact contract and version MUST exist in the collection contract registry. The binding MUST validate against that contract's binding_schema. Each type MUST declare at most one implementation of one exact contract identity. A type may implement several different contracts. 12.5 Portable fields# fields maps contract field paths to record field paths. Consumers access contract fields and MUST NOT assume that their names are also frontmatter property names. fields: title: summary status: state blockedBy: dependencies attachments: files Every unconditionally required contract field MUST be mapped. Every mapped contract field and record field MUST exist in its respective JSON Schema. The contract view contains only mapped fields. It does not expose unmapped frontmatter or the Markdown body. A consumer that requires either needs separate, explicit whole-record access. title is optional in the portable schema because TaskNotes permits filename title storage. When binding.title.storage is filename, consumers derive the effective title from the record identity/path rules in §9.13 instead of expecting a projected frontmatter value. The camel-case contract field names are stable portable identifiers. Their snake-case tasknotes-spec counterparts include: Contract field tasknotes-spec role timeEstimate time_estimate completedDate completed_date dateCreated date_created dateModified date_modified recurrenceAnchor recurrence_anchor completeInstances complete_instances skippedInstances skipped_instances recurrenceParent recurrence_parent occurrenceDate occurrence_date occurrenceMaterialization occurrence_materialization occurrenceNextTrigger occurrence_next_trigger occurrenceTemplate occurrence_template occurrencePastHorizon occurrence_past_horizon occurrenceFutureHorizon occurrence_future_horizon timeEntries time_entries blockedBy blocked_by attachments attachments 12.6 Semantic profiles and capabilities# binding.profiles and binding.capabilities describe semantics that records of this implementation may use: binding: profiles: [core-lite, recurrence, materialized-occurrences] capabilities: - dependencies - reminders - attachments - links - time-tracking - materialized-occurrences - archive These are properties of the implementation, not claims that every consuming application supports them. Before mutating a governed field, a consumer SHOULD verify its own corresponding capability. It may still perform unrelated operations when it preserves unsupported fields and invariants. 12.7 Status and priority semantics# The implementing type schema defines the legal persisted values of the mapped fields. The binding gives those values TaskNotes meaning: binding: status: values: [todo, doing, done, cancelled] default: todo completed_values: [done] skipped_values: [cancelled] default_skipped: cancelled definitions: [] priority: values: [low, normal, high] default: normal definitions: [] The following consistency rules apply: binding values MUST equal the mapped type-schema enum values; defaults MUST equal mapped collection.read_defaults values when present; completed and skipped values MUST be members of status.values; default_skipped MUST be a skipped value; completed and skipped values MUST NOT overlap for materialized occurrences; and definition semantics MUST agree with completed/skipped membership. Status and priority labels, colors, and icons are presentation hints. Status cycle, completion, skipping, auto-archive, and priority weight are semantic. 12.8 Title, recurrence, links, and operations# The remaining binding sections project the effective TaskNotes behavior defined elsewhere in this specification: title follows §9.13 and MUST agree with collection.display and collection.path; recurrence follows §4; occurrences follows §2.6.6, §4.18, §5.20, and §9.17; links follows §11; attachment membership is the portable attachments contract field; binary MIME type, digest, byte size, revision, and timestamps remain authoritative in mdbase file descriptors and are not projected into task frontmatter; archive follows §5.12; time_tracking follows §5.19 and §9.16; templating follows §5.3.5 and §9.14; and optional nlp triggers follow §9.18. Archive always operates on the portable tags contract field, so the binding does not repeat a record-specific tags_field. The implementation's fields map determines the actual frontmatter property. Application-local notification preferences and generator bookkeeping MUST NOT be placed in the binding. 12.9 Multiple implementations# A collection may contain any number of types implementing tasknotes.task 0.3.0-rc.3. TaskNotes-aware readers MUST: resolve the exact local contract; enumerate every implementation in canonical type-name order; read each matching record through that implementation's projected view; validate the projected view; and retain the concrete type identity for updates. Implementations MUST NOT merge type schemas into one synthetic schema. A record is validated by its concrete type and then by its projected contract view. When an approval, cache, or external protocol pins an implementation set, it MUST pin the exact contract digest and sorted implementation descriptors, including each implementation digest. A newly installed type is therefore not silently added to an existing approval. Creation MUST name one concrete implementing type. If no type is selected, creation fails as ambiguous. 12.10 Task-completed event# An event source that claims tasknotes.task.completed 1.0.0 MUST emit one CloudEvents structured event for each observed transition from a non-completed status to a completed status. Its data contains only: task_id, using the stable TaskNotes ID when present and otherwise the normalized path; task_path; the current title and completed status; and completed_at, the instant when TaskNotes observed the transition. The event source MUST use the mdbase event/action interoperability profile 0.1, pin the exact event-contract digest, and preserve any correlation and causation identifiers supplied by the mutation context. It MUST NOT include a complete task record merely because one is locally available. An authorized consumer can retrieve current state separately, avoiding stale snapshots and unnecessary disclosure. Contract compatibility and bridge authorization are independent. Installing TaskNotes or resolving this contract does not grant permission to publish or consume the event. 12.11 Precedence and consistency# The complete implementation is self-describing: the contract schema is authoritative for the portable projected view; the type schema is authoritative for persisted value shapes; collection is authoritative for generic mdbase behavior; lifecycle is authoritative for generic managed writes; and implements[].binding is authoritative for TaskNotes semantics. Where values intentionally mirror each other, producers MUST keep them equal. A TaskNotes-aware consumer MUST report a configuration error instead of silently choosing between contradictory values. 12.12 Safe writes# TaskNotes-aware consumers MUST preserve: unknown frontmatter properties unless explicit replacement or migration was requested; Markdown body content unless an operation explicitly replaces it; fields governed by unsupported capabilities; and unrelated type metadata and implementations. Generic mdbase operations are safe only when they preserve the same data. Completion, recurrence mutation, occurrence materialization, dependency updates, time tracking, archive, and other domain operations MUST follow the TaskNotes semantics referenced by the binding. 12.13 Complete custom-field example# --- kind: mdbase.type name: work_task version: 1 schema: dialect: json-schema-2020-12 value: type: object additionalProperties: true required: [summary, state, created_at] properties: summary: { type: string, minLength: 1 } state: { enum: [todo, doing, done, cancelled] } importance: { enum: [low, normal, high] } created_at: { type: string, format: date-time } tags: type: array items: { type: string } collection: display: name_field: summary read_defaults: state: todo importance: normal lifecycle: on_create: set: created_at: { now: true } implements: - contract: tasknotes.task version: 0.3.0-rc.3 fields: title: summary status: state priority: importance dateCreated: created_at tags: tags binding: profiles: [core-lite] capabilities: [archive] title: storage: frontmatter filename_format: title status: values: [todo, doing, done, cancelled] default: todo completed_values: [done] skipped_values: [cancelled] default_skipped: cancelled definitions: [] priority: values: [low, normal, high] default: normal definitions: [] recurrence: syntax: tasknotes maintain_due_date_offset: false reset_body_checkboxes: false occurrences: identity_roles: [recurrenceParent, occurrenceDate] default_materialization: manual default_next_trigger: completion links: accepted_formats: [wikilink, markdown] write_format: wikilink archive: archived_tag: archived move_on_archive: false time_tracking: auto_stop_on_complete: true templating: enabled: false occurrence_enabled: false ---"},{"title":"Changelog","url":"/developers/specification/CHANGELOG/","description":"Initial standalone draft of tasknotes-spec including:","product":"specification","text":"0.3.0-rc.3 - 2026-08-02# define manual ordering as an opaque string rank so clients can insert and reorder tasks without renumbering an entire view 0.3.0-rc.2 - 2026-08-02# add first-class attachments as an ordered frontmatter list of portable file links, with explicit membership, canonical-path, reference-safety, and materialized-occurrence semantics expose attachment references in the tasknotes.task mdbase contract while leaving binary metadata authoritative in the file store 0.3.0-rc.1 - 2026-07-28# adopt the discriminated first-class mdbase contract shape for tasknotes.task, including explicit contract_type: record add the tasknotes.task.completed 1.0.0 event contract and minimal privacy-preserving event-data schema for the mdbase interoperability profile separate type-file record implementation bindings from application-level event-source declarations 0.2.0-draft - 2026-05-31# add optional materialized-occurrences profile for recurrence occurrence notes, on-completion materialization, and occurrence-state reconciliation add optional NLP trigger configuration so TaskNotes clients can share capture suggestion vocabulary replace the private x-tasknotes discovery envelope with the first-class tasknotes.task 0.2.0 mdbase data contract, portable task-view schema, and implementation binding schema document the precedence and consistency rules between JSON Schema, collection, lifecycle, contract field mappings, and TaskNotes behavior 0.1.0-draft - 2026-02-20# Initial standalone draft of tasknotes-spec including: motivation, scope, and normative conventions terminology task model and field mapping temporal semantics recurrence semantics operation semantics validation model conformance profiles compatibility and migration policy collection configuration schema and provider model (tasknotes.yaml, TaskNotes data.json) full dependency (blocked_by) semantics full reminder (reminders) semantics explicit time-tracking management semantics (time_entries lifecycle, start/stop/edit/remove, and completion-triggered auto-stop configuration) explicit links chapter and link-resolution rules for projects/dependencies optional templating conformance profile with create-time template expansion/merge semantics"},{"title":"TaskNotes for Obsidian","url":"/obsidian/","description":"Install TaskNotes, create a first task, and open the default Obsidian Base views.","product":"obsidian","text":"This guide covers the TaskNotes plugin for Obsidian. It follows the \"one note per task\" principle: each task is a Markdown file with structured metadata in YAML frontmatter. Requirements# TaskNotes 4.13.0 requires Obsidian 1.12.2 or later and depends on the Bases core plugin. Before you begin, open Obsidian Settings and confirm Bases is enabled under Core Plugins. Getting Started# 1. Install and Enable# Install TaskNotes from Community Plugins in Obsidian settings, then enable it. If Bases is still disabled, enable it right away so TaskNotes views can open correctly. 2. Create Your First Task# Press Ctrl+P (or Cmd+P on macOS), run TaskNotes: Create new task, fill in the modal, and save. If you prefer inline workflows, start with a checkbox like - [ ] Buy groceries and convert it using the inline task command. 3. Open the Task List# Open your first view from the TaskNotes ribbon icon or by running TaskNotes: Open tasks view from the command palette. This opens the default Task List .base file inside TaskNotes/Views. 4. Explore# Use Core Concepts to understand the data model, Features for workflow capabilities, Views for interface behaviour, and Settings to tune TaskNotes for your vault. If you already have task-like notes, start with Adopt TaskNotes in an existing vault. Quick Links# GitHub Repository Source code, issues, releases, and contribution discussions Task Management Status, priority, dates, reminders, and recurring tasks Inline Tasks Widgets, natural language parsing, and checkbox conversion Calendar Integration Google Calendar, Outlook, and ICS subscriptions HTTP API REST API for automation and external integrations JavaScript API In-process API for companion plugins and in-vault scripts Companion Plugins Optional plugins such as Canvas Bases and TaskNotes Workflows that build on TaskNotes Migration Guide Upgrading from TaskNotes v3 to v4 Troubleshooting Common issues and how to resolve them Command Reference Every registered command, generated from the plugin source Backup & Recovery Protect task notes, Base files, settings, and integration data Specification The formal spec behind TaskNotes: data model, operations, recurrence, and conformance"},{"title":"Calendar Integration Setup","url":"/obsidian/calendar-setup/","description":"TaskNotes supports Google Calendar and Microsoft Calendar integration via OAuth 2.0.","product":"obsidian","text":"TaskNotes supports Google Calendar and Microsoft Calendar integration via OAuth 2.0. Setup (Your Own OAuth Credentials)# To connect calendars, create OAuth credentials with Google and/or Microsoft, then paste them into TaskNotes Integrations settings. The sections below walk through each provider. Google Calendar# Video by @antoneheyward In Google Cloud Console, create or select a project, enable the Google Calendar API, and create OAuth 2.0 credentials using the Desktop application type. Then copy the Client ID and Client Secret into TaskNotes (Settings -> TaskNotes -> Integrations) and click Connect Google Calendar. If your Google OAuth app is still in testing mode, add the Google account you will connect with under Google Auth Platform -> Audience -> Test users. Otherwise Google may block sign-in with a 403 access_denied error saying the app has not completed verification. Microsoft Calendar# In Azure Portal, create an App Registration for your Microsoft account type. TaskNotes currently uses Microsoft's common OAuth authority, so the app registration must allow the account type you plan to connect through that authority. Tenant-specific single-tenant authorities are not configurable yet. Under Authentication, add the Mobile and desktop applications platform and add this redirect URI: http://localhost Also turn on Allow public client flows. TaskNotes uses a local loopback callback with a dynamic port, which Microsoft matches against the registered loopback URI. If Azure does not accept the loopback redirect URI through the normal UI, configure loopback redirect support in the manifest by adding: { \"url\": \"http://127.0.0.1\", \"type\": \"Web\" } Next, add delegated Microsoft Graph API permissions (Calendars.Read, Calendars.ReadWrite, and offline_access) and grant consent when required by your organization. Copy the Application (client) ID into TaskNotes, then click Connect Microsoft Calendar. The client secret field can be left blank for public-client desktop setup. Security Notes# OAuth client IDs, client secrets, and account tokens are stored locally in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system. They are not written to TaskNotes' data.json. Tokens refresh automatically, calendar data syncs directly between your vault and provider, and you can disconnect at any time to revoke account access. Secret Storage is local to the Obsidian installation and vault. When setting up TaskNotes on another device, enter the OAuth app credentials and connect the calendar again. After disconnecting, use Forget saved credentials if you also want to remove the client ID and client secret. Troubleshooting# \"Failed to connect\" Verify credentials first, then confirm loopback redirect configuration. TaskNotes uses a local callback on 127.0.0.1 with a dynamically selected port. For Microsoft, ensure loopback redirect support is configured in the app registration. Also confirm required permissions/scopes are granted. For Google 403 access_denied errors during sign-in, confirm the account is listed as a test user in the Google Auth Platform audience settings while your OAuth app is in testing mode. \"Failed to fetch events\" Disconnect and reconnect to refresh OAuth tokens, then re-check provider-side calendar permissions. Connection lost after Obsidian restart Tokens should persist between sessions. If reconnection is required each restart, check whether Obsidian Secret Storage is available and retaining secrets for the vault."},{"title":"Companion Plugins","url":"/obsidian/companion-plugins/","description":"Companion plugins are optional Obsidian plugins that build on TaskNotes without adding every workflow to the core plugin. They run inside the same Obsidian app, use TaskNotes...","product":"obsidian","text":"Companion plugins are optional Obsidian plugins that build on TaskNotes without adding every workflow to the core plugin. They run inside the same Obsidian app, use TaskNotes' runtime API for live task reads and writes, and keep task data in ordinary Markdown files. Use companion plugins when you want a deeper product surface than a script or webhook, but you still want TaskNotes itself to stay focused on task storage, editing, views, time tracking, and calendar behavior. Available Companion Plugins# Plugin Purpose Documentation Canvas Bases TaskNotes canvas companion for Obsidian Bases views, with canvas-style boards, JSON Canvas snapshots, optional TaskNotes badges, actions, and relationship edges. Canvas Bases TaskNotes Workflows Markdown-defined automation for TaskNotes tasks, schedules, events, and manual command-palette workflows. TaskNotes Workflows More companion plugins may be documented here over time. How Companion Plugins Relate to TaskNotes# TaskNotes remains the source of truth for task behavior. Companion plugins should use the TaskNotes JavaScript Runtime API for live vault operations instead of rewriting TaskNotes frontmatter directly. This keeps task updates consistent with TaskNotes settings, task cache, events, calendar behavior, time tracking, and future data-model changes. Companion plugins can also publish their own runtime surface through api.extensions. Other plugins and scripts can discover those extension APIs from TaskNotes: const tasknotes = app.plugins.getPlugin(\"tasknotes\"); const workflows = tasknotes?.api?.extensions.get(\"tasknotes-workflows\"); The extension registry is useful when companion plugins need to expose commands, validation helpers, catalogs, or run APIs to other in-vault tools. Choosing an Integration Surface# Use case Prefer A user-facing Obsidian UI that works with TaskNotes tasks Companion plugin In-vault scripting with Templater, QuickAdd, MetaBind, or another plugin JavaScript Runtime API Local tools outside Obsidian HTTP API or TaskNotes Obsidian CLI Notifications to external services when tasks change Webhooks Direct file analysis without Obsidian running mdbase-tasknotes CLI Compatibility Expectations# Companion plugins should: Check api.apiVersion and api.hasCapability(...) before using runtime features. Use api.catalog and canonical runtime query DTOs from api.query instead of reaching into TaskNotes filter/view internals. Include a source value when mutating tasks so TaskNotes events are debuggable. Avoid reacting to their own mutations unless the behavior is explicit. Keep user data in the vault where possible, using readable Markdown or JSON files. Treat TaskNotes task notes and Bases files as user-owned documents. TaskNotes does not need every companion plugin installed. If a companion plugin is disabled, TaskNotes task notes remain normal Markdown files and TaskNotes core views continue to work."},{"title":"Canvas Bases","url":"/obsidian/companion-plugins/canvas-bases/","description":"Canvas Bases is the TaskNotes canvas companion plugin for Obsidian Bases and Canvas. It turns the current Bases result set into a canvas-style board, either as a live Bases layo...","product":"obsidian","text":"Canvas Bases is the TaskNotes canvas companion plugin for Obsidian Bases and Canvas. It turns the current Bases result set into a canvas-style board, either as a live Bases layout named Canvas Bases or as a generated JSON Canvas snapshot. Canvas Bases works with normal notes and with TaskNotes task notes. Bases remains the source for which notes appear: filters, sorting, grouping, formulas, and visible properties all come from the .base file. Canvas Bases handles spatial layout, cards, edges, zones, pinned notes, text cards, and linked canvas updates. Requirements# Obsidian 1.10.1 or newer. The Obsidian Bases core plugin. The Obsidian Canvas core plugin when opening or editing generated .canvas files. TaskNotes is optional, but must be installed and enabled for TaskNotes-specific badges, task menus, dependency edges, subtasks, time tracking, Pomodoro actions, and recurring-task zone actions. If TaskNotes is disabled, Canvas Bases still works as a Bases and Canvas plugin. TaskNotes-specific actions are skipped when TaskNotes is absent or does not expose the required runtime API capability. When to Use Canvas Bases# Use Canvas Bases when a task view benefits from spatial arrangement instead of a list, table, calendar, or Kanban column set. Common uses include: Planning project tasks on a visual board. Seeing dependencies or related notes as edges between cards. Embedding a board in a daily note, project note, or meeting note. Turning a filtered Base view into a reusable .canvas snapshot. Grouping notes with Bases, then manually arranging the result. Dropping cards into assignment zones to update a note property or run a supported TaskNotes action. If the question is only \"which tasks should appear?\", keep that in Bases filters, formulas, sorting, and grouping. Canvas Bases is for visualizing and arranging the current Bases result set. Canvas Bases Layout# After Canvas Bases is installed, open or create a .base file and add a view using the Canvas Bases layout. In the live layout: Each Base result row becomes a file card. Displayed Base properties appear on each card in the same order as the Base properties menu. Base groups become group frames. Cards and group frames can be dragged and resized. Ungrouped views place cards directly on the board. The initial card order follows the Base sort order. Inline note-body editing is available when Show body editor is enabled. Board controls support panning, zooming, fit view, reset view, and opening cards. Manual notes, manual groups, and text cards can be added without changing the Base query. Canvas Bases stores layout and board state in Canvas Bases-owned keys in the .base view config. It does not need to rewrite the core query just to remember card positions, sizes, colors, pinned notes, text cards, zones, or the linked canvas path. Materialize a Canvas# Canvas Bases can also create or update a JSON Canvas file from any active Bases view, including native and third-party Bases layouts. Run these commands from the command palette: Canvas Bases: Create canvas from current bases view Canvas Bases: Update linked canvas Canvas Bases: Open linked canvas The create command asks for the canvas path, layout, edge options, node size, and update behavior. Canvas Bases-owned node and edge IDs are stable, so updating a linked canvas can preserve existing Canvas Bases node positions and keep unrelated manual Canvas nodes and edges. The generated .canvas file is a snapshot, not a live query. Re-run Canvas Bases: Update linked canvas after changing the Base result set or board layout. TaskNotes Integration# Canvas Bases reads TaskNotes through the TaskNotes JavaScript Runtime API. It feature-detects API capabilities before using them, so the board can degrade cleanly when TaskNotes is unavailable or a capability is missing. When TaskNotes integration is enabled, Canvas Bases can: Show TaskNotes status, priority, planning, recurrence, blocked, blocking, subtask, time estimate, tracked time, and active tracking badges on task cards. Add TaskNotes task actions to card context menus through the TaskNotes task menu API. Draw dependency edges between visible tasks. Draw dependency and parent-subtask edges when the TaskNotes relationship mode is set to all. Add or remove dependency and subtask relationships by dragging from one card's link handle to another. Update mapped TaskNotes task properties when a card is dropped into a property zone. Run supported zone actions such as complete, uncomplete, archive, unarchive, start or stop time tracking, start or assign a Pomodoro, complete an occurrence, or skip an occurrence. TaskNotes remains responsible for task semantics. Canvas Bases asks TaskNotes to read and mutate tasks instead of editing task frontmatter directly. Edges and Relationships# Canvas Bases can draw edges when both endpoint notes are present on the board. Supported edge sources include: Source What it uses wikilinks Links found in the note body. properties Links stored in configured note properties. all Wikilinks and configured property links. TaskNotes dependencies Blocking relationships from TaskNotes. TaskNotes subtasks Parent-child task relationships from TaskNotes when enabled. For property edges, configure a comma-separated list of property names, such as: depends_on, related Edges can be opened from their context menu. Removable TaskNotes and property relationships can also be removed from that menu. Assignment Zones# Assignment zones are board regions that do something when a card is dropped into them. The default zone action updates a note property. A grouped Canvas Bases view can turn Bases groups into zones, so dragging a card into another status, priority, or custom-property group writes that property value back to the note. Custom zones can update another note property or run supported TaskNotes actions. This lets a board mix automatic Bases-derived groups with manual workflow areas such as review queues, time-tracking lanes, or Pomodoro focus zones. Files and Data# Canvas Bases keeps user data in normal vault files: Data Where it lives Task and note content Markdown files. Query, visible properties, sorting, and grouping .base files. Live board geometry and Canvas Bases options Canvas Bases-owned keys in the .base view config. Generated board snapshots .canvas files. Options for non-Canvas Bases active views Canvas Bases plugin data. Manual non-Canvas Bases nodes in a generated .canvas file are preserved when Canvas Bases updates that canvas. First Board# A practical first Canvas Bases setup is: Create or duplicate a TaskNotes .base view. Filter it to the tasks or notes you want on the board. Add a Canvas Bases layout view to that .base file. Choose which properties to show on cards. Enable TaskNotes badges, actions, or relationships if the board is task-focused. Arrange the cards and groups. Use the toolbar to create a linked .canvas snapshot when you want a Canvas file. Canvas Bases can also create starter files under Canvas Bases/ with a demo Base, sample notes, and a linked Canvas path. Run Canvas Bases: Create starter files from the command palette if you want a small example board to inspect before adapting your own TaskNotes views."},{"title":"TaskNotes Workflows","url":"/obsidian/companion-plugins/tasknotes-workflows/","description":"TaskNotes Workflows is a companion plugin for Markdown-defined automation. It lets you create workflow notes that respond to TaskNotes events, schedules, manual commands, and se...","product":"obsidian","text":"TaskNotes Workflows is a companion plugin for Markdown-defined automation. It lets you create workflow notes that respond to TaskNotes events, schedules, manual commands, and selected Obsidian events, then run typed actions against TaskNotes tasks. Install TaskNotes Workflows# Install from Obsidian Community Plugins Open the TaskNotes Workflows listing in the Obsidian plugin directory You can also install it from Obsidian: open Settings > Community plugins > Browse, then search for TaskNotes Workflows. The plugin is designed for workflows users often ask TaskNotes core to handle, such as: Start time tracking when a task becomes active. Stop time tracking when a task is completed. Move completed tasks into a review folder. Copy parent task context, tags, priority, dates, or dependencies to subtasks. Warn when a blocked task is moved to active. Run a daily review query. TaskNotes Workflows keeps this behavior outside TaskNotes core while still using the TaskNotes JavaScript Runtime API for safe task reads, writes, canonical queries, events, and relationship resolution. Requirements# TaskNotes must be installed and enabled. TaskNotes must expose the JavaScript runtime API. Obsidian must be open for workflows to run. Scheduled workflows run while Obsidian is running. They are not a background service when Obsidian is closed. The plugin runtime uses Obsidian APIs only. Node is used for development and build scripts, not for workflow execution, so Markdown workflow definitions can work on Obsidian mobile while the plugin is loaded. If TaskNotes is disabled or unavailable, the workflow Base can still validate and display workflow files, but TaskNotes read/write steps cannot run. Files Created by the Plugin# By default, TaskNotes Workflows uses: Path Purpose TaskNotes/Workflows/ Workflow Markdown files. TaskNotes/Views/workflows.base Generated Obsidian Base that renders workflow cards through the custom workflow view. Plugin config folder Run history and detail logs, unless a run-log folder is configured. Workflow notes are ordinary Markdown files. The YAML frontmatter is executable configuration, and the note body is for human explanation, testing notes, and maintenance guidance. First Run# On first load, the plugin can create a default workflow folder, a workflow Base, and a set of example workflow notes. The default workflow notes are disabled so they can be inspected, dry-run, edited, and enabled intentionally. The generated Base is the main workbench. It shows workflow cards with status, trigger and step summaries, recent run state, and buttons for editing, dry-running, running, and opening the source note. Workflow notes also show a compact workflow card in reading mode and live preview, so the note remains useful even when opened directly. Default Workflows# The plugin can write these starter workflows: Workflow What it demonstrates Auto-start time tracking Starts a timer when a task status changes to active. Stop time tracking on complete Stops the timer when a task is completed. Morning overdue review Runs a daily cron query and marks overdue open tasks high priority. Move completed tasks to review Moves completed task notes into a review folder. Inherit subtask contexts and tags Copies contexts and tags from the first parent task when a task becomes a subtask. Inherit subtask priority Copies priority from the first parent task when a task becomes a subtask. Inherit subtask planning dates Copies scheduled and due dates from the first parent task when a task becomes a subtask. Inherit subtask dependencies Adds the first parent task's blocking dependencies to new subtasks. Mirror parent priority to subtasks Updates existing subtasks when a parent task priority changes. Mirror parent planning dates to subtasks Updates existing subtasks when a parent scheduled or due date changes. Mirror parent dependencies to subtasks Replaces each subtask's dependencies with the parent task's current dependencies. Warn when starting a blocked task Shows a notice when a task becomes active while dependencies remain. Daily active task review Shows a daily count of tasks still marked active. Treat these as editable examples. Adjust folders, statuses, priorities, dates, and filters to match your vault before enabling mutating workflows. Workflow Shape# A workflow file looks like this: --- type: tasknotes-workflow schemaVersion: 1 id: auto-start-time-tracking name: Auto-start time tracking enabled: false description: Start a timer when a task status changes to active. triggers: - id: status-active type: tasknotes.event event: task.status.changed to: active conditions: - field: trigger.after.path operator: exists steps: - id: start-time type: time.start input: task: \"{{trigger.after.path}}\" options: description: \"Started by {{workflow.name}}\" run: mode: sequential noOverlap: true source: tasknotes-workflows maxTasks: 1 onError: stop --- # Auto-start time tracking Enable this workflow to start time tracking when a TaskNotes task moves to `active`. Required frontmatter fields: Field Type Notes type string Must be tasknotes-workflow. schemaVersion number Must be 1. id string Stable lowercase identifier. Use letters, numbers, dots, underscores, and dashes. name string Human-readable name shown in workflow cards and command-palette commands. enabled boolean Disabled workflows can be edited and dry-run but do not run automatically or from manual commands. triggers array One or more trigger definitions. conditions array Optional workflow-level guards. steps array Linear typed step pipeline. run object Run policy and safety limits. Triggers# Triggers decide when a workflow should run. TaskNotes Events# Use tasknotes.event to react to TaskNotes runtime events: triggers: - id: status-active type: tasknotes.event event: task.status.changed from: open to: active Common event names include: task.created task.updated task.deleted task.moved task.status.changed task.completed task.uncompleted task.archived task.unarchived task.scheduled.changed task.due.changed task.priority.changed task.tags.changed task.contexts.changed task.projects.changed task.reminders.changed task.dependencies.changed task.recurrence.changed time.started time.stopped pomodoro.started pomodoro.completed pomodoro.interrupted recurring.instance.completed recurring.instance.skipped The workflow editor loads available TaskNotes events dynamically from api.events.list(), so event pickers can follow the runtime API instead of relying on a hardcoded list. TaskNotes event triggers can use these filters: Field Purpose event Runtime event name. from Previous status or value for status-change workflows. to New status or value for status-change workflows. path.glob Optional path glob limiting which task files can trigger the workflow. allowSelfTrigger Allows this workflow to react to writes caused by tasknotes-workflows. Leave off unless you have a clear reason. TaskNotes event output fields include values such as trigger.after.path, trigger.after.status, trigger.before.status, trigger.changes, trigger.source, and trigger.correlationId. Cron# Cron triggers run on matching minutes while Obsidian is open: triggers: - id: weekday-review type: cron schedule: \"0 17 * * 1-5\" timezone: local The schedule uses five fields: minute, hour, day of month, month, day of week. Keep cron workflows bounded with run.maxTasks, especially if they query many tasks. Interval# Interval triggers run repeatedly while Obsidian is open: triggers: - id: half-hour-check type: interval every: 30m The plugin enforces a minimum interval to avoid excessive background work. Manual# Manual triggers let a workflow run from a card button, another plugin, or the Obsidian command palette: triggers: - id: manual type: manual Enabled workflows with a manual trigger are registered as Obsidian commands named Run: . You can launch them from the command palette or assign hotkeys in Obsidian settings. The generated command id is based on the workflow id. Changing a workflow id creates a different command, so any hotkey assigned to the old command id will need to be reassigned. Obsidian Events# Advanced Obsidian triggers are opt-in from the plugin settings. They can listen to selected vault, metadata, and workspace events: triggers: - id: project-note-opened type: obsidian.workspace event: file-open path: glob: \"Projects/**/*.md\" - id: task-note-modified type: obsidian.vault event: modify path: glob: \"Tasks/**/*.md\" - id: metadata-changed type: obsidian.metadata event: changed path: glob: \"Projects/**/*.md\" Keep path filters narrow for Obsidian triggers. Vault and metadata events can be frequent. Conditions# Conditions can appear at workflow level or on individual steps. conditions: - field: trigger.after.path operator: exists - field: trigger.after.status operator: is value: active Supported operators: Operator Meaning is / isNot Exact comparison after scalar normalization. in / notIn Check a value against an array. exists / missing Check whether a field has a value. contains Check whether a string contains text or an array contains a value. startsWith String prefix check. before / after Date comparison. onOrBefore / onOrAfter Inclusive date comparison. Step-level conditions use the same shape: steps: - id: warn type: notice.show if: - field: steps.dependencies.tasks[0].path operator: exists input: message: \"This task still has dependencies.\" References# References use constrained template expressions. Arbitrary JavaScript is not evaluated. {{workflow.id}} {{workflow.name}} {{trigger.after.path}} {{trigger.changes.status.after}} {{steps.query.tasks}} {{steps.parents.tasks[0].path}} {{item.path}} {{today}} {{now}} If a string is exactly one reference, the underlying value is preserved. If a reference is embedded in other text, the value is stringified. Use forEach when a step should run once per item: steps: - id: overdue type: task.query input: query: where: all: - field: task.due op: lt value: fn: today - field: task.status op: notIn value: - done - cancelled sort: - field: task.due direction: asc limit: 50 scope: includeArchived: false - id: mark-high type: task.patch forEach: \"{{steps.overdue.tasks}}\" input: task: \"{{item.path}}\" patch: priority: high When a step uses forEach, {{item}} refers to the current item and the step output becomes an array of per-item outputs. task.query uses the canonical TaskNotes runtime query DTO. Its output includes tasks, count, total, matched, returned, groups, groupPaths, query, and warnings. Runtime query conditions use canonical field IDs and operators: query: where: all: - field: task.status op: ne value: done - any: - field: task.due op: lte value: fn: today - field: task.priority op: eq value: high sort: - field: task.due direction: asc group: - field: task.status limit: 25 scope: includeArchived: false Common fields include task.status, task.priority, task.due, task.scheduled, task.projects, task.contexts, task.tags, task.isBlocked, and file.path. Operators include eq, ne, contains, notContains, in, notIn, exists, missing, lt, lte, gt, gte, isTrue, and isFalse. Use api.catalog.filterProperties() and api.catalog.filterOperators() for the complete runtime catalog. Steps# Steps are typed actions. The editor reads a step catalog so it can show expected inputs, output fields, examples, and TaskNotes option pickers. Task read steps: Step Output task.get One task. task.query Tasks matching a canonical TaskNotes runtime query. task.parents Parent tasks linked from the task's projects. task.subtasks Tasks that reference the current task as a project. task.dependencies Dependencies stored in blockedBy, with resolved task data when available. task.blocking Tasks blocked by the current task. task.relationships The task plus parents, subtasks, dependencies, and blocking tasks. Task write steps: Step Purpose task.create Create a new TaskNotes task. task.patch Update one or more fields. task.set Set one field. task.move Move the task note to a target folder. task.archive / task.unarchive Archive or unarchive a task. task.complete / task.uncomplete Complete or reopen a task. task.reschedule Update planning dates. task.setDue / task.clearDue Set or clear due date. task.setScheduled / task.clearScheduled Set or clear scheduled date. task.addTag / task.removeTag Mutate tags. task.addProject / task.removeProject Mutate project links. task.addContext / task.removeContext Mutate contexts. task.addDependency / task.removeDependency Mutate blocking dependencies. Time and utility steps: Step Purpose time.start Start time tracking for a task. time.stop Stop active time tracking for a task. time.appendEntry Append a time entry. notice.show Show an Obsidian notice. workflow.stop Stop a workflow early. Companion plugins and scripts can inspect the same catalog through the TaskNotes runtime extension: const tasknotes = app.plugins.getPlugin(\"tasknotes\")?.api; const workflows = tasknotes?.extensions.get(\"tasknotes-workflows\"); const steps = workflows?.listStepDefinitions(); Run Policy# Every workflow has a run policy: run: mode: sequential noOverlap: true source: tasknotes-workflows maxTasks: 25 onError: stop timeout: 30s Field Notes mode Currently sequential. Steps run in order. noOverlap Skips a new run if the same workflow is already running. source Mutation source passed to TaskNotes runtime API calls. maxTasks Safety limit for forEach batch steps. onError stop or continue. timeout Optional duration string. TaskNotes attaches source, correlation, and reason metadata to events caused by runtime API writes. Workflows use this to make runs debuggable and to avoid accidental self-trigger loops. Run Logs and Debugging# Workflow run logs are stored under the plugin's Obsidian config folder by default. You can configure a run-log folder and a log level in the plugin settings. Run records include: Workflow id, name, and source path. Trigger payload. Step statuses. Inputs and outputs, depending on the configured log level. Error text when a run fails. Use dry runs before enabling workflows that mutate tasks. Dry runs still execute the workflow path, but mutating steps should report what they would do instead of changing task files. Example: Manual Command Workflow# This workflow can be run from the command palette after it is enabled: --- type: tasknotes-workflow schemaVersion: 1 id: show-active-count name: Show active task count enabled: true description: Show a notice with the number of active tasks. triggers: - id: manual type: manual steps: - id: active type: task.query input: query: where: field: task.status op: eq value: active limit: 25 scope: includeArchived: false - id: notice type: notice.show input: message: \"Active tasks: {{steps.active.count}}\" run: mode: sequential noOverlap: true source: tasknotes-workflows maxTasks: 25 onError: stop --- # Show active task count Run this from the Obsidian command palette with `TaskNotes Workflows: Run: Show active task count`. Example: Inherit Parent Priority# This workflow copies priority from the first parent task when a task becomes a subtask: type: tasknotes-workflow schemaVersion: 1 id: inherit-subtask-priority name: Inherit subtask priority enabled: false triggers: - id: projects-changed type: tasknotes.event event: task.projects.changed - id: task-created type: tasknotes.event event: task.created conditions: - field: trigger.after.path operator: exists - field: trigger.after.projects operator: exists steps: - id: parents type: task.parents input: task: \"{{trigger.after.path}}\" - id: inherit-priority type: task.patch if: - field: steps.parents.tasks[0].priority operator: exists input: task: \"{{trigger.after.path}}\" patch: priority: \"{{steps.parents.tasks[0].priority}}\" run: mode: sequential noOverlap: true source: tasknotes-workflows maxTasks: 1 onError: stop This pattern uses task.parents rather than trying to parse project links manually. Authoring Guidelines# When writing workflow notes: Start with enabled: false fo"},{"title":"Core Concepts","url":"/obsidian/core-concepts/","description":"TaskNotes follows the \"one note per task\" principle, where each task lives as a separate Markdown note with structured metadata in YAML frontmatter.","product":"obsidian","text":"TaskNotes follows the \"one note per task\" principle, where each task lives as a separate Markdown note with structured metadata in YAML frontmatter. The Note-Per-Task Approach# Individual Markdown notes replace centralized databases or proprietary formats. Each task file can be read, edited, and backed up with any text editor or automation tool. Task Structure# A TaskNotes task is a standard Markdown file with YAML frontmatter: --- tags: - task title: Review quarterly report status: in-progress priority: high due: 2025-01-15 scheduled: 2025-01-14 contexts: - office projects: - \"[[Q1 Planning]]\" --- ## Notes Key points to review: - Revenue projections - Budget allocations ## Meeting Notes Discussion with finance team on 2025-01-10... The frontmatter contains structured, queryable properties. The note body holds freeform content—research findings, meeting notes, checklists, or links to related documents. Obsidian Integration# Since tasks are proper notes, they work with Obsidian's core features: Backlinks: See which notes reference a task Graph View: Visualize task relationships and project connections Tags: Use Obsidian's tag system for additional categorization Search: Find tasks using Obsidian's search Links: Reference tasks from daily notes, meeting notes, or project documents This approach creates many small files. TaskNotes stores tasks in a configurable folder (default: TaskNotes/Tasks/) to keep them organized. In practice, this lets TaskNotes fit into existing vault habits instead of replacing them. You keep using normal note workflows, and TaskNotes adds structure, filtering, and commands on top. YAML Frontmatter# Task properties are stored in YAML frontmatter, a standard format with broad tool support. Treat frontmatter as the machine-readable layer and the note body as the human-readable layer. TaskNotes automations and Bases filters rely on frontmatter; your project notes and context stay in the body. Property Types# TaskNotes uses several property types: Type Example Description Text title: Buy groceries Single text value List tags: [work, urgent] Multiple values Date due: 2025-01-15 ISO 8601 date format DateTime scheduled: 2025-01-15T09:00 Date with time Link projects: [\"[[Project A]]\"] Obsidian wikilinks Number timeEstimate: 60 Numeric values (minutes) Field Mapping# Property keys are configurable. If your vault uses deadline instead of due, you can map TaskNotes to use your existing field names without modifying your files. The exact rules for how fields map to semantic roles, how dates are interpreted, and how operations like completion and recurrence behave are defined in the TaskNotes Specification. The spec is the shared contract between the Obsidian plugin, the terminal UI, and any other tool that reads or writes TaskNotes data. Custom Fields# Add any frontmatter property to your tasks. User-defined fields work in filtering, sorting, and templates. Define custom fields in Settings -> TaskNotes -> Task Properties to include them in task modals and views. Bases Integration# TaskNotes v4 uses Obsidian's Bases core plugin for its main views. Bases provides: Filtering: Query tasks using AND/OR conditions Sorting: Order tasks by any property Grouping: Organize tasks by status, priority, project, or custom fields Views: Task List, Kanban, Calendar, and Agenda are all Bases views Views are stored as .base files in TaskNotes/Views/. These files contain YAML configuration that defines the view's query and display settings. You can duplicate, modify, or create new views by editing these files. This makes view behavior inspectable and predictable. If a task appears in the wrong place, you can open the .base file and see exactly which filter or grouping rule produced that result. Enabling Bases# Bases is a core plugin included with Obsidian 1.10.1+: Open Settings -> Core Plugins Enable \"Bases\" TaskNotes views will now function"},{"title":"Features","url":"/obsidian/features/","description":"TaskNotes includes task organization, time tracking, and calendar integration features.","product":"obsidian","text":"TaskNotes includes task organization, time tracking, and calendar integration features. Task Management# TaskNotes gives each task a structured set of properties, including status, priority, due and scheduled dates, tags, contexts, and optional estimates. Because these values live in frontmatter, they stay readable and portable while still powering advanced filtering and grouping in Bases. Reminders can be relative (for example, \"3 days before due\") or absolute, and completed tasks can be archived automatically to keep active work surfaces focused. Recurring tasks can stay virtual for lightweight checkoff workflows, or you can materialize individual occurrences into normal task notes when a specific instance needs its own checklist, comments, time tracking, or attachments. Occurrence notes inherit useful planning metadata from the parent while keeping their own completion state and time entries, and calendar views coalesce them with the matching virtual recurrence instance. See Task Management for details. For recurrence behavior, see Recurring Tasks. For reminder setup and data format, see Task Reminders. Filtering and Views# TaskNotes uses Obsidian's Bases engine for filtering, sorting, and grouping. Each view is a .base file, so you can inspect or edit its query logic directly instead of relying on hidden plugin state. This design also makes view customization practical: you can duplicate a default view, tweak grouping or formulas, and keep both versions side by side in your vault. For details on how Bases integration works, see Core Concepts. For Bases syntax documentation, see the official Obsidian Bases documentation. Inline Task Integration# Inline task features let you work from normal notes without context switching. Task links can display interactive cards, checkboxes can be converted into full task notes, and project notes can surface subtasks and dependency relationships in place. Natural language parsing supports date, priority, and context extraction across multiple languages, which helps keep fast capture while preserving structured data. See Inline Task Integration for details. Time Management# Time tracking records work sessions per task, and Pomodoro mode supports focused intervals with break handling. Over time, the statistics views help you compare estimated versus actual effort and spot trends in workload distribution. See Time Management for details. Calendar Integration# TaskNotes supports bidirectional OAuth sync with Google Calendar and Microsoft Outlook, plus read-only ICS subscriptions for external feeds. Calendar views include month, week, day, year, and list modes, and drag-and-drop scheduling can update tasks directly. For planning workflows, time-blocking and calendar-linked task updates connect backlog management with schedule execution in the same workspace. See Calendar Integration for details. User Fields# User fields let you extend the core model with vault-specific metadata like client, energy level, billing code, or review state. Once added, these fields become available in filters, sorting, templates, and formulas. See User Fields for details. Integrations# Beyond calendar sync, TaskNotes includes an HTTP API and webhook support for automation workflows, external dashboards, or custom tooling. See Integrations for details. Companion Plugins# TaskNotes can be extended by optional companion plugins that use the JavaScript runtime API while keeping task data in Markdown files. Canvas Bases is the TaskNotes canvas companion, adding canvas-style boards and JSON Canvas snapshots for Bases views, with optional TaskNotes badges, actions, and relationship edges. TaskNotes Workflows adds Markdown-defined automation for TaskNotes events, schedules, manual commands, and typed task actions. See Companion Plugins for details. REST API# External applications can interact with TaskNotes through its REST API for automation, reporting, and integration with other tools. See HTTP API for details."},{"title":"Calendar Integration","url":"/obsidian/features/calendar-integration/","description":"TaskNotes provides calendar integration through OAuth-connected calendar services, two Bases-powered calendar views, and read-only ICS calendar subscriptions.","product":"obsidian","text":"TaskNotes provides calendar integration through OAuth-connected calendar services, two Bases-powered calendar views, and read-only ICS calendar subscriptions. OAuth Calendar Integration# TaskNotes supports bidirectional synchronization with Google Calendar and Microsoft Outlook using OAuth authentication. This integration allows you to view external calendar events alongside your tasks and sync changes back to the calendar provider. Supported Providers# Google Calendar - OAuth 2.0 authentication with access to all calendars in your Google account Microsoft Outlook - OAuth 2.0 authentication with access to calendars in your Microsoft 365 or Outlook.com account Setup Requirements# OAuth calendar integration requires creating an OAuth application with your calendar provider. This process takes approximately 15 minutes per provider. You will need to: Create an OAuth application in Google Cloud Console or Microsoft Azure Portal Configure redirect URIs and scopes Obtain client ID and client secret Enter credentials in TaskNotes settings (Settings -> TaskNotes -> Integrations, OAuth calendar section) Synchronization Behavior# Events are fetched automatically every 15 minutes Events are also fetched when local changes occur (task creation, updates, rescheduling) Dragging calendar events to new dates/times updates the event in the calendar provider Per-calendar visibility toggles allow selective display of calendars Access tokens are automatically refreshed when expired Token Management# TaskNotes stores OAuth client credentials, access tokens, and refresh tokens in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system and kept separate from TaskNotes' data.json. Tokens are refreshed automatically before expiration. You can revoke account access or forget the saved OAuth app credentials through the integrations settings. Calendar Views# TaskNotes provides Calendar and Mini Calendar views that display tasks alongside OAuth calendar events and ICS subscriptions. Both views support drag-and-drop scheduling. For detailed view documentation, see Calendar Views. Notes linked from recurring external calendar events can be matched either across the loaded event series or only to the selected recurrence instance. Configure this in Integrations settings. Time Entry Editor# TaskNotes includes a time entry editor for tracking time spent on tasks. Time entries are created and managed through the Calendar View. Creating Time Entries# To create a time entry on the Calendar View: Click and drag on a time slot in the calendar to select a time range When the selection menu appears, choose Create time entry (timeblock appears only if the feature is enabled) Choose a task in the task selector modal A time entry is created for that task with the selected start/end range Time entries are always associated with a specific task and stored in that task's frontmatter. Multiple time entries can exist for one task. Managing Time Entries# The time entry editor modal provides functions to: View all time entries for a task Edit the start time, end time, and duration of time entries Delete time entries See the total time tracked across all entries for a task Access the time entry editor by clicking an existing time entry in the calendar. ICS Calendar Subscriptions# TaskNotes can subscribe to external calendar feeds using the iCalendar (ICS) format. This provides read-only access to events from calendar services. ICS subscriptions differ from OAuth calendar integration in that they are read-only—dragging ICS events to new dates does not update the source calendar. Add and manage ICS subscriptions from Settings -> TaskNotes -> Integrations (Calendar Subscriptions section). For details on creating notes and tasks from calendar events, see ICS Integration. Time Blocking# The Calendar View supports time blocking for scheduling dedicated work periods. To create a time block: Click and drag on a time slot in the calendar to select a time range A context menu will appear with available options Select \"Create timeblock\" from the menu (this option only appears if timeblocking is enabled in settings) Time blocks are stored in the frontmatter of daily notes and can be linked to specific tasks. This differs from time entries, which track actual time spent and are stored in task frontmatter rather than daily notes. Enable time blocking under Settings -> TaskNotes -> Features (Timeblocking section)."},{"title":"ICS Calendar Event Integration","url":"/obsidian/features/ics-integration/","description":"TaskNotes can use ICS calendar events to create notes and tasks directly from calendar entries. ICS integration creates linked notes and tasks from event data without manual re-...","product":"obsidian","text":"TaskNotes can use ICS calendar events to create notes and tasks directly from calendar entries. ICS integration creates linked notes and tasks from event data without manual re-entry. Overview# The ICS integration allows you to: View detailed information about calendar events Create notes from calendar events with customizable templates Generate tasks from events with proper scheduling and context Link existing vault content to calendar events Maintain relationships between events and created content Event context, notes, and follow-up tasks remain connected through frontmatter links. Event Information Modal# When you interact with a calendar event in TaskNotes, an information modal displays event details and available actions. The modal provides: Event Details# Event title and description Start and end times (formatted according to your locale) Location information Source calendar name Event URL (if available) Related Content# The modal shows a list of existing notes and tasks that are linked to the calendar event. Content is automatically categorized as: Task - Files containing the configured task tag Note - Files without the task tag The relationship is maintained through the ICS Event ID field in the content's frontmatter. Available Actions# Create Note - Opens a creation dialog for generating a new note from the event data. Create Task - Creates a task immediately using the event information with default settings. Link Note - Opens a file selection dialog to link an existing note to the calendar event. Refresh - Reloads the list of related content to reflect recent changes. Note Creation from Events# The note creation process allows customization of the generated content: Basic Settings# Title - Default combines event title and date, but can be modified Folder - Destination for the new note (uses default ICS note folder if configured) Template - Optional template file to structure the note content Template Usage# When a template is specified: The template file is processed with ICS-specific variables Standard TaskNotes template variables are also available Template content replaces the default event description format Frontmatter from templates is merged with required ICS fields Templates apply a consistent note structure across imported events. Default Content# Without a template, notes include: Event title as the main heading Formatted start and end times Location information Source calendar name Event description (if provided) Event URL (if available) Task Creation from Events# Tasks created from calendar events include relevant event data: Scheduled Date and Time# Tasks are scheduled using the event's start time as an ISO timestamp, preserving both date and time information. This allows for accurate scheduling that reflects the original event timing. Task Properties# Title - Uses the event title Status - Set to the default task status configured in settings Priority - Set to the default task priority Contexts - Event location is added as a context (if provided) Time Estimate - Calculated from event duration (if start and end times are available) Tags - Includes the ICS event tag and any default task tags After creation, priority, status, and schedule can be edited if event data does not match the final task plan. Content# Task content includes formatted event details similar to note creation, providing context about the original calendar event. Linking Existing Content# You can establish connections between existing vault content and calendar events: Link Process# Select an existing markdown file from your vault The file's frontmatter is updated to include the event ID The modification date is updated to reflect the change The connection appears in the related content list Bidirectional References# Calendar events can display all linked content Content files maintain references to their associated events Multiple pieces of content can be linked to a single event Content can be linked to multiple events (stored as an array) Field Mapping Integration# The ICS integration extends the field mapping system with two new fields: ICS Event ID Field# Stores the unique identifier connecting content to calendar events Default field name is icsEventId Values are stored as arrays to support multiple event associations Field name can be customized through field mapping settings ICS Event Tag Field# Tag automatically applied to content created from events Default tag is ics_event Used to identify ICS-related content throughout the system Can be customized through field mapping settings Template Variables# Templates used for ICS content creation have access to event-specific variables in addition to standard TaskNotes variables: Event Information# {{icsEventTitle}} - Event title {{icsEventStart}} - Start date and time (ISO format) {{icsEventEnd}} - End date and time (ISO format) {{icsEventLocation}} - Event location {{icsEventDescription}} - Event description {{icsEventUrl}} - Event URL {{icsEventSubscription}} - Calendar subscription name {{icsEventId}} - Unique event identifier Standard Variables# All standard TaskNotes template variables remain available: {{title}}, {{date}}, {{time}} {{priority}}, {{status}}, {{contexts}} And others as documented in the template system Configuration# ICS integration settings are located under Settings -> TaskNotes -> Integrations: Default Templates# Configure template files for consistent content creation from events. Templates are optional and the system provides sensible defaults when not specified. Default Folders# Set destination folders for content created from events. This helps organize ICS-generated content separately from other vault content if desired. Folder paths support template variables for dynamic organization: Date variables: {{year}}, {{month}}, {{day}}, {{monthName}}, etc. ICS event variables: {{icsEventTitle}}, {{icsEventLocation}}, {{icsEventDescription}} Other variables: See template variables section below Example folder paths: Daily/{{year}}/{{month}}/{{day}} creates date-based hierarchy Events/{{year}}/{{icsEventTitle}} organizes by year and event title Meetings/{{monthName}} groups by month name Filename Formats# The system uses the standard TaskNotes filename generation with event-specific context, ensuring unique and descriptive filenames for created content. Technical Implementation# Event Identification# Calendar events are identified by their unique ICS event ID, which is maintained in the frontmatter of created content. This allows the system to track relationships even if event details change. Content Type Detection# The system distinguishes between tasks and notes by checking for the presence of the configured task tag in the content's frontmatter tags array, rather than relying on file structure or naming conventions. Error Handling# The integration includes error boundaries for network issues, file operations, and template processing. Failed operations provide user feedback without interrupting the overall workflow."},{"title":"Inline Task Integration","url":"/obsidian/features/inline-tasks/","description":"TaskNotes integrates with the Obsidian editor to allow task management directly within notes. This is achieved through interactive widgets, a conversion feature for checkboxes,...","product":"obsidian","text":"TaskNotes integrates with the Obsidian editor to allow task management directly within notes. This is achieved through interactive widgets, a conversion feature for checkboxes, and natural language processing. Inline features support capture and task updates without leaving the current note. Task Link Overlays# When a wikilink to a task note is created, TaskNotes can replace it with an interactive Task Link Overlay. Enable or disable overlays from Settings -> TaskNotes -> Features (Task link overlay). The widget displays information about the task, such as status, priority, and due date, and allows actions like status/priority changes or opening the edit modal. Task link overlays in Live Preview mode show interactive widgets with status, dates, and quick actions In Source mode, task links appear as standard wikilinks until rendered Widget Features# The task link overlay displays: Status Dot: Clickable circular indicator showing current task status. Click to cycle through available statuses. Priority Dot: Color-coded indicator for task priority (only shown when assigned). Task Title: Displays the task name (truncated to 80 characters). Click to open the task edit modal. Date Information: Shows due dates (calendar icon) and scheduled dates (clock icon) with clickable context menus. Recurrence Indicator: Rotating arrow icon for recurring tasks with modification options. Action Menu: Ellipsis icon (shown on hover) provides additional task actions. The widget exposes common task actions at the link location, so status and metadata can be updated in-place. Mode-Specific Behavior# Task link overlays work in both Live Preview and Reading modes: Live Preview Mode: Widgets hide when the cursor is within the wikilink range, allowing for easy editing. Reading Mode: Widgets display with full functionality and integrate with the reading mode typography. The overlays support drag-and-drop to calendar views and provide keyboard shortcuts for quick navigation (Ctrl/Cmd+Click to open the source file). Create New Inline Task Command# The Create new inline task command opens the task creation modal from the editor and inserts a link to the new task when it is saved. This command is available in the command palette. When the cursor is on an empty line, the link is inserted at the cursor. When the cursor is on a line with content, TaskNotes inserts a new line below it and places the task link there. The command does not use the current line as the task title. To turn the current line into a TaskNote, use Convert to TaskNote or the instant conversion button next to a supported line. That flow uses the current line as the task title and replaces the original line with a link to the new task file. Instant Task Conversion# The Instant Task Conversion feature transforms lines in your notes into TaskNotes files. This works with both checkbox tasks and regular lines of text. Turn the feature on or off from Settings -> TaskNotes -> Features (Show convert button next to checkboxes). When enabled, a \"convert\" button appears next to content in edit mode. Clicking this button creates a new task note using the line text as the title and replaces the original line with a link to the new task file. This supports progressive conversion from draft notes to dedicated task files. Folder Configuration# By default, converted tasks are placed in the same folder as the current note ({{currentNotePath}}). You can change this behavior in Settings -> TaskNotes -> General (Folder for converted tasks): Leave empty: Uses your default tasks folder (configured in the same section) {{currentNotePath}}: Places tasks in the same folder as the note you're editing (default) {{currentNoteTitle}}: Creates a subfolder named after the current note Custom path: Specify any folder path (e.g., TaskNotes/Converted) Supported Line Types# The conversion feature works with: Checkbox tasks: - [ ] Task description becomes a TaskNote with task metadata Bullet points: - Some task idea becomes a TaskNote with the text as title Numbered lists: 1. Important item becomes a TaskNote Blockquoted content: > Task in callout becomes a TaskNote (preserves blockquote formatting) Plain text lines: Important thing to do becomes a TaskNote Mixed formats: > - [ ] Task in blockquote handles both blockquote and checkbox formatting Content Processing# When converting lines: Special characters like >, #, - are automatically removed from the task title Original formatting is preserved in the note (e.g., > [[Task Title]] for blockquoted content) Task metadata is extracted from checkbox tasks (due dates, priorities, etc.) Natural language processing can extract dates and metadata from plain text (if enabled) Conversion preserves surrounding formatting, including callouts, outlines, and nested lists. The feature handles edge cases like nested blockquotes and maintains proper indentation in the final link replacement. Bulk Task Conversion# The Bulk Task Conversion command converts all checkbox tasks in the current note to TaskNotes in a single operation. This command is available in the command palette as \"Convert all tasks in note to TaskNotes\". How It Works# The command: Scans the entire current note for checkbox tasks (- [ ], * [ ], 1. [ ], etc.) Includes tasks inside blockquotes (e.g., > - [ ] task in callout) Applies the same enhanced conversion logic as instant task conversion Creates individual TaskNote files for each task Replaces the original checkboxes with links to the new task files Preserves original indentation and formatting (including blockquote markers) The bulk conversion uses the same content processing as instant conversion, automatically removing special characters from task titles while preserving original formatting in the note. Usage# To use bulk conversion: Open a note containing checkbox tasks Access the command palette (Ctrl+P / Cmd+P) Search for \"Convert all tasks in note to TaskNotes\" Execute the command The command displays progress and shows a summary when complete (for example, \"Successfully converted 5 tasks to TaskNotes.\"). Important Considerations **This command modifies note content permanently.** Before using: - **Create a backup** of your note if it contains important data - **Review the tasks** to ensure they should become individual TaskNotes - **Expect processing time** - notes with many tasks may take several seconds to process - **Avoid interruption** - do not edit the note while conversion is running Performance Processing time depends on the number of tasks: - Small notes (1-10 tasks): Near-instant - Medium notes (10-50 tasks): 2-5 seconds - Large notes (50+ tasks): 10+ seconds The operation creates multiple files and updates the note content, which requires disk I/O and editor updates. Error Handling# If some tasks fail to convert, the command will: Complete successfully converted tasks Display a summary showing both successes and failures Log detailed error information to the console for troubleshooting Failed conversions typically occur due to: Tasks with titles containing invalid filename characters Insufficient disk permissions Very long task titles (over 200 characters) For large notes, converting a small section first helps validate folder and filename settings. Relationships Widget# New in v4: The Relationships Widget consolidates what were previously three separate widgets (project subtasks, task dependencies, and blocking tasks) into a single dynamic interface. The widget appears in task notes and automatically displays up to five tabs based on available relationship data: Subtasks Tab (Kanban): Shows tasks that reference the current note as a project. Uses Kanban layout for visual task management. Occurrences Tab (List): Shows materialized occurrence notes that reference the current recurring task as their parent. Uses list layout sorted by occurrence date. Projects Tab (List): Shows projects that the current task belongs to. Uses list layout. Blocked By Tab (List): Shows tasks that are blocking the current task. Uses list layout. Blocking Tab (Kanban): Shows tasks that the current task is blocking. Uses Kanban layout. Automatic Tab Management# Tabs automatically show or hide based on the presence of relationship data. If a task has no subtasks, the Subtasks tab does not appear. If a recurring task has no materialized occurrence notes, the Occurrences tab does not appear. If there are no blocking relationships, those tabs remain hidden. This keeps the interface focused on relevant information. The widget layout changes with available data, so simple tasks show fewer sections. Features# The widget embeds the TaskNotes/Views/relationships.base view directly in the editor. Every filter, grouping rule, or property shown in that .base file is exactly what appears inside the widget, so you can customize the experience by editing the file just like any other Bases view. Additional behavior: Collapsible Interface: Click the widget title to expand or collapse. The state is remembered between sessions. Persistent Grouping: Any grouping defined in the .base file is honoured, and collapsed groups retain their state per note. Task Details: Each task shows its status, priority, due date, and other configured properties. Real-time Updates: The widget updates automatically when tasks are added, modified, or deleted via Bases views. Configuration# Enable or disable the widget in Settings -> TaskNotes -> Appearance (Show relationships widget). Position the widget at the top (after frontmatter) or bottom of the note using the Relationships Position setting. Expandable Subtasks Chevron# Tasks with subtasks can display an expand/collapse chevron that toggles subtask visibility. The chevron can be positioned on the Right (default, hover to show) or on the Left (always visible, matches group chevrons). Configure this in Settings -> TaskNotes -> Appearance (Subtask chevron position). Migration from v3# In v3, TaskNotes provided three separate widgets controlled by individual settings: showProjectSubtasks and projectSubtasksPosition showTaskDependencies and taskDependenciesPosition showBlockingTasks and blockingTasksPosition These settings are replaced in v4 by: showRelationships and relationshipsPosition If you had project subtasks enabled in v3, the relationships widget is enabled automatically after upgrading to v4. The underlying Bases file changed from TaskNotes/Views/project-subtasks.base to TaskNotes/Views/relationships.base. Run the Create files action in Settings -> TaskNotes -> General -> Views & base files if relationships.base is missing. Natural Language Processing# TaskNotes includes a Natural Language Processor (NLP) that parses task descriptions to extract structured data. This allows for task creation from conversational language, such as \"Prepare quarterly report due Friday #work high priority,\" which would automatically set the due date, tag, and priority. The NLP engine supports multiple languages, including English, Spanish, French, German, Italian, Japanese, Dutch, Portuguese, Russian, Swedish, Chinese, and Ukrainian. Supported Syntax# The NLP engine recognizes: Tags and Contexts: #tag and @context syntax (triggers are customizable). Projects: +project for simple projects or +[[Project Name]] for projects with spaces. Priority Levels: Keywords like \"high,\" \"normal,\" and \"low\". Also supports a trigger character (default: !). Status Assignment: Keywords like \"open,\" \"in-progress,\" and \"done\". Also supports a trigger character (default: *). Dates and Times: Phrases like \"tomorrow,\" \"next Friday,\" and \"January 15th at 3pm\". Time Estimates: Formats like \"2h,\" \"30min,\" and \"1h30m\". Recurrence Patterns: Phrases like \"daily,\" \"weekly,\" and \"every Monday\". User-Defined Fields: Custom fields can be assigned using configured triggers (e.g., effort: high). Supports quoted values for multi-word entries. NLP parses common patterns during capture; fields can be refined in the modal afterward. Rich Markdown Editor# New in v4: The task creation modal uses a rich CodeMirror markdown editor instead of a plain textarea. Features include: Live Preview: Rendered markdown preview as you type. Syntax Highlighting: Code blocks, links, and formatting are highlighted. Wikilink Support: Create links to other notes using [[Note Name]] syntax. Keyboard Shortcuts: Ctrl/Cmd+Enter saves the task Esc or Tab to navigate out of the editor Placeholder Text: Shows an example task (e.g., \"Buy groceries tomorrow at 3pm @home #errands\") when the editor is empty. Customizable Triggers# New in v4: Triggers for NLP properties can be customized in Settings -> TaskNotes -> Features (NLP Triggers). You can configure trigger characters or strings for: Tags (default: #) - When set to #, Obsidian's native tag suggester is used Contexts (default: @) Projects (default: +) Status (default: *) Priority (default: !, disabled by default) User-Defined Fields (default: fieldname:) - Each custom field can have its own trigger Triggers support up to 10 characters and can include trailing spaces (e.g., \"def: \" for a custom field). Autocomplete# New in v4: When typing a trigger in the NLP editor, an autocomplete menu appears with available values. Navigate suggestions with arrow keys Select with Enter or Tab Autocomplete works for tags, contexts, projects, status, priority, and user-defined fields Tag autocomplete uses Obsidian's native tag suggester when using the # trigger For user fields with multi-word values, wrap the value in quotes (e.g., effort: \"very high\") The NLP engine is integrated with the task creation modal and bulk conversion features. Typing a natural language description populates the corresponding task fields automatically."},{"title":"Integrations","url":"/obsidian/features/integrations/","description":"TaskNotes integrates with external services and Obsidian's core plugins.","product":"obsidian","text":"TaskNotes integrates with external services and Obsidian's core plugins. Bases Core Plugin# TaskNotes v4 uses Obsidian's Bases core plugin for its main views (Task List, Kanban, Calendar, Agenda). Bases must be enabled in Settings -> Core Plugins. For details on Bases integration, see Core Concepts. External Calendars# TaskNotes supports bidirectional sync with Google Calendar and Microsoft Outlook via OAuth, plus read-only access to any calendar via ICS subscriptions. For setup instructions, see Calendar Integration. HTTP API# A REST API enables external applications to create, update, and query tasks. Use it for automation, browser extensions, or custom integrations. For API documentation, see HTTP API. Webhooks# Webhooks send task event payloads to external services when subscribed events occur. Optional payload transformations support service-specific formats. For configuration, see Webhooks. Companion Plugins# Companion plugins run inside Obsidian alongside TaskNotes and use the JavaScript runtime API for live task operations. They are useful when an integration needs a real Obsidian UI, command-palette commands, or vault-local configuration files. For the companion-plugin model and guides for Canvas Bases and TaskNotes Workflows, see Companion Plugins."},{"title":"Recurring Tasks","url":"/obsidian/features/recurring-tasks/","description":"TaskNotes recurring tasks use RFC 5545 RRule strings with DTSTART support and dynamic next-occurrence scheduling. The model separates recurrence patterns from the next planned i...","product":"obsidian","text":"TaskNotes recurring tasks use RFC 5545 RRule strings with DTSTART support and dynamic next-occurrence scheduling. The model separates recurrence patterns from the next planned instance, and can also create normal task notes for individual occurrences when an instance needs its own content. If you are new to recurring tasks in TaskNotes, think of the recurrence rule as the long-term plan and the scheduled field as the next concrete commitment. Most day-to-day editing affects scheduled, while recurrence editing changes the plan itself. Core Concepts# Recurring tasks operate on two independent levels: Recurring Pattern: Defines when pattern instances appear (controlled by DTSTART in the recurrence rule) Next Occurrence: The specific date/time when you plan to work on the next instance (controlled by the scheduled field) Materialized Occurrence Notes: Optional child task notes for specific occurrence dates, used when an occurrence needs its own checklist, status, time tracking, or body content This separation lets you reschedule the next occurrence without changing the pattern. Setting Up Recurring Tasks# In practice, setup is usually a two-step flow: choose a pattern, then check whether the next scheduled occurrence matches how you actually want to execute the next instance. Creating Recurrence Patterns# You can create recurring tasks through: Recurrence Context Menu in task modals for presets or custom options Preset Options such as daily, weekly, or monthly Custom Recurrence Modal with date/time pickers and RRule configuration Required Components# Recurring tasks require: Recurrence Rule: RRule string with DTSTART Scheduled Date: Next occurrence date (independent from the pattern) Materialized occurrence notes add two system fields to the occurrence note: recurrence_parent: link/path back to the recurring parent task occurrence_date: the occurrence date represented by the note DTSTART Integration# DTSTART is the anchor for pattern generation. It controls where the rule begins and, when time is included, the default time for future pattern instances. Date-only: DTSTART:20250804;FREQ=DAILY Date and time: DTSTART:20250804T090000Z;FREQ=DAILY Recurring Task Due Date# When a recurring task is completed, scheduled advances to the next occurrence. By default, due does not change. Enable Maintain due date offset in recurring tasks in Settings → TaskNotes → Features → Recurring Tasks to preserve due/scheduled spacing. Example: Scheduled: 2025-01-01 Due: 2025-01-03 Recurrence: weekly If the task advances to scheduled: 2025-01-08, the due date becomes 2025-01-10 when this setting is enabled. This setting is most useful when due dates represent a fixed lead/lag relative to scheduled work (for example, \"due two days after execution\"). If due dates are independent deadlines, leaving the setting off is usually clearer. Recurrence Pattern Examples# DTSTART:20250804T090000Z;FREQ=DAILY → Daily at 9:00 AM, starting August 4, 2025 DTSTART:20250804T140000Z;FREQ=WEEKLY;BYDAY=MO,WE,FR → Monday, Wednesday, Friday at 2:00 PM, starting August 4, 2025 DTSTART:20250815;FREQ=MONTHLY;BYMONTHDAY=15 → 15th of each month (all-day), starting August 15, 2025 DTSTART:20250831;FREQ=MONTHLY;BYMONTHDAY=-1 → Last day of each month (all-day), starting August 31, 2025 DTSTART:20250801T100000Z;FREQ=MONTHLY;BYDAY=-1FR → Last Friday of each month at 10:00 AM, starting August 1, 2025 Dynamic Scheduled Dates# The scheduled field automatically tracks the next uncompleted occurrence: Initially set to the DTSTART date Advances when occurrences are completed Recalculates when the rule changes Can be manually rescheduled independently This behavior keeps recurring tasks practical in real planning: you can preserve a stable weekly/monthly pattern while still adapting the immediate next occurrence to calendar realities. Materialized Occurrence Notes# Most recurring tasks can remain virtual: the parent task stores complete_instances and skipped_instances, and TaskNotes renders each calendar/list instance from that parent. Materialized occurrence notes are for heavier instances where the date-specific work needs its own note. Good uses include: A weekly review where each week needs a separate agenda and notes A maintenance task where each visit needs photos, links, or a checklist A recurring meeting where every occurrence should have its own time entries and completion state To create one manually, right-click a recurring task card or calendar occurrence and choose Open or create occurrence note. The Task Action Palette also exposes Open or create occurrence note for recurring tasks. If a matching note already exists for the same parent and date, TaskNotes opens it instead of creating a duplicate. An occurrence note is an ordinary TaskNotes task. It appears in views, can be edited like any other task, and shows an occurrence pill that links back to the recurring parent. On the calendar, a materialized occurrence replaces the matching virtual parent occurrence for the same parent/date pair, so you do not see both the generated instance and the note-backed instance at the same time. Its frontmatter includes: recurrence_parent: \"[[Tasks/Weekly review]]\" occurrence_date: \"2026-06-01\" scheduled: \"2026-06-01T09:30\" timeEstimate: 45 When TaskNotes creates an occurrence note, it copies the parent fields that describe how that instance should be planned: title, priority, scheduled time, due offset, contexts, projects, tags, reminders, dependencies, details, custom properties, and time estimate. Date-like fields are rebased onto the occurrence date, so a parent scheduled at 09:30 creates an occurrence scheduled at 09:30 on the selected date, and a due date one day after the parent scheduled date stays one day after the occurrence scheduled date. Occurrence notes can use a separate template from regular new tasks. Set occurrence_template on the recurring parent to point at a template note, or configure Settings → Features → Body template → Occurrence note template file as a global fallback. Parent-level occurrence_template wins over the global fallback. If neither occurrence-specific template is configured, occurrence note creation keeps the normal body template behavior. The parent task remains the source of the recurrence rule and series history. Occurrence notes do not copy the parent's recurrence, complete_instances, skipped_instances, completedDate, calendar provider IDs, or timeEntries. New time entries belong to the occurrence note once you track time there. Occurrence Filenames# By default, materialized occurrence notes use the existing filename behavior: the parent title followed by a numeric suffix. To opt in to custom filenames, set Occurrence filename template under Settings → Task Properties → Title. For example, {{title}} — {{occurrenceDate}} produces Weekly review — 2026-08-01.md. Occurrence filename templates support all regular filename variables plus these occurrence-specific variables: {{occurrenceDate}} - occurrence date, such as 2026-08-01 {{occurrenceWeek}} - ISO week, such as 2026-W31 {{occurrenceMonth}} - month, such as 2026-08 {{occurrenceYear}} - year, such as 2026 {{occurrenceMonthName}} - full month name, such as August Choose the date granularity explicitly in the template; TaskNotes does not infer it from the recurrence rule. A recurring parent can override the global template with the frontmatter property configured by Occurrence template override property (by default, occurrenceFilenameTemplate): occurrenceFilenameTemplate: \"{{title}} ({{occurrenceWeek}})\" Leaving the global template empty preserves the existing filename behavior. TaskNotes never renames existing occurrence notes, and filename collisions continue to receive a numeric suffix. Occurrence Note Policies# Each recurring parent has an Occurrence notes submenu under its recurrence menu: Create manually: occurrence notes are only created by explicit action. Create next after completion: after you complete a materialized occurrence note, TaskNotes creates the next occurrence note. Rolling window: defined by the TaskNotes spec, but not automated in the plugin yet. When Create next after completion is enabled, creating the first occurrence is still a deliberate action. After that, completing the occurrence note advances the parent recurrence state and materializes the next scheduled occurrence. HTTP API and MCP clients can create occurrence notes without using the desktop context menu. Use POST /api/tasks/:id/materialize-occurrence or the MCP tasknotes_materialize_occurrence tool with a parent task path and occurrence date. Completing a recurring instance through the API or MCP also respects existing occurrence notes and the Create next after completion policy. The same submenu also controls the next-note trigger: Completion only: create the next occurrence note only when the current occurrence is completed. Completion or skip: create the next occurrence note when the current occurrence is completed or skipped. Skip/unskip controls appear on materialized occurrence notes when a skipped status is configured. Skipping an occurrence preserves the note, updates its status, and reconciles the parent skipped_instances list. Completion Reconciliation# When a materialized occurrence note is completed, TaskNotes updates both sides of the relationship: The occurrence note is completed like a normal task. The parent adds the occurrence date to complete_instances. The parent removes that date from skipped_instances if needed. The parent recalculates scheduled to the next uncompleted occurrence. If the parent policy is Create next after completion, TaskNotes creates the next occurrence note idempotently. Uncompleting an occurrence note removes the date from the parent's complete_instances list, but it does not delete later occurrence notes that were already created. Example Behavior# # Initial state recurrence: \"DTSTART:20250804T090000Z;FREQ=DAILY\" scheduled: \"2025-08-04T09:00\" complete_instances: [] # After completing Aug 4 recurrence: \"DTSTART:20250804T090000Z;FREQ=DAILY\" scheduled: \"2025-08-05T09:00\" complete_instances: [\"2025-08-04\"] # After manually rescheduling next occurrence recurrence: \"DTSTART:20250804T090000Z;FREQ=DAILY\" scheduled: \"2025-08-05T14:30\" complete_instances: [\"2025-08-04\"] Calendar Drag and Drop# Calendar interactions follow the same model distinction: drag the concrete next item to reschedule execution, or drag a pattern instance to redefine the recurrence anchor. Recurring tasks can show: Next occurrence (solid border): dragging updates only scheduled Pattern instances (dashed border): dragging updates DTSTART and future pattern instances Materialized occurrence notes: dragging updates the occurrence note's own scheduled or due date like a normal task, without changing the parent's recurrence rule Materialized occurrence notes keep occurrence_date as their identity. If you drag the note for the June 1 occurrence to June 2, it is still the June 1 recurrence instance, now scheduled for June 2. TaskNotes suppresses the June 1 virtual parent event and leaves the June 2 virtual occurrence alone unless that date also has its own materialized note. Completion Tracking# Each occurrence can be completed or skipped independently (task cards, calendar menus, task edit modal completion calendar). Completed instances are stored in: complete_instances: [\"2025-08-04\", \"2025-08-06\", \"2025-08-08\"] Skipped instances are stored in: skipped_instances: [\"2025-08-05\"] When completion changes, scheduled updates to the next uncompleted instance. If a materialized occurrence note exists for a date, that note's own status takes precedence for that occurrence, and TaskNotes reconciles the parent compatibility lists during completion, uncompletion, skip, and unskip actions. This means completion history and next-action planning stay synchronized automatically, without manually advancing recurring tasks. Flexible Scheduling# TaskNotes intentionally allows off-pattern scheduling so recurring tasks can absorb real-world disruptions without rewriting the entire recurrence rule. The next occurrence can be: Before DTSTART Outside the pattern day At a different time than pattern instances Far ahead while pattern continues unchanged Examples# # Early start before DTSTART recurrence: \"DTSTART:20250810T090000Z;FREQ=WEEKLY;BYDAY=MO\" scheduled: \"2025-08-07T14:00\" # Off-pattern next occurrence recurrence: \"DTSTART:20250804T090000Z;FREQ=WEEKLY;BYDAY=MO\" scheduled: \"2025-08-06T15:30\" Timezone Handling# Recurring task logic uses a UTC anchor approach: Pattern generation uses UTC dates DTSTART dates are interpreted as UTC anchors Display adapts to local timezone Prevents common off-by-one date issues In other words, calculations stay stable internally while display remains local, which avoids drift when traveling or sharing vaults across timezones. Backward Compatibility# Recurring behavior remains compatible with older task data, so upgrades do not require manual note rewrites. Legacy RRule strings without DTSTART continue to work using scheduled as anchor Legacy recurrence objects are converted to RRule format Existing tasks continue to function without migration steps Mixed formats are handled transparently"},{"title":"Task Reminders","url":"/obsidian/features/reminders/","description":"TaskNotes reminders use iCalendar VALARM semantics and support both relative and absolute reminder types.","product":"obsidian","text":"TaskNotes reminders use iCalendar VALARM semantics and support both relative and absolute reminder types. The reminders system is designed to support both habit-like workflows (\"always remind me 15 minutes before\") and one-off commitments (\"alert me exactly at this date and time\"). Most users mix both styles depending on the task. Reminder Types# Relative Reminders# Relative reminders trigger from due or scheduled dates. Use relative reminders when you want reminder behavior to stay consistent even when task dates change. Examples: 15 minutes before due date 1 hour before scheduled date 2 days before due date 30 minutes after scheduled date Absolute Reminders# Absolute reminders trigger at a fixed date/time. Use absolute reminders when the reminder itself is tied to a specific moment, independent of task rescheduling. Examples: October 26, 2025 at 9:00 AM Tomorrow at 2:30 PM Next Monday at 10:00 AM Adding Reminders# You can add reminders from: Task Creation Modal Task Edit Modal Task Cards (bell icon) Reminder field context menu From a workflow perspective, task cards and context menus are fastest for quick reminders, while task modals are better for reviewing multiple reminders on the same task. Quick Reminder Options# Common shortcuts are available for both due and scheduled anchors, such as: 5 minutes before 15 minutes before 1 hour before 1 day before Quick options appear only when the anchor date exists. This prevents invalid reminder states and keeps the quick menu focused on options that can be applied immediately. Reminder Data Format# Reminders are stored in YAML frontmatter arrays. Because reminders are stored in frontmatter, they remain portable and scriptable. You can inspect or transform reminder data with any tooling that reads Markdown + YAML. Relative Structure# reminders: - id: \"rem_1678886400000_abc123xyz\" type: \"relative\" relatedTo: \"due\" offset: \"-PT15M\" description: \"Review task details\" Absolute Structure# reminders: - id: \"rem_1678886400001_def456uvw\" type: \"absolute\" absoluteTime: \"2025-10-26T09:00:00\" description: \"Follow up with client\" Field meanings: id: unique identifier type: relative or absolute relatedTo: due or scheduled (relative only) offset: ISO 8601 duration, negative before and positive after (relative only) absoluteTime: ISO 8601 timestamp (absolute only) description: optional message You typically do not need to edit these fields manually, but understanding the structure helps when debugging automation or importing task data. Visual Indicators# Tasks with reminders show a bell icon on task cards. Solid bell indicates active reminders Clicking opens quick reminder actions Reminder UI shows task context (due/scheduled dates and reminder count) These indicators are intended to make reminders discoverable in list-heavy views without opening every task. Default Reminders# Default reminders can be configured in: Settings -> TaskNotes -> Task Properties -> Reminders Defaults are applied to: Manual task creation Instant conversion Natural language task creation Default reminders are useful for recurring habits, such as pre-deadline checks or day-before planning prompts. Technical Notes# Reminders follow iCalendar VALARM concepts with ISO 8601 offsets The reminder property name can be customized through field mapping For settings-level behavior (notification channels, enable/disable state), see Features Settings."},{"title":"Task Management","url":"/obsidian/features/task-management/","description":"This page covers task creation, properties, projects, dependencies, recurring tasks, and reminders. For the underlying architecture, see Core Concepts.","product":"obsidian","text":"This page covers task creation, properties, projects, dependencies, recurring tasks, and reminders. For the underlying architecture, see Core Concepts. Use this page as the operational overview: how tasks are captured, how they are structured, and how relationships/automation behave. Detailed reference content for recurrence and reminders is split into dedicated pages linked near the end. Creating and Editing Tasks# You can create and edit tasks in a variety of ways. The primary method is through the Task Creation Modal, which can be accessed via the \"Create new task\" command or by clicking on dates or time slots in the calendar views. This modal provides an interface for setting all available task properties, including title, status, priority, and due dates. TaskNotes keeps a storage title and a filename-safe title separate. When Store title in filename is enabled, forbidden filename characters are removed from the filename while the task title is preserved whenever it cannot be represented exactly by that filename. With another filename format, such as timestamp or UUID, the full title is stored in frontmatter. For existing tasks, the Quick actions for current task command opens a keyboard-searchable action palette. It includes status, priority, time-tracking, archive, edit, and date actions, including built-in due and scheduled date presets such as today, tomorrow, this weekend, next week, and next month. TaskNotes also supports Natural Language Creation, which allows you to create tasks by typing descriptions in plain English. The built-in parser can extract structured data from phrases like \"Buy groceries tomorrow at 3pm @home #errands high priority.\" In most workflows, users combine both approaches: fast capture with natural language, then occasional structured edits in the modal when more precision is needed. Auto-Suggestions in Natural Language Input# The natural language input field includes auto-suggestion functionality that activates when typing specific trigger characters: @ - Shows available contexts from existing tasks # - Shows available tags from existing tasks + - Shows files from your vault as project suggestions * - Shows available status options (configurable trigger in Settings → Features) In task creation and edit fields, focusing the tags or contexts input also opens the available suggestions immediately, so you can pick from the current vocabulary without typing a first character. Project Suggestions# When typing + in the natural language input, you'll see up to 20 suggestions from your vault's markdown files. The suggestions display additional information to help identify files: project-alpha [title: Alpha Project Development | aliases: alpha, proj-alpha] meeting-notes [title: Weekly Team Meeting Notes] simple-project work-file [aliases: work, office-tasks] Project suggestions search across: File names (basename without extension) Frontmatter titles (using your configured field mapping) Frontmatter aliases Optional filtering by required tags, folders, and a specific frontmatter property/value defined in Settings → Appearance & UI → Project Autosuggest Selecting a project suggestion inserts it as +[[filename]], creating a wikilink to the file while maintaining the + project marker that the natural language parser recognizes. Enhanced Project Auto‑suggester (configurable cards)# Project suggestions can display configurable multi‑row cards and support smarter search. Configure up to 3 rows using a simple token syntax in Settings → Appearance & UI → Project Autosuggest. Properties: file.basename, file.name, file.path, file.parent, title, aliases, and any frontmatter key Flags: n or n(Label) → show the field name/label before the value s → include this field in + search (in addition to defaults) Literals: you can mix in fixed text or emojis between tokens Examples \"{title|n(Title)}\" → Title: Alpha Project \"🔖 {aliases|n(Aliases)}\" → 🔖 Aliases: alpha, proj-alpha \"{file.path|n(Path)|s}\" → include path in + search as well as display it Search behavior Defaults: + search always includes file basename, title (via your field mapping), and aliases |s flag: add more searchable fields on top of the defaults (e.g., file.path or a custom frontmatter key like customer) Fuzzy: optional fuzzy matching can be enabled in settings for broader, multi‑word matches Performance tips Keep rows to three or fewer for clarity and performance (the UI supports up to 3) Prefer specific searchable fields with |s on large vaults Demo Status Suggestions# When typing the status trigger character (default *) in the natural language input, you'll see suggestions for all configured status options: Status suggestions allow quick selection of statuses when creating tasks. For example, typing *in shows \"In Progress\" as a suggestion if that's one of your configured statuses. Clicking a task card's status indicator cycles through statuses in the order configured under Settings → Task Properties → Status. A status can optionally define a specific Next status for forward cycling; otherwise TaskNotes uses the configured order. Statuses marked Skip when cycling are left out of the ordered click cycle, but remain available through menus, suggestions, direct edits, and explicit next-status jumps. Additionally, you can convert any line type in your notes to TaskNotes using the Instant Conversion feature. This works with checkboxes, bullet points, numbered lists, blockquotes, headers, and plain text lines. Task Properties# Tasks store their data in YAML frontmatter with properties for status, priority, dates, contexts, projects, tags, time estimates, recurrence, and reminders. Custom fields can extend this structure. This frontmatter-first design keeps task data editable and portable while supporting consistent behavior across views and widgets. For property types and examples, see Core Concepts. For configuration options, see Task Properties Settings. Projects# TaskNotes supports organizing tasks into projects using note-based linking. Projects are represented as links to actual notes in your vault, allowing you to leverage Obsidian's linking and backlinking features for project management. This model avoids creating a separate project database. Any note can become a project anchor, and task/project relationships remain visible through normal Obsidian link tooling. Project Assignment# Tasks can be assigned to one or more projects through the task creation or editing interface. When creating or editing a task, click the \"Add Project\" button to open the project selection modal. This modal provides fuzzy search functionality to quickly find and select project notes from your vault. Project Links# Projects are stored as wikilinks in the task's frontmatter (e.g., projects: [\"[[Project A]]\", \"[[Project B]]\"]). These links are clickable in the task interface and will navigate directly to the project notes when clicked. Any note in your vault can serve as a project note simply by being linked from a task's projects field. Organization and Filtering# Tasks can be filtered and grouped by their associated projects in all Bases-driven task views. Use the Bases filter editor to add note.projects conditions, and configure the grouping menu to organize Task List or Kanban boards by project. Tasks assigned to multiple projects will appear in each relevant project group, providing flexibility in project-based organization. Project Indicators# TaskCards display visual indicators when tasks are used as projects. These indicators help identify which tasks have other tasks linked to them as subtasks, making project hierarchy visible at a glance. Subtask Creation# Tasks can have subtasks created directly from their context menu. When viewing a task that serves as a project, you can select \"Create subtask\" to create a new task automatically linked to the current project. Dependencies# Task dependencies capture prerequisite work using RFC 9253 terminology. Dependencies are stored in frontmatter as structured objects: blockedBy: - uid: \"[[Operations/Order hardware]]\" reltype: FINISHTOSTART gap: P1D uid references the blocking task, typically through an Obsidian wikilink. reltype is stored with each dependency and defaults to FINISHTOSTART for dependencies created in the UI. gap is optional and uses ISO 8601 duration syntax (for example PT4H or P2D). Whenever a dependency is added, TaskNotes updates the upstream note’s blocking list so the reverse relationship stays synchronized. Removing a dependency automatically clears both sides. Selecting dependencies in the UI# The task creation and edit modals expose “Blocked by” and “Blocking” buttons that launch a fuzzy task selector. The picker only offers valid tasks, excludes the current note, and prevents duplicate entries. The task context menu provides the same selector, enabling dependency management directly from the Task List, Kanban, and calendar views. Task cards show a fork icon whenever a task blocks other work. Clicking it expands an inline list of downstream tasks without triggering the parent card’s modal, so you can inspect dependents in place. These controls currently create and manage finish-to-start style blockers. Advanced reltype values and gap data are preserved in frontmatter, but blocking evaluation is currently based on whether unresolved dependencies exist rather than relationship-type-specific scheduling rules. Automation# Auto-Archiving# TaskNotes can automatically archive tasks when they transition into a status that has auto-archiving enabled. This keeps completed work out of your active lists without requiring manual cleanup. Configure auto-archiving per status from Settings → Task Properties → Task Statuses. Each status card includes an Auto-archive toggle and a Delay (minutes) input (1–1440). When you turn the toggle on for a status, any task moved into that status is queued for archiving once the delay elapses. Moving the task to a different status before the timer expires cancels the pending archive automatically. The auto-archive queue runs in the background and persists across plugin restarts. If TaskNotes was closed while an archive was pending, the task will be archived shortly after the plugin loads again as long as it still matches the configured status. This automation is intended to keep active views focused without manual cleanup, while still preserving archived task history in your vault. File Management and Templates# TaskNotes supports configurable task folder locations, filename generation patterns, archive behavior, and body templates for newly created tasks. These settings let you align task files with existing vault conventions (for example, date-based folders, project-based routing, or template-driven task note scaffolds). For configuration details, see Task Defaults.For template variables, see Template Variables Reference. Recurring Tasks# TaskNotes recurring tasks use RFC 5545 RRule syntax with DTSTART, separate pattern definition from next occurrence scheduling, and support independent instance completion. When an individual recurrence needs its own checklist, time entries, or notes, you can create a materialized occurrence note from the task or calendar context menu. For full behavior, examples, and edge cases, see Recurring Tasks. Task Reminders# Task reminders support relative offsets from due/scheduled dates and absolute date-time reminders. You can add reminders from task modals, task cards, and context menus. For full setup, data format, defaults, and UI behavior, see Task Reminders."},{"title":"Template Variables Reference","url":"/obsidian/features/template-variables/","description":"TaskNotes supports template variables for dynamic content generation in body templates, folder paths, and filenames. Variables use the {{variableName}} syntax and are replaced w...","product":"obsidian","text":"TaskNotes supports template variables for dynamic content generation in body templates, folder paths, and filenames. Variables use the {{variableName}} syntax and are replaced with actual values when content is created. Overview# Template variables are available in three contexts: Body templates - Content templates for task and note files Folder templates - Dynamic folder paths for file organization Filename templates - Dynamic filename generation Not all variables are available in every context. The tables below indicate where each variable can be used. Task Properties# Variables for task-specific data. Variable Description Body Folder Example {{title}} Task title Yes Yes My Task {{titleLower}} Title in lowercase Yes Yes my task {{titleUpper}} Title in uppercase Yes Yes MY TASK {{titleSnake}} Title in snake_case Yes Yes my_task {{titleKebab}} Title in kebab-case Yes Yes my-task {{titleCamel}} Title in camelCase Yes Yes myTask {{titlePascal}} Title in PascalCase Yes Yes MyTask {{priority}} Task priority value Yes Yes high {{priorityShort}} First character of priority (uppercase) Yes Yes H {{status}} Task status value Yes Yes active {{statusShort}} First character of status (uppercase) Yes Yes A {{context}} First context from contexts array No Yes work {{contexts}} All contexts (comma-separated in body, / in folder) Yes Yes work, home or work/home {{project}} First project from projects array No Yes ProjectA {{projects}} All projects joined by / No Yes ProjectA/ProjectB {{projectFilePath}} Full path of the first project, without .md No Yes Work/Projects/ProjectA {{projectFilePaths}} Full paths of all projects, joined by / No Yes Work/Alpha/Personal/Beta {{projectFolder}} Folder containing the first project note (its file path without the note's own name) No Yes Work/Projects {{projectFolders}} Folders of all projects, joined by / No Yes Work/Personal {{dueDate}} Task due date Yes Yes 2025-01-15 {{scheduledDate}} Task scheduled date Yes Yes 2025-01-10 Body Template Only# Variables available only in body templates (not folder templates). Variable Description Example {{details}} User-provided details/description Task description text {{parentNote}} Parent note name/path where task was created Projects/MyNote {{tags}} Task tags (comma-separated) urgent, review {{hashtags}} Task tags as space-separated hashtags #urgent #review {{timeEstimate}} Time estimate in minutes 30 Date and Time# Variables for current date and time values. Variable Description Format Example {{date}} Full current date YYYY-MM-DD 2025-01-07 {{year}} Current year YYYY 2025 {{shortYear}} Short year YY 25 {{month}} Current month MM 01 {{day}} Current day DD 07 {{monthName}} Full month name - January {{monthNameShort}} Abbreviated month name - Jan {{dayName}} Full day name - Tuesday {{dayNameShort}} Abbreviated day name - Tue {{week}} Week number of year WW 02 {{quarter}} Quarter of year Q 1 {{shortDate}} Compact date YYMMDD 250107 Time Variables# Variable Description Format Example {{time}} Current time (compact) HHmmss 143052 {{time24}} 24-hour time HH:mm 14:30 {{time12}} 12-hour time with AM/PM hh:mm a 02:30 PM {{hour}} Current hour (24-hour) HH 14 {{hourPadded}} Hour with leading zero HH 14 {{hour12}} Hour in 12-hour format hh 02 {{minute}} Current minute mm 30 {{second}} Current second ss 52 {{ampm}} AM/PM indicator a PM Timestamps# Variable Description Format Example {{timestamp}} Date and time combined YYYY-MM-DD-HHmmss 2025-01-07-143052 {{dateTime}} Date and time (no seconds) YYYY-MM-DD-HHmm 2025-01-07-1430 {{unix}} Unix timestamp (seconds) - 1736264852 {{unixMs}} Unix timestamp (milliseconds) - 1736264852000 {{milliseconds}} Current milliseconds SSS 123 {{ms}} Milliseconds (alias) SSS 123 Timezone# Variable Description Example {{timezone}} Timezone offset +01:00 {{timezoneShort}} Short timezone offset +0100 {{utcOffset}} UTC offset +01:00 {{utcOffsetShort}} Short UTC offset +0100 {{utcZ}} UTC Z indicator Z Unique Identifiers# Variable Description Example {{zettel}} Zettelkasten-style ID (date + seconds since midnight in base36) 250107abc {{nano}} Unique nano ID (timestamp + random string) 1736264852000x7k2m ICS Calendar Event Variables# Variables for content created from ICS calendar events. Available when creating notes or tasks from calendar events. Event Information# Variable Description Body Folder {{icsEventTitle}} Event title Yes Yes {{icsEventTitleLower}} Event title lowercase No Yes {{icsEventTitleUpper}} Event title uppercase No Yes {{icsEventTitleSnake}} Event title in snake_case No Yes {{icsEventTitleKebab}} Event title in kebab-case No Yes {{icsEventTitleCamel}} Event title in camelCase No Yes {{icsEventTitlePascal}} Event title in PascalCase No Yes {{icsEventStart}} Event start time (ISO format) Yes No {{icsEventEnd}} Event end time (ISO format) Yes No {{icsEventLocation}} Event location Yes Yes {{icsEventDescription}} Event description Yes Yes {{icsEventUrl}} Event URL Yes No {{icsEventSubscription}} Calendar subscription name Yes No {{icsEventId}} Unique event identifier (UUID) Yes No Current Note Folder Variables# Variables available for inline-created tasks and the default tasks folder. Variable Description Example {{currentNotePath}} Path to the current note's folder Projects/Notes {{currentNoteTitle}} Title/name of the current note Meeting Notes Examples# Body Template# --- created: {{date}} priority: {{priority}} status: {{status}} --- # {{title}} {{details}} Created from: {{parentNote}} Tags: {{hashtags}} Folder Template# Organize tasks by project and status: Tasks/{{project}}/{{status}} Result: Tasks/MyProject/active Organize by date hierarchy: Daily/{{year}}/{{month}}/{{day}} Result: Daily/2025/01/07 Organize ICS events by year and title: Events/{{year}}/{{icsEventTitleKebab}} Result: Events/2025/team-meeting Filename Template# Using Zettelkasten ID: {{zettel}}-{{titleKebab}} Result: 250107abc-my-task.md Using timestamp: {{shortDate}}-{{title}} Result: 250107-My Task.md Notes# YAML Safety# When used in YAML frontmatter, values containing special characters (colons, brackets, quotes) are automatically quoted to prevent parsing errors. Folder Path Sanitization# In folder templates, title values have filesystem-unsafe characters (<>:\"/\\|?*) replaced with underscores to ensure valid paths. Project file path variables preserve folder separators and sanitize unsafe characters within each path segment. Empty Values# If a variable references data that isn't available (e.g., {{project}} when no project is set), it resolves to an empty string. Case Transformations# The case transformation variables work as follows: Transform Input Output titleLower My Task Name my task name titleUpper My Task Name MY TASK NAME titleSnake My Task Name my_task_name titleKebab My Task Name my-task-name titleCamel My Task Name myTaskName titlePascal My Task Name MyTaskName"},{"title":"Time Management","url":"/obsidian/features/time-management/","description":"TaskNotes includes features for time tracking and productivity, such as a time tracker and a Pomodoro timer.","product":"obsidian","text":"TaskNotes includes features for time tracking and productivity, such as a time tracker and a Pomodoro timer. Time Tracking# TaskNotes has a time tracker to record the time spent on each task. Time tracking information is stored in the timeEntries array within each task's YAML frontmatter. Each time entry includes a start time and an end time. The time tracking interface includes controls to start and stop tracking in task views and task cards. TaskNotes prevents duplicate active sessions on the same task. Active sessions on different tasks can exist at the same time, and total time spent on each task is calculated from completed sessions. Auto-Stop Time Tracking# TaskNotes can automatically stop time tracking when a task is marked as completed. This feature ensures that time tracking data accurately reflects work completion without requiring manual timer management. The auto-stop feature works by monitoring task status changes across all views and interfaces. When a task's status changes from any non-completed state to a completed state (as defined by the custom status configuration), any active time tracking session for that task is automatically terminated. Configuration Options: Configure these under Settings -> TaskNotes -> Features (Time Tracking section). Auto-stop tracking - Enable or disable the automatic stopping behavior (enabled by default) Completion notification - Show a notice when auto-stop occurs (disabled by default) Behavior: Monitors all task status changes in real-time Stops only the specific task that was completed (other active timers continue) Preserves the recorded time data in the task's time entries Works with both standard and recurring task completions Functions across all task views (list, kanban, calendar, etc.) The feature integrates with the custom status system, so completion detection respects your configured workflow statuses rather than relying on hardcoded completion states. Pomodoro Timer# TaskNotes also includes a Pomodoro timer, which is a tool for time management that uses a timer to break down work into intervals, separated by short breaks. The Pomodoro timer in TaskNotes has a dedicated view with controls to start, stop, and reset the timer. When a task is associated with a Pomodoro session, the time is automatically recorded in the task's time tracking data upon completion of the session. Productivity Analytics# The Pomodoro Stats View provides analytics and historical data about your Pomodoro sessions. This includes a history of completed sessions, as well as metrics like completion rates and total time spent on tasks. The data can be visualized to show productivity patterns over time."},{"title":"User Fields","url":"/obsidian/features/user-fields/","description":"TaskNotes allows you to define your own custom fields for tasks. This feature allows you to add custom data to your tasks and use it for filtering, sorting, and grouping. User f...","product":"obsidian","text":"TaskNotes allows you to define your own custom fields for tasks. This feature allows you to add custom data to your tasks and use it for filtering, sorting, and grouping. User fields can store workflow-specific metadata such as owner, effort class, client, or review stage. Creating User Fields# User fields are created in the TaskNotes settings, under the \"Task Properties\" tab. To create a new user field, click the \"Add new user field\" button. Fields that are not used in filters or grouping still add frontmatter overhead, so this section focuses on fields used in views. Each user field has the following properties: Display Name: The name of the field as it will be displayed in the UI. Property Name: The name of the field as it will be stored in the frontmatter of the task note. Type: The data type of the field. The following types are supported: Text: A single line of text. Number: A numeric value (supports ranges in filters and sorting). Boolean: A true/false value stored as a checkbox in the task modal. Date: A date. List: A list of values. Default Value (optional): A default value to pre-fill when creating new tasks. The input format depends on the field type: Text: Enter the default text value. Number: Enter the default number. Boolean: Toggle to set the default state (checked/unchecked). Date: Select from presets: None, Today, Tomorrow, or Next Week. List: Enter comma-separated default values. Link Values# Use a Text field for one related link, such as a pull request or specification, and a List field for multiple related links. Task cards render wikilinks, markdown links, angle-bracket autolinks, and bare https:// URLs as clickable links. For internal note links, type [[ in a text or list field to use the same file suggestions as other TaskNotes link fields. Autosuggestion filters can narrow those note suggestions without changing how the stored field value is filtered, sorted, or grouped. File Suggestion Filtering (Advanced)# When using text or list type custom fields, you can configure autosuggestion filters to control which files appear in the autocomplete dropdown when you type [[ in the field. This is useful when you want to limit suggestions to specific types of notes. For example: An \"Assignee\" field that only suggests notes tagged with #person A \"Project\" field that only shows notes in the Projects/ folder A \"Related Document\" field filtered by a specific frontmatter property Filtering narrows wikilink suggestions in large vaults. Configuring Filters# To configure filters for a custom field: Go to Settings → Task Properties → Custom User Fields Expand the custom field card you want to configure Expand the \"Autosuggestion filters (Advanced)\" section Configure one or more of the following filters: Filter Options# Required tags: Only show files that have ANY of these tags (comma-separated) Example: person, team - shows files with either #person OR #team tag Supports hierarchical tags: project/active matches #project/active Include folders: Only show files in these folders (comma-separated) Example: People/, Teams/ - shows files in either folder Supports nested folders: Projects/Active/ matches files in that specific folder Required property key: Only show files that have this frontmatter property Example: role - shows files with a role: property in frontmatter Required property value: Expected value for the property (optional) Example: developer - when combined with property key role, shows files with role: developer Leave empty to match any value (just checks property exists) Filter Indicator# When filters are configured, a \"Filters On\" badge with a funnel icon appears next to the section title. This prevents you from forgetting that filters are active. Filter Behavior# All filters are combined with AND logic: Files must match ALL configured filters to appear Empty filters are ignored: If you don't configure a filter, it won't restrict results No filters = all files: If no filters are configured, all markdown files in your vault will appear Filters only affect autocomplete: They don't affect the actual field value or validation Autocomplete filtering and stored field values are handled independently. Example Configurations# Assignee Field (People Only)# Display Name: Assignee Property Key: assignee Type: List Autosuggestion filters: Required tags: person Include folders: People/ Project Field (Active Projects)# Display Name: Project Property Key: project Type: Text Autosuggestion filters: Required tags: project Required property key: status Required property value: active Related Note (Specific Folder)# Display Name: Related Note Property Key: related-note Type: Text Autosuggestion filters: Include folders: Documentation/, Guides/ Using User Fields# Once you have created a user field, it will be available in the following places: Task Modals: The user field will be displayed in the task creation and edit modals. Bases Filters: Add the field to Bases filter expressions (for example note.effort == \"high\") to narrow task lists and Kanban boards. Sorting: Use the Bases sort menu to order tasks by the user field. Grouping: Use the Bases group menu to create swimlanes or list groupings based on the user field. To verify a new field is active in workflow, add it to at least one saved view. Frontmatter# User field data is stored in the frontmatter of the task note. The property name you define for the user field is used as the key in the frontmatter. For example, if you create a user field with the property name \"my_field\", the data for that field will be stored in the frontmatter as follows: --- my_field: value ---"},{"title":"Adopt TaskNotes in an existing vault","url":"/obsidian/getting-started/existing-vault/","description":"Adopt TaskNotes in a vault that already contains tasks, tags, and custom frontmatter without rewriting everything first.","product":"obsidian","text":"TaskNotes can use your current folders and property names. Configure identification and field mapping before creating or converting tasks so the first write follows your vault conventions. 1. Back up the vault# Make a complete vault backup, including the hidden .obsidian directory. The task notes themselves are Markdown, while TaskNotes settings live in .obsidian/plugins/tasknotes/data.json. 2. Inspect a representative note# Choose one existing task and record: The property or tag that distinguishes tasks from ordinary notes The property names used for title, status, priority, due date, and scheduled date Whether contexts and tags are stored with or without display prefixes The folder patterns that should be included or excluded Canonical frontmatter values do not include natural-language trigger characters. Store office, not @office, and review, not #review. --- type: task status: open contexts: - office tags: - review --- 3. Choose task identification# Open Settings → TaskNotes → General. Choose Tag if every task contains one identifying tag, such as task. Choose Property if a property/value pair identifies tasks, such as type: task. Add archive, template, attachment, or other non-task locations to Excluded folders. Task identification controls indexing and every generated Base filter. Confirm it before regenerating Base files. 4. Map properties# Open Settings → TaskNotes → Task properties and map TaskNotes fields to the names already used in your notes. Avoid creating two properties for one concept, such as both due and deadline. Start with title, status, priority, due, scheduled, projects, contexts, and recurrence. Use the property types reference to check value shapes. 5. Test one note# Open one existing note and confirm that TaskNotes recognizes it. Use TaskNotes: Quick actions for current task and make a reversible edit, such as changing priority. Inspect the frontmatter before testing a larger set. If the note is not recognized, use the troubleshooting decision tree. 6. Generate views from the final mapping# Open Settings → TaskNotes → General → Views & base files and create or update the default Base files. Generated filters and columns use the current task identifier and field mapping. The update action replaces configured default Base files. Copy any customized Base to a new filename before updating it. 7. Convert incrementally# Convert or edit a small group first. Keep normal version-control or backup checkpoints between batches. Existing notes do not need to move into the default TaskNotes/Tasks folder if your storage and exclusion settings already cover their location."},{"title":"Obsidian mobile guide","url":"/obsidian/getting-started/mobile/","description":"What is shared between TaskNotes desktop and mobile, and which integrations differ on mobile.","product":"obsidian","text":"TaskNotes task files, Base files, settings, and most commands work on Obsidian mobile. Sync the complete vault, including .base files and .obsidian/plugins/tasknotes/data.json, when you want the same configuration on every device. Before opening TaskNotes# Install an Obsidian mobile version compatible with the current TaskNotes requirement. Enable the Bases core plugin. Confirm the TaskNotes plugin and its data.json have finished syncing before changing settings. Open a small default Base first and allow the initial index to finish. Mobile differences# Area Mobile behavior HTTP API and MCP server Desktop only. The HTTP API settings section is hidden on mobile. Calendar integrations Available, with an option to disable calendar integration on mobile when startup time or provider behavior is a problem. Settings layout Uses the same six tabs. Desktop-only controls are omitted where they cannot run. Keyboard commands Commands remain available in the command palette; desktop key bindings may not have a mobile equivalent. Wide views Calendar, Kanban, and large tables may require horizontal scrolling or a narrower Base configuration. A practical mobile setup# Keep task cards compact under Settings → Appearance and UI. Limit visible Base columns and calendar event layers. Increase remote calendar refresh intervals when mobile networking or battery use matters. Use the task creation modal or command palette for predictable capture. Keep HTTP automation on a desktop Obsidian instance. If mobile stops loading tasks# Wait for vault sync to finish, confirm Bases is enabled, and run TaskNotes: Refresh cache. Then reopen the affected Base. If the problem is isolated to calendar data, enable Disable calendar integration on mobile and restart Obsidian before investigating the provider connection on desktop."},{"title":"Backup, restore, and removal","url":"/obsidian/guides/backup-recovery/","description":"Back up, restore, reset, and uninstall TaskNotes while protecting task notes, views, settings, and integration data.","product":"obsidian","text":"TaskNotes keeps task content in your vault and configuration in the plugin data file. A complete backup includes both. What to back up# Data Typical location Why it matters Task notes Your configured task folders Titles, properties, details, recurrence, and time entries Base views TaskNotes/Views/ or custom paths Filters, formulas, layout, and custom views Plugin settings .obsidian/plugins/tasknotes/data.json Field mapping, statuses, defaults, integrations, and view command paths Daily notes Your daily-note folder Pomodoro history when daily-note storage is enabled mdbase configuration tasknotes.yaml, mdbase.yaml, or .mdbase/ when configured Shared collection and schema configuration Treat data.json as sensitive because integration configuration can include credentials or tokens. Store backups accordingly. Create a restorable backup# Close Obsidian or disable TaskNotes so settings are not being written. Copy the entire vault, including hidden files. Verify the backup contains .obsidian/plugins/tasknotes/data.json. Keep at least one version from before a migration or bulk edit. File-history sync is useful, but it is not a substitute for a separate tested backup. Restore# Close Obsidian. Restore task notes and Base files first. Restore .obsidian/plugins/tasknotes/data.json if you also need the previous settings. Reopen Obsidian and confirm Bases is enabled. Run TaskNotes: Refresh cache and open one default Base. If provider credentials have expired or were intentionally excluded from the backup, reconnect those integrations instead of restoring stale tokens. Reset configuration safely# Do not delete data.json as a first troubleshooting step. Close Obsidian. Rename data.json to data.json.backup-YYYY-MM-DD. Reopen Obsidian and test with fresh defaults. Restore the backup while Obsidian is closed if the reset does not help. A reset affects settings, configured statuses and priorities, integration state, saved views, and plugin-stored Pomodoro history. It does not delete task Markdown files. Uninstall# Disabling or uninstalling TaskNotes leaves task notes and .base files in the vault. After uninstalling, remove generated folders only if you have inspected them and confirmed they contain no content you want to keep. To remove plugin settings as well, close Obsidian and remove .obsidian/plugins/tasknotes/ after making a backup. Task metadata remains readable YAML, but TaskNotes-specific Base view types and interactive widgets will no longer render. Recovery checklist# Missing tasks: restore the note files, then verify task identification and excluded folders. Missing settings: restore data.json with Obsidian closed. Broken default views: regenerate them from General → Views & base files. Broken custom views: restore the individual .base files from history. Lost Pomodoro history: restore the configured storage source, which may be plugin data or daily-note frontmatter."},{"title":"Build a custom Base","url":"/obsidian/guides/custom-bases/","description":"Create a custom Obsidian Base for TaskNotes while keeping generated defaults safe and upgradeable.","product":"obsidian","text":"TaskNotes views are ordinary Obsidian .base files. The safest workflow is to copy a generated Base, give it a new path, and customize the copy. Start from a copy# Open TaskNotes/Views/ in the file explorer. Duplicate the closest default, such as tasks-default.base. Rename the copy, for example work-tasks.base. Open the copy and make changes with the Bases interface or source editor. Avoid editing the only copy of a generated default. Update default base files replaces the files configured as defaults. Preserve task identification# Every task view needs a filter that matches the identification method in Settings → TaskNotes → General. For tag identification: filters: and: - file.hasTag(\"task\") For property identification: filters: and: - note[\"type\"] == \"task\" Also preserve any excluded-folder conditions generated from your settings. Add a focused view# This example starts with recognized tasks, then limits the view to the work context: filters: and: - file.hasTag(\"task\") - list(contexts).contains(\"work\") views: - type: tasknotesTaskList name: Work order: - status - priority - due - file.name sort: - column: due direction: ASC Use canonical stored values in filters. Natural-language prefixes such as @ and # are input syntax, not part of stored context and tag values. Point a command at the custom Base# Open Settings → TaskNotes → General → View commands and change the relevant command path. Resetting that mapping returns it to the generated default path. Upgrade safely# When TaskNotes ships improved templates: Keep your custom file at its own path. Run Update default base files. Compare the regenerated default with your copy. Bring across only the formulas, filters, or view options you want. The generated template reference always reflects the current source and default field mapping. Recovery# If a custom Base no longer opens, validate its YAML indentation and remove the most recent filter or formula change. You can create a fresh default from settings at any time, then copy your custom view into it one section at a time."},{"title":"TaskNotes HTTP API","url":"/obsidian/HTTP_API/","description":"The TaskNotes HTTP API provides local HTTP access to tasks, time tracking, pomodoro, calendars, webhooks, and NLP parsing.","product":"obsidian","text":"The TaskNotes HTTP API provides local HTTP access to tasks, time tracking, pomodoro, calendars, webhooks, and NLP parsing. Availability# Desktop only Disabled by default Started when Obsidian starts and TaskNotes API is enabled Bound to loopback (127.0.0.1) only, not the local network Browser CORS requests are allowed only from loopback origins such as localhost, 127.0.0.1, and [::1] Not available on mobile Enable it in Settings -> TaskNotes -> Integrations -> HTTP API. Base URL# http://localhost:{PORT} Default port is 8080. Authentication# Authentication is optional. If apiAuthToken is empty, all API requests are accepted. If apiAuthToken is set, send Authorization: Bearer . Set a token for any workflow where local browser pages, scripts, or other desktop apps are not fully trusted. Example: curl -H \"Authorization: Bearer YOUR_TOKEN\" http://localhost:8080/api/health Response Format# Success: { \"success\": true, \"data\": {} } Error: { \"success\": false, \"error\": \"Error message\" } Endpoint Index# System# GET /api/health GET /api/docs GET /api/docs/ui POST /api/nlp/parse POST /api/nlp/create Tasks# GET /api/tasks POST /api/tasks GET /api/tasks/:id PUT /api/tasks/:id DELETE /api/tasks/:id POST /api/tasks/:id/toggle-status POST /api/tasks/:id/archive POST /api/tasks/:id/complete-instance POST /api/tasks/:id/materialize-occurrence POST /api/tasks/query GET /api/filter-options GET /api/stats Bases# POST /api/bases/default-files/update Time Tracking# POST /api/tasks/:id/time/start POST /api/tasks/:id/time/start-with-description POST /api/tasks/:id/time/stop GET /api/tasks/:id/time GET /api/time/active GET /api/time/summary Pomodoro# POST /api/pomodoro/start POST /api/pomodoro/stop POST /api/pomodoro/pause POST /api/pomodoro/resume GET /api/pomodoro/status GET /api/pomodoro/sessions GET /api/pomodoro/stats Calendars# GET /api/calendars GET /api/calendars/google GET /api/calendars/microsoft GET /api/calendars/subscriptions GET /api/calendars/events Webhooks# POST /api/webhooks GET /api/webhooks DELETE /api/webhooks/:id GET /api/webhooks/deliveries See docs/webhooks.md for event and transform details. Route Details# Health# GET /api/health# Returns service state plus vault metadata. curl http://localhost:8080/api/health Tasks# GET /api/tasks# Basic task listing with pagination only. Query params: limit (default 50, max 200) offset (default 0) Important: Filtering params such as status, priority, tag, project, context, due_before, due_after, overdue, completed, archived, and sort are rejected on this endpoint with HTTP 400. Use POST /api/tasks/query for filtering. Example: curl \"http://localhost:8080/api/tasks?limit=25&offset=0\" Response fields: data.tasks data.pagination with total, offset, limit, hasMore data.vault data.note Task objects include configured TaskNotes user fields in customProperties, keyed by their frontmatter property key. POST /api/tasks# Create one task. Required: title Common optional fields: details, status, priority, due, scheduled tags, contexts, projects recurrence, recurrence_anchor, timeEstimate, reminders blockedBy blockedBy accepts an array of dependency objects: uid: link or identifier for the blocking task, such as [[Project setup]] reltype: one of FINISHTOSTART, FINISHTOFINISH, STARTTOSTART, or STARTTOFINISH gap: optional ISO 8601 duration, such as P1D blocking is a read-only reverse relationship in API responses. To make a task block existing tasks, update those existing tasks' blockedBy fields. curl -X POST http://localhost:8080/api/tasks \\ -H \"Content-Type: application/json\" \\ -d '{\"title\":\"Review docs\",\"priority\":\"high\",\"blockedBy\":[{\"uid\":\"[[Draft docs]]\",\"reltype\":\"FINISHTOSTART\"}]}' Returns HTTP 201 with created task data. GET /api/tasks/:id# Get one task by path id. :id must be URL-encoded task path. Single-task reads include the task body in details. Configured TaskNotes user fields are returned in customProperties, keyed by their frontmatter property key. curl \"http://localhost:8080/api/tasks/TaskNotes%2FTasks%2FReview%20docs.md\" PUT /api/tasks/:id# Update task with partial payload. Configured TaskNotes user fields can be updated either by their frontmatter property key or via customProperties. curl -X PUT \"http://localhost:8080/api/tasks/TaskNotes%2FTasks%2FReview%20docs.md\" \\ -H \"Content-Type: application/json\" \\ -d '{\"status\":\"in-progress\"}' DELETE /api/tasks/:id# Delete task file. POST /api/tasks/:id/toggle-status# Toggle task status via configured workflow. POST /api/tasks/:id/archive# Toggle archive state. POST /api/tasks/:id/complete-instance# Complete recurring instance. Request body: Optional date (ISO string). If omitted, uses current date context. When the recurring parent uses materialized occurrence notes, this endpoint completes the matching occurrence note if one exists. If the parent is set to Create next after completion and no matching occurrence note exists yet, TaskNotes creates and completes that occurrence note instead of only recording a virtual complete_instances entry. POST /api/tasks/:id/materialize-occurrence# Create or return a materialized occurrence note for a recurring task date. This endpoint is idempotent for the same parent and date. Request body: Required date (ISO date string, for example 2026-06-01) POST /api/tasks/query# Advanced filtering. Request body is a FilterQuery object. FilterQuery is still the supported advanced query shape for the HTTP API. The root object is a group with: type: \"group\" id conjunction: \"and\" | \"or\" children (conditions or groups) Optional top-level query options: sortKey, sortDirection groupKey, subgroupKey Example: { \"type\": \"group\", \"id\": \"root\", \"conjunction\": \"and\", \"children\": [ { \"type\": \"condition\", \"id\": \"c1\", \"property\": \"status\", \"operator\": \"is\", \"value\": \"open\" } ], \"sortKey\": \"due\", \"sortDirection\": \"asc\" } Filter tasks by context: { \"type\": \"group\", \"id\": \"root\", \"conjunction\": \"and\", \"children\": [ { \"type\": \"condition\", \"id\": \"context\", \"property\": \"contexts\", \"operator\": \"contains\", \"value\": \"@office\" } ], \"sortKey\": \"due\", \"sortDirection\": \"asc\" } Filter active, unarchived tasks, similar to the default available-task view: { \"type\": \"group\", \"id\": \"root\", \"conjunction\": \"and\", \"children\": [ { \"type\": \"condition\", \"id\": \"not-archived\", \"property\": \"archived\", \"operator\": \"is-not-checked\" }, { \"type\": \"condition\", \"id\": \"not-completed\", \"property\": \"status.isCompleted\", \"operator\": \"is-not-checked\" } ], \"sortKey\": \"due\", \"sortDirection\": \"asc\", \"groupKey\": \"none\" } Condition fields: type: \"condition\" id: any stable string for your client property: a task property, such as title, status, priority, tags, contexts, projects, blockedBy, blocking, due, scheduled, completedDate, dateCreated, dateModified, archived, hasSubtasks, dependencies.isBlocked, dependencies.isBlocking, timeEstimate, recurrence, or status.isCompleted operator: one of is, is-not, contains, does-not-contain, is-before, is-after, is-on-or-before, is-on-or-after, is-empty, is-not-empty, is-checked, is-not-checked, is-greater-than, is-less-than, is-greater-than-or-equal, or is-less-than-or-equal value: required for comparison operators, omitted for empty/checked operators For user-defined fields, use property: \"user:\". Response: data.tasks data.total data.filtered data.vault GET /api/filter-options# Returns filter options for UI builders. GET /api/stats# Returns summary counts: total, completed, active, overdue, archived, withTimeTracking Bases# POST /api/bases/default-files/update# Overwrite the configured default TaskNotes .base files with templates generated from the current TaskNotes settings. This is the same write operation as Settings -> TaskNotes -> Views & base files -> Update files and replaces manual edits in those configured default files. curl -X POST http://localhost:8080/api/bases/default-files/update Response fields: data.created: default files created because they were missing data.updated: existing default files overwritten with current templates data.skipped: configured default files skipped Time Tracking# POST /api/tasks/:id/time/start# Starts a new active time entry for that task. POST /api/tasks/:id/time/start-with-description# Starts time tracking and writes description on the new active entry. Request body: { \"description\": \"Implementation\" } POST /api/tasks/:id/time/stop# Stops active time entry for that task. GET /api/tasks/:id/time# Returns per-task time summary and entries. GET /api/time/active# Returns currently active sessions across tasks. Important: Multiple active sessions can exist across different tasks. GET /api/time/summary# Returns aggregate time summary. Query params: period (for example today, week, month, all) from (ISO date) to (ISO date) Example: curl \"http://localhost:8080/api/time/summary?period=week\" Pomodoro# POST /api/pomodoro/start# Starts a session. Optional request fields: taskId (URL path of task) duration (number) POST /api/pomodoro/stop# Stops and resets current session. POST /api/pomodoro/pause# Pauses running session. POST /api/pomodoro/resume# Resumes paused session. GET /api/pomodoro/status# Returns current state plus computed totals (totalPomodoros, currentStreak, totalMinutesToday). GET /api/pomodoro/sessions# Returns history. Query params: limit date (YYYY-MM-DD) GET /api/pomodoro/stats# Returns stats for today or provided date. Query params: date (YYYY-MM-DD) Calendars# GET /api/calendars# Returns provider connectivity overview and subscription counts. GET /api/calendars/google# Returns Google provider details. If disconnected, returns { \"connected\": false }. GET /api/calendars/microsoft# Returns Microsoft provider details. If disconnected, returns { \"connected\": false }. GET /api/calendars/subscriptions# Returns ICS subscriptions with runtime fields such as lastFetched and lastError. GET /api/calendars/events# Returns merged event list from connected providers and ICS subscriptions. Query params: start (ISO date/datetime) end (ISO date/datetime) Response includes: events total sources (counts by provider) Webhooks# POST /api/webhooks# Registers webhook. Required fields: url events (non-empty array) Optional fields: id secret active transformFile corsHeaders GET /api/webhooks# Lists registered webhooks. Stored secrets are not returned. DELETE /api/webhooks/:id# Deletes webhook. GET /api/webhooks/deliveries# Returns last 100 delivery records. OpenAPI Docs# GET /api/docs# Returns OpenAPI JSON generated from registered controllers. GET /api/docs/ui# Returns Swagger UI. Errors# Common status codes: 400 invalid request or invalid state 401 missing/invalid bearer token (when auth token is configured) 404 missing task/webhook/resource 500 internal error Security Notes# Current behavior: CORS allows all origins (*). Transport is HTTP only (no TLS). Node server is started with server.listen(port) and does not explicitly bind to 127.0.0.1. Practical guidance: Set an auth token. Treat API port as sensitive and keep it firewalled. If you expose this port outside localhost, route through a trusted reverse proxy and TLS. Troubleshooting# API unavailable# Confirm API is enabled in settings. Confirm Obsidian is running. Confirm selected port is free. Reload plugin or restart Obsidian after changing API enable/port. 401 Authentication required# Check token value. Check Bearer prefix. Remove whitespace around token. Unexpected task list behavior# If you pass filters to GET /api/tasks, the endpoint returns 400 by design. Use POST /api/tasks/query."},{"title":"TaskNotes JavaScript Runtime API","url":"/obsidian/javascript-api/","description":"TaskNotes exposes an in-process runtime API on the loaded Obsidian plugin instance:","product":"obsidian","text":"TaskNotes exposes an in-process runtime API on the loaded Obsidian plugin instance: const tasknotes = app.plugins.plugins.tasknotes; const api = tasknotes?.api; This API is for Obsidian companion plugins and in-vault scripting tools such as Templater, QuickAdd, and MetaBind. It runs inside Obsidian and uses the same TaskNotes services, settings, cache, and vault permissions as the plugin UI. This is separate from the HTTP API. The runtime API does not start a server, does not use bearer-token authentication, and is only available inside the running Obsidian app. For user-facing extensions built on this API, see Companion Plugins. For a concrete automation companion plugin, see TaskNotes Workflows. The TypeScript contract lives in src/api/runtime-api.ts. It is intentionally small and type-focused so it can later become a standalone @tasknotes/runtime-api package for companion plugins. Version and Capabilities# Check the API version and capabilities before using methods that may not exist in older TaskNotes versions: const tasknotes = app.plugins.plugins.tasknotes; const api = tasknotes?.api; if (!api || api.apiVersion !== 1 || !api.hasCapability(\"tasks.write\")) { throw new Error(\"This workflow requires TaskNotes runtime API v1 task writes\"); } Current capabilities: model.read model.validate catalog.read extensions.read extensions.register tasks.read tasks.write tasks.delete tasks.move tasks.events relationships.read events.list time.read time.write time.summary pomodoro.read pomodoro.write pomodoro.events recurring.write recurring.materialize recurring.events settings.snapshot bases.write nlp.parse ui.task-menu query.tasks query.validate query.explain query.filter-options stats.tasks system.health lifecycle.events errors.typed Namespaces# Prefer the namespaced API for new code: await api.tasks.update(\"Tasks/example.md\", { status: \"active\" }); const subtasks = await api.relationships.subtasks(\"Tasks/example.md\"); await api.time.start(\"Tasks/example.md\", { description: \"Deep work\" }); await api.pomodoro.start({ taskPath: \"Tasks/example.md\", duration: 25 }); The older flat methods, such as api.getTask(path) and api.parseNaturalLanguage(text), remain available as compatibility aliases. Extension Registry# Companion plugins can publish their own runtime API namespace through api.extensions. This is the preferred way to extend TaskNotes without adding arbitrary properties to the core API object. const tasknotes = this.app.plugins.getPlugin(\"tasknotes\"); const api = tasknotes?.api; if (!api?.hasCapability(\"extensions.register\")) { return; } const handle = api.extensions.register({ id: this.manifest.id, namespace: \"tasknotes-workflows\", displayName: \"TaskNotes Workflows\", version: this.manifest.version, capabilities: [\"tasknotes-workflows.run\", \"tasknotes-workflows.events\"], api: { runWorkflow: async (workflowId, input) => { // companion plugin implementation }, }, }); this.register(() => handle.unregister()); Other plugins can discover and consume extension namespaces: const workflows = api.extensions.get(\"tasknotes-workflows\"); if (api.hasCapability(\"tasknotes-workflows.run\")) { await workflows.runWorkflow(\"start-timer-on-active\", { taskPath: \"Tasks/example.md\" }); } Extension namespaces are normalized to lowercase and may use letters, numbers, dots, underscores, or dashes. Capability names are also normalized to lowercase. Prefix extension capabilities with the extension namespace to avoid collisions. Companion Plugin Access# Companion plugins can read the TaskNotes plugin instance from Obsidian's plugin registry: const tasknotes = this.app.plugins.getPlugin(\"tasknotes\"); const api = tasknotes?.api; if (!api?.hasCapability(\"tasks.events\")) { return; } this.registerEvent( api.events.on(\"task.status.changed\", (event) => { console.log(event.taskPath, event.changes.status); }) ); If TaskNotes is disabled or has not loaded yet, api will be unavailable. Companion plugins should handle that case and retry after plugin load if needed. TypeScript# Use the exported runtime contract for type safety: import type { TaskNotesRuntimeApiV1 } from \"tasknotes/src/api/runtime-api\"; type TaskNotesPluginInstance = { api?: TaskNotesRuntimeApiV1; }; const tasknotes = app.plugins.getPlugin(\"tasknotes\") as TaskNotesPluginInstance | null; const api = tasknotes?.api; if (api?.apiVersion === 1 && api.hasCapability(\"tasks.write\")) { await api.tasks.setStatus(\"Tasks/example.md\", \"active\"); } TaskNotes is still loaded by Obsidian at runtime. The TypeScript contract only gives companion plugins compile-time checking and autocomplete. Model# The runtime API exposes a small model namespace backed by @tasknotes/model: const info = api.model.info(); const config = api.model.config(); const validation = api.model.validateTask(task); Method Description api.model.info() Returns the model package name, TaskNotes spec version, and runtime API version. api.model.config() Returns a resolved, Obsidian-free model configuration snapshot derived from TaskNotes settings. api.model.validateTask(task) Validates a partial or complete task against the shared model schema and TaskNotes status rules. api.model.validatePatch(patch) Validates a task patch before passing it to a runtime task mutation. Catalog# Use api.catalog to build companion-plugin editors without hardcoding TaskNotes values: const statuses = api.catalog.statuses(); const writableFields = api.catalog.writableFields(); const operators = api.catalog.filterOperators(); Method Description api.catalog.statuses() Returns configured TaskNotes status definitions. api.catalog.priorities() Returns configured TaskNotes priority definitions. api.catalog.userFields() Returns configured user-defined field mappings. api.catalog.fields() Returns core, computed, and user field metadata with value type, writability, and frontmatter key when available. api.catalog.writableFields() Returns only fields that runtime task mutations may write. api.catalog.filterProperties() Returns canonical query fields, aliases, value types, and supported operators. api.catalog.filterOperators() Returns canonical query operators, labels, value requirements, and accepted aliases. api.catalog.relationships() Returns relationship categories supported by api.relationships. api.catalog.dependencyRelTypes() Returns dependency relationship types accepted by api.tasks.addDependency. api.catalog.events() Returns the same runtime event catalogue as api.events.list(). Tasks# All paths are vault-relative Markdown file paths. Method Description api.tasks.get(path) Returns a task by path, or null when no task is cached at that path. api.tasks.list(query?) Returns all tasks, or tasks matching a runtime task query. Prefer api.query.tasks() when count and grouping metadata matters. api.tasks.create(taskData, context?) Creates a task using the normal TaskNotes creation service. api.tasks.update(path, patch, context?) Updates one or more task fields using the normal TaskNotes update service. api.tasks.delete(path, context?) Deletes the task file through TaskNotes' delete service. api.tasks.complete(path, options?, context?) Marks a task complete. api.tasks.uncomplete(path, options?, context?) Moves a completed task back to a non-completed status. api.tasks.setStatus(path, status, context?) Sets task status. api.tasks.setPriority(path, priority, context?) Sets task priority. api.tasks.setDue(path, date, context?) / clearDue(path, context?) Sets or clears due date. api.tasks.setScheduled(path, date, context?) / clearScheduled(path, context?) Sets or clears scheduled date. api.tasks.archive(path, archived, context?) Archives or unarchives a task, including archive-folder movement when configured. api.tasks.move(path, targetFolder, context?) Moves the task note and refuses to overwrite an existing file. api.tasks.addTag/removeTag Mutates task tags. api.tasks.addProject/removeProject Mutates project links. api.tasks.addContext/removeContext Mutates contexts. api.tasks.setReminders/addReminder/removeReminder Mutates reminders. api.tasks.addDependency/removeDependency Mutates blocking dependencies stored in blockedBy. Example: const task = await api.tasks.create( { title: \"Review automation design\", status: \"open\", priority: \"normal\", scheduled: \"2026-06-01\", tags: [\"tasknotes\"], }, { source: \"my-companion-plugin\", correlationId: crypto.randomUUID(), reason: \"manual workflow command\", } ); await api.tasks.complete(task.path); Relationships# Relationship methods resolve TaskNotes' project-as-parent links and blockedBy dependencies into task records where possible. Method Description api.relationships.parents(path) Returns parent tasks referenced from the task's projects. api.relationships.subtasks(path) Returns tasks that reference this task as a project. api.relationships.dependencies(path) Returns blockedBy dependencies with resolved task data when available. api.relationships.blocking(path) Returns tasks that are blocked by this task. api.relationships.all(path) Returns the task plus parents, subtasks, dependencies, and blocking tasks. Example: const relationships = await api.relationships.all(\"Tasks/example.md\"); for (const subtask of relationships.subtasks) { await api.tasks.setPriority(subtask.path, relationships.task.priority); } Time Tracking# Method Description api.time.start(path, options?, context?) Starts time tracking and returns the updated task. api.time.stop(path, context?) Stops the active time entry and returns the updated task. api.time.active() Returns active time entries with task, path, entry, and entry index. api.time.summary(options?) Returns aggregate time totals, top tasks, projects, and tags. api.time.task(path) Returns one task's time summary and normalized time entries. api.time.append(path, entry, context?) Appends a time entry. api.time.deleteEntry(path, entryIndex, context?) Deletes a time entry through TaskNotes' service. Query, Stats, And System# The query, stats, and system namespaces expose HTTP/MCP-style support data without requiring companion plugins to reach into TaskNotes internals. Runtime queries use a stable DTO rather than TaskNotes' internal view state. const result = await api.query.tasks({ where: { all: [ { field: \"task.status\", op: \"eq\", value: \"active\" }, { field: \"task.due\", op: \"lte\", value: { fn: \"today\" } }, ], }, sort: [{ field: \"task.due\", direction: \"asc\" }], group: [{ field: \"task.status\" }], limit: 25, scope: { includeArchived: false, folders: [\"Tasks\"], }, }); Runtime query fields are canonical IDs such as task.status, task.priority, task.due, task.projects, task.isBlocked, file.path, and user.. api.catalog.filterProperties() returns the complete queryable field catalog, including aliases such as status and user:. Canonical operators are eq, ne, contains, notContains, in, notIn, exists, missing, lt, lte, gt, gte, isTrue, and isFalse. Legacy operator aliases such as is, is-not, is-on-or-before, and is-not-empty are accepted and normalized. api.query.tasks() returns explicit count semantics: total: tasks in scope before filtering matched: tasks matching where before offset and limit returned: tasks returned after offset and limit tasks: returned task records groups: optional group details with task paths query: the normalized canonical query warnings: non-fatal normalization notes Method Description api.query.tasks(query?) Validates, normalizes, and executes a runtime task query. api.query.validate(query) Validates a query without executing it. api.query.normalize(query) Returns the canonical normalized query, or throws a typed invalid_input API error. api.query.explain(query) Returns validation, normalized query, count, grouping, and applied sort/limit details for dry run. api.query.filterOptions() Returns available statuses, priorities, contexts, projects, tags, folders, and user properties. api.stats.tasks(query?) Returns task counts, status/priority counts, archive/completion counts, and time-tracking totals. api.system.health() Returns runtime status, API version, capabilities, vault identity, and task count. TaskNotes compiles this DTO into its internal filter engine. Companion plugins should treat the runtime DTO and the catalog metadata as the public query contract. Task Menu UI# Companion plugins can reuse the standard TaskNotes task context menu through api.ui.taskMenu. This keeps task actions, relationship actions, recurrence controls, and future menu changes behind the runtime API boundary instead of requiring companion plugins to import TaskNotes internals. This surface is only available inside Obsidian. It is not exposed through the HTTP API. Method Description api.ui.taskMenu.show({ taskPath, event, targetDate?, onUpdate?, promoteOccurrenceControls? }) Shows the standard TaskNotes task context menu at a mouse event. api.ui.taskMenu.showAtElement({ taskPath, element, targetDate?, onUpdate?, ... }) Shows the standard TaskNotes task context menu anchored to an element. api.ui.taskMenu.populate(menu, { taskPath, targetDate?, onUpdate?, ... }) Adds the standard TaskNotes task context menu items to an existing Obsidian Menu so plugins can extend it. All methods resolve taskPath through the TaskNotes task cache and throw a typed task_not_found error when the path does not point to a cached task. targetDate defaults to today and is used by date-sensitive recurring-task menu items. onUpdate is called after menu actions mutate the task; when omitted, TaskNotes refreshes its own task views. promoteOccurrenceControls moves recurring-instance controls to the top of the menu. Example context menu: nodeEl.addEventListener(\"contextmenu\", async (event) => { event.preventDefault(); await api.ui.taskMenu.show({ taskPath: task.path, event, onUpdate: () => refreshGraph(), }); }); Example composed menu: const menu = new Menu(); await api.ui.taskMenu.populate(menu, { taskPath: task.path, onUpdate: () => refreshGraph(), }); menu.addSeparator(); menu.addItem((item) => item .setTitle(\"Focus in graph\") .setIcon(\"network\") .onClick(() => selectGraphNode(task.path)) ); menu.showAtMouseEvent(event); Pomodoro# Method Description api.pomodoro.status() Returns current Pomodoro state. api.pomodoro.start(options?, context?) Starts a Pomodoro session. api.pomodoro.stop(context?) Stops and resets the active Pomodoro session. api.pomodoro.pause(context?) Pauses the current session. api.pomodoro.resume(context?) Resumes a paused session. api.pomodoro.assignTask(pathOrNull, context?) Assigns or clears the current session task. api.pomodoro.sessions(options?) Returns Pomodoro session history. api.pomodoro.stats(date?) Returns Pomodoro stats for a date or today. Recurring Tasks# Method Description api.recurring.toggleCompleteInstance(path, date?, context?) Toggles completion for a recurring task instance. api.recurring.toggleSkippedInstance(path, date?, context?) Toggles skipped state for a recurring task instance. api.recurring.materializeOccurrence(path, date, context?) Creates or returns an occurrence note for a recurring task date. Natural Language Parser# const parsed = api.nlp.parse(\"Write draft friday 2pm #writing @desk\"); api.parseNaturalLanguage(text) remains as a compatibility alias. Parsing does not create or modify task files. See NLP API for HTTP endpoint details and parser behavior. Settings Snapshot# const settings = api.settings.snapshot(); console.log(settings.defaultTaskStatus); The returned object is a snapshot. Mutating it does not change TaskNotes settings. api.getSettingsSnapshot() remains available as a compatibility alias. Bases# api.bases.updateDefaultFiles() regenerates the configured default TaskNotes .base files from the current TaskNotes settings and returns the created, updated, and skipped file paths. const result = await api.bases.updateDefaultFiles(); console.log(result.updated); Mutation Context# Mutating methods accept an optional context object: { source: \"tasknotes-workflows\", correlationId: \"run-2026-06-01T09-00-00\", reason: \"status chang"},{"title":"mdbase-tasknotes CLI","url":"/obsidian/mdbase-tasknotes-cli/","description":"mdbase-tasknotes (mtn) is a standalone command-line tool for managing TaskNotes tasks directly on markdown files. It uses mdbase to read and write task files and tasknotes-nlp-c...","product":"obsidian","text":"mdbase-tasknotes (mtn) is a standalone command-line tool for managing TaskNotes tasks directly on markdown files. It uses mdbase to read and write task files and tasknotes-nlp-core for natural language parsing. When to use this vs TaskNotes Obsidian CLI# If you are looking for the built-in obsidian tasknotes:* commands exposed by the plugin itself, see TaskNotes Obsidian CLI. TaskNotes ships with tasknotes-cli (tn), which communicates with the Obsidian plugin over its HTTP API. mdbase-tasknotes operates directly on the markdown files instead. tn (tasknotes-cli) mtn (mdbase-tasknotes) Requires Obsidian Yes — plugin must be running with API enabled No Operates on HTTP API Markdown files directly via mdbase Use when Obsidian is open and you want live sync Obsidian is closed, on a server, or in scripts Time tracking Via plugin API Via frontmatter timeEntries Task creation NLP via API NLP via bundled tasknotes-nlp-core Install npm install -g tasknotes-cli npm install -g mdbase-tasknotes Use mtn when: Obsidian isn't running or isn't available (headless servers, SSH sessions, CI pipelines) You want to manage tasks from the terminal without any background process You're scripting task creation or querying in shell workflows You're on a machine where Obsidian isn't installed Both tools read and write the same task files, so they can be used interchangeably on the same vault. Install# npm install -g mdbase-tasknotes Setup# Using an existing TaskNotes vault# If you already use TaskNotes with mdbase spec generation enabled (Settings → Integrations → Enable mdbase spec), point mtn at your vault root: mtn config --set collectionPath=/path/to/your/vault The plugin generates mdbase.yaml and _types/task.md automatically — mtn reads these to understand your task schema, including your custom statuses and priorities. Creating a standalone collection# To create a new collection without Obsidian: mtn init ~/tasks mtn config --set collectionPath=~/tasks This generates mdbase.yaml, _types/task.md, and a tasks/ folder with sensible defaults (statuses: open, in-progress, done, cancelled; priorities: low, normal, high, urgent). Creating tasks# Create tasks using natural language. Tags, contexts, projects, dates, priorities, and recurrence are extracted automatically: mtn create \"Buy groceries tomorrow #shopping @errands\" mtn create \"Write quarterly report due friday #work +quarterly-review\" mtn create \"Call dentist high priority @phone\" mtn create \"Water plants every monday #home\" Supported patterns# Pattern Example Extracted as #tag #shopping Tag @context @errands Context +project +quarterly-review Project (stored as wikilink) Date words tomorrow, friday, next week Due date Priority words high priority, urgent Priority Recurrence every day, weekly, every monday Recurrence rule Estimate ~30m, ~2h Time estimate The NLP parser reads your collection's status and priority enum values from _types/task.md, so any custom values you define there are automatically recognized. Querying tasks# List tasks# # Default: open tasks ordered by due date mtn list # Filter by status, priority, or tag mtn list --status in-progress mtn list --priority high mtn list --tag work # Show overdue tasks mtn list --overdue # Raw mdbase where expression mtn list --where 'due < \"2026-03-01\" && priority == \"urgent\"' # JSON output for scripting mtn list --json Show task detail# mtn show \"Buy groceries\" mtn show tasks/Buy\\ groceries.md Tasks can be referenced by title or file path. Title matching tries exact match first, then substring. Search# Full-text search across titles, body content, tags, contexts, and projects: mtn search quarterly Updating tasks# Complete a task# mtn complete \"Buy groceries\" Sets status to done and records the completion date. Update fields# mtn update \"Write report\" --status in-progress mtn update \"Write report\" --priority urgent --due 2026-03-01 mtn update \"Write report\" --add-tag important --remove-tag draft mtn update \"Write report\" --add-context office Archive and delete# mtn archive \"Write report\" # Adds \"archive\" tag mtn delete \"Old task\" # Checks for backlinks first mtn delete \"Old task\" --force # Skip backlink check Time tracking# Track time spent on tasks via the timeEntries frontmatter field — the same format TaskNotes uses. # Start a timer mtn timer start \"Write report\" mtn timer start \"Write report\" -d \"Drafting introduction\" # Check active timers mtn timer status # Stop the running timer mtn timer stop # View time log mtn timer log mtn timer log --period today mtn timer log --period week mtn timer log --from 2026-02-01 --to 2026-02-28 Projects and statistics# Projects# # List all projects mtn projects list mtn projects list --stats # With completion percentages # Show tasks for a project mtn projects show quarterly-review Statistics# mtn stats Shows total tasks, completion rate, overdue count, breakdown by status and priority, and total time tracked. Interactive mode# Launch a REPL with live NLP preview that updates as you type: mtn interactive # or mtn i Type a task description and the preview line shows how it will be parsed (title, tags, dates, priority). Press Enter to create the task. Configuration# Configuration is stored at ~/.config/mdbase-tasknotes/config.json. mtn config --list # Show all settings mtn config --set collectionPath=/path/to/vault # Set collection path mtn config --get collectionPath # Get a setting Collection path resolution# The collection path is resolved in order: --path / -p flag on any command MDBASE_TASKNOTES_PATH environment variable collectionPath in config file Current working directory Command reference# Command Alias Description mtn init [path] Initialize a new collection mtn create Create a task from natural language mtn list [options] ls List tasks with filters mtn show Show full task detail mtn complete done Mark task as completed mtn update [options] Update task fields mtn delete rm Delete a task mtn archive Add archive tag mtn search Full-text search mtn timer start Start time tracking mtn timer stop Stop running timer mtn timer status Show active timers mtn timer log Show time entry log mtn projects list List projects mtn projects show Show project tasks mtn stats Show task statistics mtn interactive i Interactive REPL mtn config [options] Manage configuration"},{"title":"Migrating from v3 to v4","url":"/obsidian/migration-v3-to-v4/","description":"TaskNotes v4 migrates all views to the Bases system. This guide covers what changed and how to update your setup.","product":"obsidian","text":"TaskNotes v4 migrates all views to the Bases system. This guide covers what changed and how to update your setup. Back up before migratingBack up the complete vault, including the hidden .obsidian directory, before changing views or plugin data. Requirements# Obsidian 1.10.1 or later for early TaskNotes v4 releases Obsidian 1.12.2 or later for the current TaskNotes 4.13.0 release Bases core plugin enabled (Settings → Core Plugins → Bases) What Changed# Views are Now Bases Files# All task views (Task List, Kanban, Calendar, Agenda) are now .base files stored in TaskNotes/Views/. This replaces the custom view system in v3. v3 v4 Views stored in plugin settings Views stored as .base files Custom filter UI Bases filter syntax Saved views in settings Default views are separate files; exported v3 saved views share one multi-view file Automatic Migration on First Launch# When you first open TaskNotes v4: Default .base files are created in TaskNotes/Views/ Ribbon icons and commands now open these .base files Your existing task files are unchanged Converting Saved Filter Views# If you had saved filter views in v3, you can export them to one .base file: Go to Settings → TaskNotes → General → Views & base files. Find Export v3 saved views to Bases. Run the export. TaskNotes creates TaskNotes/Views/all-saved-views.base with one Base view for each saved v3 view. This is a one-way conversion. The original saved views remain in settings until you delete them. Breaking Changes# View Configuration# v3 saved views with custom filters need manual conversion to Bases filter syntax. Simple filters (status, priority, due date) convert automatically. Complex filters may need adjustment. v3 Filter Example: status: in-progress priority: high v4 Bases Syntax: filters: and: - status == \"in-progress\" - priority == \"high\" See the Obsidian Bases documentation for filter syntax details. Minimum Obsidian Version# Early v4 releases required Obsidian 1.10.1. The current release requirement is generated on the version compatibility page. Use the manifest requirement for the exact TaskNotes version you install. New Features in v4# OAuth Calendar Integration# v4 adds Google Calendar and Microsoft Outlook integration: View external calendar events alongside tasks Drag events to reschedule (syncs back to calendar provider) Events sync every 15 minutes See Calendar Setup for configuration. Kanban Swimlanes# The Kanban view now supports horizontal swimlane grouping: views: - type: tasknotesKanban groupBy: property: status config: swimLane: priority Time Entry Editor# A dedicated modal for managing time entries: Alt-drag on calendar to create time entries View total tracked time per task Edit and delete time entries Troubleshooting# Views Not Loading# Verify Bases core plugin is enabled (Settings → Core Plugins) Check that .base files exist in TaskNotes/Views/ Restart Obsidian Missing Saved Views After Upgrade# Saved views from v3 are preserved in settings. Use Export v3 saved views to Bases in Settings → TaskNotes → General → Views & base files to create the multi-view .base file. Filter Syntax Errors# Bases uses different filter syntax than v3. Common issues: Problem Solution status: done Use status == \"done\" Multiple conditions Wrap in and: or or: block Date comparisons Use date(due) < today() Downgrading to v3# Migration is one-way. If you need to downgrade: Uninstall TaskNotes v4 Install TaskNotes v3 from releases Reconfigure your saved views manually Your task files are unaffected—only view configurations change. View Templates# For complete .base file examples, see Default Base Templates."},{"title":"TaskNotes NLP API","url":"/obsidian/nlp-api/","description":"The NLP API parses natural-language task text and optionally creates a task.","product":"obsidian","text":"The NLP API parses natural-language task text and optionally creates a task. In-vault scripts can also call the parser directly from the loaded plugin: const tasknotes = app.plugins.plugins.tasknotes; const parsed = tasknotes.api.parseNaturalLanguage(\"Review PR tomorrow #code @work\"); For the full in-process API exposed at tasknotes.api, including task updates, time tracking, settings snapshots, and events, see TaskNotes JavaScript API. Endpoints# POST /api/nlp/parse POST /api/nlp/create Both endpoints require a JSON body with text. Request Format# { \"text\": \"Review PR #123 tomorrow high priority @work\" } Notes: text is required and must be a string. Per-request locale is not currently supported. Parser language comes from TaskNotes settings (nlpLanguage). POST /api/nlp/parse# Parses text and returns two objects: parsed: direct parser output taskData: normalized task payload that would be used for creation Example response (shape): { \"success\": true, \"data\": { \"parsed\": { \"title\": \"Review PR\", \"tags\": [\"123\"], \"contexts\": [\"work\"], \"projects\": [], \"priority\": \"high\", \"status\": null, \"dueDate\": \"2026-02-22\", \"scheduledDate\": null, \"dueTime\": null, \"scheduledTime\": null, \"recurrence\": null, \"estimate\": null, \"isCompleted\": false }, \"taskData\": { \"title\": \"Review PR\", \"priority\": \"high\", \"status\": \"open\", \"tags\": [\"123\"], \"contexts\": [\"work\"], \"due\": \"2026-02-22\", \"dateCreated\": \"2026-02-22T09:00:00.000Z\", \"dateModified\": \"2026-02-22T09:00:00.000Z\" } } } If parser does not detect status, taskData.status falls back to your configured default task status. Parsed due and scheduled date-times in taskData use the same YYYY-MM-DDTHH:mm format as created tasks, and NLP trigger values for user-defined fields are returned under customFrontmatter. POST /api/nlp/create# Parses text and creates a task in one call. Returns HTTP 201 on success. Example: curl -X POST http://localhost:8080/api/nlp/create \\ -H \"Content-Type: application/json\" \\ -d '{\"text\":\"Call mom due friday 2pm #personal\"}' Response fields: data.task (created task) data.parsed (parser output) What the Parser Extracts# The parser can extract: Dates and times (tomorrow, friday 2pm, ISO dates) Priority terms (high priority, urgent, symbol patterns) Status terms (mapped to your configured statuses) Tags (#tag) Contexts (@context) Projects (+project) Time estimates (2h, 30min, estimate 45m) Recurrence (daily, weekly, every monday) Exact parsing behavior depends on your TaskNotes NLP settings and trigger configuration. In-Vault Parser Method# Templater, QuickAdd, MetaBind, and other in-vault scripts can use the loaded plugin instance directly: const tasknotes = app.plugins.plugins.tasknotes; const parsed = tasknotes.api.parseNaturalLanguage(\"Write draft friday 2pm #writing @desk\"); parseNaturalLanguage(text) returns the same parser output shape as data.parsed from POST /api/nlp/parse. It uses your current TaskNotes settings, including custom status values, priority values, NLP language, NLP trigger configuration, user fields, and calendar locale. This method only parses text. It does not create or modify task files. For task creation and updates from in-vault scripts or companion plugins, use the broader TaskNotes JavaScript API. Example Templater use: <%* const tasknotes = app.plugins.plugins.tasknotes; const text = await tp.system.prompt(\"Task\"); const parsed = tasknotes.api.parseNaturalLanguage(text); tR += `title: ${parsed.title}`; %> Error Responses# Common errors: 400: missing/invalid text 401: auth required (if API token is enabled) 500: parse/processing error Error shape: { \"success\": false, \"error\": \"Text field is required and must be a string\" } Client Examples# JavaScript# async function parseTask(text) { const response = await fetch(\"http://localhost:8080/api/nlp/parse\", { method: \"POST\", headers: { \"Content-Type\": \"application/json\" }, body: JSON.stringify({ text }) }); return response.json(); } async function createTaskFromText(text) { const response = await fetch(\"http://localhost:8080/api/nlp/create\", { method: \"POST\", headers: { \"Content-Type\": \"application/json\" }, body: JSON.stringify({ text }) }); return response.json(); } Python# import requests def parse_task(text): response = requests.post( \"http://localhost:8080/api/nlp/parse\", json={\"text\": text}, ) return response.json() def create_task_from_text(text): response = requests.post( \"http://localhost:8080/api/nlp/create\", json={\"text\": text}, ) return response.json() Authentication# If API auth token is enabled, include bearer token: Authorization: Bearer YOUR_TOKEN"},{"title":"TaskNotes Obsidian CLI","url":"/obsidian/obsidian-cli/","description":"TaskNotes can register commands directly with the Obsidian desktop CLI. This is useful when Obsidian is already running and you want shell access to task creation, time tracking...","product":"obsidian","text":"TaskNotes can register commands directly with the Obsidian desktop CLI. This is useful when Obsidian is already running and you want shell access to task creation, time tracking, or Pomodoro control without going through the HTTP API. Use this page for the built-in obsidian ... commands exposed by the plugin itself. If you want a standalone terminal tool that works directly on Markdown files without Obsidian running, see mdbase-tasknotes CLI. Requirements# Obsidian desktop 1.12.2 or newer TaskNotes installed and enabled in the target vault Obsidian running when you invoke the CLI The Obsidian CLI resolves commands against a vault context. In practice, it is safer to pass vault= explicitly instead of relying on the default vault. Discovering commands# List available TaskNotes commands: obsidian help | rg 'tasknotes:' You should see: tasknotes:capture tasknotes:start-time tasknotes:stop-time tasknotes:time-status tasknotes:pomodoro tasknotes:capture# Create a task from free text, explicit flags, or both. obsidian tasknotes:capture vault=test text=\"Review PR tomorrow #work @desk\" By default, text= is parsed with TaskNotes NLP. Explicit flags override parsed values. Literal title mode# Use literal when you want the text treated as an exact title instead of being parsed. obsidian tasknotes:capture vault=test text=\"Fix parser edge case\" literal Explicit fields# Supported override flags: title details status priority due scheduled tags contexts projects recurrence recurrence-anchor reminders estimate Example: obsidian tasknotes:capture vault=test \\ text=\"Write release notes tomorrow #docs\" \\ priority=high \\ status=in-progress \\ reminders='due:-PT1H' Reminder format# reminders= accepts either: a semicolon-separated shorthand such as due:-PT1H;scheduled:-PT30M;at:2026-04-02T09:00 a JSON array in the same shape TaskNotes stores internally Recurrence anchor# Use recurrence-anchor=scheduled or recurrence-anchor=completion to control how recurring tasks advance. tasknotes:start-time# Start time tracking for a task. You can target a task by: path exact title fuzzy query Examples: obsidian tasknotes:start-time vault=test title=\"Write release notes\" obsidian tasknotes:start-time vault=test query=\"release notes\" description=\"Drafting first pass\" obsidian tasknotes:start-time vault=test path=\"TaskNotes/Write release notes.md\" tasknotes:stop-time# Stop time tracking for a task. Examples: obsidian tasknotes:stop-time vault=test title=\"Write release notes\" obsidian tasknotes:stop-time vault=test path=\"TaskNotes/Write release notes.md\" If you omit task lookup flags, TaskNotes will stop the only active session when that is unambiguous. tasknotes:time-status# Show time-tracking status for either: all active sessions one resolved task Examples: obsidian tasknotes:time-status vault=test obsidian tasknotes:time-status vault=test title=\"Write release notes\" obsidian tasknotes:time-status vault=test path=\"TaskNotes/Write release notes.md\" When a task is targeted, the command returns that task's summary, active session, and time entries. With no lookup flags, it returns the currently active sessions across the vault. tasknotes:pomodoro# Control Pomodoro state from the CLI. Supported actions: status start pause resume stop short-break long-break Inspect state# obsidian tasknotes:pomodoro vault=test action=status Start a work session# You can start a Pomodoro with or without a linked task. obsidian tasknotes:pomodoro vault=test action=start duration=25 obsidian tasknotes:pomodoro vault=test action=start title=\"Write release notes\" duration=25 Task lookup for action=start supports the same selectors as time tracking: path exact title fuzzy query Pause, resume, and stop# obsidian tasknotes:pomodoro vault=test action=pause obsidian tasknotes:pomodoro vault=test action=resume obsidian tasknotes:pomodoro vault=test action=stop Breaks# obsidian tasknotes:pomodoro vault=test action=short-break obsidian tasknotes:pomodoro vault=test action=long-break Choosing between CLI surfaces# Use the built-in Obsidian CLI when: Obsidian is already open you want plugin-aware behavior, including current cache, defaults, templates, time tracking, and Pomodoro state you are scripting on the same machine as the running vault Use mdbase-tasknotes CLI when: Obsidian is not running you need headless/server workflows you want direct file-level automation over a task collection Notes# path is the most reliable task selector for automation. Immediately after creating a task, exact title lookup can lag briefly until the in-memory cache catches up. These commands are desktop-only because they depend on the Obsidian desktop CLI."},{"title":"Command reference","url":"/obsidian/reference/commands/","description":"Every TaskNotes command registered with Obsidian, generated from the plugin command definitions.","product":"obsidian","text":"This page is generated from the commands registered by TaskNotes. Command IDs are stable integration identifiers; names are the English labels shown in Obsidian. Command ID Available in Open mini calendar view open-calendar-view Global Open calendar view open-advanced-calendar-view Global Open tasks view open-tasks-view Global Open agenda view open-agenda-view Global Open Pomodoro timer open-pomodoro-view Global Open Kanban board open-kanban-view Global Update default base files update-default-base-files Global Open Pomodoro statistics open-pomodoro-stats Global Open task & project statistics open-statistics Global Create new task create-new-task Global Convert current note to task convert-current-note-to-task Global Convert checkbox task to TaskNote convert-to-tasknote Editor Convert all tasks in note batch-convert-all-tasks Editor Insert tasknote link insert-tasknote-link Editor Create new inline task create-inline-task Editor Quick actions for current task quick-actions-current-task Global Quick actions for task under cursor quick-actions-task-under-cursor Editor Edit current task edit-current-task Global Cycle current task status cycle-current-task-status Global Cycle current task priority cycle-current-task-priority Global Add project to current task add-project-to-current-task Global Add subtask to current note add-subtask-to-current-note Global Go to today's note go-to-today Global Start Pomodoro timer start-pomodoro Global Stop Pomodoro timer stop-pomodoro Global Pause/resume Pomodoro timer pause-pomodoro Global Refresh cache refresh-cache Global Export all tasks as ICS file export-all-tasks-ics Global Sync all tasks to Google Calendar sync-all-tasks-google-calendar Global Sync current task to Google Calendar sync-current-task-google-calendar Global View release notes view-release-notes Global Start time tracking (select task) start-time-tracking-with-selector Global Edit time entries (select task) edit-time-entries Global Create or open task create-or-open-task Global Create or open task and start time tracking create-or-open-task-with-time-tracking Global Postpone overdue scheduled tasks to today rollover-overdue-scheduled-tasks Global Generated from 36 registered commands."},{"title":"Version compatibility","url":"/obsidian/reference/compatibility/","description":"Current TaskNotes and Obsidian compatibility requirements, generated from the plugin manifest.","product":"obsidian","text":"Current release# Item Value TaskNotes 4.13.0 Minimum Obsidian version 1.12.2 Desktop only No Bases core plugin Required The minimum version above applies to the current TaskNotes release. Older releases had different requirements; consult versions.json or the relevant release note when maintaining an older installation."},{"title":"Generated default Base templates","url":"/obsidian/reference/default-base-templates/","description":"Exact default Obsidian Base files generated by the current TaskNotes source and default settings.","product":"obsidian","text":"These are the exact templates TaskNotes 4.13.0 produces with default settings. Your generated files reflect your own field mapping and other settings, so customized output can differ. Regenerating with Update files overwrites configured default Base files. Copy a customized file to a new path before updating it. mini-calendar-default.base# Command/template ID: open-calendar-view # Mini Calendar # Generated with your TaskNotes settings filters: and: - file.hasTag(\"task\") formulas: priorityWeight: 'if(priority==\"none\",0,if(priority==\"low\",1,if(priority==\"normal\",2,if(priority==\"high\",3,999))))' daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)' dueIn: 'if(due.isEmpty(), \"\", if(formula.daysUntilDue == 0, \"Today\", if(formula.daysUntilDue == 1, \"1 day\", if(formula.daysUntilDue > 1, formula.daysUntilDue + \" days\", if(formula.daysUntilDue == -1, \"1 day overdue\", formula.daysUntilDue * -1 + \" days overdue\")))))' daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)' daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()' daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()' isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != \"done\"' isDueToday: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")' isDueThisWeek: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")' isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")' isRecurring: 'recurrence && !recurrence.isEmpty()' hasTimeEstimate: 'timeEstimate && timeEstimate > 0' timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)' efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)' timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - \"7d\").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)' timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)' dueMonth: 'if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), \"No due date\")' dueWeek: 'if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), \"No due date\")' scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"Not scheduled\")' scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"Not scheduled\")' dueDateCategory: 'if(due.isEmpty(), \"No due date\", if(date(due) < today(), \"Overdue\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), \"This week\", \"Later\")))))' timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(timeEstimate < 30, \"Quick (<30m)\", if(timeEstimate <= 120, \"Medium (30m-2h)\", \"Long (>2h)\")))' ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, \"Today\", if(((number(now()) - number(file.ctime)) / 86400000) < 7, \"This week\", if(((number(now()) - number(file.ctime)) / 86400000) < 30, \"This month\", \"Older\")))' createdMonth: 'file.ctime.format(\"YYYY-MM\")' modifiedMonth: 'file.mtime.format(\"YYYY-MM\")' priorityCategory: 'if(priority==\"none\",\"None\",if(priority==\"low\",\"Low\",if(priority==\"normal\",\"Normal\",if(priority==\"high\",\"High\",\"No priority\"))))' projectCount: 'if(!projects || list(projects).length == 0, \"No projects\", if(list(projects).length == 1, \"Single project\", \"Multiple projects\"))' contextCount: 'if(!contexts || list(contexts).length == 0, \"No contexts\", if(list(contexts).length == 1, \"Single context\", \"Multiple contexts\"))' trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(!timeEntries || list(timeEntries).length == 0, \"Not started\", if(formula.efficiencyRatio < 100, \"Under estimate\", \"Over estimate\")))' nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))' daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))' hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)' isToday: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"))' isThisWeek: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"))' nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), \"No date\", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), \"Overdue/Past\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")), \"Today\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\")), \"Tomorrow\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")), \"This week\", \"Later\")))))' nextDateMonth: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-MM\"), date(scheduled).format(\"YYYY-MM\")), if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"No date\")))' nextDateWeek: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), date(due).format(\"YYYY-[W]WW\"), date(scheduled).format(\"YYYY-[W]WW\")), if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"No date\")))' urgencyScore: 'if(due.isEmpty() && scheduled.isEmpty(), formula.priorityWeight, formula.priorityWeight + max(0, 10 - if(formula.daysUntilNext, formula.daysUntilNext, 0)) + (1 - ((number(date(formula.nextDate)) - number(date(date(formula.nextDate).format(\"YYYY-MM-DD\")))) / 86400000)))' timeTrackedFormatted: 'if(timeEntries, if(list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) >= 60, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / 60).floor() + \"h \" + (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) % 60).round() + \"m\", list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round() + \"m\"), \"0m\")' dueDateDisplay: 'if(due.isEmpty(), \"\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") == (today() - \"1 day\").format(\"YYYY-MM-DD\"), \"Yesterday\", if(date(due) < today(), formula.daysUntilDue * -1 + \"d ago\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), date(due).format(\"ddd\"), date(due).format(\"MMM D\")))))))' views: - type: tasknotesMiniCalendar name: \"Due\" order: - status - priority - due - scheduled - projects - contexts - file.tags - blockedBy - file.name - recurrence - complete_instances - file.tasks sort: - property: due direction: ASC dateProperty: due - type: tasknotesMiniCalendar name: \"Scheduled\" order: [] dateProperty: scheduled - type: tasknotesMiniCalendar name: \"Created\" dateProperty: file.ctime - type: tasknotesMiniCalendar name: \"Modified\" dateProperty: file.mtime kanban-default.base# Command/template ID: open-kanban-view # Kanban Board filters: and: - file.hasTag(\"task\") formulas: priorityWeight: 'if(priority==\"none\",0,if(priority==\"low\",1,if(priority==\"normal\",2,if(priority==\"high\",3,999))))' daysUntilDue: 'if((due.isEmpty() == false), ((number(date(due)) - number(today())) / 86400000).floor(), null)' dueIn: 'if(due.isEmpty(), \"\", if(formula.daysUntilDue == 0, \"Today\", if(formula.daysUntilDue == 1, \"1 day\", if(formula.daysUntilDue > 1, formula.daysUntilDue + \" days\", if(formula.daysUntilDue == -1, \"1 day overdue\", formula.daysUntilDue * -1 + \" days overdue\")))))' daysUntilScheduled: 'if((scheduled.isEmpty() == false), ((number(date(scheduled)) - number(today())) / 86400000).floor(), null)' daysSinceCreated: '((number(now()) - number(file.ctime)) / 86400000).floor()' daysSinceModified: '((number(now()) - number(file.mtime)) / 86400000).floor()' isOverdue: '(due.isEmpty() == false) && date(due) < today() && status != \"done\"' isDueToday: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")' isDueThisWeek: '(due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")' isScheduledToday: '(scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")' isRecurring: 'recurrence && !recurrence.isEmpty()' hasTimeEstimate: 'timeEstimate && timeEstimate > 0' timeRemaining: 'if(timeEstimate && timeEstimate > 0, timeEstimate - if(timeEntries, list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0), 0), null)' efficiencyRatio: 'if(timeEstimate && timeEstimate > 0 && timeEntries, (list(timeEntries).filter(value.endTime).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0) / timeEstimate * 100).round(), null)' timeTrackedThisWeek: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime) >= today() - \"7d\").map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)' timeTrackedToday: 'if(timeEntries, list(timeEntries).filter(value.endTime && date(value.startTime).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")).map((number(date(value.endTime)) - number(date(value.startTime))) / 60000).reduce(acc + value, 0).round(), 0)' dueMonth: 'if((due.isEmpty() == false), date(due).format(\"YYYY-MM\"), \"No due date\")' dueWeek: 'if((due.isEmpty() == false), date(due).format(\"YYYY-[W]WW\"), \"No due date\")' scheduledMonth: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-MM\"), \"Not scheduled\")' scheduledWeek: 'if((scheduled.isEmpty() == false), date(scheduled).format(\"YYYY-[W]WW\"), \"Not scheduled\")' dueDateCategory: 'if(due.isEmpty(), \"No due date\", if(date(due) < today(), \"Overdue\", if(date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"), \"Today\", if(date(due).format(\"YYYY-MM-DD\") == (today() + \"1 day\").format(\"YYYY-MM-DD\"), \"Tomorrow\", if(date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"), \"This week\", \"Later\")))))' timeEstimateCategory: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(timeEstimate < 30, \"Quick (<30m)\", if(timeEstimate <= 120, \"Medium (30m-2h)\", \"Long (>2h)\")))' ageCategory: 'if(((number(now()) - number(file.ctime)) / 86400000) < 1, \"Today\", if(((number(now()) - number(file.ctime)) / 86400000) < 7, \"This week\", if(((number(now()) - number(file.ctime)) / 86400000) < 30, \"This month\", \"Older\")))' createdMonth: 'file.ctime.format(\"YYYY-MM\")' modifiedMonth: 'file.mtime.format(\"YYYY-MM\")' priorityCategory: 'if(priority==\"none\",\"None\",if(priority==\"low\",\"Low\",if(priority==\"normal\",\"Normal\",if(priority==\"high\",\"High\",\"No priority\"))))' projectCount: 'if(!projects || list(projects).length == 0, \"No projects\", if(list(projects).length == 1, \"Single project\", \"Multiple projects\"))' contextCount: 'if(!contexts || list(contexts).length == 0, \"No contexts\", if(list(contexts).length == 1, \"Single context\", \"Multiple contexts\"))' trackingStatus: 'if(!timeEstimate || timeEstimate == 0 || timeEstimate == null, \"No estimate\", if(!timeEntries || list(timeEntries).length == 0, \"Not started\", if(formula.efficiencyRatio < 100, \"Under estimate\", \"Over estimate\")))' nextDate: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), if(date(due) < date(scheduled), due, scheduled), if((due.isEmpty() == false), due, scheduled))' daysUntilNext: 'if((due.isEmpty() == false) && (scheduled.isEmpty() == false), min(formula.daysUntilDue, formula.daysUntilScheduled), if((due.isEmpty() == false), formula.daysUntilDue, formula.daysUntilScheduled))' hasDate: '(due.isEmpty() == false) || (scheduled.isEmpty() == false)' isToday: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\"))' isThisWeek: '((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(due).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") >= today().format(\"YYYY-MM-DD\") && date(scheduled).format(\"YYYY-MM-DD\") <= (today() + \"7 days\").format(\"YYYY-MM-DD\"))' nextDateCategory: 'if(due.isEmpty() && scheduled.isEmpty(), \"No date\", if(((due.isEmpty() == false) && date(due) < today()) || ((scheduled.isEmpty() == false) && date(scheduled) < today()), \"Overdue/Past\", if(((due.isEmpty() == false) && date(due).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")) || ((scheduled.isEmpty() == false) && date(scheduled).format(\"YYYY-MM-DD\") == today().format(\"YYYY-MM-DD\")), \"Today\", if(((due.isEmpty() == false) && date(due).fo"},{"title":"HTTP route index","url":"/obsidian/reference/http-routes/","description":"Implemented TaskNotes HTTP API routes generated from controller decorators.","product":"obsidian","text":"This index is generated from controller route decorators. The build fails if an implemented route is absent from the narrative HTTP API guide or NLP API guide. Method Path Controller POST /api/bases/default-files/update BasesController GET /api/calendars CalendarsController GET /api/calendars/events CalendarsController GET /api/calendars/google CalendarsController GET /api/calendars/microsoft CalendarsController GET /api/calendars/subscriptions CalendarsController GET /api/docs SystemController GET /api/docs/ui SystemController GET /api/filter-options TasksController GET /api/health SystemController POST /api/nlp/create SystemController POST /api/nlp/parse SystemController POST /api/pomodoro/pause PomodoroController POST /api/pomodoro/resume PomodoroController GET /api/pomodoro/sessions PomodoroController POST /api/pomodoro/start PomodoroController GET /api/pomodoro/stats PomodoroController GET /api/pomodoro/status PomodoroController POST /api/pomodoro/stop PomodoroController GET /api/stats TasksController GET /api/tasks TasksController POST /api/tasks TasksController DELETE /api/tasks/:id TasksController GET /api/tasks/:id TasksController PUT /api/tasks/:id TasksController POST /api/tasks/:id/archive TasksController POST /api/tasks/:id/complete-instance TasksController POST /api/tasks/:id/materialize-occurrence TasksController GET /api/tasks/:id/time TimeTrackingController POST /api/tasks/:id/time/start TimeTrackingController POST /api/tasks/:id/time/start-with-description TimeTrackingController POST /api/tasks/:id/time/stop TimeTrackingController POST /api/tasks/:id/toggle-status TasksController POST /api/tasks/query TasksController GET /api/time/active TimeTrackingController GET /api/time/summary TimeTrackingController GET /api/webhooks WebhookController POST /api/webhooks WebhookController DELETE /api/webhooks/:id WebhookController GET /api/webhooks/deliveries WebhookController Generated from 40 implemented routes."},{"title":"Settings source reference","url":"/obsidian/reference/settings-source/","description":"The six TaskNotes settings tabs, their controls, and the complete default settings snapshot generated from source.","product":"obsidian","text":"TaskNotes currently exposes 6 settings tabs. This inventory is generated from the tab renderer and English translation source so additions cannot silently disappear from the documentation. General# Source: src/settings/tabs/generalTab.ts Setting Purpose Default tasks folder Default location for new tasks. Supports folder template variables like {{currentNotePath}}, {{currentNoteTitle}}, and {{projectFilePath}}, plus Daily Notes-style date tokens like YYYY/MM/DD. Folder for inline-created tasks Folder where tasks created from inline commands or checkbox conversion will be created. Leave empty to use the default tasks folder. Use {{currentNotePath}} for the current note's folder, or {{currentNoteTitle}} for a subfolder named after the current note. Move archived tasks to folder Automatically move archived tasks to an archive folder Archive folder Folder to move tasks to when archived. Supports template variables like {{year}}, {{month}}, {{priority}}, etc. Identify tasks by Choose whether to identify tasks by tag or by a frontmatter property Task tag Tag that identifies notes as tasks (without #). Existing .base view filters keep their old tag when this changes; update default Base files or edit those filters. Hide identification tags in task cards When enabled, tags matching the task identification tag (including hierarchical matches like 'task/project') will be hidden from task card displays Hidden tag scope Choose whether hiding identification tags also hides nested tags. Task property name The frontmatter property name (e.g., \"category\") Task property value The value that identifies a note as a task (e.g., \"task\") Auto-create default files Automatically create missing default base view files on startup. Disable to prevent deleted sample files from being recreated. Create default files Create the default .base files in TaskNotes/Views/ directory. Existing files will not be overwritten. Update default files Overwrite the configured default .base files with templates generated from your current TaskNotes settings. Export v3 saved views to Bases Convert all your saved views from TaskNotes v3 into a single .base file with multiple views. This helps migrate your v3 filter configurations to the new Bases system. Excluded folders Comma-separated list of folders to exclude from task indexing and project suggestions UI language Select the language used for TaskNotes interface text Use Markdown links in frontmatter Generate markdown links ([text](path)) instead of wikilinks ([[link]]) in frontmatter properties. ⚠️ Requires the 'obsidian-frontmatter-markdown-links' plugin to work correctly. Show release notes after update Automatically open release notes when TaskNotes is updated to a new version Check for new releases on startup Check GitHub once when TaskNotes starts and show a notice when a newer compatible release is available View release notes See what's new in the latest version of TaskNotes Task properties# Source: src/settings/tabs/taskPropertiesTab.ts Setting Purpose No static controls detected This tab is assembled dynamically. Modal fields# Source: src/settings/tabs/modalFieldsTab.ts Setting Purpose No static controls detected This tab is assembled dynamically. Appearance & UI# Source: src/settings/tabs/appearanceTab.ts Setting Purpose Default visible properties Choose which properties appear on task cards by default. Group complete and skip actions in a submenu Nest the complete and skip actions under a submenu in the task context menu. Turn off to show them directly in the menu. Time format Display time in 12-hour or 24-hour format throughout the plugin Default view The calendar view shown when opening the calendar tab Custom view day count Number of days to show in custom multi-day view First day of week Which day should be the first column in week views Show weekends Display weekends in calendar views Show week numbers Display week numbers in calendar views Show today highlight Highlight the current day in calendar views Show current time indicator Display a line showing the current time in timeline views Selection mirror Show a visual preview while dragging to select time ranges Calendar locale Calendar locale for date formatting and calendar system (e.g., \"en\", \"fa\" for Farsi/Persian, \"de\" for German). Leave empty to auto-detect from browser. Show scheduled tasks Display tasks with scheduled dates by default Show due dates Display task due dates by default Show due dates when scheduled Display due dates even for tasks that already have scheduled dates Show time entries Display completed time tracking entries by default Show recurring tasks Display recurring task instances by default Show ICS events Display events from ICS subscriptions by default Time slot duration Duration of each time slot in timeline views Start time Earliest time shown in timeline views (HH:MM format) End time Latest time shown in timeline views (HH:MM format). Use values above 24:00 to show early next-day hours, such as 26:00 for 2 AM. Initial scroll time Time to scroll to when opening timeline views (HH:MM format) Event minimum height Minimum height for events in timeline views (pixels) Show tracked tasks in status bar Display currently tracked tasks in Obsidian's status bar Show relationships widget Display a widget showing all relationships for the current note (subtasks, projects, dependencies) Relationships position Where to position the relationships widget Show task card in note Display a task card widget at the top of task notes showing the task details and actions Strike through completed task titles Draw a line through completed task card titles. Turn off to keep completed tasks easier to read Show expandable subtasks Allow expanding/collapsing subtask sections in task cards Expand subtasks by default Show project subtasks expanded when task cards are rendered Subtask chevron position Position of expand/collapse chevrons in task cards Views button alignment Alignment of the views/filters button in the task interface Single-click action Action performed when single-clicking a task card Double-click action Action performed when double-clicking a task card Features# Source: src/settings/tabs/featuresTab.ts Setting Purpose Task link overlay Show interactive overlays when hovering over task links Disable overlay for aliased links Do not show the task widget if the link contains an alias (e.g. [[Task|Alias]]). Show convert button next to checkboxes Display an inline button next to Markdown checkboxes that converts them to TaskNotes Keep checkbox when converting Leave the original Markdown checkbox marker in place when converting a checkbox to a TaskNote link Enable natural language task input Parse due dates, priorities, and contexts from natural language when creating tasks Default to scheduled When NLP detects a date without context, treat it as scheduled rather than due NLP language Language for natural language processing patterns and date parsing Open task after creation Choose whether the task creation modal opens the new task note after saving. Use body template Use a template file for task body content Body template file Path to template file for task body content. Supports template variables like {{title}}, {{date}}, {{time}}, {{priority}}, {{status}}, etc. Use occurrence note template Use a separate fallback template for materialized occurrence notes when the recurring task has no occurrence_template Occurrence note template file Path to template file for materialized occurrence notes. A recurring task's occurrence_template field takes priority over this fallback. Template variables: See the setting in Obsidian for contextual details. Use task defaults on instant convert Apply default task settings when converting text to tasks instantly Work duration Duration of work intervals in minutes Short break duration Duration of short breaks in minutes Long break duration Duration of long breaks in minutes Long break interval Number of work sessions before a long break Auto-start breaks Automatically start break timers after work sessions Auto-start work Automatically start work sessions after breaks Pomodoro notifications Show notifications when Pomodoro sessions end Show Pomodoro in status bar Display the active Pomodoro countdown in Obsidian's status bar Sound enabled Play sound when Pomodoro sessions end Sound volume Volume for Pomodoro sounds (0-100) Pomodoro data storage Configure where Pomodoro session data is stored and how it's managed. Mobile sidebar Where to open the Pomodoro timer on mobile devices Enable notifications Enable task reminder notifications Notification type Type of notifications to show Send test reminder Send a test reminder using the current notification type and sound settings. Notification sound Play a sound when task reminders trigger Sound volume Volume for task reminder sounds (0-100) Preview notification sound Play the configured task reminder sound Hide completed tasks from overdue Exclude completed tasks from overdue task calculations Disable note indexing Disable automatic indexing of note content for better performance Suggestion debounce Delay in milliseconds before showing suggestions Auto-stop time tracking Automatically stop time tracking when a task is marked complete Time tracking stop notification Show notification when time tracking is automatically stopped Maintain due date offset in recurring tasks Keep the offset between due date and scheduled date when recurring tasks are completed Reset checkboxes on recurrence Reset all Markdown checkboxes in the task body when a recurring task is completed and rescheduled Enable timeblocking Enable timeblocking feature for lightweight scheduling in daily notes. When enabled, 'Timeblock' option appears in the calendar drag context menu. Show timeblocks Display timeblocks from daily notes by default Default timeblock color The default color used when creating new timeblocks Enable debug logging Log detailed drag-and-drop and view diagnostics to the developer console. Useful for troubleshooting. Integrations# Source: src/settings/tabs/integrationsTab.ts Setting Purpose Generate mdbase type definitions See the setting in Obsidian for contextual details. Disable calendar integrations on mobile Skip Google, Microsoft, and ICS calendar loading on Obsidian mobile. Desktop calendar integrations are unchanged. Calendar integrations are disabled on this mobile device See the setting in Obsidian for contextual details. Enable task export When enabled, tasks with dates will be automatically synced to Google Calendar as events. Target calendar See the setting in Obsidian for contextual details. Sync trigger Which task date should trigger calendar event creation. Create as all-day events When enabled, tasks are created as all-day events. When disabled, uses time estimate for duration. Default event duration Duration in minutes for timed events (used when task has no time estimate). Event title template Template for event titles. Available variables: {{title}}, {{status}}, {{priority}} Include task details in description Add task metadata (priority, status, tags, etc.) to the event description. Include Obsidian link Add a link back to the task in Obsidian in the event description. Default reminder Add popup reminders to timed Google Calendar events. Enter minutes before the event, separated by commas. Leave empty to use calendar defaults. Common values: 15, 30, 60, 1440. Automatic sync behavior See the setting in Obsidian for contextual details. Sync on task create Automatically create calendar event when a new task is created. Sync on task update Automatically update calendar event when a task is modified. Sync on task complete Update calendar event when a task is completed (adds checkmark to title). Delete event on task delete Remove calendar event when the corresponding task is deleted. Manual sync actions See the setting in Obsidian for contextual details. Sync all tasks Sync all existing tasks to Google Calendar. This will create events for tasks that haven't been synced yet. Unlink all tasks Remove all task-event links without deleting calendar events. Default note template Path to template file for notes created from ICS events Default note folder Folder for notes created from ICS events ICS note filename format How filenames are generated for notes created from ICS events Custom ICS filename template Template for custom ICS event filenames Use ICS event end time as task due date When enabled, tasks created from calendar events will have their due date set to the event's end time. For all-day events, the due date will be set to the event date. For timed events, the due date will include the end time. Recurring event related notes Choose whether notes linked to one recurrence of an external calendar event appear across the loaded series or only on the selected instance. Add calendar subscription Add a new calendar subscription from ICS/iCal URL or local file New calendar See the setting in Obsidian for contextual details. Refresh all subscriptions Manually refresh all enabled calendar subscriptions Enable automatic export Automatically keep an ICS file updated with all your tasks Export file path Path where the ICS file will be saved (relative to vault root) Update interval (between 5 and 1440 minutes) How often to update the export file Use task duration for event length When enabled, uses the task's time estimate (duration) instead of due date for the calendar event end time. This is useful for GTD workflows where scheduled + duration represents work planning, while due date represents deadlines. Exclude completed tasks When enabled, completed tasks are omitted from ICS exports. Completed statuses are taken from your task statuses settings. Exclude archived tasks When enabled, archived tasks are omitted from ICS exports. Require due date When enabled, only tasks with a due date are included in ICS exports. Require scheduled date When enabled, only tasks with a scheduled date are included in ICS exports. Export now Manually trigger an immediate export Export status: See the setting in Obsidian for contextual details. Enable HTTP API Start local HTTP server for API access API port Port number for the HTTP API server API authentication token Required for API authentication. If empty, a token is generated when the server starts. Enable MCP server Expose TaskNotes tools via Model Context Protocol at /mcp endpoint. Requires HTTP API to be enabled. Add webhook Register a new webhook endpoint Complete default settings snapshot# The following JSON is generated from DEFAULT_SETTINGS. Empty strings and disabled flags are intentional defaults. { \"tasksFolder\": \"TaskNotes/Tasks\", \"moveArchivedTasks\": false, \"archiveFolder\": \"TaskNotes/Archive\", \"taskTag\": \"task\", \"taskIdentificationMethod\": \"tag\", \"hideIdentifyingTagsInCards\": false, \"hideIdentifyingTagsMode\": \"all\", \"taskPropertyName\": \"\", \"taskPropertyValue\": \"\", \"excludedFolders\": \"\", \"defaultTaskPriority\": \"normal\", \"defaultTaskStatus\": \"open\", \"taskOrgFiltersCollapsed\": false, \"taskFilenameFormat\": \"zettel\", \"storeTitleInFilename\": true, \"customFilenameTemplate\": \"{{title}}\", \"occurrenceFilenameTemplate\": \"\", \"occurrenceFilenameTemplateProperty\": \"occurrenceFilenameTemplate\", \"taskCreationDefaults\": { \"defaultContexts\": \"\", \"defaultTags\": \"\", \"defaultProjects\": \"\", \"useParentNoteForTaskCreation\": false, \"useParentNoteAsProject\": false, \"useParentHeaderAsProject\": false, \"inheritParentTaskProperties\": false, \"defaultTimeEstimate\": 0, \"defaultRecurrence\": \"none\", \"defaultDueDate\": \"none\", \"defaultDueTime\": \"none\", \"defaultScheduledDate\": \"today\", \"defaultScheduledTime\": \"none\", \"bodyTemplate\": \"\", \"useBodyTemplate\": false, \"occurrenceBodyTemplate\": \"\", \"useOccurrenceBodyTemplate\": false, \"defaultReminders\": [] }, \"openTaskAfterCreation\": \"none\", \"calendarViewSettings\": { \"defaultView\": \"dayGridMonth\", \"customDayCount\": 3, \"slotDu"},{"title":"Release Notes","url":"/obsidian/releases/","description":"Welcome to the TaskNotes release notes. Here you can find detailed information about each version, including new features, bug fixes, and improvements.","product":"obsidian","text":"Welcome to the TaskNotes release notes. Here you can find detailed information about each version, including new features, bug fixes, and improvements. Latest Releases# Version 4.x (Current)# 4.13.0 4.12.5 4.12.4 4.12.3 4.12.2 4.12.1 4.12.0 4.11.1 4.11.0 4.10.2 4.10.1 4.10.0 4.9.2 4.9.1 4.9.0 4.8.1 4.8.0 4.7.2 4.7.1 4.7.0 4.6.0 4.5.3 4.5.2 4.5.1 4.5.0 4.4.0 4.3.3 4.3.2 4.3.1 4.3.0 4.2.1 4.2.0 4.1.3 4.1.2 4.1.1 4.1.0 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 4.0.0-beta.3 4.0.0-beta.2 4.0.0-beta.1 4.0.0-beta.0 Version 3.x# 3.25.6 3.25.4 3.25.3 3.25.2 3.25.1 3.25.0 3.24.6 3.24.5 3.24.4 3.24.3 3.24.2 3.24.1 3.24.0 3.23.4 3.23.3 3.23.2 3.23.1 3.23.0 3.22.1 3.22.0 3.21.0 3.20.1 3.20.0 3.19.1 3.19.0 3.18.2 3.18.1 3.18.0 3.17.1 3.17.0 3.16.4 3.16.3 3.16.2 3.16.1 3.16.0 3.15.1 3.15.0 3.14.0 3.13.4 3.13.3 3.13.2 3.13.1 3.13.0 3.12.2 3.12.1 3.12.0 3.11.2 3.11.1 3.11.0 3.10.0 3.9.1 3.9.0 3.8.7 3.8.6 3.8.5 3.8.1 3.7.1 3.7.0 3.6.0 3.5.1 3.4.2 3.4.1 3.4.0 3.3.0 3.1.1 3.1.0 3.0.1 3.0.0 Version 2.x# 2.2.3 2.2.2 2.2.1 2.2.0 2.1.0 2.0.4 2.0.3 2.0.2 2.0.1 2.0.0 Version 1.x# 1.2.0 1.1.0 1.0.0 Early Versions (0.x)# 0.8.0 0.7.0 0.6.3 0.6.2 0.6.1 0.6.0 0.4.2 0.4.1 0.4.0 0.3.0 0.2.4 0.2.3 0.2.2 Getting Updates# To update TaskNotes: Open Obsidian Go to Settings → Community Plugins Find TaskNotes and click \"Update\" Restart Obsidian if prompted Feedback# Found a bug or have a feature request? Please: Check existing GitHub Issues Create a new issue with details"},{"title":"Untitled","url":"/obsidian/releases/0.2.2/","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.1...0.2.2","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.1...0.2.2"},{"title":"Untitled","url":"/obsidian/releases/0.2.3/","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.2...0.2.3","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.2...0.2.3"},{"title":"Untitled","url":"/obsidian/releases/0.2.4/","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.3...0.2.4","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.3...0.2.4"},{"title":"Untitled","url":"/obsidian/releases/0.3.0/","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.4...0.3.0","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.2.4...0.3.0"},{"title":"Untitled","url":"/obsidian/releases/0.4.0/","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.3.0...0.4.0","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.3.0...0.4.0"},{"title":"Untitled","url":"/obsidian/releases/0.4.1/","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.1","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.1"},{"title":"Untitled","url":"/obsidian/releases/0.4.2/","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.2","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.4.0...0.4.2"},{"title":"Untitled","url":"/obsidian/releases/0.6.0/","description":"TaskNotes documentation.","product":"obsidian","text":""},{"title":"Untitled","url":"/obsidian/releases/0.6.1/","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.0...0.6.1","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.0...0.6.1"},{"title":"Untitled","url":"/obsidian/releases/0.6.2/","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.1...0.6.2","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.1...0.6.2"},{"title":"Untitled","url":"/obsidian/releases/0.6.3/","description":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.2...0.6.3","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/chronosync/compare/0.6.2...0.6.3"},{"title":"Untitled","url":"/obsidian/releases/0.7.0/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.7.0","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.7.0"},{"title":"Untitled","url":"/obsidian/releases/0.8.0/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.8.0","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.6.3...0.8.0"},{"title":"Untitled","url":"/obsidian/releases/1.0.0/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.8.0...1.0.0","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/0.8.0...1.0.0"},{"title":"Untitled","url":"/obsidian/releases/1.1.0/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/1.0.0...1.1.0","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/1.0.0...1.1.0"},{"title":"Untitled","url":"/obsidian/releases/1.2.0/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/1.1.0...1.2.0","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/1.1.0...1.2.0"},{"title":"Untitled","url":"/obsidian/releases/2.0.0/","description":"TaskNotes 2.0.0 - Major Feature Release","product":"obsidian","text":"TaskNotes 2.0.0 - Major Feature Release Major New Features: Kanban Board View Visual task management with drag-and-drop functionality Dynamic grouping by status, priority, or context Search filtering across all columns Real-time updates and collapsible columns Enhanced Pomodoro System SVG progress circle with refined visual timer Persistent session history and statistics tracking Dedicated Pomodoro Statistics view with completion metrics Enhanced UI with improved controls and display Advanced Task Filtering & Grouping Unified filtering system with search, status, context, priority filters Date range filtering with overdue task support Flexible grouping options (status, priority, context, due date) Performance-optimized filtering using cache indexes Enhanced Recurring Tasks Visual distinction with special styling and indicators Per-date completion tracking with smart UI controls Context menus filtered to prevent status conflicts Clear completion status display for selected dates UI/UX Improvements: Task Management Enhanced task edit modal with improved form layout Context menu (right-click) for quick property changes Autocomplete for contexts and tags in task forms Optimistic UI updates for better responsiveness View Enhancements Agenda view with improved layout and timeline organization Enhanced note cards with consistent styling across views Improved calendar integration with better visual indicators Unified card styling system across all views Performance & Reliability Migrated to unified CacheManager from legacy FileIndexer DOM reconciliation system for efficient UI updates Enhanced async handling and error management Improved cache update handling and race condition prevention Additional Improvements: Enhanced due date modal with better styling Improved time tracking UX with visual feedback Better task archival feedback and UI consistency Refined keyboard navigation and accessibility Updated README with comprehensive feature documentation Bug Fixes: Fixed 'No due date' group positioning in task list Resolved various UI spacing and alignment issues Improved handling of edge cases in recurring task logic Enhanced stability of cache operations and file handling This major release significantly expands TaskNotes capabilities with new views, enhanced filtering, and improved user experience while maintaining data compatibility with previous versions."},{"title":"Untitled","url":"/obsidian/releases/2.0.1/","description":"Bug Fixes and Enhancements:","product":"obsidian","text":"TaskNotes 2.0.1 - Recurring Tasks and Filtering Improvements# Bug Fixes and Enhancements: Recurring Task Improvements: Fixed recurring tasks not appearing in correct due date groups (Today, Tomorrow, etc.) Recurring tasks now properly appear in 'Today' group when selected date matches recurrence pattern Enhanced recurring task visual styling with distinctive indicators and backgrounds Smart context menus for recurring tasks that prevent conflicting status changes Fixed recurrence values not loading properly in task edit modal Task Filtering and Grouping: Improved 'No due date' group positioning to appear at bottom of task list Enhanced FilterService with target date awareness for intelligent recurring task grouping Fixed cache integration issues where recurrence changes didn't trigger proper view updates All views now properly refresh and regroup tasks when recurrence properties change UI and Data Consistency: Fixed data format mismatch between stored abbreviations and UI display for day names Improved task edit modal to properly convert between storage format and UI format Enhanced cache workflow integration for seamless task property updates Better synchronization between task edits and view refreshes Technical Improvements: Added conversion helper methods for consistent day name handling Enhanced cache manager with proper recurring task support Improved event emission and handling for task updates Better error handling and data validation in task modals This release focuses on making recurring tasks work seamlessly with the filtering and grouping system while maintaining data consistency and improving the overall user experience."},{"title":"Untitled","url":"/obsidian/releases/2.0.2/","description":"Bug Fixes:","product":"obsidian","text":"TaskNotes v2.0.2# Bug Fixes: Fixed recurring tasks without due dates not appearing in agenda view Recurring tasks now properly show on their scheduled days in agenda view Settings Improvements: Enhanced Priorities settings tab with comprehensive usability improvements Added detailed descriptions, help sections, and column headers Added input validation and better visual organization Matches the improved usability of the Statuses settings tab Technical Details: Modified FilterService date range filtering to properly handle recurring tasks without due dates Added logic to check if recurring tasks should appear on any date within the specified range Uses existing isRecurringTaskDueOn helper for accurate recurrence calculations Maintains full backward compatibility for all existing functionality"},{"title":"Untitled","url":"/obsidian/releases/2.0.3/","description":"Bug Fixes:","product":"obsidian","text":"Bug Fixes: Fixed recurring tasks without due dates not appearing in agenda view Recurring tasks now properly show on their scheduled days in agenda view Command Improvements: Removed layout-specific commands (open-linked-views, open-grid-layout, open-tabs-layout) Removed popout window commands for cleaner command palette Added 'Refresh TaskNotes cache' command for troubleshooting Simplified ribbon icons to focus on core functionality Technical Details: Enhanced FilterService initial task set logic to include recurring tasks without due dates Modified getTaskPathsInDateRange() to check all recurring tasks for date range inclusion Added async processing with batched performance optimizations Maintained backward compatibility and existing performance characteristics Root cause: CacheManager only indexed tasks by actual due dates, excluding recurring tasks without due dates from date-based queries The agenda view now correctly displays recurring tasks without due dates on their appropriate scheduled days."},{"title":"TaskNotes v2.0.4","url":"/obsidian/releases/2.0.4/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.0.3...2.0.4","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.0.3...2.0.4 Allow multiple statuses to be filtered for at the same time, bringing status filtering in line with context and priority filtering Fix flickering during kanban drag and drop"},{"title":"TaskNotes v2.1.0 - Major Feature Release","url":"/obsidian/releases/2.1.0/","description":"This release introduces significant workflow enhancements and editor integration features that streamline task management directly within the Obsidian editing experience.","product":"obsidian","text":"This release introduces significant workflow enhancements and editor integration features that streamline task management directly within the Obsidian editing experience. NEW FEATURES:# Instant Task Conversion One-click conversion of checkbox tasks to dedicated TaskNotes with inline convert buttons Streamlined workflow for transforming simple tasks into structured task files Configurable via settings to enable/disable the feature Interactive Task Link Overlays Live task previews displayed on wikilinks in live preview mode Hover and click interactions for editing tasks without leaving the current note Context menus and inline task information display Smart detection of task-related wikilinks with automatic enhancement Enhanced Date Handling Improved overdue task detection that considers both due and scheduled dates Better date consistency across all views and components Expanded field mapping support for time tracking and completion data IMPROVEMENTS:# Performance & Reliability Comprehensive resource cleanup to prevent memory leaks Enhanced error handling with better user feedback Performance optimizations in calendar view and task rendering Improved DOM reconciliation and widget management Accessibility & UX Enhanced accessibility with ARIA attributes and keyboard navigation Consistent BEM CSS naming across all components Better input validation and security measures Improved visual consistency throughout the interface Technical Enhancements Fixed deprecated Obsidian API usage for better compatibility Standardized date handling using date-fns library Configurable pomodoro field mapping Better separation of concerns in component architecture This release maintains full backward compatibility while adding new features that enhance the daily task management workflow."},{"title":"TaskNotes v2.2.0","url":"/obsidian/releases/2.2.0/","description":"TaskNotes documentation.","product":"obsidian","text":"Major Features# Task Deletion: Added task deletion functionality with confirmation modal and proper event handling Pomodoro Data Migration: Implemented migration utility for backward compatibility with existing Pomodoro session data Enhanced Calendar Navigation: Improved CalendarView date navigation and refresh logic Core Improvements# Timezone-Safe Date Handling: Complete overhaul of date utilities to ensure consistent timezone handling across the codebase Centralized Task Management: Refactored task creation and editing to use centralized TaskService architecture Improved Date Filtering: Enhanced FilterService with better date comparison logic for due and scheduled tasks Pomodoro Session Tracking: Refactored session tracking and duration calculations for better accuracy UI/UX Enhancements# Visual Consistency: Updated font sizes and UI element widths for better readability Pomodoro Button Styling: Enhanced button styles with consistent visual feedback Inline Widget Cleanup: Improved task update handling and cleaned up inline widget styles Technical Improvements# Safer Date Parsing: Replaced parseISO with parseDate utilities for more robust date handling ISO Timestamp Support: Updated timestamp generation to return ISO format with local timezone offset Performance Optimizations: Various refactoring improvements for better code maintainability and performance"},{"title":"Untitled","url":"/obsidian/releases/2.2.1/","description":"Fix #22 and #24","product":"obsidian","text":"Fix #22 and #24"},{"title":"Untitled","url":"/obsidian/releases/2.2.2/","description":"TaskNotes documentation.","product":"obsidian","text":""},{"title":"Untitled","url":"/obsidian/releases/2.2.3/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.2.2...2.2.3","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.2.2...2.2.3"},{"title":"Untitled","url":"/obsidian/releases/3.0.0/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.3.0...3.0.0","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/2.3.0...3.0.0"},{"title":"Untitled","url":"/obsidian/releases/3.0.1/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.0.0...3.0.1","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.0.0...3.0.1"},{"title":"Untitled","url":"/obsidian/releases/3.1.0/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.0.1...3.1.0","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.0.1...3.1.0"},{"title":"Untitled","url":"/obsidian/releases/3.1.1/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.1.0...3.1.1","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.1.0...3.1.1"},{"title":"Release Notes: 3.10.0","url":"/obsidian/releases/3.10.0/","description":"This version introduces a new data storage option for tasks, adds a status bar component for time tracking, and includes several bug fixes and internal improvements.","product":"obsidian","text":"This version introduces a new data storage option for tasks, adds a status bar component for time tracking, and includes several bug fixes and internal improvements. New Features# Option to Store Task Title in Filename# A new setting, storeTitleInFilename, is available under \"Task Filenames\" in the settings tab. This feature changes how task titles are stored. Implementation Details: When this setting is enabled, creating a new task will use its title to generate the filename (e.g., My New Task.md). The title field will be omitted from the task's frontmatter. For reading tasks, the application will first look for a title field in the frontmatter. If it is not found, the system will use the filename as the task's title. This ensures backward compatibility with existing tasks. When a task's title is updated, and this setting is active, the file itself is automatically renamed to match the new title. The file's frontmatter is updated before the rename operation occurs to ensure data integrity. Enabling this setting disables and hides the other filename format options (Zettelkasten, timestamp, custom). This setting is disabled by default. Status Bar Component for Tracked Tasks# A new UI component has been added to the app's status bar to display tasks with active time-tracking sessions. Functionality: When a single task is being tracked, its title (truncated if necessary) is displayed in the status bar. The full title is visible in a tooltip. When multiple tasks are being tracked, a count of these tasks is displayed. The tooltip lists the titles of the tracked tasks. The status bar item is hidden when no tasks are being tracked. This feature is controlled by the \"Show tracked tasks in status bar\" setting and is disabled by default. Customizable First Day of Week for Mini Calendar# The mini calendar view now respects the \"First day of the week\" setting in Obsidian's general settings. The calendar grid will adjust to start the week on the day you have configured (e.g., Sunday or Monday). Bug Fixes# Search Functionality: Resolved a type error in the search filter that occurred when a task's title or context field was null. The code now handles null values gracefully during search operations. File Renaming: Corrected the order of operations when storeTitleInFilename is enabled. The previous implementation could rename the file before its frontmatter was updated, which has now been fixed. Internal Improvements & Documentation# Service Refactoring: The TaskService, FieldMapper, and MinimalNativeCache have been updated to handle the new logic for storing and retrieving task titles from filenames. StatusBarService: A new StatusBarService was implemented to encapsulate the logic for the new status bar component, including its creation, updates, and event handling. Issue Templates: The GitHub issue templates for bug reports and questions have been updated to be more structured and improve the quality of submitted reports. Documentation: Added a new section to the documentation explaining the storeTitleInFilename feature in detail."},{"title":"Release Notes: 3.11.0","url":"/obsidian/releases/3.11.0/","description":"This release introduces a new project management system, significant enhancements to the Pomodoro timer and workflows, and a number of quality-of-life improvements and bug fixes.","product":"obsidian","text":"This release introduces a new project management system, significant enhancements to the Pomodoro timer and workflows, and a number of quality-of-life improvements and bug fixes. New Features# Project Management# A new project management system has been integrated, allowing for better organization and tracking of tasks within projects. Note-Based Projects: Projects are now properly integrated into TaskNotes. You can link tasks to any note in your vault, effectively turning that note into a project. This leverages Obsidian's core linking capabilities, allowing you to see all tasks related to a project in the backlinks of the project note. Project Selection UI: A new project selection modal has been added to the task creation and editing modals. It features fuzzy search to quickly find and assign tasks to project notes. Filtering and Grouping by Project: The Filter Bar in all views now includes a \"Project\" filter, allowing you to see tasks for one or more specific projects. The \"Group By\" option now includes \"Project\", which organizes the Task List and Kanban views by project. Clickable Project Links: In task cards and other views, project names are now clickable links that take you directly to the project note. Workflow and UI Enhancements# Redesigned Pomodoro Timer: The Pomodoro timer has been completely redesigned for a more modern and user-friendly experience. New Interface: A more compact and visually appealing interface. Time Adjustment: You can now add or subtract time from the current session or the prepared timer. Skip Break: A \"Skip break\" button is now available after a work session. Enhanced Pomodoro Stats: The Pomodoro statistics view has been improved to provide more insights. Overview Section: A new overview section shows today's completed Pomodoros, total focus time, and a comparison with yesterday's performance. Instant Task Conversion: The \"Convert task to TaskNote\" command has been streamlined. It now instantly converts a checkbox task into a TaskNote without opening the creation modal, reducing friction. Quick Actions for Current Task: A new command, \"Quick actions for current task,\" allows you to open the action palette for the currently active TaskNote, providing quick access to common operations. Improved Sorting Logic: The task sorting algorithm has been enhanced. When the primary sorting criterion (e.g., due date) is the same for multiple tasks, a fallback sorting order is applied: scheduled date -> due date -> priority -> title. This ensures a more predictable and logical ordering of tasks. Archive Button in Edit Modal: An \"Archive\" button has been added to the task edit modal, allowing for quick archiving and unarchiving of tasks. Week Start Day Setting: All calendar views now respect the \"Start week on\" setting from Obsidian's calendar preferences. Bug Fixes and Minor Improvements# Recurring Task Date Consistency: A critical bug has been fixed where recurring task dates could appear on the wrong day in different timezones (especially CST). The handling of dates and timezones for recurring tasks is now more robust, ensuring consistency across all views. Pomodoro Daily Note Integration: The Pomodoro service now correctly handles adding session history to daily notes, preventing the creation of duplicate entries. Template Processing: The {{parentNote}} template variable now correctly resolves to a properly formatted markdown link. YAML frontmatter in templates is now processed more safely to avoid parsing errors. Date Validation: The complete_instances field for recurring tasks now has stricter validation to filter out invalid entries, improving data integrity. Natural Language Processing: The natural language parser now correctly applies scheduled times (e.g., \"do something at 5pm\") to created tasks. Agenda View Quick Select: A bug that prevented the date quick-select menus in the Agenda View from working after the first use has been fixed. Styling and CSS: Numerous styling improvements have been made across the plugin for a more polished and consistent look and feel, including to the Pomodoro views, task cards, and modals. Documentation: The documentation has been updated to reflect the new project management features. New workflow guides for \"Habit Tracking\" and \"Project Management\" have been added."},{"title":"Release Notes 3.11.1","url":"/obsidian/releases/3.11.1/","description":"This release focuses on adopting Obsidian's official APIs and improving plugin stability through better resource management.","product":"obsidian","text":"API Modernization & Performance Improvements# This release focuses on adopting Obsidian's official APIs and improving plugin stability through better resource management. Improved autocomplete# Replaced custom autocomplete implementation with Obsidian's native AbstractInputSuggest API Better keyboard navigation and visual consistency More responsive type-ahead support for contexts and tags in task modals API modernization# Atomic Frontmatter Updates: Now uses FileManager.processFrontMatter for safer file modifications Eliminates risk of data corruption during migration processes More reliable handling of YAML frontmatter updates Native Link Parsing: Switched to Obsidian's built-in parseLinktext API More robust wikilink parsing with better edge case handling Improved consistency with Obsidian's internal link processing Vault-Specific Storage: View preferences now use App.loadLocalStorage/saveLocalStorage Fixes issue where settings were shared across different vaults Each vault now maintains its own view state and preferences Bug fixes & stability# Memory Leak Prevention: Properly register and cleanup event listeners Event listeners are now tracked with EventRef objects for proper cleanup Prevents memory leaks when plugin is disabled or reloaded Debounce Optimization: Uses Obsidian's built-in debounce function More efficient calendar refresh operations Better performance consistency UI Polish: Fixed sentence case issues throughout the interface Security & reliability# Resource Cleanup: Enhanced plugin lifecycle management Better cleanup of event listeners and cached data Improved plugin disable/enable reliability"},{"title":"Release Notes - 3.11.2","url":"/obsidian/releases/3.11.2/","description":"TaskNotes documentation.","product":"obsidian","text":"Internal Improvements# API Standardization# Replaced custom wikilink parsing with Obsidian's native parseLinktext API Migrated from custom debounce function to Obsidian's built-in debounce utility Files Updated# TaskLinkOverlay.ts: Updated wikilink parsing FilterService.ts: Improved project link resolution TaskLinkDetectionService.ts: Simplified link detection MinimalNativeCache.ts: Standardized project link handling KanbanView.ts: Replaced custom debounce implementation Test files: Updated mocks accordingly"},{"title":"Release Notes - 3.12.0","url":"/obsidian/releases/3.12.0/","description":"TaskNotes documentation.","product":"obsidian","text":"New Features# Project Subtasks Widget# Add a collapsible widget that displays tasks linked to the current project note Widget appears automatically in project notes and shows all tasks that reference the rpoject Includes collapsible interface with persistent state across sessions Updates automatically when tasks are modified or deleted Can be enabled or disabled in plugin settings under \"Show project subtasks widget\" Bug Fixes# FilterBar Improvements# Fixed FilterBar not updating dynamically when tasks get new contexts or projects (#138) Fixed archived tasks' contexts and projects still appearing in filter bar (#139) Resolved FilterBar showing projects with [[]] brackets Fixed empty status list display on initial load Improved initialization reliability with better event handling Task Display# Fixed wikilink alias handling in TaskCard and inline displays (#145, #147) Fixed projects not loading correctly in task edit modal (#141) Improved cursor positioning in live preview mode Documentation# Added documentation for project subtasks widget feature Updated inline task integration documentation Added configuration settings documentation"},{"title":"Release Notes - 3.12.1","url":"/obsidian/releases/3.12.1/","description":"TaskNotes documentation.","product":"obsidian","text":"New Features# Project Subtasks Widget Enhancements# New button for task creation - Added \"New\" button to widget header for quick task creation Auto-populated project field - New tasks automatically reference the current note as their project Improved positioning - Widget now appears at the end of documents for better user experience Improve visual design - Added dashed border to indicate virtual/generated content and improved styling Bug Fixes# Timezone and Date Handling# Fixed timezone boundary issues in Agenda view date filtering (#153) Resolved missing tasks that were scheduled 7 days ago or yesterday due to timezone drift Enhanced date normalization in AgendaView for consistent behavior across timezones Improved task filtering with better date handling in getTasksForDate() UI and Display Improvements# Fixed cursor positioning to prevent cursor appearing after project subtasks widget Resolved pre-populated projects not displaying correctly in task creation modal Improved widget rendering with CSS-only styling approach for better performance Settings Reorganization# New Misc Tab# Renamed \"Performance\" tab to \"Misc\" and moved to end of settings tab list Consolidated miscellaneous features into a single organized location Improved settings navigation by grouping related toggles together Settings Moved to Misc Tab# Status bar toggle - Show tracked tasks in status bar Project subtasks widget toggle - Show project subtasks widget in notes Notes indexing toggle - Disable note indexing for performance optimization Documentation Updates# Settings Documentation# Updated all documentation to reflect new settings organization Created comprehensive Misc Settings documentation with detailed explanations Removed outdated references from Advanced Settings documentation Updated troubleshooting guides with correct setting locations Reference Updates# Updated inline task feature documentation to reference new Misc tab location Fixed all setting location references throughout documentation Maintained backward compatibility information for users upgrading"},{"title":"Release Notes - 3.12.2","url":"/obsidian/releases/3.12.2/","description":"TaskNotes documentation.","product":"obsidian","text":"Bug Fixes# Calendar & Date Handling# Fixed off-by-one date bugs in completion calendar (#160) Resolved timezone inconsistency where calendar showed one date but completion was recorded for another Calendar rendering now uses UTC dates consistently across all components Fixed \"Friday tasks appearing on Saturday\" issue in completion tracking Task Management# Fixed project filters not working in agenda view (#161) Project filtering now works consistently across all views Fixed edit modal crash when tasks have empty project properties Added null checks to prevent \"Cannot read properties of null\" errors Handles null, undefined, and empty string project values gracefully Fixed autofill suggestions not updating internal state (#159) Context and tag suggestions now properly sync with modal internal state Clicking suggestions now correctly updates the task data UI & Styling# Fixed consistent styling for priorities and statuses settings tabs (#130) Added missing BEM classes for proper grid alignment Priority inputs now use same styling as status inputs Fixed table column misalignment issues Documentation# Improved README and documentation Enhanced overview section with better flow and natural language Added time-tracking and pomodoro feature descriptions Fixed broken documentation links Updated Core Features section with more accurate descriptions Testing# Added comprehensive tests for date handling issues Increased test coverage for calendar and completion functionality Added tests reproducing and verifying fixes for off-by-one date bugs"},{"title":"Release Notes - 3.13.0","url":"/obsidian/releases/3.13.0/","description":"##Technical Changes","product":"obsidian","text":"Major Changes# Filtering System Overhaul# Hierarchical Query Builder: Complete redesign of the filtering system with a query builder interface Saved Views: Users can save, manage, and switch between custom filter configurations FilterBar Redesign: Updated to use Obsidian components with improved styling UI Updates# FilterBar Integration: Added to all task views (Kanban, List, Calendar, Agenda) with state management Dropdown Improvements: Status and priority filters now use display labels Dropdown Positioning: Fixed positioning and CSS styling issues New Features# Natural Language Processing# Nested Tag Support: Tags with forward slashes are now supported (e.g., project/subtask) Interface# Project Note Decorations: Updated styling and visual elements Task Modal Styling: Refined task creation and editing interfaces Bug Fixes# Filter System# Fixed handling of empty arrays in \"Projects is not empty\" conditions Fixed incomplete filter conditions handling Fixed saved views dropdown persistence when filters change Fixed view options disappearing on refresh Fixed view selector dropdown behavior Testing# Fixed multiple unit and integration test failures Fixed migration workflow test for YAML parsing errors Expanded test coverage for task service completion Code Quality# Removed debug console.log statements Improved async handling and import organization Better search functionality implementation ##Technical Changes Refactoring# Refactored FilterBar with Obsidian components Updated filter rule definitions and UI components Improved state management across views Updated ViewStateManager Development# Updated Typescript configuration Added new Filter Utils.ts utility module Improved code organization"},{"title":"Release Notes - 3.13.1","url":"/obsidian/releases/3.13.1/","description":"TaskNotes documentation.","product":"obsidian","text":"New Features# Saved Filter Views Storage# Saved filter views now sync across devices with your vault Views are stored in plugin data instead of browser localStorage Automatic migration from previous storage system on first load FilterBar Behavior# Filter panel now stays open when clicking elsewhere in the interface Panel only closes when the filter button is clicked again Eliminates accidental filter panel closures during normal use Performance Improvements# Filter Operations# Adding and removing filters is now significantly faster Reduced lag when building complex filter queries Search input state preserved during filter modifications Migration System# Early migration detection prevents DOM errors on first use Better error handling during plugin initialization Cleaner migration process for new users Bug Fixes# First-Time User Experience# Fixed \"removeChild\" DOM errors when using filters for the first time Resolved race conditions between migration and UI initialization Added fallback UI states for improved reliability FilterBar Stability# Added DOM connection checks before manipulation Improved error boundaries in filter rendering Better cleanup of event listeners on component destruction Technical Changes# View State Management# Saved views migrate from localStorage to plugin data system ViewStateManager now uses plugin settings for persistence Enhanced migration detection and completion tracking Error Handling# Added safety checks for DOM element manipulation Graceful degradation when filter operations fail Improved logging for troubleshooting migration issues"},{"title":"Release Notes - 3.13.2","url":"/obsidian/releases/3.13.2/","description":"TaskNotes documentation.","product":"obsidian","text":"Performance Improvements# FilterBar and Saved Views# Fixed performance issue where adding new filter conditions would unnecessarily re-evaluate all existing filters Added \"Select...\" placeholder option for new filter conditions to prevent premature filtering Eliminated unnecessary cache re-indexing when saving or deleting saved views Made settings system smarter to only trigger cache updates when indexing-related settings actually change Filter Processing# Implemented index-backed filtering that processes significantly fewer tasks for filtered views Added intelligent query result caching with automatic expiration to eliminate redundant operations Improved candidate selection using existing status, date, and overdue task indexes Enhanced set intersection logic for multiple AND conditions to further reduce processing Bug Fixes# Filter Logic# Fixed critical bug where index optimization incorrectly excluded valid results for OR queries containing indexed conditions Added detection logic to prevent unsafe optimizations when indexed conditions are part of OR groups Improved query structure analysis to ensure filter correctness Saved Views# Fixed issue where modifying one saved view could affect others due to shared object references Added proper deep cloning of FilterQuery objects throughout the ViewStateManager Ensured saved views remain independent when modified Technical Details# Index Optimization Safety# Index optimizations now only apply when provably safe (AND relationships between indexed conditions) Added recursive query analysis to detect OR groups containing indexed conditions Maintains filter correctness while providing performance benefits where safe Cache Management# Cache-related settings tracking: taskTag, excludedFolders, disableNoteIndexing, storeTitleInFilename, fieldMapping Query result caching with 30-second auto-expiration and immediate invalidation on data changes Debug logging available for performance monitoring Performance Impact# Filter building is now responsive with no lag when adding conditions Saved view operations are instant with no unnecessary re-indexing Repeated filter operations are nearly instant due to intelligent caching Significant memory usage reduction for large vaults"},{"title":"Release Notes - 3.13.3","url":"/obsidian/releases/3.13.3/","description":"TaskNotes documentation.","product":"obsidian","text":"Bug Fixes# Fixed recurring task completion date recording# Resolved issue where \"mark completed for this date\" context menu option recorded completion for the wrong date Fixed timezone inconsistency between completion date storage and checking logic Recurring tasks now properly track completion status per calendar date Improved recurring task filtering# Fixed \"Is completed\" filter condition to respect per-date completion status for recurring tasks Filter results now accurately reflect whether recurring tasks are completed for specific dates Enhancements# AgendaView improvements# Restored Today button with improved header layout Reorganized header into three sections: navigation controls, period title, and actions Fixed recurring task display to show tasks on their actual recurrence dates rather than just scheduled dates Removed keyboard navigation shortcuts (left/right arrows) Interface updates# Enhanced AgendaView header styling with better spacing and visual hierarchy Added responsive design for mobile layouts Improved button styling with proper hover and focus states Technical Changes# Updated TaskService to use consistent local timezone formatting for completion dates Enhanced FilterService to properly evaluate recurring task completion status Improved AgendaView task fetching to use FilterService.getTasksForDate() for better recurrence handling Testing# Added comprehensive test coverage for timezone handling and date formatting consistency Added tests to verify recurring task completion behavior across different scenarios"},{"title":"Release Notes - 3.13.4","url":"/obsidian/releases/3.13.4/","description":"Thanks to @cathywu, @Crunchnuggetz, @Poly-0000, @jpmoo and finally @bcohen44 for reporting the FilterBar crashes that led to identifying these migration issues.","product":"obsidian","text":"Bug Fixes# FilterBar Migration Issues# Fixed critical TypeError crashes when upgrading from versions prior to 3.13.0 Resolved Cannot read properties of undefined (reading 'forEach') and Cannot read properties of undefined (reading 'find') errors in FilterBar rendering Added detection for old FilterQuery format and automatic replacement with fresh defaults Users upgrading from older versions now get clean filter states instead of broken data structures Preserved valid sort and grouping settings when replacing incompatible filter data Added error boundaries with console warnings for better debugging Thanks to @cathywu, @Crunchnuggetz, @Poly-0000, @jpmoo and finally @bcohen44 for reporting the FilterBar crashes that led to identifying these migration issues. Features# Calendar View Improvements# Added ICS refresh button directly in the Advanced Calendar view toolbar ICS calendar subscriptions can now be refreshed without opening settings Button integrates with existing ICS subscription service and triggers immediate calendar re-render Improved ICS settings layout with horizontal button arrangement Enhanced calendar styling with proper hover states and removed unnecessary CSS overrides Extended today highlight disable to timegrid columns for visual consistency Notes# This release focuses on stability improvements for users upgrading from older versions. The FilterBar migration fixes ensure that users moving from pre-3.13.0 versions will have a smooth experience with the new filtering system introduced in 3.13.0. The ICS refresh button provides better user experience by allowing calendar data to be updated directly from the calendar view without navigating to settings."},{"title":"Release 3.14.0","url":"/obsidian/releases/3.14.0/","description":"TaskNotes documentation.","product":"obsidian","text":"New Features# Project Management Enhancements# Project Indicator Icons: TaskCard now displays visual indicators when tasks are used as projects [#191] - Thanks to @Poly-0000 for the suggestion Project Filtering: Added comprehensive project filtering functionality to the main plugin [#191] Create Subtask Option: Added \"Create subtask\" option to task card context menu for improved project workflow [#192] - Thanks to @Poly-0000 for the feature request Project Detection: Enhanced ProjectSubtasksService with isTaskUsedAsProject method for better project identification [#191] User Interface Improvements# Drag-and-Drop Saved Views: Implemented drag-and-drop reordering for saved views to improve workflow customization [#203] - Thanks to @jpmoo for the suggestion Project Styling: Added CSS styling for project indicator icons to improve visual hierarchy [#191] Created Date Sorting: Added 'Created Date' as a sort key option for better task organization [#188] - Thanks to @bl4z3ng41n for the PR Bug Fixes# Calendar and Recurring Tasks# Calendar Resize Support: Fixed duration updates for recurring tasks via calendar resize operations All-Day Handling: Improved recurring task all-day handling in calendar view [#201] - Thanks to @anomatomato and @bespokecomp for reporting Settings and State Management# Pomodoro Session Persistence: Fixed issue where pomodoro sessions were being cleared when changing settings [#196] - Thanks to @anomatomato for the bug report Technical Changes# Performance and Stability# Enhanced cache management and event handling for project-related functionality Improved error handling in project subtask operations Optimized project detection algorithms for better performance Code Organization# Refactored project-related services for better modularity Enhanced TypeScript type definitions for project functionality Improved service initialization and cleanup processes Documentation# Updated README with new project assets and feature documentation"},{"title":"Release 3.15.0","url":"/obsidian/releases/3.15.0/","description":"TaskNotes documentation.","product":"obsidian","text":"New Features# NLP Input Enhancements# Auto-suggestions: Added autocomplete functionality for tags and contexts in NLP input [#131] - Thanks to @Poly-0000 for the suggestion Project Auto-suggestions: Enhanced project auto-suggestions with rich display and field mapper integration Context and Tag Suggestions: Implemented auto-suggestion system to prevent typos and improve consistency [#131] Calendar Integration# ICS Event Integration: Added comprehensive ICS calendar event support with content creation capabilities [#122, #220] - Thanks to @donjjones and @Crunchnuggetz for the feature requests ICS Event Creation: Integrated ICS events into field mapping and type system for note creation [#122, #220] ICS Settings: Added ICS integration settings to calendar tab Calendar Hover Previews: Implemented hover preview functionality for advanced calendar - Thanks @nightroman for noticing this Time Entry Interaction: Added time entry interaction functionality to advanced calendar Time Management# Auto-stop Tracking: Added automatic time tracking termination when tasks are completed - Thanks to @cathywu for the suggestion [#184] Total Tracked Time: Enhanced edit modal to display total tracked time information [#181] - Thanks to @bcohen44 for the feature request Pomodoro View: Added task card display and improved controls to pomodoro view [#184] Timeblock Management: Enhanced TimeblockInfoModal with editing and deletion capabilities [#74] - Thanks to @bepolymathe for the suggestion User Interface Improvements# Fuzzy Note Pickers: Enhanced note pickers with title and alias support [#192] - Thanks to @Poly-0000 for the feedback Persistent Column Ordering: Added persistent column ordering to kanban board [#61] - Thanks to @slepsl for the suggestion Click-outside Support: Added click-outside and keyboard support to filter bar [#227] - Thanks to @cstelmach for the UX improvement request UI Polish: Removed unnecessary borders, shadows and transitions from various UI elements Bug Fixes# Task Management# Nested Tags: Fixed support for nested tags in FilterBar TypeError Resolution: Resolved TypeError when calling includes on non-array values Calendar Integration# Default Time Estimate: Fixed calendar click-to-add operations to respect default time estimate setting [#233] - Thanks to @nightroman for the bug report Time Slot Duration: Improved click detection in calendar to use time slot duration setting [#233] Documentation# Auto-suggestion Documentation: Added comprehensive documentation for auto-suggestion functionality ICS Integration Guide: Created detailed ICS calendar integration documentation Release Notes: Added comprehensive release notes documentation with links to all versions Inline Task Widget: Added screenshots and documentation for inline task widgets Technical Changes# Code Organization# Enhanced service architecture for ICS integration Improved field mapping system for calendar events Optimized auto-suggestion algorithms Enhanced type definitions for new functionality Performance# Improved rendering performance for pomodoro view Optimized calendar event handling Enhanced note picker search capabilities"},{"title":"Release 3.15.1","url":"/obsidian/releases/3.15.1/","description":"TaskNotes documentation.","product":"obsidian","text":"New Features# Kanban Board Enhancements# Show Empty Status Columns: Kanban board now displays empty columns for all configured statuses, providing better visual structure and workflow clarity Enhanced Task Grouping: Introduced GetGroupedTasksOptions interface for improved task grouping functionality with target date support and group pre-population [#236] - Thanks to @srcnDev for the implementation Calendar Improvements# All-Day Event Styling: Added line-through styling for completed all-day events in the Advanced Calendar view [#252, #254] - Thanks to @anomatomato for reporting the issue and submitting the PR Task Event Customization: Task events in the Advanced Calendar now include CSS classes based on their tags (e.g., fc-tag-meeting, fc-tag-work), enabling custom styling per tag [#243, #244] - Thanks to @jradam for the feature request and implementation Bug Fixes# Kanban Board# Duplicate Column Prevention: Fixed issue where renaming existing statuses in Kanban configuration could result in duplicate columns appearing in the board [#258] - Thanks to @mat2022a for the bug report Subtask Widget Issues# Split Pane Display: Resolved issue where subtask widgets would inappropriately appear on notes in split panes when focusing on different notes [#234] Table Cell Interference: Fixed subtask widgets appearing inside table cells when editing tables in project notes [#207] Technical Changes# Documentation# Fixed line break formatting issues in documentation files Code Organization# Improved task grouping architecture with new options interface Enhanced calendar event rendering system for better tag-based customization Refined subtask widget positioning logic for better editor integration"},{"title":"TaskNotes 3.16.0","url":"/obsidian/releases/3.16.0/","description":"Extra thanks to @Totobal5 for multiple code contributions including (tricky!) Pomodoro timer fixes and advanced calendar resizing fixes","product":"obsidian","text":"New Features# Task Management# Bulk Task Conversion: Added command to convert all checkbox tasks in a note to TaskNotes at once (#28) - Thanks to @TheSnakePolyglot for the feature request Instant Task Conversion Enhancement: Enable instant task conversion for any line type, not just existing tasks (#259, #262) - Thanks to @ghelton and @cathywu for the suggestions Default Project Setting: Added option to set a default project for new tasks in task creation settings (#250) - Thanks to @davidszerman for the request Advanced Tag and Project Parsing: Implement intelligent parsing of tags and projects during instant task conversion (#260) - Thanks to @mdbraber for reporting this bug Enhanced Filter Bar Integration: Added FilterBar integration to subtask widget for better task organization (#267) - Thanks to @mdbraber for the suggestion Calendar and Views# Custom Multi-Day Calendar View: Added configurable custom multi-day calendar view with support for 3-day, work week, and full week layouts (#282) - Thanks to @girisumit for the feature request Responsive Calendar UI: Hide calendar title in narrow containers for better responsive design (#285) - Thanks to @girisumit for the improvement suggestion Locale-Aware Date Formatting: Added locale-aware date formatting to advanced calendar view (#210) - Thanks to @emes81 for highlighting this usability issue Saved Views Enhancement: Added view options support to saved views with active view name display in filter condition builder (#245) - Thanks to @kmaustral and @digitaldoctors for the feedback Task Organization# Drag and Drop Status Reordering: Added drag and drop reordering for status configurations with hamburger menu icon (#291) - Thanks to @23426356587 for the suggestion Overdue Tasks Filter: Added setting to hide completed tasks from overdue status display (#300) - Thanks to @Lankly and @violetbp for reporting the issue Project Group Enhancements: Made project group labels clickable in Task List View with ctrl+hover preview support (#198) - Thanks to @jpmoo for the suggestion Pomodoro Timer# Background Timer Continuity: Pomodoro timer now continues running when app is minimized or loses focus (#136) - Thanks to @Poly_0000 for reporting and @Totobal5 for the fix System Notifications: Convert Pomodoro notices to system notifications for better visibility (#136) Manual Duration Adjustment: Fixed manually adjusted Pomodoro duration being ignored on start (#293) - Thanks to @Totobal5 for identifying and fixing Task Completion Sorting: Sort completed tasks to end of Pomodoro task selector for better organization Bug Fixes# UI and Interaction# Tooltip Standardization: Standardized tooltips to use Obsidian's native setTooltip function to eliminate duplicate tooltips (#257) - Thanks to @digitaldoctors for the bug report Open Note Button Stability: Stabilized Open note button hover behavior and made font size consistent with other modal buttons Date Context Menu Clarity: Added titles to date context menus for better user clarity (#253) - Thanks to @digitaldoctors for the suggestion Project Removal: Fixed project removal in edit modal not saving changes properly (#213) Advanced Calendar Resizing: Fixed Advanced Calendar view not resizing correctly in detached windows (#137) - Thanks to @macbikegeek for reporting and very much to @Totobal5 for the fix Calendar and Recurring Tasks# Timezone Bug Fixes: Resolved multiple timezone-related off-by-one bugs in recurring task completion and agenda view display - A big thanks to @jpmoo and @kmaustral for reporting and describing in detail this bug Custom Calendar Display: Fixed undefined days display in custom calendar view Calendar Recurrence: Resolved timezone-based off-by-one bugs in calendar recurrence calculations - Thanks to @jpmoo and @kmaustral for reporting this bug Task Management# Pomodoro Task Tracking: Handle task filename changes in pomodoro view to prevent tracking issues (#289) - Thanks to @cathywu for the report Plugin Conflict Protection: Made suggestion objects defensive against potential plugin conflicts (#304) - Thanks to @zeltak for reporting the plugin conflict Instant Conversion Improvements: Use cleaned title for NLP parsing in instant task conversion with fallback to default tasks folder (#128) - Thanks to @bepolymathe for reporting the folder issues Improvements# User Interface# Minimalist Design System: Implemented consistent borderless button design system across all components UI Polish: Applied minimalist styling with cleaned up borders and shadows throughout the interface Settings Enhancement: Enhanced settings explanatory sections with improved minimalist styling Advanced Calendar Title: Made advanced calendar title smaller for better proportions Search and Filtering# Enhanced Search: Improved search functionality to preserve existing filters when performing new searches Filter Preservation: Better handling of filter states across different search operations Development and Code Quality# Code Documentation: Improved code comments and documentation throughout the codebase Linting Cleanup: Resolved various linting errors and improved code consistency Test Infrastructure: Updated timezone-related tests to work reliably in CI environment GitHub Actions: Added timeouts and offline preferences to improve CI reliability Technical Improvements# Reduced excessive console logging from filter components Updated Jest coverage thresholds to realistic levels Improved error handling in various components Improved defensive programming practices throughout the codebase Contributors# Extra thanks to @Totobal5 for multiple code contributions including (tricky!) Pomodoro timer fixes and advanced calendar resizing fixes"},{"title":"TaskNotes 3.16.1","url":"/obsidian/releases/3.16.1/","description":"TaskNotes documentation.","product":"obsidian","text":"New Features# Task Management# Visual Filter State Indicators: Added visual state indicators for active saved views in FilterBar to provide better feedback when a saved view is currently active Bug Fixes# Link Generation and Consistency# Obsidian Link Format Compliance: Fixed \"Insert tasknote link\" and \"Convert task to TaskNote\" commands to use Obsidian's native generateMarkdownLink method, respecting user's link format preferences in Files & Links settings [#312] - Thanks to @nightroman for reporting the inconsistency and requesting proper format support Consistent Link Formatting: Both commands now generate links in the same format and are compatible with external tools when markdown links are preferred Timezone and Date Handling# Recurring Task Completion Fix: Resolved critical timezone bug where recurring task completion dates were stored incorrectly in non-UTC timezones [#314] - Thanks to @kmaustral for detailed reporting and testing across multiple views UTC Date Consistency: Updated all date utilities to use UTC methods consistently across calendar components, fixing off-by-one date issues in task completion tracking Calendar Date Normalization: Added createSafeUTCDate utility function and converted MiniCalendarView navigation to UTC methods for reliable date handling User Interface# Sort Arrow Visibility: Enhanced sort direction arrow visibility and positioning in filter condition builder with increased font size, bold weight, and accent color [#307] - Thanks to @kmaustral for noting the arrow was difficult to see in dark mode Duplicate Tooltip Prevention: Removed duplicate tooltips on recurring task indicators by using Obsidian's native setTooltip function instead of HTML title attributes Pointer Cursor Consistency: Added pointer cursor styling to all buttons in Pomodoro view for better usability [#308] - Thanks to @anomatomato for the contribution Error Handling and Stability# Daily Note Creation Protection: Added proper error handling for createDailyNote failures across TimeblockCreationModal, PomodoroService, and helper utilities, preventing \"Cannot read properties of undefined\" errors Security Compliance: Replaced unsafe innerHTML assignment with textContent in drag handle creation to resolve ESLint security violations Improvements# User Interface# Calendar Styling Enhancements: Improved advanced calendar view with better borders, header text readability, and removed custom scrollbar styling for system consistency Enhanced Visual Definition: Added border and border radius to calendar container, plus consistent borders on column headers and toolbar for cleaner appearance Development and Code Quality# Test Infrastructure: Added missing setTooltip mock to resolve 39 failing TaskCard tests Documentation Updates: Improved documentation formatting and appearance Technical Improvements# Enhanced date handling throughout the codebase with UTC method standardization Improved defensive programming practices for timezone-sensitive operations Better error messaging for daily note creation failures Code security improvements with ESLint compliance"},{"title":"TaskNotes 3.16.2","url":"/obsidian/releases/3.16.2/","description":"TaskNotes documentation.","product":"obsidian","text":"New Features# Task Link Integration# Markdown Link Support for Inline Task Widgets: Extended task link detection and rendering to support both wikilinks and markdown links. The plugin now properly renders [text](path) markdown links as interactive inline task widgets in both live preview and reading modes [#312] - Thanks to @nightroman for noting the missing link overlays on markdown links Improvements# Link Processing# Link Detection: Improved TaskLinkDetectionService to detect both [[wikilinks]] and [markdown](links) with proper URL decoding for paths containing spaces Link Rendering: Updated both TaskLinkOverlay (live preview) and ReadingModeTaskLinkProcessor (reading mode) to handle both link types consistently API Integration: Uses proper Obsidian API functions (parseLinktext() and getFirstLinkpathDest()) for reliable link resolution"},{"title":"TaskNotes 3.16.3","url":"/obsidian/releases/3.16.3/","description":"TaskNotes documentation.","product":"obsidian","text":"Bug Fixes# User Interface# Create Task Modal Accessibility: Fixed UI issues when creating tasks with natural language input disabled. The modal now opens in an expanded state with immediate access to all input fields, eliminating the need to click or tab before entering task details [#324] - Thanks to @nightroman for reporting this usability issue Timezone Handling# Recurring Task Calendar Display: Fixed timezone-related display bug where recurring tasks appeared on the wrong day for users in negative UTC timezones. Tuesday tasks no longer incorrectly appear on Monday in the calendar view Task Completion Calendar: Improved timezone consistency in the TaskEditModal completion calendar to ensure dates display correctly across all timezones Task Conversion# Context Detection in Instant Tasks: Fixed instant task conversion to properly detect and preserve contexts specified with \"@context\" syntax when converting inline tasks to TaskNotes [#320] - Thanks to @nslee123 for reporting this issue Time Preservation: Fixed instant task conversion to preserve time information when converting tasks with scheduled or due times. Time components are now correctly carried over during the conversion process Improvements# Code Quality# Test Coverage: Added comprehensive unit tests for InstantTaskConvertService context detection to ensure reliable context parsing in future releases"},{"title":"TaskNotes 3.16.4","url":"/obsidian/releases/3.16.4/","description":"This ensures users can always edit task titles regardless of the modal type or natural language input settings.","product":"obsidian","text":"Bug Fixes# User Interface# Task Modal Title Field: Fixed regression from version 3.16.3 where the title field was inadvertently removed from all task modals. The title field is now properly displayed with correct visibility logic: Edit modals: Title field always visible in the details section Create modals with natural language input enabled: Title field visible in details section (as the main input becomes the NLP textarea) Create modals with natural language input disabled: Title field only appears at the top of the modal This ensures users can always edit task titles regardless of the modal type or natural language input settings."},{"title":"TaskNotes 3.17.0","url":"/obsidian/releases/3.17.0/","description":"This release introduces improvements to recurring task handling with full DTSTART (start date/time) integration, addressing long-standing challenges in recurring task management...","product":"obsidian","text":"Major Features# Enhanced Recurring Tasks with DTSTART Support# This release introduces improvements to recurring task handling with full DTSTART (start date/time) integration, addressing long-standing challenges in recurring task management and filtering. Background and Motivation: The previous recurring task system created difficulties for users in filtering and managing task schedules. Users experienced unintuitive behavior where recurring tasks couldn't be treated consistently with regular tasks, making it challenging to see when the next occurrence would appear or to dynamically update task schedules upon completion. This implementation follows RFC 5545 standards to provide a more robust foundation for recurring task behavior. Key Improvements: DTSTART Integration: All recurring tasks now include proper start dates and times in their recurrence rules, ensuring consistent behavior across timezones and providing a clear anchor point for the recurring pattern Dynamic Date Updates: The task.scheduled field now always shows the next uncompleted occurrence, automatically updating when tasks are completed rather than showing static pattern dates Flexible Next Occurrence Scheduling: The next scheduled occurrence can now be placed anywhere - before the pattern start date, outside the recurring pattern, or at any custom time, giving users complete control over scheduling Visual Hierarchy: Pattern instances display with dashed borders while the next scheduled occurrence shows with solid borders, providing clear visual distinction between the recurring pattern and the active next task Independent Time Control: Pattern instances and next occurrences can have different times (e.g., daily pattern at 9 AM, next occurrence at 2:30 PM), allowing for exceptions without breaking the recurring pattern Dual Drag Behavior: Dragging pattern instances updates the recurring pattern timing globally, while dragging the next occurrence reschedules only that specific instance Automatic DTSTART Addition: The system automatically adds DTSTART when completing recurring tasks, editing recurrence rules, or converting tasks to recurring, ensuring backward compatibility while upgrading task definitions Manual Rescheduling Support: Clear flags indicate when tasks have been manually rescheduled, maintaining transparency about schedule modifications Expandable Project Subtasks# A new feature allows users to expand project task cards to view subtasks inline with proper visual hierarchy. Features: Chevron Controls: Click chevron icons on project task cards to expand/collapse subtask display Configurable: New \"Show expandable subtasks\" setting allows users to enable/disable the feature Responsive Pomodoro View# The Pomodoro view now adapts seamlessly to different container sizes with comprehensive responsive design. Thanks to @oliverlalan for requesting this improvement (#339). Enhanced Filename Templates# Significant expansion of available template variables for task creation, providing much greater flexibility in filename patterns. New Template Variables: Date/Time Variations: shortDate, monthName, dayName, week, quarter, time12, time24 Unix Timestamps: unix (seconds), unixMs (milliseconds) Title Case Variations: titleLower, titleUpper, titleSnake, titleKebab, titleCamel, titlePascal Short Forms: priorityShort, statusShort for single-letter representations Unique Identifiers: zettel (Zettelkasten ID), nano (high-precision unique ID) The settings UI now documents all 40+ available template variables for easy reference. Thanks to @fastrick for the original unix timestamp request. Bug Fixes# Critical Timezone Handling Fixes# This release resolves multiple timezone-related bugs that affected users worldwide, particularly those in non-UTC timezones. These fixes implement the \"UTC Anchor\" principle for consistent date handling. Major Timezone Bugs Fixed: Recurring Task Completion: Fixed critical issue where marking recurring tasks complete would affect the wrong day for users in certain timezones, addressing reports from multiple users including issues #327, #322, and #314 Calendar Date Misalignment: Resolved off-by-one day errors in calendar rendering and task indicators, addressing inconsistencies across different views (originally reported by @Crunchnuggetz in issue #129, with additional reports from @donjjones and @robmikulec) Weekly Task Display: Fixed issue where weekly recurring tasks set for specific days (e.g., Tuesdays) were showing completion dates on the wrong day (Monday) - reported by @jpmoo in issue #322 Task Completion Date Bug: Resolved bug where complete_instances was being set to the previous day, causing tasks to remain visible in Agenda view until manually corrected - reported in issue #314 Date Parsing Inconsistencies: Eliminated mixing of UTC and local date parsing that caused timezone-dependent behavior across the application Filter Date Handling: Fixed date filtering to work consistently across all timezones Agenda View \"Today\" Detection: Corrected timezone-sensitive today detection that affected agenda headers ICS Import Timezone Issues: Resolved timezone problems with both recurring and single events from ICS imports Technical Implementation: Introduced parseDateToUTC() function for consistent UTC anchoring of date-only strings Updated date comparison functions to use UTC anchors throughout Replaced timezone-sensitive date operations with consistent UTC-based alternatives Comprehensive audit and fix of all date handling patterns in the codebase Project Filtering Improvements# Resolved critical bugs in project filtering that prevented proper task display and project selection. Fixes: Wikilink Resolution: Fixed handling of relative vs absolute project wikilinks (e.g., [[../Projects/My Project]] vs [[My Project]]) - thanks to @xorander00 for the detailed bug report Filter Grouping Logic: Corrected AND/OR grouping in project filters to prevent showing too many tasks Missing Projects: Fixed issue where not all projects appeared in filter dropdown selection Cache Management: Improved cache invalidation and project name extraction with better validation Subtask Widget Improvements# Fixed several issues with the project subtasks widget affecting user experience and reliability. Widget Fixes: View State Persistence: Fixed issue where subtask widget views would reset when switching between notes or modifying subtasks (reported by @Poly-0000 in issue #329) Filter State Isolation: Prevented filter settings from bleeding between different notes' subtask widgets Configurable Positioning: Added setting to control widget placement at top or bottom of notes (requested by @michelebugio in issue #164) Event Listener Management: Improved cleanup to prevent memory leaks and event accumulation Event Bubbling: Fixed issue where clicking subtasks would trigger both subtask and parent task modals Styling Isolation: Prevented completion styles from affecting nested subtasks incorrectly ICS Calendar Integration# Timezone Processing: Fixed timezone handling bug in ICS calendar subscriptions where VTIMEZONE components weren't being registered before parsing events, causing incorrect display times for timezone-specific calendar events. Performance and Reliability# Cache Optimization: Restored FilterService cache TTL to 30 seconds after temporary reduction, balancing performance with data freshness. Type Safety: Added proper type assertions for ICAL.TimezoneService calls to resolve TypeScript compilation issues. Error Handling: Enhanced error handling and null safety checks throughout project filtering and service initialization. Technical Improvements# UTC Anchor Implementation# Comprehensive implementation of the UTC Anchor principle for robust timezone handling: All date-only strings now consistently parsed as UTC anchors Date comparison operations standardized using UTC methods Eliminated timezone-dependent date creation patterns Added comprehensive timezone test coverage Service Architecture# Expanded Projects Service: Enhanced state management and tracking for expandable project subtasks with proper cleanup and memory management. View State Manager: Improved view state persistence across different contexts and note switches. Documentation Updates# Updated recurring tasks documentation to reflect new behavior Added timezone handling guides for developers Enhanced calendar views documentation with drag behavior explanations Comprehensive template variable documentation Breaking Changes# Date Handling: While maintaining backward compatibility for user data, the internal date handling now consistently uses the UTC Anchor principle. Migration Notes# Existing recurring tasks will continue to work without modification. The system automatically adds DTSTART components when users interact with recurring tasks (completing, editing, or rescheduling)."},{"title":"TaskNotes 3.17.1","url":"/obsidian/releases/3.17.1/","description":"This patch release resolves three critical timezone-related bugs that affected users in specific timezones, particularly those west of UTC (such as users in the Americas). These...","product":"obsidian","text":"Bug Fixes# Critical Timezone Handling Fixes# This patch release resolves three critical timezone-related bugs that affected users in specific timezones, particularly those west of UTC (such as users in the Americas). These fixes ensure consistent calendar rendering and task interaction behavior across all timezones. Completions Calendar Rendering (#322)# Fixed three critical timezone bugs in the completions calendar that caused visual misalignment for users in timezones west of UTC: Day Number Display: Corrected day numbers in the calendar grid to display accurately regardless of user timezone by replacing timezone-sensitive formatting with UTC-anchored date extraction Month Comparison Logic: Fixed current month highlighting logic that was mixing local and UTC date values, causing incorrect month boundary detection Calendar Navigation: Updated previous/next month navigation to use consistent UTC methods, preventing timezone drift when navigating between months These fixes ensure the completions calendar visual representation aligns with the underlying UTC-anchored recurrence data for all users. Advanced Calendar Drag-and-Drop Operations (#344)# Resolved a critical bug where all-day tasks would shift back by one day after dragging and dropping them in the Advanced Calendar view. This issue particularly affected users in timezones ahead of UTC. Thanks to @trang-ngn for reporting this issue with clear reproduction steps. Root Cause: The drag-and-drop system was using formatDateForStorage() which applies UTC methods to Date objects provided by FullCalendar. For users in positive UTC offset timezones, this would cause the stored date to be one day earlier than the date shown in the UI. Fixed Operations: All-day and timed event drag-and-drop (handleEventDrop) External task drag-and-drop from outside the calendar (handleExternalDrop) Modal-based task scheduling (scheduleTask) Date selection task creation (handleDateSelect) Timeblock creation and event resizing operations Event context menu date handling The fix ensures that the date displayed in the calendar UI exactly matches the date that gets stored in the task data. Task Completion Status Checks (#322)# Fixed incorrect completion status checks in recurring tasks caused by timezone-sensitive date formatting in getEffectiveTaskStatus(). Root Cause: The function was using timezone-sensitive date-fns format() for completion date comparisons, causing completion status to be checked against the wrong date for users west of UTC (e.g., checking October 26 instead of October 27 for EDT users). Solution: Replaced timezone-sensitive formatting with formatDateForStorage() to ensure consistent UTC-anchored date strings that match the format used in complete_instances. This fix ensures recurring task completions are correctly identified regardless of user timezone, preventing tasks from incorrectly appearing as incomplete. Technical Implementation# All fixes implement the established \"UTC Anchor\" principle for consistent timezone handling: Consistent use of UTC-anchored date operations for date-only comparisons Replacement of timezone-sensitive date formatting with UTC-based alternatives Proper separation of display dates (which can be timezone-sensitive) from storage dates (which must be timezone-neutral)"},{"title":"TaskNotes 3.18.0","url":"/obsidian/releases/3.18.0/","description":"A complete reminder system has been added to TaskNotes, providing iCalendar VALARM-compliant reminder functionality.","product":"obsidian","text":"New Features# Task Reminders System# A complete reminder system has been added to TaskNotes, providing iCalendar VALARM-compliant reminder functionality. Core Features: Support for both relative reminders (e.g., \"15 minutes before due date\") and absolute reminders (specific date/time) Visual reminder indicators on task cards with clickable bell icons Integration with task creation and editing workflows User Interface: Reminder Modal: Modal for managing task reminders with form validation and real-time preview Reminder Context Menu: Quick access to common reminder options (5min, 15min, 1hr, 1day before due/scheduled dates) Reminder management accessible from task creation modal, edit modal, and task cards Default Reminders: Configure default reminders that automatically apply to new tasks Support for multiple default reminders per task type Applies to both manual task creation and instant conversion workflows Property-Based Task Identification# Tasks can now be identified using frontmatter properties instead of requiring tags. Configure property name and value for task identification (e.g., categories: [[Tasks]]) Full backward compatibility with existing tag-based workflows Addresses modern Obsidian property-based vault organization patterns Thanks to @mdbraber for the feature request (#340) Enhanced Saved Views# Clicking an active saved view now clears all filters, providing quick access to unfiltered task list Preserves sort and group settings while resetting filters Thanks to @oldjove for the suggestion (#351) Parent Note as Project Option# New setting to automatically use parent note as project during instant task conversion Useful for users who organize tasks within project-specific notes Merges with existing default projects to avoid duplicates Thanks to @FindingJohnny for the feature request (#348) Bug Fixes# ICS Calendar Integration# Fixed recurring event exceptions: Properly handle EXDATE properties and RECURRENCE-ID for modified instances Eliminated duplicate events: Resolved issue where deleted or rescheduled recurring events from external calendars still appeared Thanks to @robmikulec for reporting the recurring events issue (#342) Settings Persistence# Fixed settings reset during updates: Prevent user configuration loss when plugin updates introduce new default settings Apply deep merge strategy to preserve customizations in nested configuration objects Improvements# User Interface# Reminder modal uses consistent design patterns with task creation/edit modals Fixed task card icon overlap issues with proper spacing for multiple indicators Code Quality# Added unit test coverage for new reminder functionality Improved type safety with proper TypeScript interfaces for reminder data structures Improved error handling and user feedback across reminder operations Technical Details# Data Model Changes# Added optional reminders array field to TaskInfo interface Extended field mapping support for custom reminder property names Enhanced cache system to include reminder data in task extraction"},{"title":"TaskNotes 3.18.1","url":"/obsidian/releases/3.18.1/","description":"Fixed critical race conditions in cache synchronization that occurred when task operations completed before Obsidian's metadata cache had fully processed file changes. This...","product":"obsidian","text":"Bug Fixes# Cache Synchronization Race Conditions (#358)# Fixed critical race conditions in cache synchronization that occurred when task operations completed before Obsidian's metadata cache had fully processed file changes. This resulted in stale or missing task data across all calendar views and task operations. Thanks to @willgraham345 for reporting the calendar auto-refresh issue Code Quality Improvements# Event Listener Management# Simplified event listener cleanup in AdvancedCalendarView by removing manual listener tracking array. Technical Details# Cache Synchronization Strategy: The implementation follows a \"wait-then-update\" pattern where all cache modifications are preceded by verification that Obsidian's metadata cache contains the expected changes. This prevents race conditions while maintaining performance through minimal wait times."},{"title":"TaskNotes 3.18.2","url":"/obsidian/releases/3.18.2/","description":"Fixed timeblocks appearing one day earlier than expected by implementing the UTC Anchor pattern throughout the timeblocking feature. The previous implementation used problematic...","product":"obsidian","text":"Bug Fixes# Timeblock Date Shift Issue (#368)# Fixed timeblocks appearing one day earlier than expected by implementing the UTC Anchor pattern throughout the timeblocking feature. The previous implementation used problematic millisecond-based date iteration that caused timezone-dependent date shift bugs. Timeblocks now appear on the correct calendar day regardless of user timezone or DST transitions. Thanks to @zolotyh-dk for reporting this issue with detailed screenshots and system information. Performance Issues with Task Views# Eliminated typing lag that occurred when Task, Agenda, and Kanban views were open in large vaults. The plugin was triggering unnecessary view updates during text editing. New Features# Enhanced Filename Template Variables (#370)# Added new timestamp variables for filename templates to support ISO 8601 formats and Google Keep compatibility: {milliseconds}, {ms} - 3-digit milliseconds (000-999) {timezone}, {utcOffset} - UTC offset in ±HH:MM format {timezoneShort}, {utcOffsetShort} - UTC offset in ±HHMM format Thanks to @mnipritom for requesting these variables. Boolean Property Identification# Enhanced property-based task identification to handle boolean values correctly. Tasks can now be identified using boolean properties in frontmatter. A big thanks to @renatomen for contributing the boolean property identification implementation, documentation, and test coverage Boolean Status Field Support (#108)# Added automatic boolean conversion for status values to support Obsidian's checkbox property format. The status field now handles boolean true/false values: String \"true\" → boolean true (in frontmatter) String \"false\" → boolean false (in frontmatter) Boolean true → string \"true\" (when read back) Boolean false → string \"false\" (when read back) Other status values remain unchanged as strings Thanks to @arminta7 for reporting the checkbox property compatibility issue and @imed-ghomari for contributing to the discussion on status field handling. And thanks again to @renatomen--the boolean property identification fix inspired this change!"},{"title":"TaskNotes 3.19.0","url":"/obsidian/releases/3.19.0/","description":"TaskNotes now includes a HTTP REST API that enables external integrations and powers companion projects. The API provides full task management capabilities with intelligent natu...","product":"obsidian","text":"New Features# HTTP REST API with Natural Language Processing# TaskNotes now includes a HTTP REST API that enables external integrations and powers companion projects. The API provides full task management capabilities with intelligent natural language processing. Key API Features: Complete CRUD operations for tasks Time tracking endpoints Task statistics and filtering Bearer token authentication CORS support for browser extensions Desktop-only implementation with mobile-safe architecture Natural Language Processing Endpoints: /api/nlp/parse - Parse natural language into structured task data /api/nlp/create - Create tasks directly from natural language input Supports extraction of dates, times, priorities, tags, contexts, projects, and recurrence Intelligent parsing of expressions like \"Review PR #123 tomorrow high priority @work\" Companion Project Integration: The HTTP API enables two new companion projects: tasknotes-cli - Command-line interface for TaskNotes task management tasknotes-browser-extension - Browser extension for quick task creation Configuration: Enable via Settings → HTTP API tab (desktop only) Configurable port (default 8080) and optional authentication token Documentation at /docs/HTTP_API.md and /docs/nlp-api.md Enhanced Calendar Integration# Calendar Export and Context Menu System# Task Calendar Export: Add tasks to external calendars (Google, Outlook, Yahoo) Download ICS files Right-click context menu support for quick calendar actions Agenda View Calendar Improvements# ICS Integration in Agenda: Calendar event cards now display in Agenda view Toggle calendar subscriptions visibility via FilterBar Always-available \"Refresh calendars\" button Normalized scheduled date handling for all-day and timed events Thanks @scottaltham-payroc for the feature request! Bug Fixes# Task Styling Enhancement (#355)# Added CSS class task-card--has-projects to task cards that contain projects. Thanks @mdbraber for the suggestion Calendar Event Scheduling# Fixed scheduled date normalization when creating tasks from ICS events: All-day events: Use YYYY-MM-DD format Timed events: Use YYYY-MM-DDTHH:mm format Consistent behavior across all calendar interfaces File Copy Script Improvements# Enhanced copy-files script with better error handling: Improved default path handling Destination directory creation Better ENOENT error handling API Documentation# New Documentation Files# HTTP_API.md - Complete API reference with examples nlp-api.md - Natural language processing capabilities and usage Technical Enhancements# Core Infrastructure# API Service Architecture: Mobile-compatible implementation using Node.js http module Platform detection prevents mobile loading Express.js alternative for lightweight operation Full error handling and validation Calendar Service Integration: Extracted reusable CalendarExportService Unified TaskContextMenu component Enhanced event listener management Development Improvements# Code Organization: Modular component extraction for better reusability Consistent API response formats Comprehensive test coverage for new features TypeScript improvements for icon handling Migration Notes# HTTP API Setup# For users wanting to enable the new HTTP API: Navigate to Settings → HTTP API tab (desktop only) Configure desired port (default 8080) Optionally set authentication token for security Restart Obsidian to start the API server Test with: curl http://localhost:8080/api/health"},{"title":"TaskNotes 3.19.1","url":"/obsidian/releases/3.19.1/","description":"Added webhook system enabling integrations with external services and automation workflows.","product":"obsidian","text":"New Features# Webhook Support# Added webhook system enabling integrations with external services and automation workflows. Webhook Management: CRUD operations for webhook configuration HTTP API endpoints for webhook management (POST /api/webhooks, GET /api/webhooks, DELETE /api/webhooks/{id}) Delivery history tracking (GET /api/webhooks/deliveries) Settings UI integration with event subscription controls Event Types: Task events: created, updated, deleted, completed, archived, unarchived Time tracking: started, stopped Pomodoro: started, completed, interrupted Recurring tasks: instance completed Reminders: triggered Security and Reliability: HMAC-SHA256 signature verification for payload authentication Automatic retries with exponential backoff (3 attempts) 10-second delivery timeout with failure monitoring Auto-disable webhooks after repeated failures Non-blocking async delivery maintains TaskNotes responsiveness Documentation and testing utilities included in docs/webhooks.md and test-webhook.js. Bug Fixes# Boolean Property Identification Regression (#367)# Fixed regression from version 3.18.2 where boolean checkbox properties stopped working for property-based task identification. During code refactoring, the comparePropertyValues function was accidentally removed, breaking boolean-to-string coercion needed for Obsidian checkbox properties. The fix restores this function with proper type-aware comparison logic, allowing boolean true/false frontmatter values to correctly match \"true\"/\"false\" setting values. Thanks to @renatomen for reporting this regression"},{"title":"TaskNotes 3.20.0","url":"/obsidian/releases/3.20.0/","description":"Folder-Based Task Filtering - Added task filtering by folder location with dropdown selection of vault folder paths, special handling for root-level tasks, and support for conta...","product":"obsidian","text":"New Features# Task Organization and Filtering# Folder-Based Task Filtering - Added task filtering by folder location with dropdown selection of vault folder paths, special handling for root-level tasks, and support for contains/empty operators. Addresses issue #369 reported by kmaustral Dynamic Task Folder Organization - Added template variable support for default task folder setting with task variables ({{context}}, {{project}}, {{priority}}, {{status}}, {{title}}) and date variables ({{year}}, {{month}}, {{day}}, {{date}}). Supports automatic folder creation and title sanitization. Addresses feature request #376 by Mara-Li Archive Task Organization - Added optional bidirectional task movement between archive folder and default tasks folder. Disabled by default with settings in Task defaults → Task organization (moveArchivedTasks, archiveFolder). Addresses feature request #402 by anareaty Enhanced UI and Controls# Enhanced Filter Bar - Improved filter bar with instant badge updates, right-click clear functionality, \"Clear All Filters\" button, and better UI synchronization across main and subtask views. Contributed by renatomen Collapsible Groups - Added collapsible groups with persisted state, chevron indicators, and keyboard navigation. Works with all grouping options while preserving wikilink functionality. Extended to subtask widget with consistent behavior. Contributed by renatomen Expand/Collapse All Controls - Added \"Expand All\" and \"Collapse All\" buttons to task list toolbar that appear when grouping is active. Contributed by renatomen Configurable UI Elements - Added settings for subtask chevron position (right/left) and saved views button positioning in task view toolbar. Contributed by renatomen Advanced API Architecture and Webhook System# Refactored HTTP API from monolithic design to controller/service pattern, reducing HTTPAPIService from 1,061 to 231 lines (78% reduction). Added dedicated controllers for tasks, time tracking, Pomodoro, system, and webhooks with 100% backward compatibility. Webhook System - Added complete webhook infrastructure with signature verification, automatic retries with exponential backoff, 10-second delivery timeout, and auto-disable after repeated failures. Supports all task lifecycle events (created, updated, deleted, completed, archived, unarchived), time tracking events, Pomodoro sessions, recurring task instances, and reminders. Webhook Testing and Development - Included standalone webhook testing server (test-webhook.js) with real-time payload inspection, signature verification testing, and comprehensive event logging for development and debugging. Improvements# UI and Visual Enhancements# TaskNotes Icons - Added TaskNotes icons throughout interface and edit task modal headers with new SVG assets. Task Card Polish - Improved status and priority dot alignment and reordered context menu (\"Copy task title\" moved to top). Addresses alignment issue #410 reported by kmaustral Button Styling - Fixed agenda view and filter popup button backgrounds with improved styling consistency. Technical Improvements# Settings Architecture - Decomposed monolithic settings.ts into focused modules: defaults, settings management, type definitions, and utilities for better maintainability. Documentation - Added extensive webhook documentation in docs/examples/webhook-transforms/ with ready-to-use transform examples for Discord (rich embeds with colors), Slack (compatible attachments), Microsoft Teams (MessageCard format), and generic JSON templates. Expanded API documentation with complete endpoint reference, examples, error handling, authentication, and OpenAPI specification. Webhook Integration Services - Enhanced core services (TaskService, PomodoroService) with webhook notifications integrated into task lifecycle events, ensuring all user actions trigger appropriate webhook deliveries for external automation and monitoring. Bug Fixes# Mobile Modal Close Button - Fixed close button (X) touch event handling in task edit modals on mobile devices, particularly Android. Addresses issue #404 reported by anareaty Test Suite Stabilization - Resolved test failures and linting errors HTTP API Field Consistency - Updated API examples to use correct 'details' field instead of deprecated 'notes' field. Addresses issue #393 reported by @nightroman Missing Webhook Trigger - Added webhook trigger for recurring task completion events. Documentation Updates# Task defaults documentation with template variables Miscellaneous settings documentation Webhook transform documentation and examples Demo GIFs for new features Thanks @renatomen! Contributors# Special thanks to the following contributors: @Mara-Li - Feature request for template variables in task folders @kmaustral - Feature requests for folder filtering and UI alignment improvements @anareaty - Bug report for mobile modal close button issue @nightroman - Reported mislead API documentation A really big thanks to @renatomen whose very polished contributions form the bulk of this update!"},{"title":"TaskNotes 3.20.1","url":"/obsidian/releases/3.20.1/","description":"Saved View Headings with Completion Counts - Added visible filter headings across all views (Task List, Subtask Widget, and Agenda) that display the current saved view name and...","product":"obsidian","text":"New Features# Enhanced View Organization and Visual Feedback# Saved View Headings with Completion Counts - Added visible filter headings across all views (Task List, Subtask Widget, and Agenda) that display the current saved view name and completion statistics in \"completed / total\" format. Shows \"All\" when no saved view is active. Headings update immediately on filter changes and persist correctly when switching tabs or reloading. Contributed by @renatomen Consistent Group Count Badges - Standardized completion count display across all group headers in Task List, Subtask Widget, and Agenda views using unified \"completed / total\" format. Removed redundant bracketed counts for cleaner presentation. Contributed by @renatomen Collapsible Agenda Date Groups - Added collapsible date headers to Agenda view with persistent state management. Date sections can be collapsed individually or controlled via \"Expand All\" / \"Collapse All\" buttons that are always visible in the FilterBar. Collapsed state is preserved between sessions using ViewStateManager. Contributed by @renatomen Improved User Interface# Reorganized Task Context Menu - Enhanced context menu organization by replacing individual buttons with logical submenus for status, priority, dates, recurrence, and reminders. Applied user-configured colors to main menu icons while maintaining all existing functionality. Bug Fixes# Calendar Integration Fixes# Outlook Calendar 500 Errors - Fixed Microsoft Outlook ICS endpoint failures by updating User-Agent header from 'TaskNotes-Plugin/1.0' to browser-compatible string and adding Accept-Language header. Improved error handling with specific guidance for Outlook 500 errors. Fixes issue #458 reported by @girisumit and @heinzochsner Recurring Tasks Date Display - Fixed timezone-dependent bug where recurring tasks appeared one day ahead or behind their actual due date in Agenda View. Replaced manual UTC date construction with parseDateToUTC() following UTC Anchor principle from development guidelines. Added regression test for consistent date handling. Fixes issue #439 reported by @brianarn and @jpmoo Task Management Fixes# Project Suggestions Crash Prevention - Fixed crash in Task Creation modal when typing \"+\" to add projects inline, caused by non-string title values in frontmatter. Added title normalization (arrays join with \", \", numbers/booleans stringify, objects become empty strings) and defensive guards in suggestion filtering. Particularly important for large vaults with heterogeneous frontmatter. Contributed by @renatomen Documentation Updates# Added screenshots demonstrating saved view headings and completion counts for Task List and Subtask Widget Created demo GIF showing Agenda view collapsible groups with Expand/Collapse All functionality Updated view documentation with new visual features Enhanced inline task documentation for Subtask Widget improvements Contributed by @renatomen Contributors# Special recognition goes to @renatomen for the substantial contributions that form the core of this release, including the saved view headings system, consistent count badges, and collapsible Agenda functionality. Thanks to the following community members for their bug reports and feedback: @girisumit and @heinzochsner - Reported Outlook calendar integration issues @brianarn and @jpmoo - Identified recurring tasks date display bug with detailed reproduction steps"},{"title":"TaskNotes 3.21.0","url":"/obsidian/releases/3.21.0/","description":"Custom User Fields Mapping - Added ability to define custom frontmatter properties for task filtering, grouping, and sorting. Users can configure field mappings in Settings → Ad...","product":"obsidian","text":"New Features# Custom User Fields System# Custom User Fields Mapping - Added ability to define custom frontmatter properties for task filtering, grouping, and sorting. Users can configure field mappings in Settings → Advanced → User Fields with support for text, number, date, boolean, and list field types. List fields preserve wikilinks and quoted tokens, while numeric fields intelligently parse mixed text-number values like \"2-Medium\" as numeric 2. Contributed by @renatomen Group and Sort by Custom User Fields - Extended grouping and sorting functionality to work with user-defined custom fields. Includes type-aware comparators for each field type and proper group header ordering when grouping and sorting by the same field. Contributed by @renatomen User Fields in Task Modals - Added custom user field support to task creation and edit modals with autocomplete suggestions from existing field values. Fields are stored as frontmatter properties and include change detection for edit scenarios. Contributed by @callumalpass Enhanced Task Interaction# Configurable Click Behavior - Added option to configure single-click and double-click behavior for task cards and inline task widgets. Users can choose between opening the edit modal or the source note file for each click type. Includes shared click handler utility with 250ms detection delay. Contributed by @fastrick Calendar Integration Enhancements# Calendar Event Filename Templates - Added separate filename template configuration for notes created from calendar events. Supports ICS-specific template variables including {icsEventTitle}, {icsEventLocation}, {icsEventDescription}, and {icsEventTitleWithDate}. The {title} variable now uses clean event titles without date suffixes. Fixes issue #362 reported by @bepolymathe Chronological ICS Event Sorting - Fixed ICS calendar events to display in chronological order by start time within each day in the agenda view. Applied to both grouped and flat agenda view modes. Fixes issue #472 reported by @Crunchnuggetz Bug Fixes# API Endpoint Improvements# Custom Status Configuration Support - Fixed API endpoints (/api/nlp/parse and /api/nlp/create) not respecting custom status configurations. API now uses proper default status logic matching the UI instead of hardcoded 'todo' values, with proper handling of boolean status values. Fixes issue #487 reported by @23maverick23 Task Creation Defaults - Fixed REST API endpoint (POST /api/tasks) missing default properties like scheduled dates, tags, and reminders. API-created tasks now receive the same defaults as UI-created tasks. Fixes issue reported by @nightroman Project Management Fixes# Project Consolidation and Display - Fixed project grouping to consolidate different formats pointing to the same file (e.g., [[project]] and [[project|alias]] now group together). Improved display formatting with clickable headers showing absolute paths without .md extensions and proper wikilink alias parsing. Task cards preserve original formats while grouping logic ignores display aliases. Fixes issues #448 reported by @minchinweb and #469 reported by @anareaty User Experience Improvements# Tag Input Sanitization - Added automatic sanitization to remove # prefixes from tag input, preventing duplicate tags like #tag1 and ##tag1. Applied to task creation, editing, and real-time input handling. Fixes issue #331 reported by @AndreMonthy Contributors# Special recognition goes to @renatomen for the extensive custom user fields system that forms the core of this release, including field mapping, filtering, grouping, and sorting capabilities. Thanks to @fastrick for implementing the configurable click behavior feature. Thanks to the following community members for their bug reports and feature requests: @23maverick23 - Reported API custom status configuration issues with detailed technical analysis @Crunchnuggetz - Identified ICS calendar event sorting problem in agenda view @minchinweb - Reported project consolidation issues with wikilink variations @anareaty - Identified project display formatting problems in kanban view @bepolymathe - Requested calendar event filename template functionality @AndreMonthy - Reported tag input sanitization issues with clear examples @nightroman - Reported API issues where defaults were not being applied"},{"title":"TaskNotes 3.22.0","url":"/obsidian/releases/3.22.0/","description":"Added modular properties system allowing users to control visibility of task properties (due date, scheduled date, priority, projects, contexts, tags, custom fields, and total t...","product":"obsidian","text":"Major Features# Modular Properties System# Added modular properties system allowing users to control visibility of task properties (due date, scheduled date, priority, projects, contexts, tags, custom fields, and total tracked time) both globally and per saved view. Properties can be configured through a new Properties dropdown in the filter bar, with settings automatically saved per view. Includes performance optimizations to render properties only when visible. Thanks to @renatomen for the initial implementation of this feature Task cards now dynamically render properties based on visibility settings with improved error handling and type safety. System supports both core properties and user-defined custom fields with proper fallback to default configurations for new users. Added total tracked time as a configurable property in the modular system, calculated from time entries and displayed consistently across all views when enabled. Bases-style Filter Bar Redesign# Complete filter bar redesign matching Obsidian's bases plugin styling with improved layout, spacing, and button appearance. Added text labels and chevron icons to all filter buttons (Sort, Filters, Properties, New) for better discoverability. Replaced dropdown menus with native Obsidian context menus featuring section headers and improved reliability. Sort/Group functionality now uses unified context menu system with better organization. Implemented intelligent filter popup positioning using boundary detection to prevent popups from hiding under adjacent panes. Increased default popup width from 300px to 500px for better usability. Moved expand/collapse controls from separate containers directly into filter headings across all views (TaskListView, AgendaView, subtask widget) for cleaner interface and consistent user experience. Added dedicated \"+ New\" task creation button to filter bar with neutral styling and proper view context awareness. Statistics view# Implement a new view to track statistics about projects and time tracking. UX# Task Interaction Improvements# Changed \"This Week\" grouping label to \"Next seven days\" for clearer, more specific language about the 7-day time period while maintaining identical underlying functionality. Fixes issue #516 reported by @anareaty External Contributions# Type-aware input fields in task modals now provide appropriate UI components based on field type (text/list with autosuggest, date with picker icon, boolean with toggle). Project autosuggest during task creation now supports multi-word project names without interrupting suggestions on spaces. Contributed by @renatomen Fixed subtask right-click context menus that were incorrectly showing parent task options instead of subtask-specific options. Enhanced inline task overlay cursor behavior with configurable timing settings (0-500ms) for predictable overlay hiding when cursor approaches link boundaries. Contributed by @renatomen Fixed project names containing commas (e.g., [[Money, Org & Adm]]) being incorrectly split, breaking selection and display across task modals, settings, and instant conversion. Now uses proper wikilink parsing to preserve comma-containing project names as single entities. Contributed by @renatomen Fixed date parsing errors caused by hardcoded field mapping not respecting user's custom field configurations. Plugin now properly uses field mapper for note date extraction with fallback to hardcoded fields for backward compatibility. Contributed by @renatomen Fixed User Fields column order in settings to match Field mapping configuration for consistency. Contributed by @renatomen Bug Fixes# Timezone and Date Handling# Fixed timezone-dependent \"Today\" identification issues across multiple views including MiniCalendarView tooltips, PomodoroService session categorization, PomodoroStatsView statistics, and StatsView date calculations. All date-sensitive components now use UTC-anchored dates for timezone-independent behavior. Fixes issue #452 reported by @MinchinWeb User Interface Fixes# Redesigned group counters with clean appearance (removed background, border, padding), positioned to far right of headers using muted text color for subtle display while maintaining left-aligned headings. Improved contrast for INTERRUPTED status badge in pomodoro statistics for better readability. Fixes issue #529 reported by @motusira Removed title length limits that were causing text truncation, allowing full title display. Fixes issue #378 reported by @nsstrickland Added all-day slot toggle to calendar view for better event organization. Fixes issue #242 requested by @Crunchnuggetz Added calendar locale configuration for international calendar support with proper localization. Contributed by @pixeler Fixed task states not refreshing when date changes at midnight, ensuring accurate daily task status updates. Fixes issue #527 reported by @jordandrako Fixed inline task overlay title wrapping using white-space: break-spaces for proper text display. Fixes issue #517 reported by @cathywu New Capabilities# Added weekday display and increment options to date picker with integration into task context menus for improved date selection experience. Fixes issue #238 requested by @girisumit Added tags to available sorting and grouping options for more flexible task organization. Fixes issue #169 requested by @bce283c Added create inline task command for quick task creation within notes with NLP project support for automatic project assignment based on context. Fixes issue #299 requested by @0dfa1bc Added filename template variables to folder templates including support for additional customization options. Fixes issue #473 requested by @oliverlalan Implemented status auto-suggestion with NLP integration for intelligent status recommendations during task creation and editing. Infrastructure Improvements# Development and Testing# Updated multiple npm dependencies including ical.js (1.5.0 → 2.2.1) and Jest (29.7.0 → 30.1.1) with compatibility fixes. Resolved all npm security vulnerabilities and updated ICS subscription service for ical.js v2.x compatibility. Fixed all test suite failures and infrastructure issues including Jest 30 compatibility, RRule mocking, TypeScript configuration, and CI environment setup. Removed coverage thresholds that were causing CI failures while maintaining test quality. Improved code quality throughout modular properties system with proper TypeScript compliance, error handling, performance optimizations, and memory cleanup functions. Replaced 'any' types with proper type guards and added comprehensive interface definitions. Contributors# Special recognition goes to @renatomen for multiple substantial contributions including type-aware custom field inputs, enhanced task interaction fixes, project name handling improvements, date parsing fixes, and settings alignment. Thanks to the following community members for their bug reports and feature requests: @anareaty - Reported grouping label confusion with clear examples @MinchinWeb - Identified timezone handling inconsistencies across multiple views @motusira - Reported contrast issues with INTERRUPTED status badge @nsstrickland - Identified title truncation problems @Crunchnuggetz - Requested all-day slot toggle for calendar views @jordandrako - Reported task state refresh issues at midnight @cathywu - Identified text wrapping problems in overlays @girisumit - Requested enhanced date picker functionality @oliverlalan - Requested template variable enhancements"},{"title":"TaskNotes 3.22.1","url":"/obsidian/releases/3.22.1/","description":"Thanks to @jhedlund for implementing the configurable recurring task due date feature.","product":"obsidian","text":"New Features# Configurable Recurring Task Due Date Behavior# Added optional due date advancement for recurring tasks. When enabled, maintains the time separation between scheduled and due dates when tasks are completed. The new \"Maintain due date offset in recurring tasks\" setting in Misc preferences controls this behavior and defaults to disabled to preserve existing behavior. Contributed by @jhedlund, fixes issue #470 Bug Fixes# Calendar and Task Display# Fixed calendar view issues where tasks were not displaying correctly due to empty status values causing infinite loops and TypeErrors. Resolved timeEntries.filter is not a function errors when loading calendar events and prevented Obsidian freezing during task creation with empty status text. Fixes issue #520 reported by @cathywu Saved Views and Property Management# Fixed property visibility settings not being preserved when saving filter views. View configurations now properly store and restore property display preferences. Fixes issue #545 reported by @anareaty Fixed saved view selection to prefer newly created views over older matching views, ensuring the correct view is activated after saving. Added proper null safety checks for FilterBar interactions to prevent errors during view save operations. User Interface Improvements# Added responsive behavior to filter bar buttons that automatically hide button text when pane width falls below 500px to prevent overflow in narrow sidebars. Uses container queries with media query fallback for broader browser support. Fixes issue #549 reported by @TonyAtlas Development Improvements# Reduced excessive console logging in TaskListView by removing 37+ debug statements while preserving essential error logging for troubleshooting. Contributors# Thanks to @jhedlund for implementing the configurable recurring task due date feature. Thanks to the following community members for their bug reports: @cathywu - Reported calendar view task display issues with detailed technical information @anareaty - Identified property visibility persistence problems in saved views @TonyAtlas - Reported filter bar overflow issues in narrow sidebars with helpful screenshots"},{"title":"TaskNotes 3.23.0","url":"/obsidian/releases/3.23.0/","description":"We extend special thanks to @renatomen for his exceptional contributions to this release:","product":"obsidian","text":"New Features# ICS Export and Calendar Integration# Added full ICS export functionality with proper RFC 5545 compliance for improved calendar application compatibility Implemented automatic ICS export with configurable interval updates (5-1440 minutes) for calendar subscription workflows Added manual \"Export all tasks as ICS file\" command for bulk export operations Thanks to @mdbraber for requesting this feature (#422) Status-Based Auto-Archive# Introduced configurable auto-archive system with per-status timeout settings (1-1440 minutes) Added persistent queue that survives plugin restarts for reliable task archiving Implemented settings UI for fine-grained control over auto-archive behavior Thanks to @TonyAtlas for requesting this feature (#547) and to @renatomen for design suggestions Multi-Language Natural Language Processing# Added NLP support for 12 languages: English, Spanish, French, German, Russian, Chinese, Japanese, Italian, Dutch, Portuguese, Swedish, Ukrainian Implemented locale-specific date parsing using chrono-node language support Enhanced pattern matching with proper handling for Latin, Cyrillic, Chinese, and Japanese scripts Thanks to @pschoenbach for requesting German language support (#563) Enhanced Project Autosuggest# Implemented configurable multi-row project cards with customizable display fields Added selective search functionality across chosen fields with simple flag system Introduced fuzzy search option for broader, multi-word matching capabilities Enhanced project selection with clear metadata display (title, aliases, path) Thanks to @renatomen for implementing this feature (#555) Bases Plugin Integration# Added experimental integration with the Bases plugin for enhanced task management workflows Implemented direct formula computation and custom property support Added clickable tags and contexts with accessibility support Created simplified kanban view integration with proper lifecycle management Thanks to @renatomen for his incredible work developing the proof-of-concept for this feature Settings UI Modernization# Complete redesign of settings interface with card-based design system Added collapsible functionality and live API documentation Enhanced calendar subscription interface with local file support Bug Fixes# Task Creation and File Handling# Fixed startup crash when templates contain empty reminders property (reported by @glpayson, #583) Implemented automatic sanitization of forbidden characters in task titles instead of blocking creation (reported by @glpayson, #590) Added support for platform-specific filename characters (hash, square brackets) Resolved inconsistent behavior between instant convert and manual task creation Project and Link Functionality# Added clickable project links in task edit modal for better navigation (requested by @anareaty, #432) Fixed completion date timezone handling to ensure consistent local time recording Corrected frontmatter property naming in Bases kanban drag-and-drop operations Property Display and Performance# Fixed custom property duplication when configured in both settings and filter bar Resolved unwanted total tracked time display showing zero values Standardized custom property identifiers with consistent prefix format Plugin Integration and Stability# Resolved Bases plugin integration issues and view switching problems Fixed kanban view loading with proper static imports and interface consistency Improved error handling and cleanup patterns for better stability Fixed API endpoints to respect custom status configurations (reported by @23maverick23, #487) Acknowledgments# Special Recognition# We extend special thanks to @renatomen for his exceptional contributions to this release: Created the enhanced project autosuggest system with configurable cards and selective search functionality (PR #555) Developed a proof-of-concept integration with the Bases plugin that demonstrated full compatibility and provided the technical foundation for our experimental Bases integration His innovative work on the Bases POC revealed that everything that I was hoping might be possible in a future integration with Bases was actually possible! Community Contributors# We're grateful to the community members whose issues were resolved in this release: @glpayson for providing detailed bug reports with reproduction steps that led to fixes for the startup crash with empty reminders (#583) and character handling improvements (#590) @mdbraber for requesting ICS export functionality that became a major feature in this release (#422) @TonyAtlas for the auto-archive feature request that resulted in the new status-based auto-archive system (#547) @anareaty for requesting clickable project links (#432) and reporting the \"This Week\" grouping label issue (#516) @pschoenbach for requesting multi-language NLP support, specifically German language support (#563) @23maverick23 for reporting API status configuration issues that improved custom status handling (#487) @Burrish for the documentation correction (#597) Full Changelog: 3.22.1...3.23.0"},{"title":"TaskNotes 3.23.1","url":"/obsidian/releases/3.23.1/","description":"Full Changelog: 3.23.0...3.23.1","product":"obsidian","text":"Bug Fixes# Bases Plugin Integration# Fixed Bases views not recognizing custom field mappings when using non-default property names. Status dots, priority colors, and dates now display correctly in Bases views when using custom field names, including Cyrillic and other localized property names. Thanks to @anareaty for reporting this issue (#607) Full Changelog: 3.23.0...3.23.1"},{"title":"TaskNotes v3.23.2 Release Notes","url":"/obsidian/releases/3.23.2/","description":"This release focusses on performance improvements. These improvements should be especially noticeable in vaults with a large number of tasks.","product":"obsidian","text":"This release focusses on performance improvements. These improvements should be especially noticeable in vaults with a large number of tasks. New Features# Added agenda/list view to Advanced Calendar New {{contexts}} template variable for joining multiple context values New {{projects}} template variable for joining multiple project values Thanks to @Mara-Li for these additions Time Format Consistency# Plugin-wide 12hr/24hr time format preference support Consistent time display across all calendar views and components Thanks to @anareaty and @Astrusia for this suggestion #431 Performance Architecture# Centralized ViewPerformanceService for all TaskNotes views Global task version cache with change detection Debounced updates with configurable batching View-specific update handlers with selective refresh logic Memory management and automatic cache cleanup Bug Fixes# Fixed cursor positioning issues when creating subtask widgets Thanks to @jhedlund for this fix! Contributors# Special thanks to contributors: @jhedlund for fixing cursor positioning with subtasks @Mara-Li for implementing context/project template variables and bracket fixes @anareaty for reporting time format inconsistencies"},{"title":"TaskNotes v3.23.3 Release Notes","url":"/obsidian/releases/3.23.3/","description":"This release addresses critical bugs with project and subtask functionality, ensuring proper field mapping support and expanding project filtering capabilities.","product":"obsidian","text":"This release addresses critical bugs with project and subtask functionality, ensuring proper field mapping support and expanding project filtering capabilities. New Features# Project Property Filter Support# Added property-based filtering for project picker dropdown Configure projects to appear in picker based on frontmatter properties (e.g., type: project) Complements existing folder and tag filtering options Thanks to @aubreyz for requesting this feature enhancement (#660) Bug Fixes# Project/Subtask Field Mapping# Fixed project and subtask functionality not working when users customize project field names ProjectSubtasksService and MinimalNativeCache now properly respect user field mapping configuration Resolves issue where hardcoded 'projects' field lookup ignored custom field mappings Thanks to @JD2026 (#674), @anareaty, (#674) and @Volker-brdb (#672) and for reporting these subtask display issues Test Infrastructure# Added missing test mocks for isTaskUsedAsProjectSync and formatDateForStorage functions Ensures test suite stability for project-related functionality"},{"title":"TaskNotes 3.23.4","url":"/obsidian/releases/3.23.4/","description":"Special thanks to contributors:","product":"obsidian","text":"Bug Fixes# Task Scheduling & Natural Language Processing# Fixed Russian weekday scheduling conflict where single weekdays (e.g., \"воскресенье\") were incorrectly interpreted as recurring tasks instead of single-day scheduling (#665, thanks to @anareaty for the report) Fixed issue where natural language processing failed to save parsed time estimates in task creation modal (#682, thanks to @RumiaKitinari for the detailed report) Fixed scheduled task grouping UTC anchor regression that caused today's tasks to appear under \"Past Scheduled\" instead of \"Today\" (#384, thanks to @jcromwell for the report) Settings & Configuration# Fixed plugin failure when excluded folders setting contains trailing commas - the parsing logic now properly filters empty strings (#664, thanks to @Yoav6 for identifying this issue) Calendar & Time Management# Fixed calendar not refreshing when task duration or time tracking changes (#382, thanks to @mdbraber) Fixed calendar not refreshing after task archive or move operations Fixed timeblock editing using stored date instead of current date for past day modifications (#647, thanks to @RumiaKitinari) Fixed Pomodoro timer not preserving task context when auto-starting sessions (#641, thanks to @RumiaKitinari) Fixed all-day tasks not rendering properly across multiple days in calendar view (thanks to Danny Talks Tech for reporting this in his video review) User Interface# Fixed mini calendar header overflow issue in sidebar view (#459, with CSS improvements suggested by @jsonshanks, thanks to @girisumit for the report) New Features & Enhancements# Visual Improvements# Added file-text icon to note cards in agenda view for better visual distinction from headers and consistency with task and calendar event icons (#662, thanks to @ras0q for the suggestion) Improved mini calendar styling, interactions, and legend display Enhanced task dot visualization to reflect accurate matching dates Settings Organization# Moved timeblocking settings to Features tab with improved usage instructions for better discoverability Documentation# Updated documentation to fix auto-archiving settings reference (#673, thanks to @antonio for pointing out the inconsistency) Contributors# Special thanks to contributors: @anareaty for reporting the Russian weekday scheduling conflict @RumiaKitinari for detailed reports on natural language processing, timeblock editing, and Pomodoro timer issues @jcromwell for reporting the scheduled task grouping UTC regression @Yoav6 for identifying the excluded folders trailing comma issue @mdbraber for reporting calendar refresh issues with time tracking changes @girisumit for reporting the mini calendar header overflow issue @jsonshanks for providing CSS improvement suggestions for the mini calendar @ras0q for suggesting the file-text icon addition to agenda view @antonio for pointing out the auto-archiving documentation inconsistency Danny Talks Tech for reporting the all-day task rendering issue in his video review This release focuses primarily on bug fixes and stability improvements, particularly around calendar functionality, natural language processing, and user interface polish."},{"title":"TaskNotes 3.24.0","url":"/obsidian/releases/3.24.0/","description":"Special thanks to all this release's contributors:","product":"obsidian","text":"New Features# Agenda View Overdue Section# Added separate \"Overdue\" section in Agenda view instead of mixing overdue tasks with today's tasks (#557, thanks to @backyardbiomech for the detailed report) Collapsible section with task completion statistics and proper internationalization support Includes overdue recurring tasks based on their scheduled dates Task Dependencies and Blocking Relationships# Implemented blocking/blocked task dependencies with persistent relationships (#701, thanks to @prayidae for the detailed feature request) Tasks can be marked as blocking other tasks or blocked by other tasks Dependency relationships persist in frontmatter as structural links Dynamic blocked state computed based on blocking task completion status Task Card Widget in Notes# Added configurable task card widget displaying at the top of task notes (#576, thanks to @jhedlund for the request) Provides immediate access to task actions and context menus without requiring command palette Uses CodeMirror widget system for integration Appears above project subtasks widget when both enabled Can be disabled via settings Hierarchical Subgrouping# Implemented hierarchical subgrouping functionality for TaskListView and AgendaView (thanks to @renatomen for this major feature contribution) Allows two-level task organization (e.g., Group by Status, Subgroup by Priority) Cross-view support with consistent behavior State persistence for expand/collapse preferences Custom user fields supported as subgroup options Internationalization Support# Added i18n framework with multi-language support Support for German, Spanish, French, Russian, Chinese, and Japanese Translation coverage for command palette entries and UI strings Localized agenda and filter interface elements Template Variables# Added {{hashtags}} template variable for space-separated hashtag rendering (#612, thanks to @strazto for the suggestion) Added {{currentNoteTitle}} template variable for note-specific folder organization (#637, thanks to @Mara-Li for the request) Added template variable support for archive folder paths (#677, thanks to @dsebastien for the request) Fixed {{project}} variables to properly extract basenames from wikilinks (#490, thanks to @nsstrickland for the detailed bug report) Project and Subtask Management# Enhanced task modals with project and subtask management capabilities Added \"Add to project\" and \"Add subtasks\" sections in task creation/edit modals Context menu options for assigning tasks to projects and adding subtasks Collapsible lists with visual separators between form sections View and Grouping Enhancements# Added \"Completed Date\" as grouping option for analyzing productivity (#430, thanks to @anareaty for the suggestion) Added \"Status\" as sorting option in Kanban and Task List views (#633, thanks to @mdbraber for the report) Implemented per-grouping column persistence for Kanban views Smart default ordering respecting StatusManager and PriorityManager configurations Bug Fixes# Calendar and Advanced Calendar# Fixed calendar not refreshing when task duration or time tracking changes Fixed calendar not refreshing after task archive or move operations Fixed agenda duplication for all-day ICS events (#695, thanks to @realJohnDoe for the report) Added configurable eventMinHeight for Advanced Calendar to make short duration tasks readable (#718, thanks to @Ruboks-Cube for the detailed report) Fixed multi-day task creation in month/year view to properly calculate time estimates (#564, thanks to @same774 for the report) Kanban View# Fixed kanban view losing columns after upgrades (#689, thanks to @mikesale for the report) Fixed clearing filters defaulting to \"none\" instead of \"status\" grouping (#679, thanks to @camara-tech-pro for the question) Fixed column order changes when switching between views (#710, thanks to @phortx for the report) Fixed kanban drag-and-drop for custom field grouping (#494, thanks to @anareaty for the report) Enhanced save view modal functionality with improved styling and accessibility Task Management# Fixed HTTP API task creation to return sanitized title matching stored content (#635, thanks to @nightroman for the detailed report) Fixed #task tag being incorrectly added when using property-based task identification (#570, thanks to @RobbK17 for the report) Fixed recurring task completion styling in Bases views (#669, thanks to @jordandrako for the report) Hierarchical Tag Support# Added hierarchical tag support with exclusion patterns for Obsidian nested tags (#584, thanks to @renatomen for the detailed feature request) Hierarchical matching allows searching for parent tags to match child tags (e.g., t/ef matches t/ef/project, t/ef/task) Exclusion patterns support using - prefix to exclude specific tags and their children Maintains backward compatibility with existing substring matching Natural Language Processing and Tags# Fixed nested tags losing slashes in agenda view rendering (#712, thanks to @antonio for the report and fix) Added support for hyphens in NLP tag parsing (#568, thanks to @jordandrako for the report) Settings and Configuration# Fixed property value truncation in project autosuggest settings by adding input debouncing (#705, thanks to @aubreyz for the report) Improved webhook transform error handling with detailed logging (#719, thanks to @stephen-netu for the detailed report) Added save button disable logic to prevent duplicate task creation (thanks to @hamlim for the report and implementation) Code Quality and Development# Configured Prettier formatter for consistent code formatting (#717, thanks to @ras0q for the request) Applied ESLint fixes reducing problems from 209 to 97 Added format and format:check scripts for development workflow Fixed browser extension repository URL in README (thanks to @elijahmanor for the correction) Enhancements# Performance and Reliability# Added debouncing to project autosuggest property inputs Improved error handling for webhook transform failures User Interface# Added time display based on timeEstimate property in task statistics (thanks to Sergen Aras for the implementation) Enhanced language selection display with native scripts Settings Organization# Reorganized settings with improved categorization Added collapsible functionality to various UI sections Enhanced accessibility with proper button labeling Documentation# Added documentation for task dependencies feature Updated comprehensive subgrouping feature documentation Enhanced template variable documentation Updated various view documentation for new features Contributors# Special thanks to all this release's contributors: Feature Contributors# @renatomen for implementing the major hierarchical subgrouping feature and hierarchical tag support feature request (#584) @antonio for implementing nested tag slash preservation and providing the fix @elijahmanor for fixing the browser extension repository URL @sergenaras for implementing time display based on timeEstimate property in task statistics @hamlim for implementing save button disable logic to prevent duplicate task creation Issue Reporters and Feature Requesters# @backyardbiomech for the detailed overdue recurring tasks report (#557) @prayidae for the detailed task dependencies feature request (#701) @jhedlund for requesting task context menu in notes (#576) @anareaty for requesting completed date grouping (#430) and reporting kanban custom field drag issues (#494) @mdbraber for reporting missing status sorting option (#633) @strazto for requesting hashtags template variable (#612) @Mara-Li for requesting currentNoteTitle template variable (#637) @dsebastien for requesting archive folder template support (#677) @nsstrickland for the detailed project variable bug report (#490) @realJohnDoe for reporting ICS all-day event duplication (#695) @Ruboks-Cube for reporting short duration task rendering issues (#718) @same774 for reporting multi-day task creation issues (#564) @mikesale for reporting kanban column loss (#689) @camara-tech-pro for the kanban grouping question (#679) @phortx for reporting column order changes (#710) @nightroman for the detailed HTTP API title sanitization report (#635) @RobbK17 for reporting property identification tag issue (#570) @jordandrako for reporting recurring task styling in Bases (#669) and NLP tag parsing with hyphens (#568) @aubreyz for reporting project autosuggest truncation issue (#705) @ras0q for requesting code formatting improvements (#717) @stephen-netu for the detailed webhook transform script loading report (#719)"},{"title":"TaskNotes 3.24.1","url":"/obsidian/releases/3.24.1/","description":"This patch release fixes the task card widget introduced in 3.24.0 to only display on actual task notes.","product":"obsidian","text":"Bug Fixes# Task Card Widget# Fixed task card widget appearing on all notes instead of only task notes Widget now properly respects task identification settings (tag or property-based) This patch release fixes the task card widget introduced in 3.24.0 to only display on actual task notes."},{"title":"TaskNotes 3.24.2","url":"/obsidian/releases/3.24.2/","description":"TaskNotes documentation.","product":"obsidian","text":"Fixed# (#766) Fixed tag parsing incorrectly identifying notes with tags containing \"task\" (like \"pkm-task\") as task notes Added exact hierarchical tag matching for task identification to prevent false positives Preserved substring matching behavior for filter bar searches where it's desired Only exact matches or hierarchical children (like \"task/work\") now identify notes as tasks Thanks to @anareaty and @fastrick for reporting this issue (#767) Fixed subgroups not rendering under the \"Overdue\" agenda group Thanks to @renatomen for reporting this issue (#768) Fixed calendar view appearing empty in week and day views due to invalid time configuration values Added time validation in settings UI with proper error messages and debouncing Added runtime sanitization in calendar with safe defaults (00:00:00, 24:00:00, 08:00:00) Prevents \"Cannot read properties of null (reading 'years')\" error from FullCalendar Thanks to @kmaustral for reporting (#769) Fixed NLP processor incorrectly assigning hardcoded \"waiting\" status when \"blocked\" appears in task titles NLP now only uses user-defined status configurations when available, ignoring hardcoded fallback patterns Prevents unexpected status assignments for users with custom status workflows Fallback patterns still work when no custom status configurations are defined Thanks to @renatomen for reporting this issue"},{"title":"TaskNotes 3.24.3","url":"/obsidian/releases/3.24.3/","description":"TaskNotes documentation.","product":"obsidian","text":"(#776) Fixed screens failing to load with \"toLowerCase is not a function\" error Issue occurred when frontmatter tags array contained non-string values (numbers, booleans, etc.) Added type validation to filter out non-string values before processing tags Valid string tags continue to work normally while invalid types are safely skipped Thanks to @kmf and @Andre-Ioda for help debugging this issue"},{"title":"TaskNotes 3.24.4","url":"/obsidian/releases/3.24.4/","description":"(#768) Fixed calendar view crashes when tasks contain null values in grouping fields","product":"obsidian","text":"Fixed# (#768) Fixed calendar view crashes when tasks contain null values in grouping fields Added null/undefined checks in sort comparisons to prevent localeCompare errors Calendar now handles null values in tags, contexts, and custom fields gracefully Thanks to @kmaustral for reporting (#601) Fixed Unicode characters not displaying in tags and contexts Unicode characters (Š, Ė, Ž, Ą, etc.) are now properly preserved in tags and contexts Affects Agenda View, Task List View, and all other views displaying tags Thanks to @Kapinekas for reporting (#778) Fixed cursor artifacts in CodeMirror widgets Thanks to @jhedlund for the fix Fixed task card widgets in note editor not updating for archive and time tracking changes Task card widgets now properly detect when tasks are archived/unarchived Task card widgets now properly detect when time tracking starts/stops Blue \"tracking\" border now appears/disappears correctly in live preview Archive styling now updates correctly in live preview Changed# (#751) Status bar tracked task click behavior now opens task notes directly Single tracked task: opens the task note immediately Multiple tracked tasks: shows selector modal to choose which task note to open Provides faster access to tracked tasks compared to previous task list view (#727) \"Create New Inline Task\" command now respects the \"Include Current Note in Project\" setting When enabled, the current note is automatically added as a project to inline tasks Provides consistency with instant convert functionality Thanks to @chrisfeagles for the suggestion Improved link handling throughout the plugin using Obsidian's native APIs Replaced manual wikilink generation with FileManager.generateMarkdownLink() Now respects user's link format settings (wikilink vs markdown, relative paths) Replaced manual link parsing with parseLinktext() for proper alias handling Better compatibility with future Obsidian updates Added centralized link utilities in linkUtils.ts Refactored widget cursor styles into reusable utility class Consolidated shared CSS into .cm-widget-cursor-fix utility Improved maintainability across widget components"},{"title":"TaskNotes 3.24.5","url":"/obsidian/releases/3.24.5/","description":"(#806) Fixed Bases views crashing on Obsidian 1.10.0 startup","product":"obsidian","text":"Fixed# (#806) Fixed Bases views crashing on Obsidian 1.10.0 startup TaskNotes Bases views (Task List and Kanban) now restore correctly when already open at startup Added defensive checks in setEphemeralState to handle early lifecycle calls Added focus() method to view objects for proper restoration Made root elements focusable to support Obsidian 1.10.0 view lifecycle (#792, #800) Fixed markdown-style project and dependency links not being recognized in frontmatter Added support for markdown link format [text](path) in projects and blockedBy fields Handles URL-encoded paths like [Car Maintenance](../../projects/Car%20Maintenance.md) Markdown links now render as clickable links showing display text instead of raw [text](path) format Links are properly resolved for grouping, filtering, and project-task associations Previously only wikilink format [[path]] was supported Prevents automatic removal of project assignments when editing tasks Thanks to @minchinweb for reporting (#780) Fixed \"Cannot Create Timeblocks\" error when daily notes folder doesn't exist Added proper error handling when createDailyNote fails due to missing folder Improved error messages to guide users to check Daily Notes plugin configuration Prevents uncaught errors from obsidian-daily-notes-interface package Thanks to @uberunix for reporting"},{"title":"TaskNotes 3.24.6","url":"/obsidian/releases/3.24.6/","description":"(#440) Fixed inline task replacement not working for links with relative paths","product":"obsidian","text":"Added# Added release notes viewer New view displays release notes in a dedicated tab when plugin updates Automatically opens after updating to a new version Access anytime via command palette \"TaskNotes: View release notes\" or Settings > General Release notes are rendered using native Obsidian markdown rendering Includes link to view all releases on GitHub Fully internationalized with i18n support Auto-generation system ensures correct version is loaded without manual updates Fixed# (#440) Fixed inline task replacement not working for links with relative paths Markdown links with relative paths like [task](../../../GTD/tasks/task.md) now display inline previews Wikilinks with relative paths now work correctly Removed overly aggressive path sanitization that was stripping .. from all link paths Works in both Live Preview and Reading Mode Thanks to @minchinweb for reporting (#814) Fixed markdown links in projects field not being recognized on Project notes Tasks with markdown-style project links [text](path) now appear in project's Subtasks section Updated project link detection to use parseLinkToPath utility which handles both wikilinks and markdown links Handles URL-encoded paths like [z Test Project](z%20Test%20Project.md) Thanks to @minchinweb for reporting (#827) Fixed project links being generated as markdown links for users with markdown links enabled in Obsidian settings Project links in frontmatter are now always generated as wikilinks [[link]] by default for Obsidian compatibility Obsidian does not support markdown links in frontmatter properties without third-party plugins Added optional setting to enable markdown links in frontmatter for users with obsidian-frontmatter-markdown-links plugin Setting only appears when user has markdown links enabled globally in Obsidian Thanks to @nightroman for reporting"},{"title":"TaskNotes 3.25.0","url":"/obsidian/releases/3.25.0/","description":"Added Calendar view for Bases plugin integration (requires Bases 1.10.0+)","product":"obsidian","text":"Added# Added Calendar view for Bases plugin integration (requires Bases 1.10.0+) Supports month, week, day, year, and list views Property-based events from note date properties (configurable start date, end date, and title properties) Custom card rendering in list view for tasks, timeblocks, ICS events, and property-based events Layout options: time format, weekend visibility, all-day slot, today highlight, scroll time, event height Visibility toggles for event types (scheduled, due, recurring, time entries, timeblocks, property-based) Date validation to handle invalid property values Drag-and-drop to update property-based event dates in frontmatter Full internationalization support for calendar features in 7 languages (English, French, Spanish, German, Japanese, Russian, Chinese) Added grouped rendering support for Bases integration list and kanban views List view displays collapsible groups with toggle controls Kanban view renders grouped columns with drag-drop support Automatically detects ungrouped views and renders as flat list (#842) Added keyboard navigation support for task forms Action bar icons now focusable with proper tab order and ARIA attributes Enter and Space keys trigger actions on focused elements Added submenu support for reminders button for better keyboard accessibility Improved focus indicators for better visual feedback Thanks to @maybetm for this excellent contribution! Changed# Migrated Bases integration to use public API (Bases 1.10.0+) with graceful fallback to internal API for older versions Fixed# (#789) Fixed folder path truncation in settings causing tasks to be created in wrong paths Changed debounce to trailing mode to ensure final value is saved instead of partial input Fixes issue where rapid typing, paste, or autocomplete would save incomplete folder paths Thanks to @sascha224 for reporting (#806) Fixed Bases views crashing on Obsidian 1.10.0 startup TaskNotes Bases views (Task List and Kanban) now restore correctly when already open at startup Added defensive checks in setEphemeralState to handle early lifecycle calls Added focus() method to view objects for proper restoration Made root elements focusable to support Obsidian 1.10.0 view lifecycle (#825) Fixed single/double click settings not applying to calendar views Shared click handling now works consistently across Advanced Calendar and Bases Calendar Ctrl/Cmd+click opens tasks in new tab as expected Single and double-click actions respect user settings (#699) Fixed Obsidian freezing when moving calendar tab to new window Skip calendar resize during window transfer to prevent freeze Calendar may display incorrectly after move but can be fixed by switching views Prevents complete UI lockup during tab transfer (#816) Fixed template variables not processing in ICS subscription note folder paths Template variables like {{year}}, {{month}}, {{date}} now work in ICS note folder settings Extracted folder template processing into shared utility for consistency Added support for ICS-specific variables: {{icsEventTitle}}, {{icsEventLocation}}, {{icsEventDescription}} Users can now organize ICS notes in date-based hierarchies (e.g., Daily/{{year}}/{{month}}/) Thanks to @j-peeters for reporting (#813) Fixed subscribed ICS calendars irregularly disappearing from calendar views Added 5-minute grace period after cache expiration to keep events visible during refresh Trigger automatic background refresh when cache is stale or missing Initialize ICS service instances early so views can register event listeners before data loads Prevents disappearance during network errors or when calendar opens at Obsidian startup Thanks to @j-peeters for reporting (#829) Fixed time estimates and recurrence patterns being lost during instant task conversion Added timeEstimate field to ParsedTaskData interface Time estimates from natural language parsing now properly transferred to task frontmatter Parsed values now take priority over default settings RRule strings passed directly without conversion (preferred format) Thanks to @Justin-Burg for reporting (#826) Fixed task card widget not appearing when Obsidian starts with task note open Deferred dispatch calls to avoid \"EditorView.update not allowed during update\" error Widget now renders correctly on startup without requiring workarounds Thanks to @nightroman for reporting (#781), (#841) Fixed ICS calendar events displaying incorrect times due to timezone conversion issues Events with non-IANA timezone identifiers (e.g., TZID=Zurich without VTIMEZONE) now display at correct local times Fixed Outlook/Exchange calendar events showing original timezone instead of user's local timezone Replaced unreliable toJSDate() conversion with toUnixTime() for accurate UTC timestamp handling Affects all ICS subscriptions including Infomaniak, Outlook, and other providers with non-standard timezone formats Thanks to @chrlaney for reporting and @wilf80 for detailed analysis (#810) Fixed recurring tasks with overdue due dates disappearing from agenda view Recurring tasks now check both due and scheduled dates for overdue status Previously only scheduled was checked for recurring tasks, causing tasks with overdue due dates to be hidden Ensures consistent overdue detection logic between recurring and non-recurring tasks Thanks to @skyrunner15 for reporting (#822) Fixed mini calendar showing incorrect dates in negative UTC offset timezones Calendar tooltips and month displays now show correct dates for users in Americas/Pacific timezones UTC-anchored dates are now converted to local calendar dates before formatting Fixes off-by-one day error that affected date selection and display Thanks to @kenhsmith for reporting"},{"title":"TaskNotes 3.25.1","url":"/obsidian/releases/3.25.1/","description":"(#854) (#695) Fixed all-day ICS calendar events displaying on wrong day and appearing twice","product":"obsidian","text":"Fixed# (#854) (#695) Fixed all-day ICS calendar events displaying on wrong day and appearing twice All-day events now stored as date-only strings (YYYY-MM-DD) instead of UTC timestamps Events display on correct calendar date regardless of user timezone (fixes issue in PST, EST, and other negative UTC offset timezones) All-day events no longer appear twice in Agenda view Updated all date parsing throughout the codebase to handle date-only format correctly Maintains compatibility with FullCalendar and preserves iCalendar RFC 5545 semantics for VALUE=DATE events Thanks to @needo37 for reporting #854 and @realJohnDoe for reporting #695 (#859) Fixed multi-day task creation in Bases calendar view Extracted shared task creation logic to calendar-core.ts for consistency between calendar views Multi-day all-day selections now correctly set time estimate based on number of days dragged Timed task selections (week view) now correctly calculate duration in minutes Single-day clicks no longer override default time estimate settings Both Bases calendar and AdvancedCalendarView now use same logic for consistent behavior Fixed all-day task rendering to use 24-hour days (1440 minutes = 1 day on calendar) Follows UTC Anchor principle for date-only strings Thanks to @anareaty for reporting"},{"title":"TaskNotes 3.25.2","url":"/obsidian/releases/3.25.2/","description":"(#857) Fixed Mini Calendar opening previous day's daily note when clicked","product":"obsidian","text":"Fixed# (#857) Fixed Mini Calendar opening previous day's daily note when clicked Affects users in negative UTC offset timezones (Americas, Pacific) Thanks to @tsweezy for reporting (#871) Fixed Bases Kanban drag-and-drop updating wrong property when grouped by custom fields Added support for both Bases 1.10.0+ format ({property: string, direction: string}) and legacy string format Note: GroupBy is not exposed in the Bases public API (config.get('groupBy') returns undefined) Known limitation: When grouping by projects, Bases groups by literal wikilink strings, not resolved file paths Tasks with different wikilink formats pointing to the same project file will appear in separate columns Example: [[Project]], [[path/to/Project]], and [[Project|Alias]] create separate columns This differs from native TaskNotes Kanban which resolves all wikilinks to absolute paths Thanks to @kmaustral for reporting Added# Added date navigation configuration for Bases calendar views Hardcoded date option: Set a specific date (YYYY-MM-DD format) for the calendar to display on load Property-based navigation: Automatically navigate to dates from filtered note properties Three navigation strategies: First result, Earliest date, or Latest date Changed# Release notes now bundle all versions from current and previous minor series with collapsible sections Added setting to disable automatic release notes display after updates"},{"title":"TaskNotes 3.25.3","url":"/obsidian/releases/3.25.3/","description":"(#899) Fixed \"Folder for converted tasks\" setting being hidden when convert button is disabled","product":"obsidian","text":"Added# (#877) Added standard Obsidian CSS classes to settings tab buttons for improved theme compatibility Fixes issue where themes like Retroma couldn't distinguish active tabs Thanks to @Bregor for the contribution Fixed# (#899) Fixed \"Folder for converted tasks\" setting being hidden when convert button is disabled Setting now always visible since it affects command palette task conversion Resolves confusion for users who convert tasks via command palette Thanks to @nnnell for the fix (#905), (#907) Fixed project filter incorrectly affecting custom field suggestions Custom field wikilink suggestions ([[) now show all vault files instead of only filtered projects Task Edit modal now uses consistent hierarchical tag matching with Task Creation modal Thanks to @renatomen for the thorough fix and tests"},{"title":"TaskNotes 3.25.4","url":"/obsidian/releases/3.25.4/","description":"(#937), (#956) Added optional setting to hide identification tags in task cards","product":"obsidian","text":"Added# (#937), (#956) Added optional setting to hide identification tags in task cards New \"Hide identification tags in task cards\" setting (only visible when using tag-based identification) Hides exact matches (e.g., #task) and hierarchical children (e.g., #task/project, #task/work/urgent) Reduces visual clutter while keeping tags in frontmatter for organizational purposes Backward compatible - disabled by default Thanks to @renatomen for implementing this feature and @edakimling for reporting (#911) Added custom field suggestion filtering New autosuggestFilter field to UserMappedField interface allows filtering suggestions by current filter context Added collapsible filter section in settings with visual indicator Comprehensive test coverage for custom field filtering feature Thanks to @renatomen for this enhancement Fixed# (#903) Fixed Edit Task modal not adding completedDate when marking tasks as done Edit Task modal now correctly adds completedDate when changing status to completed Fixed Edit Task modal adding empty contexts and projects arrays to frontmatter Behavior now consistent with other completion methods (Agenda view, widget context menu, quick actions) Thanks to @nightroman for reporting (#969), (#967) Fixed Bases Kanban layout not displaying correctly when no groupBy is configured All tasks were appearing in a single \"None\" column Columns now appear in the order defined in TaskNotes settings (not alphabetical) Detects invalid Bases grouping and falls back to status-based grouping Tasks are properly distributed across status columns Thanks to @mweichert for the fix and @PacoTaco2, @abuhammer for reporting"},{"title":"Tasknotes 3.25.6","url":"/obsidian/releases/3.25.6/","description":"(#1013) Fixed inability to subscribe to Apple iCloud calendars","product":"obsidian","text":"Fixed# (#1013) Fixed inability to subscribe to Apple iCloud calendars Calendar URLs copied from Apple Calendar (starting with webcal://) can now be pasted directly Previously required manually changing the URL format before it would be accepted Works with both standard and secure calendar URLs (webcal:// and webcals://) Thanks to @nickbirch51 for reporting (#1022) Fixed tasks randomly disappearing from views and not being recognized Tasks would appear initially but disappear after a few seconds, especially during long sessions Restarting Obsidian or using \"Refresh Cache\" would only temporarily fix the issue Thanks to @seepage87 for reporting and @alejandrospoz for help debugging (#968) Fixed timeEntries being duplicated when mapped to custom property name When timeEntries was configured to use a custom property name in Metadata settings (e.g., time_entries), saving tasks would create duplicate entries in both the custom property and the default timeEntries property FieldMapper now correctly uses only the configured property name for time tracking data Thanks to @minchinweb for reporting this issue (#953) Fixed non-task notes incorrectly appearing as subtasks in views Notes with Parent or project properties but no task tag/property no longer show up as tasks Views now update correctly when task tags are removed from files Improved performance for large vaults by optimizing cache invalidation Thanks to @renatomen for reporting and submitting PR #955"},{"title":"Untitled","url":"/obsidian/releases/3.3.0/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.1.1...3.3.0","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.1.1...3.3.0"},{"title":"Untitled","url":"/obsidian/releases/3.4.0/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.3.0...3.4.0","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.3.0...3.4.0"},{"title":"Untitled","url":"/obsidian/releases/3.4.1/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.0...3.4.1","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.0...3.4.1"},{"title":"Untitled","url":"/obsidian/releases/3.4.2/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.1...3.4.2","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.1...3.4.2"},{"title":"Untitled","url":"/obsidian/releases/3.5.1/","description":"This release focusses on significant performance improvements by migrating away from the baroque plugin caching system to Obsidian's native cache.","product":"obsidian","text":"This release focusses on significant performance improvements by migrating away from the baroque plugin caching system to Obsidian's native cache. Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.4.0...3.5.1"},{"title":"Untitled","url":"/obsidian/releases/3.6.0/","description":"Fix task tag check. Add optional timeblocking.","product":"obsidian","text":"Fix task tag check. Add optional timeblocking."},{"title":"TaskNotes v3.7.0 Release Notes","url":"/obsidian/releases/3.7.0/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.6.0...3.7.0","product":"obsidian","text":"Reading Mode Task Previews (thank you @amithkk)# Task link previews now work in Reading Mode in addition to Live Preview Consistent interactive experience across all Obsidian view modes Same functionality: click to edit, right-click for context menu, hover for file preview New ReadingModeTaskLinkProcessor.ts with dedicated CSS styling Task Action Palette# New quick-action command palette for rapid task management Access via command palette: \"TaskNotes: Open Task Action Palette\" Change status/priority with fuzzy search, set dates, start/stop timers, archive/delete tasks Handles recurring task instances vs. series intelligently Fully keyboard navigable with categorized actions Natural Language Task Input# Parse natural language when creating tasks: \"Buy groceries tomorrow 3pm high priority @home #errands\" Powered by chrono-node for robust date/time parsing Extracts dates, priorities, status, contexts (@), tags (#), recurrence, and time estimates Multi-line support: first line parsed, additional lines become task details Toggle in Settings → Basic Defaults UI/UX Improvements# Enhanced Task Creation Modal# Smart input mode with simplified interface when natural language is enabled Progressive disclosure to detailed form when needed Better conversion flow with pre-populated forms Live filename preview as you type Settings & Modal Improvements# Moved Natural Language Input to Basic Defaults section Updated task link overlay description to mention both view modes Reusable confirmation modal for consistent dialogs Better error handling and accessibility improvements Bug Fixes# Fixed: Inline Tasks Not Respecting Default Status & Priority (Issue #58)# Problem: Inline task conversion applied \"none\" instead of configured defaults Solution: Changed useDefaultsOnInstantConvert default from false to true Timer Function Standardization# Fixed browser compatibility by replacing Node.js timer types with browser-native timers Resolved timing issues across different environments Enhanced Task Link Overlays# Better path resolution with security enhancements Graceful fallbacks for invalid or missing task files Improved handling of rapid view changes Technical Improvements# Enhanced Date Support# Full due date and scheduled date support in task creation and filename generation New filename template variables: {dueDate} and {scheduledDate} (YYYY-MM-DD format) Support for ISO dates, relative dates, named dates, and natural language Performance & Code Quality# Improved event handling with better refresh logic Layout change listeners for immediate overlay updates Enhanced error handling with user-friendly messages Better TypeScript types and modular design New Files & Dependencies# New Files# src/editor/ReadingModeTaskLinkProcessor.ts src/modals/TaskActionPaletteModal.ts src/services/NaturalLanguageParser.ts src/modals/ConfirmationModal.ts styles/task-action-palette-modal.css New Dependency# chrono-node: Natural language date parsing library What's Changed# Feat/task previews in reading mode by @amithkk in https://github.com/callumalpass/tasknotes/pull/57 New Contributors# @amithkk made their first contribution in https://github.com/callumalpass/tasknotes/pull/57 Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.6.0...3.7.0"},{"title":"Version 3.7.1","url":"/obsidian/releases/3.7.1/","description":"Files with Major Changes:","product":"obsidian","text":"Major UI/UX Enhancements# Interactive Inline Task Previews# Clickable Status Dots: Status indicators in inline task previews are now interactive - click to cycle through task statuses directly from the preview Clickable Date Fields: Due and scheduled dates are now clickable and open dedicated modals for quick editing Enhanced Visual Design: Redesigned with minimal styling Improved spacing and vertical alignment between status dots, priority indicators, and task titles Better hover effects with brightness and subtle animations Status dots now use bordered design for better visibility Modernized Task Card Design# Interactive Status Cycling: Click status dots on task cards to quickly change task status Improved Mobile Support: Better touch targets and responsive behavior Enhanced Animations: Smooth hover effects, scaling, and transition animations Cleaner Layout: Streamlined design with better visual hierarchy Enhanced Natural Language Processing# Advanced Date Parsing# Explicit Trigger Recognition: Now recognizes specific phrases: Due dates: \"due on\", \"deadline\", \"must be done by\", \"needs to be completed\" Scheduled dates: \"scheduled for\", \"start on\", \"work on\", \"planned for\" Configurable Defaults: New setting to choose whether ambiguous dates default to \"due\" or \"scheduled\" Enhanced Recurrence Patterns: \"every [weekday]\" patterns (every monday, every friday) Plural day patterns (mondays, tuesdays, etc.) \"Every other\" interval patterns (every other week, every 2 days) Multiple days (\"every tuesday and thursday\") Improved Date/Time Handling# Better Time Component Support: Enhanced parsing of specific times with dates Robust Validation: Improved handling of edge cases and malformed input Smart Cleanup: Automatic removal of duplicate tags and contexts Performance & Developer Experience# Instant Task Conversion Improvements# Real-time Updates: Task link overlays refresh immediately after task conversion Smart Caching: Improved metadata cache management for newly created tasks Better Error Handling: Enhanced validation with user-friendly error messages Multi-line Support: Enhanced conversion of tasks with details from multiple selected lines Technical Improvements# Improved Event Handling: Fixed n.dispatch is not a function error with proper validation BEM CSS Methodology: Migrated to Block Element Modifier naming for better CSS organization Performance Optimizations: Reduced unnecessary re-renders and improved widget caching Enhanced State Management: Better synchronization between UI updates and task data Modal & Interface Enhancements# Enhanced Date/Time Modals# Better Keyboard Navigation: Enter to save, Escape to cancel Separate Time Inputs: Dedicated date and time fields for precision Quick Date Buttons: Common date selections for faster input Improved Accessibility: Proper ARIA labels and screen reader support Better User Experience# One-Click Status Changes: Direct status cycling from any task preview Direct Date Editing: Click any date to immediately edit it Enhanced Visual Feedback: Better hover states, transitions, and loading animations Accessibility Improvements: Enhanced keyboard navigation and screen reader support Bug Fixes & Stability# Fixed: Inline task widget dispatch errors that caused console warnings Fixed: Vertical alignment issues with different-sized status and priority indicators Fixed: Layout conflicts between flexbox and inline display properties Fixed: Spacing issues in inline task previews causing cramped appearance Fixed: Missing task link overlay refreshes after instant task conversion Configuration & Settings# New User Settings# Natural Language Default: Configure whether ambiguous dates default to \"due\" or \"scheduled\" Enhanced Task Creation: Improved default value application for instant task conversion Technical Details# Files with Major Changes: Enhanced inline task previews (TaskLinkWidget.ts, TaskLinkOverlay.ts) Modernized task card design (TaskCard.ts) Advanced natural language processing (NaturalLanguageParser.ts) Improved modal interfaces (DueDateModal.ts, ScheduledDateModal.ts) Comprehensive CSS overhaul with BEM methodology"},{"title":"Untitled","url":"/obsidian/releases/3.8.1/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.7.1...3.8.1","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.7.1...3.8.1"},{"title":"TaskNotes 3.8.5 Release Notes","url":"/obsidian/releases/3.8.5/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.1...3.8.5","product":"obsidian","text":"UI/UX Improvements# Compact Filter Bar (Special thanks to @amithkk :tada: )# Complete redesign of FilterBar component with compact, modern interface Native Obsidian dropdowns replace basic HTML select elements for better consistency Collapsible controls - settings are hidden by default with expandable controls via settings button Visual indicators showing active filter count on settings button Integrated search bar with search icon and improved visual hierarchy Right-aligned control buttons for better layout organization Advanced Calendar View Integration# Unified view options - calendar view toggles now integrated into FilterBar dropdown Streamlined interface - removed separate toggle controls in favor of FilterBar integration Consistent UX across different view types with shared filter/view controls Dynamic option management with real-time updates and state synchronization Enhanced Natural Language Processing# Improved Text Processing# Better whitespace handling with new cleanupWhitespace() function for consistent text normalization Enhanced priority detection with improved pattern matching and conflict resolution Completion status support - added isCompleted field to parsed task data More robust text extraction across tags, contexts, priorities, and dates Date and Time Handling Improvements# Enhanced date parsing with better timezone handling for date-only strings Improved date normalization with direct Date constructor to avoid timezone issues Better error handling for invalid date strings and edge cases More robust timestamp formatting with validation checks Testing Infrastructure# Comprehensive Test Suite# Complete testing infrastructure with Jest configuration for both unit and integration tests Enhanced mocking system with improved Obsidian API mocks and better type safety Integration test helpers with utilities for end-to-end workflow testing Improved test coverage across core components and services Mock Improvements# Updated mock factories with better type consistency and realistic data generation Enhanced DOM simulation for better UI component testing Improved date-fns mocking with support for \"MMM d, yyyy h:mm a\" format Better Obsidian API compatibility in test mocks Developer Experience# Type Safety Enhancements# Refactored type definitions for improved consistency across the codebase Better TypeScript integration with enhanced type checking and inference Improved callback types for better development experience Build and Deployment# Updated GitHub Actions with artifact uploader v4 for improved CI/CD Enhanced development workflow with better testing and build processes User Interface Polish# Task Creation Modal# Improved placeholder text with more natural language examples Better user guidance for natural language task input format Clearer instruction formatting for enhanced user experience Visual Consistency# Native Obsidian styling throughout filter and control components Consistent iconography using Obsidian's icon system Improved responsive design with better mobile and small screen support Bug Fixes and Stability# Error Handling# Improved error handling in date parsing and normalization functions Better validation for user input and edge cases Enhanced robustness in text processing and natural language parsing Code Quality# Refactored components for better maintainability and performance Simplified scheduled date logic with cleaner default handling Enhanced code organization with better separation of concerns What's Changed# Add compact filter bar by @amithkk in https://github.com/callumalpass/tasknotes/pull/73 Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.1...3.8.5"},{"title":"Untitled","url":"/obsidian/releases/3.8.6/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.5...3.8.6","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.5...3.8.6"},{"title":"Untitled","url":"/obsidian/releases/3.8.7/","description":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.6...3.8.7","product":"obsidian","text":"Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.8.6...3.8.7"},{"title":"Release Notes v3.9.0","url":"/obsidian/releases/3.9.0/","description":"This release introduces a host of new features, bug fixes, and significant enhancements to improve your task and time management experience. Key updates include a more powerful...","product":"obsidian","text":"This release introduces a host of new features, bug fixes, and significant enhancements to improve your task and time management experience. Key updates include a more powerful and standards-compliant recurrence system, a streamlined user interface, and improved performance. A special thank you to amithkk (https://github.com/amithkk) for their contributions to this release! New Features# RRule-Based Recurrence: Task recurrence is now powered by the iCalendar standard (RFC 5545), allowing for more complex and flexible recurring task schedules. A migration assistant will help you update your existing tasks to the new format. Interactive Recurring Task Calendar: An interactive calendar has been added to the task edit modal, allowing you to visualize and manage individual completions of recurring tasks. \"Show\" Dropdown in Filter Bar: A unified \"Show\" dropdown has been added to the filter bar, providing enhanced filtering options for your tasks. Insert Tasknote Link Command: A new command has been added to insert a link to a tasknote, streamlining your workflow. Dedicated Inline Task Folder Setting: You can now specify a dedicated folder for inline tasks, with support for {{currentNotePath}} to save tasks in the same folder as the current note. \"Show Due Dates When Scheduled\" Setting: A new setting allows you to display due dates for scheduled tasks in the calendar view. Compact Filter Bar: A more compact filter bar option is now available for a cleaner interface. (Thanks, amithkk!) Multiple New Ribbon Icons: New ribbon icons have been added for extended views and actions, providing quicker access to features. \"Highlight Today\" in Calendar View: The calendar view now highlights the current day for better visibility. New Documentation Site: A new documentation site, built with MkDocs, is now available with improved structure and searchability. CI/CD and Testing: A comprehensive testing suite using Jest has been added to improve code quality and prevent regressions. GitHub Actions workflows have been implemented for automated testing, documentation deployment, and releases. Enhancements# UI/UX Improvements: The task edit and creation modals have been redesigned for a more minimalist and intuitive experience. Task-related icons have been updated for better clarity. Context menus have been added to task cards for quick actions. The agenda view sorting options have been fixed. The recurring calendar widget is now centered and on a separate line from its label. Dropdown menus now handle clicks on text labels more reliably. Performance and Reliability: The task link overlay has been refactored to use a ViewPlugin for better performance. The Advanced Calendar view now handles resizing and being moved to a new window more gracefully. The natural language processing for task creation has been improved with a fallback mechanism. Date parsing and handling have been made more robust, especially for UTC and different date formats. Development Workflow: ESLint configuration has been updated with new rules and plugins for better code consistency. The build process for CSS has been improved. The development guidelines have been updated to reflect the new architecture. Bug Fixes# Fixed an issue where agenda view sorting options were not working correctly. Fixed a bug that caused a forced reflow when moving the Advanced Calendar to a new window. Resolved a TypeError in the task modal's suggestion filtering. Fixed an issue where the Pomodoro task selector did not show all un-archived tasks. Corrected the filtering of daily notes in the getNotesForDate function. Fixed a bug where the underlying markdown of a task link was not revealed on hover. Removed misleading placeholder symbols from the settings. Addressed various linting issues and improved code quality. Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.7.1...3.9.0"},{"title":"Release Notes: 3.9.1","url":"/obsidian/releases/3.9.1/","description":"New Features","product":"obsidian","text":"New Features GitHub Issue Templates: Added templates for bug reports and feature requests to streamline issue submission and ensure all necessary information is provided. Bug Fixes Pomodoro Timer: Fixed an issue where a long break would incorrectly start after the first work session. The timer now correctly schedules a short break as intended. Task Creation: The \"Magic Wand\" (Natural Language Processing) now properly fills the context and tag fields in the task creation modal. Default contexts and tags are preserved if none are found in the natural language input. What's Changed# Add github issue templates by @amithkk in https://github.com/callumalpass/tasknotes/pull/101 Full Changelog: https://github.com/callumalpass/tasknotes/compare/3.9.0...3.9.1"},{"title":"TaskNotes 4.0.0-beta.0","url":"/obsidian/releases/4.0.0-beta.0/","description":"Beta Release","product":"obsidian","text":"Beta Release You may encounter issues. Report problems on GitHub Issues. What's New in v4# TaskNotes v4 migrates all views to the Bases system. Breaking Changes# Minimum Obsidian version: 1.10.1 View commands now use Bases files - Ribbon icons and command palette commands (Calendar, Kanban, Tasks, Agenda, Project Subtasks) now open .base files created automatically in your vault Saved filter views - Custom saved views can be converted to .base files using a conversion button in settings Added# OAuth Calendar Integration# Google Calendar and Microsoft Outlook integration via OAuth 2.0 View and sync calendar events in Bases calendar Drag events in the TaskNotes bases calendar to change the event's time online Events sync every 15 minutes or upon local change Requires creating your own OAuth application (approximately 15 minutes) See Calendar Setup Guide Time Entry Editor Modal# Dedicated interface for managing time entries Alt-drag on Bases calendar to create time entries View total tracked time per task Edit and delete time entries Access via Task Action Palette (Alt/Opt + Enter) Kanban Swimlane Layout# Horizontal swimlane grouping option for Bases Kanban Group tasks by status, priority, or other fields Hide empty columns Configurable column widths Improved drag-and-drop in swimlane mode Saved View Converter# Conversion button in settings to convert saved filter views to .base files Original settings preserved Converted views created in TaskNotes/Views/ Changed# View System Architecture# All views now use Bases architecture Calendar, Kanban, Tasks, Agenda, and Project Subtasks are .base files Views stored in TaskNotes/Views/ Keyboard shortcuts and ribbon icons map to .base files Configure file paths in Settings → Integrations → Bases Integration Calendar# Control which calendar sources display Toggle Google Calendar, Microsoft Calendar, and ICS events independently Configurable list view with custom day count (2-10 days) Improved timezone handling for recurring events Settings# Reorganized settings tabs OAuth calendar settings in Integrations tab Updated help text Fixed# (#843) Fixed task tag being added when \"Identify tasks by\" is set to \"Property\" TaskCreationModal, TaskEditModal, and InstantTaskConvertService now respect taskIdentificationMethod setting Thanks to @jack2game Fixed dark mode calendar borders Fixed Bases Kanban column ordering - Thanks to @mweichert Fixed state management bug in FilterSettingsComponent Fixed timezone handling for recurring events Migration Guide# First Launch# Default view files are created automatically in TaskNotes/Views/ Ribbon and command palette commands now open .base files Review Settings → General to customize view file paths Converting Saved Filter Views# Go to Settings → General Click the conversion button to convert saved filter views to .base files Converted views appear in a file in TaskNotes/Views/ Calendar Integration (Optional)# Go to Settings → Integrations → OAuth Calendar Integration Follow the Calendar Setup Guide Create OAuth applications with Google and/or Microsoft (approximately 15 minutes) Enter Client ID and Secret in calendar cards Click Connect Known Limitations# Quick OAuth setup is disabled - only advanced setup (your own credentials) is available Saved filter views require manual conversion using the button in settings Migration is one-way - downgrading to v3 may require manual reconfiguration OAuth setup requires creating applications with Google/Microsoft Feedback# Report issues on GitHub. Include: Obsidian version Steps to reproduce Console errors (Ctrl/Cmd + Shift + I) Whether issue occurs after migration or fresh install"},{"title":"TaskNotes 4.0.0-beta.1","url":"/obsidian/releases/4.0.0-beta.1/","description":"Beta Release","product":"obsidian","text":"Beta Release You may encounter issues. Report problems on GitHub Issues. Added# Added context menus for time entries and ICS events in calendar Time entries: Right-click shows task context menu, left-click opens time entry editor modal ICS/Google/Microsoft Calendar events: Right-click shows ICS event context menu with options to show details, create task/note, link note, and copy info Added calendar icon to ICS event titles for better visual distinction Added hover tooltips for timeblocks in calendar views Added MiniCalendar view for Bases integration Monthly calendar grid with dot indicators on days with notes Configurable date property (file.ctime, note.dateCreated, etc.) Fuzzy selector modal for selecting notes on clicked days Ctrl+click (or Cmd+click on Mac) on any day opens/creates daily note Added virtual scrolling and lazy rendering to Bases views for high-performance handling of large datasets TaskListView: Virtual scrolling for 100+ tasks in flat and grouped views with collapsible groups KanbanView: Virtual scrolling for regular columns (30+ tasks) and swimlane cells (30+ tasks per cell) Tested with up to 30,000 notes with no performance degradation Thanks to @aubreyz and @turingexmachina for their reports of performance issues and diagnosis help Changed# Refactored Bases integration to use public API and trust pre-sorted data Migrated all three views (Task List, Kanban, Calendar) to clean class-based architecture Removed legacy view files and ~500 lines of redundant sorting/grouping logic Introduced BasesDataAdapter, PropertyMappingService, and BasesViewBase abstractions Trusts Bases plugin to provide pre-sorted and pre-grouped data via public API Reduced code duplication by 40% while maintaining full feature parity Refactored calendar modules to use ES6 imports instead of lazy require() calls Removed all dynamic require() calls from calendar-core.ts and calendar-view.ts Consolidated all imports at module top level Improves code maintainability, makes dependencies explicit, and follows modern TypeScript best practices Time entry events now show task context menu on right-click (previously had no context menu) Replaced MinimalNativeCache with just-in-time TaskManager for improved reliability Removed complex index synchronization in favor of direct MetadataCache queries Eliminated 7 internal indexes (tasksByDate, tasksByStatus, overdueTasks, etc.) Added minimal DependencyCache for task dependencies and project references only Zero startup time (no index building required) Always provides fresh, accurate task data from Obsidian's MetadataCache Completed internationalization with 100% translation coverage across all supported languages Added 90 missing translation keys to English base Completed 829 translations across 6 languages (German, Spanish, French, Japanese, Russian, Chinese) All locales now have complete coverage (1745/1745 keys) Improved translation quality for migration system, calendar settings, statistics, ICS events, and filter components Migrated to i18n-state-manager CLI tool for translation management Replaced custom scripts with more robust i18n-state-manager package Added i18n-state.config.json for project-specific patterns New features: find-unused, check-duplicates, improved stale detection Hash-based state tracking and ripgrep-based scanning for performance Bases view templates now generate dynamically based on user settings Task filters adapt to user's task identification method (tag or property) Property ordering reflects defaultVisibleProperties setting Uses correct YAML object notation for Bases filters Maintains backward compatibility with legacy static templates Updated Bases CalendarView to show TaskNotes in property-based events Tasks can now be visualized on calendar via any date property (dateCreated, scheduled, due, etc.) Previously all TaskNotes were filtered out from property-based events Fixed# (#1022, #684) Fixed tasks randomly disappearing when Smart Connections plugin is enabled Eliminated race condition caused by index synchronization delays TaskManager now reads directly from Obsidian's MetadataCache instead of maintaining separate indexes No more timing-sensitive code that could conflict with other plugins' metadata processing Tasks will always be visible regardless of other plugins' processing times Thanks to @alejandrospoz, @seepage87, @amarjt, @luckb0x, camara-tech for reporting and help debugging. (#992) Fixed \"Failed to resolve module specifier 'obsidian'\" error when moving recurring task instances in calendar Removed unnecessary dynamic imports that were causing module resolution failures Consolidated imports at top of calendar-core.ts module Thanks to @jalooc for reporting this issue Fixed task dependencies not displaying on task cards TaskManager now properly calculates isBlocked and isBlocking flags from dependency data Added missing property extractors and renderers in TaskCard for all dependency-related fields Dependency information now shows correctly in Bases views, task note widgets, and other views Shows \"Blocked (n)\" and \"Blocking (n)\" pills, plus detailed task links Fixed Bases property mapping for user-configured field names PropertyMappingService now correctly strips prefixes and applies FieldMapper transformations Example: User configures \"state\" → \"status\", Bases provides \"note.state\", now correctly maps to \"status\" Ensures TaskCard properly recognizes and renders user-configured properties Fixed Bases views not respecting user-configured visible properties Now prioritizes Bases 1.10.0+ public API config.getOrder() method Removed reliance on internal API paths that no longer work Filters out blocked/blocking properties when using defaults (only shown when explicitly requested via blockedBy) Fixed MiniCalendar UTC anchoring for consistent timezone-independent date handling Fixed DateValue conversion in BasesDataAdapter DateValue objects have {date: Date, time: boolean} structure Now properly checks for value.date instanceof Date before legacy conversion methods Fixes property-based events in CalendarView"},{"title":"TaskNotes 4.0.0-beta.2","url":"/obsidian/releases/4.0.0-beta.2/","description":"Beta Release","product":"obsidian","text":"Beta Release You may encounter issues. Report problems on GitHub Issues. Added# (#1090) Portuguese (Brazil) translation Full Portuguese (pt-BR) localization support A big thanks to @andysteel for the contribution Configurable task modal fields New \"Modal Fields\" settings tab for complete control over task creation and edit modals Configure which fields appear in creation vs edit modals independently Drag-and-drop reordering of fields within groups (metadata, organization, dependencies, custom) Enable/disable individual fields (including core fields like contexts, tags, time estimate) Organize fields into groups Automatic migration of existing user-defined fields Title and details fields support visibility toggling (ordering fixed for consistency) Rich markdown editor for NLP task creation Replaced plain textarea with full CodeMirror markdown editor Live preview, syntax highlighting, and wikilink support Ctrl/Cmd+Enter keyboard shortcut to save task Esc/Tab keyboard shortcuts for modal control Customizable NLP triggers with autocomplete Configure custom trigger characters/strings for each property type (tags, contexts, projects, status, priority) Supports user-defined field triggers CodeMirror-based autocomplete with keyboard navigation (arrow keys, Enter, Tab) Quote support for multi-word values in user fields Native tag suggester integration when using # trigger Inline task link overlay enhancements Configurable visible properties for inline task cards PropertySelectorModal for selecting which properties to display Improved layout: title prioritized, horizontal scrolling for metadata Real-time updates when task data changes New utility services TriggerConfigService - manages NLP trigger configurations PropertySelectorModal - reusable multi-select property picker Property helpers for consistent property handling across views Kanban column reordering via drag and drop Drag column headers to reorder columns Column order is saved per grouping property Visual feedback during drag operations Mini calendar enhancements (in progress) Week numbers column Heat map intensity visualization Note preview tooltips on hover Keyboard navigation Unified Relationships widget Consolidated project subtasks, task dependencies, and blocking relationships into a single dynamic widget Four automatic tabs: Subtasks (Kanban), Projects (List), Blocked By (List), Blocking (Kanban) Tabs automatically show/hide based on available relationship data Bases views handle all data updates reactively - no manual refresh needed Single configuration setting: show/hide and position (top/bottom) Significantly reduced code complexity (430 fewer lines) Fixed# (#1084) Fixed word wrapping in NLP preview items Thanks to @maybetm for the fix (#975) Fixed advanced calendar list headers not respecting theme colors Thanks to @hugohil for the fix (#1089) Fixed embedded task list bases growing unbounded and leaving large empty space Embedded bases now scroll internally instead of expanding to show all tasks Consistent behavior between task list and kanban embedded views Thanks to @same774 for reporting with screenshot Bases Calendar view options now working correctly Fixed \"Highlight today\" toggle not applying - now properly adds/removes CSS class when toggled Fixed calendar view type (month/week/day/etc) not being saved when changed via calendar buttons View type is now persisted when users click month/week/day buttons in the calendar UI (#1050) Task modal no longer adds unwanted empty contexts and projects arrays FieldMapper now checks if arrays are empty before writing to frontmatter Thanks to @nightroman for reporting this issue Inline task link overlay fixes Fixed layout prioritization: title now prioritized over metadata Added horizontal scrolling for metadata to prevent overflow Fixed real-time update listeners for task data changes Fixed group collapse/expand functionality in TaskListView Re-registered click event listener for group headers using Component API Groups can now be properly collapsed and expanded Fixed config loading race condition in KanbanView and CalendarView Config is now properly loaded in onload() lifecycle method Views wait for config before rendering options Fixed MiniCalendarView to use direct Bases API like other views Consistent use of Component lifecycle methods Proper cleanup in onunload() Changed# NLP system overhaul Replaced StatusSuggestionService wrapper with direct NaturalLanguageParser usage Consolidated trigger configuration into unified TriggerConfigService Enhanced NaturalLanguageParser with full trigger and user field support Removed custom # tag autocomplete in favor of Obsidian's native tag suggester (when using # trigger) Task card and editor improvements Simplified TaskCard interface - removed unused options (showCheckbox, showArchiveButton, groupByDate) Refactored TaskLinkWidget to use unified TaskCard component for consistency Added support for inline vs. block layout modes in task cards Improved task card BEM CSS with better styling for inline mode Settings UI enhancements NLP triggers now configurable through Settings > Features tab Added settings for inline task card visible properties Improved appearance tab with property selector integration Better organization of NLP-related settings Refactored Bases views to use Component lifecycle properly Views now extend Component and use onload()/onunload() Automatic cleanup of event listeners via Component.registerDomEvent() Improved state management and ephemeral state handling Improved development experience Converted ESLint errors to warnings for non-blocking development Fixed various linting issues and unused imports Removed# Removed StatusSuggestionService (functionality consolidated into NaturalLanguageParser) Breaking Changes# Relationships widget settings consolidated (automatic migration) Old settings removed: showProjectSubtasks, projectSubtasksPosition, showTaskDependencies, taskDependenciesPosition New unified settings: showRelationships, relationshipsPosition Widget now appears on ALL notes (tasks, projects, regular notes) - Bases filtering controls which tabs are visible Migration: Existing users will see the new unified widget automatically. If you had project subtasks enabled, relationships widget will be enabled by default Bases file change: The command mapping changed from 'project-subtasks': 'TaskNotes/Views/project-subtasks.base' to 'relationships': 'TaskNotes/Views/relationships.base' Run \"Create Default Files\" in Settings > General to create the new relationships.base file"},{"title":"TaskNotes 4.0.0-beta.3","url":"/obsidian/releases/4.0.0-beta.3/","description":"Beta Release","product":"obsidian","text":"Beta Release You may encounter issues. Report problems on GitHub Issues. Added# Updated task card styling Increased status dot size from 16px to 18px Added subtle shadows and transitions to card hover states Updated hover effects on status and priority dots with scaling and removed glow Modified metadata pills with backdrop blur and adjusted spacing Added box shadows to interactive elements (dates, projects, tags) on hover Updated animations to use cubic-bezier easing Added gradient accents to subtask and blocking task borders Fixed subtasks appearing behind parent card hover backgrounds Fixed subtask click and context menu events bubbling to parent cards Fixed subtasks inheriting parent priority and status colors (#361) Added completion-based recurrence support with recurrence_anchor field Tasks can now recur based on completion date instead of scheduled date Set recurrence_anchor: completion in task frontmatter to enable this behavior When completing a recurring task, the next occurrence will be scheduled relative to the completion date The DTSTART in the RRULE automatically updates to the completion date, ensuring calendar views show future occurrences at the correct dates Defaults to scheduled (original behavior) if not specified Useful for tasks like \"Exercise weekly\" where you want the next occurrence 7 days after you actually complete it, not 7 days after it was scheduled Example: Complete a weekly task 2 days late, and the next occurrence will be 7 days from the completion date (not the original scheduled date) Thanks to @luciolebrillante for the original feature request, and @jhedlund, @nschenone, @BryanWall, @realJohnDoe, and @kazerniel for additional input and interest (#416) Added support for skipped recurrence instances with skipped_instances field Recurring tasks can now have individual instances marked as \"skipped\" without completing them Skipped instances are stored in the skipped_instances frontmatter array (e.g., [\"2025-11-15\", \"2025-11-22\"]) Right-click on a recurring task instance in calendar views to skip/unskip it Visual styling differentiates skipped instances: Calendar views: Gray background with muted appearance Task cards: Strike-through text with gray styling Skipped instances don't affect the recurrence pattern - future instances continue as scheduled Useful for holidays, vacations, or other planned exceptions to recurring tasks Thanks to @mdbraber for the suggestion to use an array similar to complete_instances, and @jerzy-dudzic for reporting the issue Fixed# (#893) Fixed yearly recurring tasks not always updating scheduled date to next occurrence when completed Increased look-ahead period for yearly recurrence from 365 days to 800 days (~2.2 years) Also optimized look-ahead periods for other frequencies: daily (30 days), weekly (90 days), monthly (400 days) Ensures the next occurrence is always found when completing recurring task instances Thanks to @VenturaNotes for reporting (#951) Fixed yearly recurring tasks not showing up in calendar's weekly, 3-day, or day views Extended the look-ahead period for yearly recurring tasks when generating calendar instances Calendar views now look ahead ~2.2 years for yearly tasks to ensure occurrences appear even in short date ranges Only displays instances that fall within the actual visible calendar range Weekly recurring tasks were unaffected and continued to work correctly Thanks to @bespokecomp for reporting (#889) Fixed git merge conflicts in calendar subscription metadata Calendar subscription lastFetched and lastError fields are now stored in memory instead of being saved to disk Prevents git conflicts when syncing vaults across multiple computers that independently fetch calendar subscriptions The \"last synced\" timestamp in settings will reset on plugin reload, but subscriptions will re-fetch automatically Thanks to @karlfrohlich for reporting Fixed recurrence modal not loading DTSTART date/time when editing existing recurrence rules The custom recurrence modal now correctly parses and displays the start date and time fields Fixed parser that was splitting on = instead of : for DTSTART values (#1097) Fixed custom properties and formulas not displaying in Bases views Updated TaskCard to use Bases API's getValue() method for formulas and custom note properties Formulas now work correctly using formula.NAME syntax Custom note properties now work correctly using note.PROPERTY syntax Thanks to @cathywu for reporting (#1099) Fixed issues with default Bases file creation Fixed double-prefix bug in relationships template that generated invalid filter expressions like note.note.projects Fixed race condition where files created during plugin load wouldn't appear in file explorer Default Bases files now generate with correct property paths and appear reliably in the file explorer Thanks to @kmaustral for reporting (#1110) Fixed open recurring tasks appearing crossed out in Tasks view Removed stale selectedDate property that was never updated in v4 Tasks view now uses fresh UTC-anchored \"today\" for correct recurring task completion status Fixes issue where tasks completed yesterday would appear crossed out today for users in positive UTC offset timezones Also fixed KanbanView to use UTC-anchored dates for consistency Thanks to @kmaustral for reporting (#1118) Fixed user-defined fields not working in inline task conversion User-defined fields like >customfield value now properly convert to frontmatter when using the \"TaskNote: Convert task to TaskNote\" command Fixed fields appearing with internal IDs (e.g., field_1761435101864) instead of configured frontmatter key names Array values are now properly joined with commas Added userFields property to ParsedTaskData interface to support custom fields throughout the conversion flow Thanks to @guncav for reporting Fixed kanban column width CSS constraints not matching settings Updated CSS min-width from 280px to 200px and max-width from 350px to 500px to match slider range Column width slider now works correctly across the full 200-500px range Kanban view now shows empty columns for all user-defined statuses when grouping by status Empty columns appear for custom statuses defined in settings, even when no tasks have that status Allows users to drag tasks into empty status columns Works in both flat kanban view and swimlane mode Respects the existing \"Hide empty columns\" setting Thanks to @williamcheuk03 for reporting this issue"},{"title":"TaskNotes 4","url":"/obsidian/releases/4.0.1/","description":"TaskNotes 4.0.1 is a stability-focused major release that finishes the migration to Obsidian's Bases core plugin. Every task-facing view (Task List, Kanban, Calendar, Agenda...","product":"obsidian","text":"TaskNotes 4.0.1 is a stability-focused major release that finishes the migration to Obsidian's Bases core plugin. Every task-facing view (Task List, Kanban, Calendar, Agenda, Mini Calendar, and the embedded Relationships widget) now runs on .base files. This refactor simplifies the plugin codebase, removes bespoke UI logic, and lets workflows feel native to Obsidian—views are just files in your vault. Highlights# New features and improvements: Performance improvements Virtual scrolling in Task List and Kanban views handles 30,000+ tasks without performance degradation OAuth calendar integration Google Calendar and Microsoft Outlook bi-directional sync Drag calendar events in the TaskNotes calendar to update them online Configurable modals and NLP New Modal Fields settings tab for moving, hiding, or requiring fields in create/edit modals Rich markdown editor and customizable NLP triggers, including autocomplete for user fields Time management features Time Entry Editor Modal Improved Timeblock creation and management Completion-based recurrence with recurrence_anchor field Skippable recurrence instances Bases architecture changes: Bases-first architecture Task views ship as .base files inside TaskNotes/Views/ Commands and ribbon buttons now open files you control Filtering/grouping/sorting uses Bases YAML instead of TaskNotes-specific UI Agenda is a dedicated list-mode calendar .base file for fast daily/weekly reviews Inline workflows stay in sync Unified Relationships widget embeds a Bases view so project subtasks, dependencies, and blocking tasks stay in one place Task cards inside notes honor the same Bases filtering/grouping rules as standalone views Why Bases?# Moving everything to Bases allowed us to delete thousands of lines of bespoke filtering logic, state management, and widget code. The plugin now leans on Obsidian's supported API, which: Reduces maintenance overhead and improves reliability Lets advanced users version-control and audit their view definitions Makes saved views portable between vaults Keeps TaskNotes behavior consistent with other Obsidian-native workflows Upgrade Notes# Obsidian 1.10.1 or later is required (Bases public API with group-by support) Enable the Bases core plugin before opening TaskNotes views Run Settings → TaskNotes → General → Create Default Files if you need fresh .base files Use Export All Saved Views to Bases to convert any legacy FilterBar saved views into .base files The Relationships widget uses TaskNotes/Views/relationships.base; adjust that file to change what appears inside notes Breaking Changes# The old FilterBar UI has been removed—all filtering and saved views live in .base files Legacy widget settings (showProjectSubtasks, showTaskDependencies, etc.) were replaced with showRelationships and relationshipsPosition Task view commands now fail if their mapped .base file is missing; configure paths under Settings → TaskNotes → General → View Commands Priority sorting now uses alphabetical order instead of custom weights In v3, TaskNotes used priority \"weights\" to determine sort order (higher weight = higher priority) In v4, Obsidian's Bases plugin sorts priorities alphabetically by their value The weight field has been removed from the settings UI Workaround: Name your priority values to sort alphabetically in your desired order Example: 1-urgent, 2-high, 3-medium, 4-normal, 5-low Or: a-urgent, b-high, c-medium, d-normal, e-low Agenda view has been replaced by the list view in Calendar Grouping is not supported in this view, so the \"Overdue\" group is no longer provided A separate \"Overdue\" view is available in the \"Task List\" base file Known Issues# Users upgrading from versions prior to 3.x should export saved views to Bases before deleting old plugin data Embedded Bases views still require the Bases plugin to remain enabled; disabling Bases will hide TaskNotes task views Details# Added# Virtual scrolling and lazy rendering to Bases views for handling thousands of notes without performance degradation - Thanks to @aubreyz and @turingexmachina for reporting performance issues and help with diagnosis Google Calendar and Microsoft Outlook integration via OAuth 2.0 with automatic syncing Time Entry Editor Modal for managing time entries (Alt-drag on calendar to create) Kanban Swimlane Layout with horizontal grouping and configurable column widths Saved View Converter button in settings to convert v3 saved filter views to .base files Context menus for time entries and ICS events in calendar views Calendar icon to ICS event titles for better visual distinction Hover tooltips for timeblocks in calendar views MiniCalendar view for Bases integration with monthly grid and dot indicators - Thanks to @aubreyz and @turingexmachina for reporting performance issues and help with diagnosis (#1090) Portuguese (Brazil) translation - Thanks to @andysteel for the contribution Configurable task modal fields with drag-and-drop reordering in new \"Modal Fields\" settings tab Rich markdown editor for NLP task creation with syntax highlighting and wikilink support Customizable NLP triggers with autocomplete and keyboard navigation Inline task link overlay enhancements with configurable visible properties Kanban column reordering via drag and drop with saved order per grouping property Mini calendar enhancements including week numbers, heat map visualization, note preview tooltips, and keyboard navigation Unified Relationships widget consolidating project subtasks, dependencies, and blocking relationships with automatic tabs Updated task card styling with improved hover effects, shadows, and gradient accents (#361) Completion-based recurrence support with recurrence_anchor field for tasks that recur based on completion date - Thanks to @luciolebrillante for the original feature request, and @jhedlund, @nschenone, @BryanWall, @realJohnDoe, and @kazerniel for additional input and interest (#416) Support for skipped recurrence instances with skipped_instances field and right-click skip/unskip in calendar - Thanks to @mdbraber for suggesting the array approach and @jerzy-dudzic for reporting the issue Sub-grouping support to Bases Task List view with nested grouping by any property and collapsible groups Documentation for default Bases templates showing all default .base file templates with examples Changed# All views (Calendar, MiniCalendar, Kanban, Tasks, Agenda, Project Subtasks) now use Bases architecture with .base files Calendar sources (Google, Microsoft, ICS events) can be toggled independently with improved timezone handling Reorganized settings tabs with OAuth calendar settings in Integrations tab Refactored Bases integration to use public API and trust pre-sorted data Refactored calendar modules to use ES6 imports instead of lazy require() calls Time entry events now show task context menu on right-click Replaced MinimalNativeCache with just-in-time TaskManager for zero startup time and always-fresh task data Completed internationalization with 100% translation coverage across all 6 supported languages Migrated to i18n-state-manager CLI tool for improved translation management Bases view templates now generate dynamically based on user settings with adaptive task filters Updated Bases CalendarView to show TaskNotes in property-based events NLP system overhaul with consolidated trigger configuration and direct NaturalLanguageParser usage Simplified TaskCard interface and refactored TaskLinkWidget for consistency Settings UI enhancements with NLP triggers configurable through Features tab Refactored Bases views to use Component lifecycle properly with automatic cleanup Improved development experience by converting ESLint errors to warnings Renamed \"Advanced Calendar\" to \"Calendar\" throughout the UI Improved timeblock visual styling in calendar views with reduced border width and softer shadows Updated \"Export All Views\" button to \"Export V3 Views\" to clarify it migrates v3 saved views Improved internationalization (i18n) support in General settings tab with all Bases integration settings using translation keys Changed default Tasks List template view order with \"All Tasks\" first and added \"Unscheduled\" view Fixed# (#843) Fixed task tag being added when \"Identify tasks by\" is set to \"Property\" - Thanks to @jack2game for reporting Fixed dark mode calendar borders Fixed Bases Kanban column ordering - Thanks to @mweichert for reporting Fixed state management bug in FilterSettingsComponent Fixed timezone handling for recurring events (#1022, #684) Fixed tasks randomly disappearing when Smart Connections plugin is enabled by eliminating race condition - Thanks to @alejandrospoz, @seepage87, @amarjt, @luckb0x, and camara-tech for reporting and help debugging (#992) Fixed \"Failed to resolve module specifier 'obsidian'\" error when moving recurring task instances in calendar - Thanks to @jalooc for reporting Fixed task dependencies not displaying on task cards with proper isBlocked and isBlocking flags Fixed Bases property mapping for user-configured field names Fixed Bases views not respecting user-configured visible properties Fixed MiniCalendar UTC anchoring for consistent timezone-independent date handling Fixed DateValue conversion in BasesDataAdapter for property-based events in CalendarView (#1084) Fixed word wrapping in NLP preview items - Thanks to @maybetm for the fix (#975) Fixed advanced calendar list headers not respecting theme colors - Thanks to @hugohil for the fix (#1089) Fixed embedded task list bases growing unbounded and leaving large empty space - Thanks to @same774 for reporting with screenshot Fixed \"Highlight today\" toggle and calendar view type persistence in Bases Calendar view options (#1050) Fixed task modal adding unwanted empty contexts and projects arrays - Thanks to @nightroman for reporting Fixed inline task link overlay layout prioritization and horizontal scrolling for metadata Fixed group collapse/expand functionality in TaskListView Fixed config loading race condition in KanbanView and CalendarView Fixed MiniCalendarView to use direct Bases API like other views (#893) Fixed yearly recurring tasks not always updating scheduled date to next occurrence when completed - Thanks to @VenturaNotes for reporting (#951) Fixed yearly recurring tasks not showing up in calendar's weekly, 3-day, or day views - Thanks to @bespokecomp for reporting (#889) Fixed git merge conflicts in calendar subscription metadata by storing in memory instead of disk - Thanks to @karlfrohlich for reporting Fixed recurrence modal not loading DTSTART date/time when editing existing recurrence rules (#1097) Fixed custom properties and formulas not displaying in Bases views using getValue() method - Thanks to @cathywu for reporting (#1099) Fixed issues with default Bases file creation including double-prefix bug and race condition - Thanks to @kmaustral for reporting (#1110) Fixed open recurring tasks appearing crossed out in Tasks view by using UTC-anchored dates - Thanks to @kmaustral for reporting (#1118) Fixed user-defined fields not working in inline task conversion to TaskNote - Thanks to @guncav for reporting Fixed kanban column width CSS constraints not matching settings slider range Fixed Kanban view showing empty columns for all user-defined statuses when grouping by status - Thanks to @williamcheuk03 for reporting (#1103) Fixed TaskNotes/Views folder being created unnecessarily on startup - Thanks to @Wayment9504 for reporting (#1133) Fixed empty priority columns not showing in Kanban view when \"Hide empty columns\" is disabled - Thanks to @luckb0x for reporting Fixed OAuth calendar cards showing \"Unknown account\" by removing non-functional Account field - Thanks to @Oblique for reporting Fixed incorrect Bases syntax in default template files with correct parameter naming Fixed incorrect Bases syntax in \"Export V3 Views\" feature with correct YAML structure (#1127) Fixed custom priority colors not being respected in Task List and Subtasks sections - Thanks to @HPmattsloper for reporting (#1043) Fixed inability to set \"at time of event\" (0 offset) as default reminder in settings - Thanks to @dblinnikov for reporting (#1055) Fixed break sessions being logged as type: work when started via command/hotkey - Thanks to @0-BSCode for reporting and debugging (#1024) Fixed date/time picker immediately closing when selecting time on iPhone by refactoring to native Modal components - Thanks to @3zra47 for reporting (#1122) Fixed inline task titles being truncated too aggressively with increased max-width - Thanks to @jacorvillo for reporting Fixed Obsidian crashes when invalid time values entered in Bases calendar view configuration (#1120) Fixed custom field mappings not being respected throughout the application - Thanks to @kmaustral for reporting (#1121) Fixed custom user fields being saved with auto-generated IDs instead of user-defined property keys - Thanks to @guncav for reporting (#1123) Fixed relationships widget only displaying on task notes, now appears on both task and project notes - Thanks to @dblinnikov for reporting Fixed time entries not showing in calendar view for tasks without scheduled or due dates (#1091) Fixed task card and relationships widgets appearing inside footnote editors - Thanks to @3zra47 for reporting (#1086) Fixed calendar \"+more\" popover showing white text on white background in dark mode - Thanks to @same774 for reporting (#1076) Fixed inability to create timeblocks ending at midnight (00:00) - Thanks to @skoove for reporting (#958) Fixed cursor jumping and layout shifts when typing near task card or relationships widgets in live preview - Thanks to @thesmithmode for detailed debugging information (#513) Fixed task card and relationships widgets not appearing in reading mode and fixed critical memory leak - Thanks to @berzernberg for reporting Removed# Removed StatusSuggestionService (functionality consolidated into NaturalLanguageParser) Removed legacy FilterBar UI - all filtering now lives in .base files Removed legacy views"},{"title":"TaskNotes 4.0.2","url":"/obsidian/releases/4.0.2/","description":"This release fixes some of the more urgent (and easy-to-fix) bugs that were introduced in the v4 major release. Thanks to everyone for your patience, and to those who have repor...","product":"obsidian","text":"This release fixes some of the more urgent (and easy-to-fix) bugs that were introduced in the v4 major release. Thanks to everyone for your patience, and to those who have reported issues, for taking the time to do so. There will be more releases over the coming weeks to iron out some of v4's kinks. Added# Added \"Not Blocked\" view to default task list template Shows incomplete tasks that are ready to work on (not blocked by incomplete dependencies) Uses Bases list.filter() to check completion status of each blocking task This new view can be accessed by regenerating the Task List view, or by copying the filters from the default base templates documentation Fixed# (#1145, #1156) Fixed default Kanban view requiring manual 'Group by' configuration Default Kanban template now automatically includes groupBy property set to status Resolves \"Kanban requires a 'Group by' property to be configured\" error on first use Users no longer need to manually configure grouping through the Sort menu Thanks to @randomness42 and @seepage87 for reporting Fixed user-defined custom fields appearing as user:field_xxx in generated base templates Custom fields now use their actual property names (e.g., effort instead of user:field_1761435303709) Ensures Bases can properly query user-defined properties Also fixed totalTrackedTime to correctly map to the configured timeEntries property name (#1145) Improved Kanban error message when no 'Group by' property is configured Now includes instructions: \"Click the 'Sort' button and select a property under 'Group by'\" Thanks to @randomness42 for the suggestion (#1139, #1141) Fixed relationships widget not appearing in project notes Project references are now resolved to full file paths when indexing Uses Obsidian's link resolution API to handle wikilinks, markdown links, and relative paths Restores v3.x behavior where subtasks appear in parent project notes Thanks to @jhedlund, @n1njaznutz, and @luckb0x for reporting and testing Fixed dependency blocking status to be status-aware \"Blocked (x)\" pill now only appears when tasks have incomplete blocking dependencies Tasks with all completed blocking dependencies no longer show as blocked Fixed cache invalidation bug causing blocking/blocked pills to disappear when editing tasks When a task is modified, only forward dependencies are cleared (stored in its frontmatter) Reverse dependencies are preserved (stored in other tasks' frontmatter) Changed# Removed custom TaskNotes icon from task modals Task creation and edit modals now use Obsidian's standard title styling Thanks to @kepano for the suggestion Moved default base templates documentation to docs/views/ Location: docs/views/default-base-templates.md Added cross-references to official Obsidian Bases documentation Updated code comments to reference new documentation path Fixed incorrect quote escaping in default base templates documentation YAML examples now use proper single quotes for strings containing double quotes"},{"title":"TaskNotes 4.0.3","url":"/obsidian/releases/4.0.3/","description":"TaskNotes documentation.","product":"obsidian","text":"Fixed# (#1157) Fixed task embeds appearing on new line instead of inline with bullets in lists Changed inline task cards to use span elements instead of divs for proper inline flow Added max-width constraint to prevent wrapping when tasks are wider than editor Task embeds now display correctly inline with bullet points during live preview Thanks to @3zra47 for reporting (#1168) Fixed mini calendar stealing focus every few seconds when pinned to sidebar Thanks to @DearHaruHaru for reporting (#1161, #1162) Fixed \"unexpected scalar\" YAML parsing error in generated tasks-default.base template Changed nested quotes in \"Not Blocked\" filter from double to single quotes Thanks to @benschifman and @InterstellarRaccoon for reporting, @GarrettKaupp for identifying the fix Changed# Updated task modal UI to use native Obsidian patterns for better theme compatibility Thanks to @kepano for feedback"},{"title":"TaskNotes 4.0.4","url":"/obsidian/releases/4.0.4/","description":"TaskNotes documentation.","product":"obsidian","text":"Added# (#1134, #779) Added CMD+Enter (Mac) / Ctrl+Enter (Windows/Linux) keyboard shortcut support for saving in all modals Works from any input field in task creation, task edit, time entry, timeblock, and property selector modals Thanks to @luckb0x, @hamlim and @nightroman for the feature requests Fixed# (#1181) Fixed vertical overflow in Kanban view columns with fewer than 15 tasks Prevents cards from extending beyond column boundaries before virtualization activates Thanks to @lomarcanys for reporting (#1177) Bases views now anchor recurring completion and calendar navigation to the right date Recurring completion from Bases Task List/Kanban uses the task's scheduled/due date instead of \"today\" (fixes complete_instances) Bases calendar navigation and property-based events use UTC anchors to avoid previous-day jumps Thanks to @nslee123 for flagging the issue Bases calendar navigation now respects UTC-anchored dates to avoid landing on the previous day Corrected all-day end date calculation to prevent off-by-one spans Added regression test for the UTC anchor behavior Thanks to KaCii for flagging the issue Changed# Refactored plugin styling to better align with Obsidian's native UI conventions Replaced all cursor: pointer with cursor: var(--cursor) (100+ instances) to follow Obsidian's cursor convention Removed forced border: none; box-shadow: none rules that were fighting against Obsidian's native button styling Scoped custom .tn-btn button system to settings modal only (.mod-settings), allowing Obsidian's native button styles to work elsewhere Thanks to @kepano for guidance"},{"title":"TaskNotes 4.0.5","url":"/obsidian/releases/4.0.5/","description":"TaskNotes documentation.","product":"obsidian","text":"Changed# (#790) Task edit modal now shows unresolved project links with appropriate styling Similar to how dependencies are displayed, unresolved projects now appear with visual indication Hovering over an unresolved project shows a tooltip explaining it couldn't be resolved Thanks to @aubreyz for reporting Fixed# (#1011) Fixed chevrons incorrectly showing on tasks with no subtasks Project index was incorrectly adding all linked files instead of only files referenced in the projects field Now properly parses the projects field and only indexes those specific files as projects Also fixed alias handling in project and dependency links - aliases are now correctly stripped before link resolution Thanks to @craziedde for reporting (#1200) Fixed kanban drag & drop not updating task properties correctly Dragging tasks to different columns now properly triggers business logic (completedDate, auto-archive, webhooks) Previously, kanban updates bypassed updateProperty and directly modified frontmatter Thanks very much to @tvoklov for the PR (#1203) Fixed autocomplete dropdown being clipped inside NLP field boundaries Configure CodeMirror tooltips to render in document.body instead of constrained editor container Prevents suggestion dropdown from being hidden when it extends beyond the NLP field height Thanks to @Andrei-Ioda for reporting (#1172) Fixed task lists and checkboxes rendering incorrectly in task details editor Remove padding-left override on .cm-line to allow CodeMirror decorations (checkboxes, indentation) to render properly Content padding is now handled by .cm-content while .cm-line uses natural spacing Thanks to @nightroman for reporting Fixed relationships widget not appearing on project notes without frontmatter Widget now correctly shows on any note referenced as a project by tasks, regardless of whether the note has frontmatter Fixed task card and relationships widgets not appearing when opening notes in source mode Removed live preview mode restriction to allow widgets to render in both source and live preview modes (#901) Fixed calendar view toolbar buttons overflowing on narrow screens Added flex-wrap: wrap to calendar header toolbar to allow buttons to wrap to multiple lines Thanks to @RumiaKitinari for reporting (#1193), (#1194), (#1185) Fixed new calendar views not respecting user's default calendar settings Previously, new Bases calendar views used hardcoded inline defaults instead of user-configured preferences Calendar view initialization now correctly uses plugin.settings.calendarViewSettings as the fallback Thanks @ki5ck, @minchinweb and @ThamirysOlv for reporting Fixed calendar to ensure that it respects user's locale Tries to use calendar locale, then tries UI language, then system language, then falls back to English (#1043) Fixed default reminders with \"at time of event\" (0 offset) not being applied to tasks UI was displaying \"1\" instead of \"0\" for zero-offset reminders in settings Thanks to @dblinnikov for reporting (#1206) Fixed NLP status parsing regressions with trigger prefixes and temporal keywords Manually typing status trigger + label now correctly parses (e.g., *Done when label is Done) Status values containing temporal keywords no longer misparsed as dates (e.g., Expedite = Now) Thanks very much to @renatomen for the PR (#1212) Fixed \"Show release notes on update\" toggle not saving correctly Thanks to @Jon-dog for reporting (#1197) Add Portuguese language to list of translations in general tab settings Allows users to select the Portuguese translation option Thanks to @andysteel for the PR Fixed file properties displaying incorrectly in Bases views File properties like file.name, file.basename, file.size, etc. were showing as \"Title\" or returning null Now correctly extracts and displays all file properties from Obsidian's file metadata Supports both direct TFile properties (name, basename, extension, path, size, ctime, mtime) and computed properties (links, embeds, tags, backlinks, aliases)"},{"title":"TaskNotes 4.1.0","url":"/obsidian/releases/4.1.0/","description":"(#1245), (#793) Added custom icon support for task statuses","product":"obsidian","text":"Added# (#1245), (#793) Added custom icon support for task statuses Configure a Lucide icon name (e.g., check, circle, clock) per status in Settings → Task Properties → Task Statuses Icons display instead of the colored dot, inheriting the status color Browse available icons at lucide.dev Improves accessibility by allowing shape-based status differentiation Thanks to @3Fish for the feature request and @Raonmir2, @aubreyz, @prayidae, and @anareaty for the discussion on accessibility and icon-based indicators (#1259) Added Property Types Reference documentation Documents expected data types (text, list, date, number) for all frontmatter properties Includes format specifications, examples, and a complete YAML reference Thanks to @Oblique82 for the suggestion (#1248) Added formula property support for sub-grouping in Bases Task List view Formula properties (e.g., formula.myFormula) now appear in the Sub-group by dropdown Supports all Bases Value types including strings, numbers, booleans, dates, and lists Thanks to @prayidae for the feature request (#1070) Added formula property support for swimlanes in Bases Kanban view Formula properties now appear in the Swim Lane dropdown Fixed swimlanes displaying empty when grouping by formula properties Note: Dragging tasks between formula-based columns/swimlanes is disabled (formulas are computed values) Thanks to @cathywu for reporting (#1010), (#1126) Added batch task selection and editing in Task List and Kanban views Shift+click to select multiple tasks Right-click selected tasks to open batch context menu Batch operations: change status, priority, due date, scheduled date, archive, delete Drag multiple selected cards in Kanban to move them together Click the selection count indicator to clear selection Thanks to @jalooc and @solidabstract for the feature requests (#1207) Added inline search box to Bases views (Task List, Kanban, Calendar) Enable via \"Enable search box\" toggle in view settings Searches across title, status, priority, tags, contexts, projects, and visible custom properties Press Escape or click × to clear search Thanks to @renatomen for the PR (#363) Added \"Create or open task\" command with NLP-based quick task creation Open via command palette or assign a hotkey Search existing tasks or type natural language to create new tasks (e.g., \"Buy groceries tomorrow #shopping\") Press Enter to select an existing task, Shift+Enter to create a new task Real-time preview shows parsed title, due date, priority, tags, and other metadata Can be used when adding sub-tasks to create sub-tasks on-the-fly Thanks to @luciolebrillante for the feature request (#1044), (#1222) Added unsaved changes confirmation when closing task edit modal Detects modifications to any field (title, dates, priority, tags, etc.) Shows confirmation dialog with Save/Discard/Keep Editing options Prevents accidental data loss from clicking outside the modal or pressing Escape Thanks to @renatomen for the PR and @0-BSCode for the feature request (#904) Added visual highlighting for overdue and past dates on task cards Overdue due dates now display in red text Past scheduled dates now display in blue text Thanks to @ras0q for the suggestion (#1164) Added priorityWeight formula to all default Bases templates for priority-based sorting Formula maps each priority value to a numeric weight based on your custom priority configuration Sort by formula.priorityWeight in ascending order to get highest priority tasks first Example: if(priority==\"high\",0,if(priority==\"normal\",1,if(priority==\"low\",2,999))) Thanks to @jhedlund for the suggestion (#1257), (#1064) Added configurable event stacking options for Bases Calendar view Allow events to overlap: Toggle whether timed events visually overlap or display side-by-side in week/day views Max stacked events: Limit horizontal event stacking in week/day views (0 = unlimited) Max events per day: Limit events shown per day cell in month view (0 = auto based on cell height) Max event rows per day: Limit event rows per day cell in month view (0 = unlimited) Configure per-view in the Bases Calendar view settings under Layout Thanks to @3zra47 and @hasanyilmaz for the feature requests Changed# Improved inline task conversion to merge TasksPlugin and NLP parsing results Previously, if a task had hashtags (e.g., - [ ] Buy milk tomorrow #groceries), NLP parsing was skipped entirely Now NLP always parses the clean title to extract dates/times, then merges with TasksPlugin-extracted metadata TasksPlugin explicit values (emoji dates like 📅) take priority over NLP-inferred values Tags, contexts, and projects from both sources are combined and deduplicated Polished task card styling for a more native Obsidian look Simplified hover and focus states to use native Obsidian colors Removed blur filter and shadows from metadata pills Fixed subtask chevron vertical alignment with status dot Reduced swimlane label column width in Kanban view (#1151) Increased mini calendar heatmap color intensity for better visibility Days with notes now show more noticeable colors, especially with low note counts Intensity levels increased from 10/25/45/65% to 25/40/55/70% Thanks to @arreme for the suggestion Fixed# (#1271) Fixed custom user fields not appearing in task modals after creation New custom fields are now automatically added to both creation and edit modals Deleting a custom field also removes it from modal configuration Updating a field's display name syncs to the modal configuration Thanks to @craziedde for reporting (#1256) Fixed links in custom properties not rendering as clickable in task cards Wikilinks ([[Note]]) now render correctly in Bases views Markdown links ([text](url)) now render correctly in all views Links in list-type properties are also properly rendered Thanks to @3zra47 for reporting (#1157) Fixed inline task embeds breaking layout when placed in indented bullet lists Task titles now wrap naturally within line boundaries instead of forcing the entire card to a new line Metadata (dates, tags, etc.) stays inline when space permits, with horizontal scrolling on hover when needed Thanks to @3zra47 for reporting (#1241) Fixed deleting custom priorities in settings removing the wrong priority when multiple priorities exist Thanks to @Anthonyhunter100 for reporting (#1165) Fixed Kanban view grouping by list properties (contexts, tags, projects) treating multiple values as a single combined column Tasks with multiple values now appear in each individual column (e.g., a task with contexts: [work, call] appears in both \"work\" and \"call\" columns) Added \"Show items in multiple columns\" option (enabled by default) to control this behavior Fixed drag-and-drop to properly add/remove individual values instead of replacing the entire list Fixed swimlane mode to also respect list property explosion Thanks to @dictionarymouse for reporting (#1217) Fixed inconsistent Ctrl+Click/Cmd+Click behavior for opening notes in new tabs Note cards and internal links now properly support Ctrl/Cmd+Click to open in new tab Added middle-click support for opening in new tab Thanks to @diegomarzaa for reporting (#1265) Fixed task edit modal corrupting markdown-style project links on save Links like [Project Name](path.md) were being wrapped in extra brackets: [[[Project Name](path.md)]] Plain text project names are now preserved as-is instead of being converted to wikilinks Markdown-style project links now resolve properly and display as linked (not orange/unresolved) Thanks to @minchinweb for reporting (#1266) Fixed Kanban view scroll position resetting to top of column after any change Clicking status dots, priority, or other task properties no longer jumps the column back to top Scroll position is now preserved for both regular columns and swimlane cells Thanks to @essouflenfer for reporting (#485), (#1221), (#1262) Fixed NLP parser not recognizing non-ASCII characters in tags, contexts, and projects Tags like #investigación were being truncated at accented characters (e.g., #investigaci) Non-Latin scripts (Chinese, Cyrillic, Japanese, etc.) were not recognized at all (e.g., @家, #杂事, @ознакомиться) Parser now uses Unicode-aware regex patterns to support all languages and scripts Thanks to @Arachnidai, @fidelaznar, and @qian1ing for reporting (#1249) Fixed project preview in task creation modal showing quadruple brackets ([[[[Project]]]]) Projects selected from autocomplete were being wrapped in extra wikilink brackets in the preview display Thanks to @2vzqwz8tvg-png for reporting (#1249) Fixed custom priority ordering in settings being unclear and non-intuitive Priority cards are now draggable to reorder (like statuses) Priorities are displayed in weight order (lowest to highest priority) New priorities are added at the end (highest priority) instead of with a fixed weight Thanks to @2vzqwz8tvg-png for reporting (#1272) Fixed recurrence anchor not being saved when set to \"completion\" during task creation Selecting \"completion\" as the recurrence anchor now correctly persists to the task frontmatter Thanks to @blaxcky for reporting (#1128) Fixed NLP parser not allowing slashes in context names Contexts like @shopping/groceries were being split into @shopping and /groceries Hierarchical context names now work the same as tags and projects Thanks to @wealthychef1 for reporting (#1170) Fixed dateCreated and dateModified not using custom property names when creating notes from calendar events Notes created from ICS events now respect the field mapping configured in settings Thanks to @maddie-m for reporting (#1171) Fixed calendar event toggles not responding to changes after initial load Toggling \"Show scheduled tasks\", \"Show due tasks\", and other event filters now correctly updates the calendar Previously, changing these toggles had no effect until the view was reloaded Thanks to @hangryscribe3 for reporting (#1198) Fixed project links being created relative to the wrong file when editing from Bases views Relative paths in project links are now correctly resolved relative to the task note file Previously, editing a task from a Bases view would create project links relative to the .base file Thanks to @minchinweb for reporting"},{"title":"TaskNotes 4.1.1","url":"/obsidian/releases/4.1.1/","description":"TaskNotes documentation.","product":"obsidian","text":"Added# (#1277) Icon autosuggestion for custom status settings Type to search through all available Lucide icons Thanks to @Arachnidai for the suggestion New formula properties in default Base templates Date calculations: daysUntilDue, daysUntilScheduled, daysSinceCreated, daysSinceModified Boolean helpers: isOverdue, isDueToday, isDueThisWeek, isScheduledToday, isRecurring, hasTimeEstimate Time tracking: timeRemaining, efficiencyRatio, timeTrackedThisWeek, timeTrackedToday, timeTrackedFormatted Grouping: dueMonth, dueWeek, scheduledMonth, scheduledWeek, dueDateCategory, timeEstimateCategory, ageCategory, createdMonth, modifiedMonth, priorityCategory, projectCount, contextCount, trackingStatus Combined due/scheduled: nextDate, daysUntilNext, hasDate, isToday, isThisWeek, nextDateCategory, nextDateMonth, nextDateWeek - work with whichever date comes first Sorting: priorityWeight, urgencyScore (combines priority with date proximity) Display: dueDateDisplay (relative dates like \"Today\", \"Tomorrow\", \"3d ago\") Action-oriented views (Not Blocked, Today, Overdue, This Week) now sort by urgency score, showing most important tasks first See Default Base Templates documentation for full details Note: To get these new formulas, either copy them from the documentation, or delete your .base files in TaskNotes/Views/ and restart Obsidian to regenerate them Changed# (#1282) Added spacing between task title and metadata in inline task widgets for improved readability Thanks to @3zra47 for the suggestion Custom status icons now display in all context menus (task context menu, batch operations menu, and task creation/edit modals) Added embedded video guide for Google Calendar OAuth setup in documentation Thanks to @antoneheyward for the tutorial Fixed# (#1279) Fixed Kanban column width setting not being respected on mobile devices Thanks to @guncav for reporting (#1026), (#1177) Fixed recurring task completion from Base views recording the wrong date for users in negative UTC offset timezones (e.g., PST/PDT) when completing tasks in the evening The bug caused complete_instances to record the next day instead of the user's current calendar day Thanks to @3zra47 and @nslee123 for reporting and providing detailed reproduction steps"},{"title":"TaskNotes 4.1.2","url":"/obsidian/releases/4.1.2/","description":"TaskNotes documentation.","product":"obsidian","text":"Fixed# Significant performance improvements for Bases views (TaskList, Kanban, Calendar) Reduced extractDataItems time from ~4 seconds to ~5-10ms for large vaults (6000+ tasks) Computed file properties (file.backlinks, file.links, etc.) are now fetched lazily during render instead of upfront Only visible items (with virtualization) trigger expensive property computations Added debouncing to onDataUpdated to prevent UI freezes during typing Timeblock generation now uses Obsidian's metadataCache instead of file reads Added date range filtering for calendar events to skip events outside visible range (#1285) Calendar view uses 5-second debounce to prevent flickering while typing Thanks to @steven-murray for reporting Calendar view switching (month/week/day/list) is now much faster View type is now saved on unload instead of on every change Fixed task edit modal archive button being too narrow on mobile devices (#1319) Added missing properties to Field Mapping settings recurrence_anchor - now in Settings > Task Properties > Task Details skipped_instances - now in Settings > Task Properties > Metadata Properties Thanks to @kazerniel for reporting (#1310) Fixed inline task conversion deleting text when task title exceeds filename limits Text that cannot fit in the filename is now preserved in the task note's body Thanks to @prayidae for reporting (#1301) Fixed inline task wikilinks leaving blank space when no metadata properties are visible Thanks to @Richard-UMPV for reporting (#1317) Fixed project autosuggest filters not working correctly when only \"Required Property Key\" is configured NLP + trigger now properly filters by property existence when no property value is specified Modal \"Add to project\" button now shows consistent results with inline autosuggest Thanks to @JacksonMcDonaldDev for reporting (#1287), (#1307) The \"New\" button in Bases views now opens the TaskNotes creation modal Tasks created from Bases views now respect default properties (status, priority, etc.) Tasks are now created in the configured default folder instead of the views folder Thanks to @anareaty and @sylvainfct-dot for reporting (#1291) Fixed Microsoft Calendar OAuth documentation using wrong redirect URI Added instructions for configuring via Azure manifest editor Thanks to @PlecotusAustriacus for reporting Added# (#803) New command \"Convert current note to task\" to add task properties to an existing note Thanks to @GardarikanetS and @diegomarzaa for suggesting (#1080) Custom user fields now support default values Each field type has an appropriate input: text field, number input, toggle, date preset dropdown, or comma-separated list Defaults are applied when creating tasks via modal, instant conversion, \"Create or open task\" command, or HTTP API Thanks to @bradyrx for suggesting Changed# Added documentation link to settings panel (links to tasknotes.dev) Reorganized settings panel for improved discoverability Removed \"Defaults\" tab - default values are now configured alongside each property in the Task Properties tab Moved task filename format settings to the Title property section Moved project autosuggest settings to the Projects property section Body template setting moved to the Features tab Added descriptions to each property explaining its purpose Moved \"Folder for converted tasks\" setting to General tab under Task Storage for better discoverability Updated setting description to clarify that leaving empty uses the default tasks folder"},{"title":"TaskNotes 4.1.3","url":"/obsidian/releases/4.1.3/","description":"This patch fixes a critical performance issue affecting the Calendar views. As a bonus, it adds a configurable \"split\" view to the task creation/edit modals.","product":"obsidian","text":"This patch fixes a critical performance issue affecting the Calendar views. As a bonus, it adds a configurable \"split\" view to the task creation/edit modals. Added# Split layout for task modals on wide screens (900px+) Details editor appears in a dedicated right column when the modal is expanded New setting \"Split layout on wide screens\" in Modal Fields settings tab to toggle this behavior Improves usability by showing form fields and details side-by-side Fixed# (#1330) Fixed calendar view regression taking 5 seconds to load and respond to user interactions Initial calendar load is now immediate again User interactions (drag/drop, creating timeblocks, etc.) respond instantly Removed redundant date filtering (FullCalendar handles this more efficiently) Thanks to @ysafonov, @kmaustral, @sunjiawe, @Мизгирь, and @FiliusIcari for reporting"},{"title":"TaskNotes 4.10.0","url":"/obsidian/releases/4.10.0/","description":"TaskNotes documentation.","product":"obsidian","text":"Added# New companion plugin: TaskNotes Workflows adds Markdown-defined automation for TaskNotes tasks, events, schedules, and manual commands. It keeps automation workflows outside TaskNotes core while using the runtime API for safe task reads, writes, queries, events, and relationship resolution. See TaskNotes Workflows. (#1530) Auto-start time tracking starts a timer when a task moves into active work. Thanks to @Jendrik0 and @benmartinek for the request and follow-up. (#222, #184) Stop time tracking on complete stops active timers when a task is completed. Thanks to @bcohen44 and @cathywu for the requests, and @amarjt for the follow-up. (#265) Stamp started timestamp records a custom started timestamp when a task first moves into active work. Thanks to @cathywu, @digitaldoctors, and @Leo310 for the request and discussion. (#1703) Clear scheduled when started clears the scheduled date when a task moves into active work. Thanks to @kmaustral for the request. (#1293) Rollover overdue scheduled tasks moves incomplete tasks with past scheduled dates back to today. Thanks to @grosserfrank for the request. (#1896) Escalate upcoming due tasks raises priority as due dates approach. Thanks to @Neptune-Illusion for the request. (#214, #518, #1785, #1855) The subtask inheritance workflows can copy parent contexts, tags, priority, planning dates, and dependencies into new subtasks. Thanks to @timfidd, @bepolymathe, @AndyEveritt, @lindsaylearns, @tomsymonds, @wedgen, @poulpoulsen, and @misolex for the related requests and discussion. (#1166) Blocked task review provides a reminder-style review for blocked tasks without automatically deleting dependency links. Thanks to @jpmoo and @jortscity for the request and follow-up. Added a versioned TaskNotes JavaScript runtime API for companion plugins, with namespaced model validation, canonical task query validation/normalization/explain helpers, catalogs, query/support helpers, lifecycle events, typed errors/results, task, time-tracking, Pomodoro, recurring-task, settings, NLP, event, and extension-registry surfaces. Runtime API mutations carry source and correlation metadata so companion plugins can debug and coordinate workflow runs. See JavaScript API. Added documentation for the companion-plugin model. See Companion Plugins. (#288, #345, #361, #523, #573, #703, #925, #929, #1115, #1137, #1260, #1303, #1324, #1394, #1445, #1509, #1735, #1736, #1743, #1780, #1874, #1951, #1974) Added support for TaskNotes spec 0.2.0 materialized occurrences, including recurrence parent/date fields, generated mdbase schema roles, parent reconciliation when occurrence notes are completed, occurrence notes that inherit parent planning metadata without copying history, occurrence note controls in task, calendar, and edit-modal completion menus, and visible occurrence identity on task cards. This gives recurring tasks a concrete occurrence-note path for per-instance state, related notes, subtasks, templates, scheduling changes, completion history, and calendar behavior without forcing every recurring task to create files. See Recurring Tasks and Property Types Reference. Thanks to @LuxBetancourt, @jerzy-dudzic, @luciolebrillante, @BryanWall, @jhedlund, @kazerniel, @nschenone, @realJohnDoe, @cathywu, @Lorite, @EllenGYY, @JcMinarro, @gsssr, @slipstyle, @3zra47, @Leonard-44, @ak-42, @RumiaKitinari, @atos2212-blip, @kmaustral, @eugenedefox, @notDavid, @zitongcharliedeng, and @Jomo94 for the related recurrence, occurrence, completion, and calendar requests. (#1951) Added Calendar support for recurring tasks stretched between scheduled and due dates when the existing stretch option is enabled. Date-only ranges stay as all-day spans, and timed ranges render once per day in the range. Thanks to @atos2212-blip for the request. (#1751, #1792, #1969) Added a Task List and Kanban view option to hide top-level subtasks when their parent task is also in the filtered view, while still allowing inherited expanded relationships to show the subtasks under the parent. Thanks to @Glint-Eye and @Proxybat for the request and follow-up, and @stanley-910 and @Spencerduran for the earlier PRs. Changed# Moved core TaskNotes model behavior for field mapping, dates, recurrence, time-tracking, and adapter operation planning into a shared package used by the plugin and companion tooling. Calendar views now coalesce materialized occurrence notes with their matching virtual recurring instances. Dragging a materialized occurrence reschedules that occurrence note without changing the parent recurrence rule or the note's occurrence_date identity. See Recurring Tasks. Improved the Calendar Bases View Options menu by splitting settings into clearer groups and hiding view-specific controls until they apply to the selected calendar mode. Fixed# (#1976) Fixed embedded Calendar and Agenda Bases so \"Navigate to date from property\" can use the containing note's date property when the Base rows do not have that property. Thanks to @matesvecenik for reporting this. (#1977) Fixed Calendar and Agenda views showing duplicate all-day entries when a task's scheduled date and due date are the same day. Timed due dates on the same day still show as separate deadline markers. Thanks to @pdgBC for reporting this. Fixed the release notes view using cramped interface typography instead of regular reading typography. (#216) Improved inline conversion for Tasks plugin task lines, including Dataview-style fields, priority markers, recurrence text, date aliases, block links, and safer trailing-field parsing. Thanks to @ksdavidc for the request, @natleahh for the Dataview example, and @hangryscribe3 and @nayatiuh for the discussion. (#1974) Stopped Calendar and Agenda property-based events from logging date parse errors for entries that do not have the selected date property. Thanks to @Jomo94 for suggesting completed-date Agenda events. (#1973) Reduced unnecessary Calendar view recreations when external calendar providers are reported in a different order, and preserved Calendar scroll position when a config-driven refresh has to recreate the view. Thanks to @e-zz for reporting this. (#1972) Fixed ICS calendar event related notes so standalone events with similar numeric IDs no longer show unrelated notes or tasks on every event. Thanks to @ks-studio-net for reporting this. (#1970) Fixed generated default Base filters so updating default files applies configured excluded folders to TaskNotes task views. Thanks to @henrim01 for reporting that templates could still appear in regenerated views. (#1968) Fixed inline task link overlays collapsing on Obsidian mobile, which could hide the task title and leave a tall empty gap after the widget. Thanks to @renatomen for reporting and diagnosing the containment issue."},{"title":"TaskNotes 4.10.1","url":"/obsidian/releases/4.10.1/","description":"TaskNotes documentation.","product":"obsidian","text":"Added# Added a startup check for new compatible TaskNotes releases. When a new release is available, TaskNotes shows a notice that opens the TaskNotes entry in Obsidian's Community Plugins browser. (#1989) Added a command-palette action plus runtime and HTTP API actions for updating configured default .base files from the current TaskNotes templates. Thanks to @businessBoris for the request. (#1115) Added API and MCP support for creating materialized occurrence notes from recurring tasks, and made headless recurring-instance completion respect occurrence notes when the parent uses Create next after completion. Thanks to @gsssr for the original request, @slipstyle for the follow-up, and @martin-forge for identifying the API/MCP gap. Fixed# (#1985) Fixed embedded Calendar and Agenda time-grid views drifting out of alignment inside callouts and Reading mode. Thanks to @matesvecenik for reporting and sharing screenshots. (#1986) Fixed the local HTTP API rejecting requests from the TaskNotes browser extension's Chrome extension origin. Thanks to @n1njaznutz for reporting this. (#1980) Added mobile bottom spacing to Agenda Calendar views so the last visible tasks can scroll above Obsidian's bottom navigation bar. Thanks to @Jomo94 for reporting and sharing the screenshot. (#1984) Fixed mobile task link overlays hiding configured inline task card properties such as scheduled date, due date, contexts, and projects. Thanks to @stil-sudo for reporting. (#1979) Kept the left-positioned subtask chevron from overlapping the task status control on mobile task cards. Thanks to @Jomo94 for reporting and sharing the screenshot. (#1903) Reduced the Edit Task modal's mobile action-button footer so Open note, Archive, Delete, Save, and Cancel take two rows instead of three on iPhone-sized screens. Thanks to @3zra47 for the original report and @krzyfu for the follow-up about the button area crowding the editor. (#1982) Preserved scroll position in TaskNotes Bases after task edits and data refreshes, avoiding jumps back to the top on mobile. Thanks to @3zra47 for reporting. (#1978) Restored Obsidian editor shortcuts such as insert link, headings, and list toggles inside the Edit Task modal's Details editor. Thanks to @krzyfu for reporting this."},{"title":"TaskNotes 4.10.2","url":"/obsidian/releases/4.10.2/","description":"TaskNotes documentation.","product":"obsidian","text":"Fixed# (#1995) Fixed Bases Calendar views showing both a materialized occurrence note and its matching virtual recurring task instance. Thanks to @rdefaccio for reporting this. (Discussion #1994) Fixed timed recurring tasks failing to advance their due dates when due-date offset preservation is enabled. Thanks to @mgrecar for raising this."},{"title":"TaskNotes 4.11.0","url":"/obsidian/releases/4.11.0/","description":"TaskNotes documentation.","product":"obsidian","text":"Added# (#730, #1897, #1942, #1998) Added Canvas Bases, an optional companion plugin that turns Obsidian Bases views into canvas-style boards and reusable JSON Canvas snapshots, with TaskNotes badges, task menus, dependency and subtask edges, and assignment zones for supported TaskNotes actions. See Canvas Bases for setup details. Thanks to @DillPickle80, @BradGaddis, @Hyadhuad, and @AlinaWithAFace for the visual planning requests, and to @renatomen, @prayidae, and @maranqz for the related discussion. Added a TaskNotes starter note that is created and opened automatically on first install to introduce task creation, inline conversion, and embedded Bases views. Added a runtime API surface for companion plugins to show or populate the standard TaskNotes task context menu. (#2000) Added separate settings for using the active note as a project during normal task creation and during inline task creation or instant conversion. Thanks to @BlueScreen32 for suggesting the split. (#1303, #2001) Added separate templates for materialized occurrence notes, including parent-level occurrence_template support and a global fallback setting. Thanks to @BrucePlumb for suggesting a separate occurrence-note template and @ak-42 for the related per-recurrence template request. (#2006) Added the projected local finish time beside the remaining duration while a Pomodoro is running. See Pomodoro View for the timer behavior. Thanks to @abbiefalls90 for suggesting this. (#2016) Added a setting for recurring external calendar event related notes, so Google, Microsoft, and ICS recurrences can either share notes across the series or keep notes limited to the selected instance. See Integrations Settings for the setting. Thanks to @akhtsang for reporting this, and to @cathywu and @mdbraber for the earlier series-linking discussion. Changed# (#1737) Clarified that changing the task tag does not automatically update existing Base view filters. Thanks to @goldorak00 for reporting this, and to @Domcoppinger and @imsuck for the first-time setup feedback. (#2005) Excluded archived task notes and archived project-note references from Task & Project Statistics. Thanks to @Xiarno for suggesting this. Added a local review-type lint check that catches dependency-resolution warnings from Obsidian's online review before submission. Improved dependency and project relationship cache updates so ordinary note edits avoid unnecessary relationship recalculation, while blocked and blocking state stays current when dependency status changes. Improved filter and view query caching so filter options update immediately after relevant task-field changes while large Task List, Kanban, and Calendar queries avoid repeated vault scans. Extended the in-app release notes bundle to include the current major release, with collapsed versions rendered only when opened. Fixed# (#2015) Fixed Google Calendar events from the previous six months disappearing from Calendar and Mini Calendar views after a fresh sync. Thanks to @akhtsang for reporting this. (#2013) Fixed task-card status and priority dots becoming oversized on touch-capable desktop devices. Thanks to @RumiaKitinari for reporting this. (#2009) Restored Tab and Shift+Tab focus movement in the Create new task modal's natural language input instead of letting the markdown editor indent the title. Thanks to @prepare4robots for reporting this. (#2007) Fixed status autocomplete in the task creation modal leaving status value fragments in the task title when the editor auto-paired the status trigger. Thanks to @prepare4robots for reporting this. (#2004) Fixed the Pomodoro start command forgetting the selected task after it was completed, so reopening the task lets it be picked up again. Thanks to @MPourjam for reporting this. (#1996) Made Kanban card drag-and-drop show a clear drop slot marker while cards are being repositioned, so the landing position remains visible during sorting. Thanks to @phillipadsmith for reporting this. Fixed runtime API dependency removal so removing the last dependency from a task also clears the mapped blockedBy property from the note."},{"title":"TaskNotes 4.11.1","url":"/obsidian/releases/4.11.1/","description":"TaskNotes documentation.","product":"obsidian","text":"Added# (#2024) Added materialized occurrence notes to the Relationships widget, so recurring parent task notes can show their occurrence notes in an Occurrences tab. See Relationships Widget. Thanks to @3zra47 for requesting this. (#2022) Added a Skip instance / Unskip instance action to the recurring task edit modal's completion calendar, so skipped dates can be adjusted from the same date menu as completions. See Recurring Tasks. Thanks to @AmonAmarthFTW for requesting this. (#2048) Added current due and scheduled dates to the edit modal's task information. Thanks to @1activegeek for requesting this. (#2058, #2059) Added natural-language parsing and the full date picker to date-type custom fields. Thanks to @chmac for requesting this. (#2060) Added date-type custom fields to the task right-click menu under Custom dates. Thanks to @chmac for requesting this. (#2067) Added an Edit task action to the task card context menu, including inline task cards. Thanks to @DarkCellar for requesting this. (#2068) Added reminders input support to the MCP tasknotes_create_task and tasknotes_update_task tools. Thanks to @Spirit597 for requesting this. (#2069) Added an Add project action to the Quick Actions palette. Thanks to @chmac for requesting this. Fixed# (#2007) Fixed a remaining task creation autocomplete case where a status value containing another status label could leave status fragments in the task title. Thanks to @prepare4robots for the follow-up report. (#2031) Fixed quick task creation failing when natural language input created a recurring task with a scheduled time. Thanks to @rdefaccio for reporting this. (#2034) Fixed Advanced Calendar timed events switching to a high-contrast mobile fill when Obsidian is narrowed or split on desktop. Thanks to @RumiaKitinari for reporting this. (#2039) Fixed broken images on the Workflows and Calendar Setup documentation pages. Thanks to @chmac for reporting this. (#2045) Fixed custom modal fields assigned to Basic Information not appearing in task creation or edit modals. Thanks to @chmac for reporting this. (#2063) Fixed project autocomplete storing ambiguous project links without the selected note's folder path. Thanks to @chmac for reporting this. (#2072) Fixed inline task links to headings so they show both the task title and heading instead of only the heading. Thanks to @spasche for reporting this. (#2075) Fixed multiday Calendar events being clipped to one day when a Base is embedded in Reading view. Thanks to @ddevaal for reporting this. (#2079) Fixed the reminder modal's Absolute tab so it switches from relative fields to absolute date and time fields. Thanks to @JunwonYoon for reporting this and identifying the CSS specificity issue. Changed# Improved local review checks so unsafe direct Object.prototype method access is caught before submission."},{"title":"TaskNotes 4.12.0","url":"/obsidian/releases/4.12.0/","description":"[!info] TaskNotes v5 beta","product":"obsidian","text":"[!info] TaskNotes v5 beta TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release. The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface. TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand. TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter. Security# Calendar OAuth credentials and account tokens are now stored in Obsidian Secret Storage instead of TaskNotes' data.json, with automatic migration for existing connections. See Calendar Integration. Thanks to @mcuste for the contribution Updated bundled HTTP, address parsing, and schema validation dependencies to versions containing their current security fixes. Added# Added portable task attachment references. Attachments now round-trip as an ordered attachments link list in task frontmatter and are exposed through the TaskNotes model and runtime API. These are collection-file references only; attachment bytes and binary metadata remain owned by the host. (#2142) MCP tasknotes_create_task and tasknotes_update_task now accept customProperties for configured TaskNotes user fields. Thanks to @phillipadsmith for suggesting this. (#2126, #2134) Added optional filename templates for materialized recurring occurrence notes, with explicit date, ISO week, month, year, and month-name variables plus per-parent overrides. Existing naming remains unchanged until a template is configured. See Recurring Tasks. Thanks to @raphaelfaouakhiri for reporting and implementing this. (#2105) Added {{projectFolder}} and {{projectFolders}} folder template variables for storing tasks alongside linked project notes. See Template Variables. Thanks to @carypruitt for this contribution. Changed# Generated TaskNotes type contracts now include configured natural-language capture triggers, allowing compatible clients to offer the same field suggestions. Rebuilt the TaskNotes documentation with reorganized navigation, full-text search, mobile and accessibility improvements, and references generated from the current commands, settings, compatibility metadata, HTTP routes, and default Bases. Added practical guides for adopting TaskNotes in an existing vault, mobile use, custom Bases, and backup and recovery. See the TaskNotes documentation. (#2088) Convert current note to task now uses your default scheduled date when the note does not already have scheduled frontmatter, while the None default still leaves converted notes unscheduled. See Task Properties. Thanks to @e-zz for suggesting this. Fixed# Plugin settings now recover when Obsidian briefly returns no data while reloading an externally changed settings file, preventing a post-reload error without overwriting the existing settings. (#2194) Pomodoro task selection suggestions now keep rich task cards at the menu width, preventing task titles from wrapping one letter per line. Thanks to @Evilgenee for reporting this. (#2196) Drag-to-reorder now works for Task List Bases embedded in Live Preview notes, matching the behavior of directly opened Bases and Reading mode embeds. Thanks to @jimbo108108 for reporting this. (#2198) Agenda Bases can now show overdue scheduled or due tasks on today's row with showOverdueOnToday, and regenerated default Agenda files enable that behavior by default. Thanks to @vicrdguez for reporting this. (#2182) Checklist progress on task cards now excludes cancelled markdown checklist items such as [-] from the completed/total count. Thanks to @ctrl-q for reporting this. (#2180) Inline task cards in Live Preview now keep their click and context menu handlers active on Obsidian 1.13, so clicking a rendered task link opens the edit modal instead of revealing the raw wikilink. Thanks to @npondel for the detailed diagnosis and @minchinweb for confirming the issue. (#2171) Stopped recurring notification and status-bar scans from reading unindexed notes directly from disk while preserving the fallback for direct task lookups. Thanks to @tgrosinger for identifying and diagnosing the excessive vault reads. (#2174) Open or create occurrence note from Quick Actions now uses the recurring task's scheduled occurrence date, preventing duplicate occurrence notes keyed to the day the action was run. Thanks to @chmac for reporting this. (#2169) Regenerated default Base views now include tasks whose identifying property is stored as a list containing the configured task value. Thanks to @GlebYavorski for reporting this. (#2166) Fixed Task List views configured to start collapsed so the first chevron click expands only the selected group instead of expanding every other group. Thanks to @renatomen for reporting and fixing this. (#2165) Convert current note to task now reads configured field mappings, including list-valued title fields such as aliases, and preserves an existing aliases list when the title is unchanged. Thanks to @jkuball for reporting this. (#2164) Flat Kanban boards now clear stale swimlane layout state when they rerender, preventing columns from occasionally stacking into one vertical strip after switching tabs. Thanks to @brienna for reporting this. (#2160, #2161) Generated Kanban Bases now use the correct TaskNotes status property and configuration block. Rich Bases status values render as their configured labels, while pinned columns and saved column order are honored. Thanks to @kevin-4c for the detailed reports and diagnosis. (#2111, #2159) Recurring task instances now remain visible through the final day of Calendar and Agenda ranges in positive-offset time zones, regardless of the configured first day of the week. Thanks to @Arachnidai and @odxn0803 for reporting this. (#2155) Regenerated default Calendar Bases now inherit the app-level time slot duration instead of hardcoding 30 minutes. Existing per-Base time settings remain intentional overrides. Thanks to @SZZ504232 for reporting this. (#2154) Timed ICS events without a TZID now preserve their floating wall time in the user's local timezone instead of being interpreted as UTC. Thanks to @cloesophia for the reproducible calendar sample. (#2152) Fixed paginated Google Calendar refreshes for calendars with many events so secondary calendars do not disappear after Google returns a second page. Thanks to @wobafett for reporting and diagnosing this. (#2141) Fixed Task List groups for tasks without scheduled or due dates showing a raw Bases icon object instead of None. Thanks to @ks-studio-net for reporting this. (#2140) The edit task modal now shows saved task-identification tags when hiding identification tags is disabled. Thanks to @3zra47 for reporting this. (#2148) Empty list-like frontmatter values no longer become literal \"null\" entries when tasks are edited. Thanks to @minchinweb for reporting this. (#2120, #2135) Long all-day event titles in Calendar week and day views now truncate instead of stretching the all-day row. Thanks to @same774 and @ks-studio-net for reporting this. (#2124) Fixed a Kanban crash when opening or closing the edit modal immediately after moving a task between list-valued swimlanes such as contexts. Thanks to @Decia-C for reporting this. (#2114) Completing a rescheduled occurrence for a scheduled-anchored recurring task now advances the parent from the moved occurrence date instead of an earlier original occurrence date. Thanks to @chrabia for reporting this. (#2113) Failed Google Calendar manual refreshes no longer make the next immediate refresh show a misleading success notice. Thanks to @JohWQ for reporting this. (#2109) TaskNotes no longer injects instant-conversion controls into embedded or detached Markdown editors, preventing checkbox notes opened from unrelated Bases from freezing Obsidian on mobile. Thanks to @jmartinmcfly for the clear reproduction and recording. (#2107, #2108) Creating tasks with Store title in filename enabled now handles duplicate or case-variant titles without failing or replacing the task title with a suffixed filename. Thanks to @AdmiralClackington for reporting and diagnosing this. (#2106) Regenerated default Calendar Base files now use your configured first day of the week instead of forcing Sunday. Thanks to @atos2212-blip, @cweekly, @idontcode34, and @hikatamika for reporting this. (#2100) Tags added while creating a task now keep the same frontmatter order as tags added later from the task context menu. Thanks to @mgrecar for reporting this. (#2092) New non-recurring tasks created directly in a completed status now get a completed date, so completed-date views can find them immediately. Thanks to @Crell for reporting this. (#2096) Fixed TaskNotes Kanban swimlanes falling back to None when the swimlane used a Bases formula that was not already cached by Bases. Thanks to @ddevaal for reporting this. (#2093) TaskNotes now retries custom Bases view registration when the Bases core plugin is enabled after TaskNotes, preventing default views from showing Unknown view type until TaskNotes is reloaded. Thanks to @yaye-work for reporting this. (#2084) The Relationships widget no longer prevents editor text selection from autoscrolling when dragging below the bottom edge of a task note. Thanks to @lostwildland for reporting this. (#2081, #2103) Kept task card and relationships widgets visible in reading mode when Obsidian scroll or preview updates remove their DOM, and refreshed visible widgets promptly after metadata changes. Thanks to @mukhozhuk for reporting and debugging this and @martin-forge for fixing it. (#2064, #2066) Recurring tasks now advance correctly after their next scheduled date is manually adjusted, preserving due-date offsets and times without jumping back to an earlier occurrence. Thanks to @chmac for reporting and fixing this. (#2018) Fixed Hide empty columns in Kanban views with swimlanes so columns with no visible tasks are hidden while pinned columns remain. Thanks to @scottTomaszewski for reporting and fixing this. Fixed recurring all-day ICS subscription events keeping the original end date on later instances, which could cause calendar list views to show events under the wrong day. Thanks to @abbiefalls90. (#2033) Fixed the project folder badge on task cards so, when expandable subtasks are enabled, it expands or collapses inline subtasks instead of showing an unavailable-action notice. Thanks to @abbiefalls90 for the fix and @scottkodai for the follow-up feedback. (#2040, #2041) Stopped newly created tasks from filling the Google Calendar retry queue when calendar export is disabled. Thanks to @chmac for reporting and fixing this. (#2046, #2051) The date and time picker now focuses the natural-language input when it is enabled, making keyboard-driven quick actions ready for immediate typing. Thanks to @DevOps-Toast for reporting this and @ther12k for fixing it. (#2125, #2129) Materialized recurring occurrence notes now record the date they were actually completed, while the parent recurring task continues to track the occurrence date. Thanks to @raphaelfaouakhiri for reporting and fixing this. (#2173, #2175) Completion-anchored recurring tasks with materialized occurrence notes now schedule the next occurrence from the day the occurrence was actually completed. Thanks to @chmac for reporting and fixing this. (#1982) Preserved the Task List's own scroll position during Bases refreshes so long mobile lists do not jump back to the top after task updates. Thanks to @3zra47 for the follow-up report. (#1863) Microsoft Calendar event updates now accept opaque Exchange calendar IDs instead of failing local validation before contacting Microsoft Graph. Thanks to @fmacondray for reporting this and providing the follow-up stack trace."},{"title":"TaskNotes 4.12.1","url":"/obsidian/releases/4.12.1/","description":"[!info] TaskNotes v5 beta","product":"obsidian","text":"[!info] TaskNotes v5 beta TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release. The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface. TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand. TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter. Changed# (#2204) Public documentation is now published from the dedicated tasknotes.dev repository. Plugin release notes and internal documentation remain in this repository. Updated compatibility with Obsidian's current plugin review and settings search. Fixed# Fixed TaskNotes interface elements sometimes appearing in the wrong window when using Obsidian pop-out windows. Improved confirmation dialogs, icons, and modal styling to use Obsidian's current interface APIs."},{"title":"TaskNotes 4.12.2","url":"/obsidian/releases/4.12.2/","description":"[!info] TaskNotes v5 beta","product":"obsidian","text":"[!info] TaskNotes v5 beta TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release. The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface. TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand. TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter. Fixed# (#2212) Fixed TaskNotes settings sections appearing pushed across the Obsidian settings pane on desktop. Thanks to @RafaQNunes for reporting this."},{"title":"TaskNotes 4.12.3","url":"/obsidian/releases/4.12.3/","description":"[!info] TaskNotes v5 beta","product":"obsidian","text":"[!info] TaskNotes v5 beta TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release. The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface. TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand. TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter. Fixed# (#2212) Fixed TaskNotes settings sections appearing offscreen or blank on Obsidian 1.13 desktop. Thanks to @RafaQNunes for reporting this, and to @m4to-3pe and @matthewrishii for confirming it remained in 4.12.2. (#2213) Runtime plugin-data updates now avoid writing when Obsidian cannot safely read an existing TaskNotes data.json, preventing calendar sync, Pomodoro, ICS, or auto-archive state writes from replacing saved settings. Thanks to @3zra47 for the follow-up details and file-history evidence. (#2216) Fixed updated default Kanban Bases grouping every task into the None column when grouping by status. The generated Kanban templates now use the real status property, and existing Kanban files using task.status keep grouping from TaskNotes task data. Thanks to @Esvorst for reporting this. (#2120, #2135) Long all-day event titles in Calendar week and day views now truncate in the all-day row instead of stretching it vertically. Thanks to @same774 and @ks-studio-net for reporting this, and to @Admorei for confirming it remained in 4.12.2."},{"title":"TaskNotes 4.12.4","url":"/obsidian/releases/4.12.4/","description":"[!info] TaskNotes v5 beta","product":"obsidian","text":"[!info] TaskNotes v5 beta TaskNotes v5 is available as an opt-in beta alongside TaskNotes 4.12. TaskNotes 4.12 remains the recommended stable release. The major change in v5 is support for portable TaskNotes collections. These collections can be used in both Obsidian and the TaskNotes app, which is also available in beta, so the same tasks can be managed through either interface. TaskNotes collections are built on mdbase, a Markdown-native collection format. mdbase Connect provides the permissioned bridge that makes those collections available to the TaskNotes app. Your tasks remain ordinary Markdown files in your vault; mdbase adds a shared structure that compatible tools can understand. TaskNotes v5, mdbase Connect, and the TaskNotes app are all under active development. Please use a backed-up vault, expect some rough edges, and report any problems you encounter. Changed# (#2187) Improved TaskNotes startup performance by allowing Bases registration to finish asynchronously. Thanks to @tgrosinger for the contribution. Fixed# (#2232) Opening an occurrence note from a completion-anchored recurring task now uses the task's scheduled occurrence date instead of defaulting to today. Thanks to @chmac for reporting this. (#2247) Creating a new inline task now removes nested wikilink and Markdown-link markup from the inserted task link's display text. Thanks to @bgk0018 for reporting this. (#2231) Fixed Agenda views with showOverdueOnToday showing the same task twice when both its scheduled and due dates were overdue. Thanks to @takashit16833 for reporting this. (#2206) The time entry editor now opens much faster for tasks with many tracked sessions by delaying the heavier description editor setup until a description field is focused. Thanks to @Sapere-Kyle for reporting this. (#2239) Fixed Task List Bases embedded in mobile notes leaving a large blank gap after the final task card. Thanks to @same774 for reporting this and @prethrive for sharing a workaround. (#2238) The Relationships widget now stays below long Live Preview Dataview tables and no longer appears twice after switching to Reading mode. Thanks to @Romek1769 for reporting this. (#2250) Hardened Google Calendar task metadata updates: duplicate Google Calendar fields are now repaired atomically without replacing concurrent task edits, and synchronization finishing after a disconnect no longer writes stale event metadata. Thanks to @3zra47 for reporting the corrupted task data that prompted this review. (#2229) Google Calendar OAuth authorization now opens in the system browser instead of Obsidian's Web Viewer, avoiding Google's 401 malformed-request page in the in-app browser. Thanks to @prethrive for reporting this and confirming the workaround. Skipping a recurring task instance from Task List or Kanban now records the task's occurrence date instead of the view's current date. Thanks to @renatomen for the contribution. (#2130) Tasks added by external sync while Obsidian is closed are now exported to Google Calendar after TaskNotes starts. Thanks to @seththepeacock for reporting this and @raphaelfaouakhiri for the contribution. (#2246) Fixed materialized recurring occurrences hiding occurrence-template filename suffixes in TaskNotes views. Thanks to @raphaelfaouakhiri for reporting and fixing this issue. (#2221) Fixed PUT /api/tasks/:id ignoring empty arrays for contexts and blockedBy: sending {\"contexts\": []} or {\"blockedBy\": []} now clears the corresponding frontmatter field instead of silently leaving the previous value in place. The deletion pass previously fired only on a literal undefined, which JSON cannot express, so HTTP clients had no way to clear these fields. Thanks to @tgrosinger for the contribution. (#2191) Completing or skipping a recurring occurrence that was moved earlier than its original date no longer schedules that original date again. Thanks to @martin-forge for the contribution. (#2193) Google Calendar event descriptions written with formatting now read as plain text in event details, copied text, and generated notes, instead of showing raw HTML tags. Paragraph breaks, list structure, and link addresses are kept. Thanks to @martin-forge for the contribution. (#2192) Agenda and list cards for Google and Microsoft calendar events now show the name of the calendar the event belongs to, instead of the generic \"Calendar\" label. Thanks to @martin-forge for the contribution."},{"title":"TaskNotes 4.12.5","url":"/obsidian/releases/4.12.5/","description":"TaskNotes documentation.","product":"obsidian","text":"Fixed# (#2255) Notes with an in-note task card no longer jump while scrolling in reading mode. The card is now restored only after scrolling settles instead of being re-injected every frame against Obsidian's virtualised reading view. Thanks to @logicelf for the detailed diagnosis. (#2256) Kanban swimlane order now follows the view's sort configuration again: with a formula or property sort applied, the swimlane holding the top-sorted task floats to the top of the board as it did before the swimlane ordering option was introduced. Thanks to @tsweezy for reporting this. (#2222) The TaskNotes settings tab bar now wraps to a second line instead of clipping the Integrations tab beside the documentation link on narrow settings panes. Thanks to @nextstitch and @YongcaiHuang for reporting this."},{"title":"TaskNotes 4.13.0","url":"/obsidian/releases/4.13.0/","description":"HTTP API and MCP clients now require authentication. If you previously connected without a token, copy the API token from Settings → TaskNotes → Integrations into your client...","product":"obsidian","text":"Before updating# HTTP API and MCP clients now require authentication. If you previously connected without a token, copy the API token from Settings → TaskNotes → Integrations into your client's authentication settings. Requests must include Authorization: Bearer . If the token is empty when the server starts, TaskNotes generates and saves one; leaving it empty no longer disables authentication. See HTTP API. Security# (#2292) Required authentication for local API/MCP listeners. OAuth callbacks now use an OS-assigned loopback port, accept each authorization state only once, and return fixed pages without reflecting callback text. Thanks to @martin-forge for the hardening. Added# Added a dedicated TaskNotes v5 and app beta section to the plugin's release notes, including instructions for joining the Android test. The announcement appears once rather than repeating inside individual versions. (#2147) Added context-menu actions for recording task completion today, on the scheduled date, on the due date, or on a chosen date. The actions can be grouped in a submenu from Appearance settings. See Completing Tasks. Rescheduling a recurring task can reactivate affected completed or skipped instances after confirmation. See Recurring Tasks. Completion-date actions, submenu settings, and rescheduling confirmations are translated into all supported languages. Thanks to @renatomen for the contribution. Fixed# (#2291) Preserved background task updates when saving an older task edit window, including recurring completion history and properties changed or removed elsewhere. Thanks to @martin-forge for the fix. (#2294) Stopped plugin startup when an existing settings file cannot be read, preserving it for recovery instead of starting services with default settings. Thanks to @GGlider for reporting settings loss in #1591 and @martin-forge for the fix. (#2322) Fixed metadata edits deleting the saved title when a filename cannot represent it, such as for long titles. Existing title properties are preserved on unrelated edits; this does not recover previously deleted titles. Thanks to @1dezer1 for reporting. (#2255, #2300) Fixed task cards repeatedly disappearing and being restored while scrolling in Reading mode, which could pull the note down to the bottom. Thanks to @logicelf for the diagnosis and @nelsonlove for the fix. (#2318) Kept calendar events chronological when a Base sort is configured, using Base order for tasks at the same time. Thanks to @ky1ejs for reporting #1411 and @martin-forge for the fix. (#2319) Avoided duplicate recurring-task projections when TaskNotes has recorded the original occurrence date of a calendar move. Completion and skip history remain visible when requested. Other move cases are unchanged. Thanks to @martin-forge for the fix. (#2309) Fixed Google calendars enabled through the primary alias using the wrong color, ignoring visibility toggles, or losing their calendar name on event cards and linked notes. Thanks to @martin-forge for the fix. (#2279) Fixed Google Calendar authorization stalling when the system browser opens but does not report back that it launched. Authorization now completes or times out independently, and overlapping attempts cannot stop the active connection attempt. Thanks to @DamienDLR for the diagnosis. (#2298, #2299) Kept timed recurrence anchors when saving custom recurrence or completing a completion-anchored instance. Timed anchors are written with Z and retain their time, including seconds, without a device-timezone conversion. Date-only rules and scheduled-anchor completion are unchanged. See Recurring Tasks. Thanks to @wellsbk1 for reporting. (#2043, #2055) Fixed tasks created with the default Subtasks view's + button missing their project and immediately disappearing from the view. Thanks to @kudrmax for reporting and @ther12k for the initial fix. (#2284) Prevented repeated activation of instant checkbox conversion from creating duplicate TaskNotes while the first conversion is still in progress. Thanks to @doyoonear for reporting. (#2314) Fixed rescheduled ICS recurring events appearing at their original time and cancelled occurrences remaining visible. Thanks to @benschifman for reporting. (#1849) Fixed context menus stacking on top of each other. Only one menu stays open at a time, and clicking the same indicator again closes its menu. This previously applied to date fields only, and now covers priority, status, recurrence, reminders, task, ICS event, and batch menus. Thanks to @3zra47 for reporting and @YBKF for the contribution. (#2303) Removed the extra space after inline task links on desktop while retaining the task menu on touch devices. Thanks to @nelsonlove for the fix. Changed# (#2316) Clarified the Google OAuth Desktop app setup and redirect-mismatch troubleshooting, including why fixed Web application redirect URLs are not reliable with dynamic callback ports. See Calendar Setup. Thanks to @TomaszGaweda for reporting and following up."},{"title":"TaskNotes 4.2.0","url":"/obsidian/releases/4.2.0/","description":"Added Korean (한국어) language support","product":"obsidian","text":"Added# Added Korean (한국어) language support Full translation of all 1911 localization keys Korean language option now available in Settings → General → Language Adopted Obsidian 1.11.0 API features with backwards compatibility Settings tab now displays TaskNotes icon in the sidebar (Obsidian 1.11.0+) Settings sections now use native SettingGroup for improved visual grouping (Obsidian 1.11.0+) Falls back gracefully to traditional section headers on older Obsidian versions (#59) Added shortYear template variable for custom filename and folder templates Use {shortYear} in filename templates (e.g., \"25\" for 2025) Use {{shortYear}} in folder templates Thanks to @Pixeltica for the feature request (#1393) Option to prevent auto-creation of default Base view files on startup New \"Auto-create default files\" toggle in Settings → Integrations → Bases Integration When disabled, deleted sample Base files will not be recreated on plugin load The manual \"Create Default Files\" button remains available for on-demand recreation Thanks to @wealthychef1 for the feature request (#1408) Shift+click on status icon to cycle backwards through statuses Normal click cycles forward through status order Shift+click cycles in reverse order Thanks to @JerryLu086 for the feature request (#1410) Task creation modal now starts in vim insert mode when vim keybindings are enabled Previously required pressing 'i' before typing when Obsidian vim mode was active The modal now automatically enters insert mode on focus, allowing immediate typing Thanks to @Leo310 for the feature request Added button tooltips to calendar view toolbar Hovering over navigation and view buttons now shows descriptive hints Buttons include: Today, Previous, Next, Month, Week, Day, Year, List Added tooltips to task modal action icons Icon buttons for status, date, project, priority, recurrence, and reminder now show tooltips on hover Improves discoverability for new users (#503) Settings now sync automatically across devices via Obsidian Sync Changes to custom statuses, priorities, and other settings apply immediately without restart Thanks to @jhedlund for the feature request and @l-mb for the implementation (#1403) Kanban view option to consolidate status icons in column headers New \"Show status icon in column header only\" toggle in Kanban view settings (disabled by default) When enabled and grouped by status, shows the icon in the column header and hides it on cards Reduces visual redundancy when the column already indicates the status Thanks to @l-mb for the feature request and implementation (#1401) Calendar view option to span tasks between scheduled and due dates New \"Span tasks between scheduled and due dates\" toggle in Calendar view Layout settings When enabled, tasks with both scheduled and due dates display as multi-day bars Provides Gantt chart-style visualization for project planning Thanks to @0atman for the feature request (#1334) {{currentNotePath}} now works for \"Create new inline task\" command The inline task folder setting with {{currentNotePath}} previously only worked for checkbox conversion Now also applies when using the \"Create new inline task\" command from the command palette Thanks to @kmaustral for the feature request (#1264) Option to open Pomodoro timer in mobile sidebar instead of note panel New \"Mobile sidebar\" setting in Settings → Features → Pomodoro Timer Choose between: Note panel (default tab behavior), Left sidebar, or Right sidebar Allows quick swipe access to the timer without switching notes on mobile devices Thanks to @Evthestrike for the feature request (#1220) Option to use ICS event end time as task due date New \"Use ICS event end time as task due date\" toggle in Settings → Integrations → Calendar Subscriptions When enabled, tasks created from calendar events will have their due date set to the event's end time For all-day events, uses the event date (not the ICS container end date which is the next day per ICS spec) For timed events, includes the exact end time Defaults to disabled to preserve existing behavior Thanks to @MiserMagus for the feature request (#1108) Option to use task duration instead of due date for ICS calendar export New \"Use task duration for event length\" toggle in Settings → Integrations → Automatic ICS Export When enabled, exported calendar events use scheduled date + time estimate as DTSTART/DTEND This aligns with GTD workflows where scheduled + duration represents work planning, while due date represents deadlines When disabled (default), preserves existing behavior using due date as DTEND Thanks to @bepolymathe for the feature request Fixed# (#1421) Fixed natural language parser only capturing one date when both scheduled and due dates are specified Input like \"Task scheduled for tomorrow due next week\" now correctly sets both scheduled and due dates Previously the parser would return early after finding the first date trigger, ignoring any subsequent triggers Thanks to @wealthychef1 for reporting (#1384) Fixed title being sanitized even when \"Store Task Title in Filename\" is disabled Characters like ?, <, >, :, etc. are now preserved in task titles when they won't be used in filenames When storeTitleInFilename is false, only minimal sanitization (whitespace normalization, control character removal) is applied Thanks to @allison-casey for reporting (#1028), (#1140), (#1152), (#1354), (#1362) Fixed duplicate task entries appearing in Agenda view Tasks were shown twice: once as TaskNotes events and again as property-based events with a file icon Changed default Agenda template to disable property-based events (showPropertyBasedEvents: false) Users can re-enable property-based events in view settings if needed for non-task date properties Thanks to @YIRU69, @jhedlund, @dblinnikov, @Snakiest, @WeiYiAcc, @JacksonMcDonaldDev, @jimbo108108, and @krelltunez for reporting (#1386) Fixed timeEstimateCategory formula showing \"Long (>2h)\" instead of \"No estimate\" for new tasks The condition didn't properly handle null values when timeEstimate property is unset Also fixed the same issue in trackingStatus formula Thanks to @nicou for reporting and @osxisl for the PR (#1397) Fixed Bases views (Kanban, Calendar, Task List) resetting to Calendar view after a few minutes Also fixed CalendarView corrupting other view files when saving state on unload Thanks to @music-soul1-1 for reporting (#1398) Fixed overdue strikethrough showing on completed tasks Completed tasks with past due dates no longer display overdue styling Respects the \"Hide completed from overdue\" setting which defaults to true (#1363) Fixed calendar view showing nothing when a task has an invalid date format Tasks with malformed dates (e.g., \"262025-12-16\" instead of \"2025-12-16\") no longer crash the entire calendar Invalid tasks are now skipped with a console warning, allowing other events to display normally Thanks to @Erelen for reporting Fixed today column in week/day calendar views using FullCalendar's default yellow instead of theme accent Today's column now uses a tint of the theme accent color for consistent styling (#1399) Fixed drag-and-drop not working in Kanban view on mobile Cards and columns can now be dragged using long-press gesture on touch devices Includes haptic feedback and auto-scroll when dragging near edges Thanks to @l-mb for reporting and the fix (#1381) Fixed Pomodoro \"Change Task\" menu not showing newly created tasks Tasks created while the Pomodoro view was open would not appear in the task selector Improved metadata cache synchronization to properly wait for new files to be indexed Thanks to @Ghosthael for reporting (#1344) Fixed \"Unsaved Changes\" popup appearing randomly when closing task edit modal The popup would appear even when no changes were made to the task Caused by inconsistent trailing whitespace normalization when comparing details content Thanks to @hasanyilmaz for reporting (#1402) Fixed Kanban swimlane view showing tasks in wrong column when grouped by formula After editing task metadata, cards would jump to \"None\" column until Obsidian reload Column assignment now uses Bases' computed grouping instead of cached formula outputs Thanks to @bailob for the fix (#1352) Fixed date context menu not preserving time when using increment options Using +1 day, -1 day, +1 week, or -1 week on a task with a time (e.g., 2025-12-10T16:00) now preserves the time Previously the time would be stripped, changing 2025-12-10T16:00 to 2025-12-11 instead of 2025-12-11T16:00 Thanks to @cathywu for the feature request Fixed v3 saved views exporting incorrectly to Bases format Title filters now correctly use file.name instead of note.title Archived filters now generate valid boolean expressions instead of malformed comparisons \"Is Blocked\" filters now generate correct expressions with proper operator precedence (#1036) Due dates can now be dragged in the calendar view Previously only scheduled dates were draggable; due dates were locked in place Dragging a due event now updates the task's due date property Thanks to @same774 for reporting Improved calendar view responsiveness for user interactions Task creation, editing, timeblock changes, and view option toggles now update immediately Previously these actions waited 5 seconds due to the debounce intended for external file changes The 5-second debounce is now bypassed for direct user actions while still preventing flicker during typing Improved visual affordance for Pomodoro timer duration adjustment buttons The +/- buttons below the timer now have visible backgrounds and borders Hover states show accent color border for clearer interactivity feedback Previously buttons were nearly invisible with transparent backgrounds (#1409), (#1214), (#979) Improved Calendar, Agenda, Kanban, and Stats views in pop-out windows Drag-and-drop in Kanban view now works correctly when the view is in a new window Context menus (status, priority, task) now work correctly in pop-out windows Stats view drill-down modal now appears in the correct window Search boxes, task cards, and grouped task lists render correctly Root cause: Code was using global document and standard instanceof checks which fail across windows Solution: Use ownerDocument for DOM operations and Obsidian's cross-window instanceOf() method Known limitation: Calendar event dragging does not work in pop-out windows due to FullCalendar library using global document for mouse event listeners. Use context menus or edit modals as a workaround. Updated FullCalendar to v6.1.20 Thanks to @Snakiest, @same774, and @3zra47 for reporting (#1337) Fixed \"Convert current note to task\" hotkey not applying default values from settings When user configured default status/priority as \"None\", the modal would show \"Open\" and \"Normal\" instead Root cause: Task edit modal was refreshing data from file and overwriting user-configured defaults Now preserves constructor-provided task data when converting non-task files Thanks to @guihasparyk for reporting (#1304) Fixed \"Cannot find function map on type Link\" error in Blocking view Error occurred when embedding the Relationships base and opening the Blocking view Root cause: When blockedBy contained a single dependency, Bases returned it as a Link object without a .map() method Fixed by wrapping blockedBy with list() before calling .map(), consistent with the Blocked By view Thanks to @prayidae for reporting (#1295) Fixed missing navigation link to Default Base Templates page on tasknotes.dev The page existed but was not accessible from the site navigation Thanks to @Arachnidai for reporting (#1223) Fixed \"Go to today's note\" command opening wrong date in positive UTC offset timezones In timezones like Japan (UTC+9), early morning use of this command opened yesterday's note Root cause: Incorrectly extracting UTC date components instead of local timezone date Thanks to @BrucePlumb for reporting"},{"title":"TaskNotes 4.2.1","url":"/obsidian/releases/4.2.1/","description":"(#1424) Fixed \"Create New Task\" command creating tasks in active folder instead of default folder","product":"obsidian","text":"Added# New Calendars API endpoint for access to calendar data Access calendar provider information and connection status Query events from Google Calendar, Microsoft Calendar, and ICS subscriptions Filter events by date range tasknotes-cli has been updated to make use of this endpoint Fixed# (#1424) Fixed \"Create New Task\" command creating tasks in active folder instead of default folder \"Create New Task\" now correctly uses the configured default task folder \"Create New Inline Task\" continues to use the inline task folder setting Thanks to @Gogo-XD for reporting and @TonyAtlas for confirming (#1421), (#1042) Fixed natural language parser only setting one date when both scheduled and due dates are specified Entering something like \"task due Jan 9 at Jan 9\" now correctly sets both the due date and scheduled date Thanks to @wealthychef1 and @dblinnikov for reporting (#1410) Fixed vim insert mode not activating in task creation modal The modal now correctly enters insert mode when vim keybindings are enabled Thanks to @Leo310 for the feature request (#1422) Fixed tags with dashes not being parsed correctly Tags like #my-tag were being truncated to #my Thanks to @JerryLu086 for reporting (#1419) Fixed custom statuses and priorities not saving in settings Values entered in text fields were sometimes lost when closing the settings modal Thanks to @s33a for reporting"},{"title":"TaskNotes 4.3.0","url":"/obsidian/releases/4.3.0/","description":"(#1361) Option to disable inline task overlay for aliased wikilinks","product":"obsidian","text":"Changed# (#1437) Unified template variable syntax and available variables across filename and body templates Both systems now use double-brace {{variable}} syntax consistently Single-brace {variable} syntax remains supported for backwards compatibility but is deprecated Settings UI shows a warning when deprecated single-brace syntax is detected Filename templates gain body template variables: {{contexts}}, {{tags}}, {{hashtags}}, {{timeEstimate}}, {{details}}, {{parentNote}} Body templates gain filename template variables: {{zettel}}, {{nano}}, and all extended date/time variables Thanks to @23maverick23 for reporting Added# (#1361) Option to disable inline task overlay for aliased wikilinks New setting in Features → Inline Tasks: \"Disable overlay for aliased links\" When enabled, links with aliases like [[Task|Check Status]] render as plain links Links without aliases continue to show the interactive task widget Useful when embedding tasks in prose where the widget would be disruptive Thanks to @diegomarzaa for the contribution and @jldiaz for proposing this feature in #1117 (#1199, #1205) Google Calendar export for tasks Sync tasks to Google Calendar based on scheduled or due dates Automatic sync on task create, update, complete, and delete Configurable event title templates with placeholders ({{title}}, {{status}}, {{priority}}, etc.) Event descriptions include task metadata and optional Obsidian deep link Support for all-day or timed events with customizable duration Event color customization using Google Calendar's color palette Default reminder setting for popup notifications Bulk sync and unlink actions in settings Task-event linking stored in frontmatter (googleCalendarEventId) Recurring tasks sync as Google Calendar recurring events Completed or skipped recurring instances are automatically excluded Thanks to @someromans and @Leonard-44 for requesting this feature, and @dmantisk, @farangkao, @rayvermey, and @rdpr for their input Fixed# (#1413) Fixed angle-bracket links and project title display Angle-bracket links like [Spec]() now resolve correctly Project links display frontmatter title instead of raw filename/path when available Dependency values normalize consistently across wikilinks, markdown links, and angle-bracket variants Many thanks to @normenmueller for the contribution (#1414) Kanban column headers now display configured priority labels instead of raw values Many thanks to @normenmueller for the contribution (#1416) Fixed property-based task identification mutating tags unexpectedly Tags are only written when explicitly changed by the user Task tag is only added in tag-based identification mode Fixes #1391 Thanks to @loukandr for reporting and @normenmueller for the fix (#1187) Fixed \"Unknown view types\" error when opening Bases views after upgrading from pre-V4 Users who had disabled Bases support in earlier versions could not open Bases views after upgrading Settings migration now automatically re-enables Bases support since the toggle was removed in V4 Thanks to @MiracleXYZ for reporting (#1144) Fixed relationships.base showing empty views for Projects, Blocked By, and Blocking tabs The top-level task filter was excluding non-task files from the Projects view Projects can be any file type (not just tasks), so the filter is now applied per-view Subtasks, Blocked By, and Blocking views retain the task filter; Projects view does not Users with existing relationships.base files should delete and regenerate them to get the fix Thanks to @needo37 for reporting, and @n1njaznutz, @nestor50, and @IvyDliu for investigating and confirming the solution Fixed calendar view type not persisting or applying when changed View type changes via header buttons (week/day/month) are now saved to the .base file View type changes via Bases settings panel now apply immediately without reload (#1441) Fixed task dragging broken with \"Span tasks between scheduled and due dates\" enabled Span events can now be dragged to move tasks in time Dragging shifts both scheduled and due dates proportionally, preserving the span duration Previously, dragging span events would cause a visual/data mismatch where the calendar showed the wrong position Thanks to @Peeeet for reporting"},{"title":"TaskNotes 4.3.1","url":"/obsidian/releases/4.3.1/","description":"(#1546) Added sticky kanban column headers that remain visible while scrolling","product":"obsidian","text":"Added# (#1546) Added sticky kanban column headers that remain visible while scrolling Thanks to @normenmueller for the contribution (#1458) Added CSS color classes to context tags for custom styling Each context tag now receives a unique CSS class based on its name (e.g., context-tag--color-0 through context-tag--color-19) Enables styling individual contexts via CSS snippets Thanks to @phortx for the contribution Added mdbase-spec type definition generation New setting in Integrations tab to generate mdbase-spec v0.2.0 type definition files (mdbase.yaml and _types/task.md) at the vault root Type definitions are derived from TaskNotes settings (statuses, priorities, field mappings, user fields) and regenerated automatically when settings change Enables interoperability with other tools that support the mdbase-spec format Fixed# (#1472) Fixed task dependencies not being stored as wikilinks in frontmatter Dependencies now retain their [[wikilink]] format when saved, preventing them from breaking on file rename Thanks to @renekalff for reporting (#1443) Fixed default status/priority not updating when the referenced custom value is deleted Deleting a custom status or priority that was set as the default now resets the default to the first available value Thanks to @l-mb for the contribution (#1448) Fixed project removals not persisting from the task edit modal Removing all projects from a task now correctly clears the projects field Different link formats (e.g., markdown links vs wikilinks) no longer cause false change detection Thanks to @normenmueller for the contribution (#1514), (#1517) Fixed task reminders not syncing to Google Calendar Task-specific reminders (both relative and absolute) now sync to Google Calendar Previously only the global default reminder setting was used, ignoring per-task reminders Thanks to @christenbc for the contribution (#1525), (#1531) Fixed subtask status dot not refreshing visually when clicked Status dot, checkbox, and card styling now update instantly when cycling status Thanks to @christenbc for the contribution (#1537) Fixed Google Calendar errors during bulk sync Added rate limiting to space out API calls, preventing errors when syncing many tasks at once Thanks to @Lorite for the contribution (#1515), (#1540) Fixed time loss when setting recurrence and recurrence not clearing from Google Calendar Setting recurrence on a task with a scheduled time now preserves the time, preventing Google Calendar events from appearing as all-day Clearing recurrence from a task now also removes it from the synced Google Calendar event Thanks to @christenbc for the contribution (#1428), (#1559) Fixed hierarchical tags with slashes (e.g., #project/sub-project) being truncated in link text Tags containing slashes, hyphens, and Unicode characters now render correctly Thanks to @normenmueller for the contribution and @ysafonov for reporting (#1565) Fixed Google Calendar target calendar dropdown appearing empty after app restart The dropdown now re-populates once calendars are fetched during startup Thanks to @N-HEDGER for reporting (#1567) Fixed inline task card widgets disappearing momentarily When the task cache is temporarily cleared (e.g., during Smart Connections processing), the previously-rendered widget is now preserved instead of reverting to a plain wiki link Thanks to @scztt for reporting (#1568) Fixed deleted tasks not being removed from Google Calendar When a task file is deleted outside of TaskNotes (e.g., via Obsidian's file manager), the synced Google Calendar event is now cleaned up automatically Thanks to @kmaustral for reporting Fixed Integrations tab spacing and layout issues Improved positioning of buttons and status indicators across Google Calendar, ICS, and Webhooks sections"},{"title":"TaskNotes 4.3.2","url":"/obsidian/releases/4.3.2/","description":"(#1520) Tag and Context fields in Edit Task modal now show all available suggestions immediately on focus","product":"obsidian","text":"Added# (#1520) Tag and Context fields in Edit Task modal now show all available suggestions immediately on focus Previously required typing at least one character before suggestions appeared Already-selected values are excluded from the suggestion list Thanks to @Glint-Eye for the suggestion (#1506) Added setting to configure the default color for new timeblocks New color picker in Settings > Features > Timeblocking Previously hardcoded to indigo; now user-configurable Thanks to @phillipadsmith for the suggestion Fixed# Fixed mdbase-spec type definition generation not triggering when settings change (#1456) Fixed inline tasks jumping visually when marked as completed Thanks to @3zra47 for reporting (#1364) Fixed auto-stop time tracking not triggering when completing recurring task instances Thanks to @slipstyle for reporting (#1465) Fixed all-day events synced to Google Calendar receiving wrong notification time All-day events now use Google Calendar's configured all-day notification defaults instead of a minutes-based reminder Thanks to @Jomo94 for reporting (#1470) Fixed cursor showing as default instead of pointer on interactive elements Thanks to @TheFrostedDev for reporting (#1491) Fixed boolean property values being quoted as strings in Bases filter generation When using a boolean property (e.g. tasknote: true) for task identification, the filter now correctly handles the value Thanks to @denisgorod for reporting (#1494) Fixed Kanban swimlane resetting to \"None\" on initial load and after navigation Thanks to @tnguyen2018 for reporting (#1555) Fixed \"Folder already exists\" error when creating tasks or converting inline tasks Thanks to @jkune5 for reporting (#1532) Fixed expanded task modal buttons being cut off when content exceeds viewport height Thanks to @willfanguy for reporting (#1542) Fixed declined and cancelled events from ICS calendar subscriptions appearing in calendar view Thanks to @karenchoe428 for reporting (#1556) Fixed completion-based recurring tasks not rescheduling when the recurrence interval is large Thanks to @kazerniel for reporting (#1492) Fixed hardcoded \"open\" status leaking into filenames, recurring task displays, and parsing fallbacks Users with custom default statuses (e.g. \"inbox\") no longer see \"open\" where their configured default should appear Recurring tasks now show their actual configured status instead of always displaying \"open\" when not completed Thanks to @macdrifter for reporting (#1501) Fixed Google/Microsoft Calendar event colors not showing in agenda/list view Per-event and calendar-level colors now display correctly in the list view, matching grid view behavior Added today indicator highlighting to list view day headers Thanks to @Robubble for the suggestion"},{"title":"TaskNotes 4.3.3","url":"/obsidian/releases/4.3.3/","description":"Published mdbase-tasknotes (mtn), a standalone CLI for managing tasks in markdown files via mdbase","product":"obsidian","text":"Changed# Published mdbase-tasknotes (mtn), a standalone CLI for managing tasks in markdown files via mdbase Works on the same vault and _types/task.md schema that TaskNotes generates, without requiring the plugin or HTTP API Preferable over tasknotes-cli as a lighter-weight alternative and when Obsidian is not running, on remote machines, or in scripts and CI environments Supports natural language task creation, time tracking, project aggregation, statistics, and an interactive REPL Extracted shared natural language parsing logic into the standalone npm package tasknotes-nlp-core The NLP parser and related language configuration are now shared through this package This keeps behavior consistent between the plugin and CLI tools Added# (#1549) Added setting to reset markdown checkboxes when recurring tasks are completed When enabled, all checked checkboxes (- [x]) in the task body are reset to unchecked when a recurring task instance is completed and rescheduled Useful for recurring tasks with subtask checklists that need to be repeated each instance Configurable via Settings > Features > Recurring Tasks > \"Reset checkboxes on recurrence\" Thanks to @phortx for the feature request (#1548) Added ability to create calendar events on connected external calendars directly from the calendar view When clicking or dragging to select a time slot, a new \"Create calendar event\" option appears in the context menu Opens a modal to enter event title, description, location, and select which calendar to create on Supports both Google Calendar and Microsoft Calendar providers Thanks to @Robubble for the feature request (#1597) Added MCP server for AI agent integration Exposes TaskNotes tools at /mcp endpoint, gated behind enableMCP setting Supports tasks (CRUD, query, toggle status/archive, parse from text), time tracking, pomodoro, calendar events, and task statistics Thanks to @dstotijn for the contribution Fixed# Fixed generated mdbase type definitions for task dependencies using the wrong field type In _types/task.md, blockedBy[].uid now uses type: link (was type: string) Better matches how dependency links are serialized in task frontmatter ([[...]]) Fixed generated mdbase reminder type definitions to better match TaskNotes reminder data In _types/task.md, reminders[].type now uses enum values absolute|relative reminders[].relatedTo now uses enum values due|scheduled reminders[].absoluteTime now uses type: datetime (was type: string) (#1597) Fixed webhook payloads for time tracking start-with-description containing stale data Thanks to @dstotijn for the fix (#1581) Fixed Pomodoro starting break instead of work session after app restart After completing a work session and restarting, pressing Start would incorrectly start a break Now properly resets nextSessionType when clearing stale sessions or stopping the timer Thanks to @Sirnii for the detailed bug report and root cause analysis (#1577) Fixed Edit Note/Task modal hiding action buttons when content exceeds viewport height Added vertical scroll to modal content area while keeping buttons pinned at bottom Thanks to @hossam-elshabory for reporting and @ivannin for helping in discussion (#1600) Fixed kanban view grouping not working when more than 20 views exist The getGroupByPropertyId() method had a hardcoded loop limit of 20 iterations Views at index 20 or higher would not be found, causing groupBy to return null Thanks to @IHaveNoShame for reporting (#1595) Fixed task modal floating buttons blocking content on mobile Added mobile-specific (body.is-mobile) CSS to ensure proper flex layout Button container now stays pinned at bottom without overlapping scrollable content Thanks to @Jomo94 for reporting (#1590) Fixed HTTP API not allowing blockedBy dependencies when creating tasks Added blockedBy field support to TaskService.createTask() Updated API documentation with blockedBy, recurrence, and reminders fields Thanks to @hGriff0n for reporting (#1582) Fixed recurring tasks not appearing at end of visible calendar range for non-UTC timezones Daily/weekly recurring tasks with times after ~1pm would disappear on the last day of the visible range for users in positive UTC offsets (e.g., UTC+11) Fixed date boundary comparisons in both generateRecurringInstances() and generateRecurringTaskInstances() to compare dates only, not timestamps Thanks to @benefitbug for reporting (#1580) Fixed Google Calendar sync failing after OAuth token expires with unhelpful error message When refresh tokens expire or are revoked (e.g., Google Cloud project in Testing mode, user revoked access), the error message was confusing: \"Failed to refresh google token: Request failed, status 400\" Now detects irrecoverable token errors (invalid_grant, invalid_client) and automatically disconnects the OAuth connection Shows actionable error message: \"Google Calendar connection expired. Please reconnect in Settings > Integrations.\" Prevents repeated failed refresh attempts and error message spam Thanks to @osxisl for reporting and @Naesue for helping in discussion (#1584) Fixed DOMTokenList error when task status values contain spaces Clicking the status ring on a task card threw an error when status contained spaces (e.g., \"In Progress\") Status and priority values are now sanitized before being used as CSS class names Thanks to @omber for reporting"},{"title":"TaskNotes 4.4.0","url":"/obsidian/releases/4.4.0/","description":"TaskNotes documentation.","product":"obsidian","text":"Added# Mdbase type generation now includes tn_role annotations so external tools can identify each field's role even when frontmatter names are customized (#1618) Mdbase type matching now follows your task identification settings (tag or frontmatter property), with fallback to tag matching when needed Thanks to @jimbo108108 for reporting Mdbase type status fields now include tn_completed_values so external tools can reliably identify which status values count as completed (#1576) Added an optional Checklist Progress task-card property that renders a compact progress bar and completed/total count from top-level markdown checkboxes Uses metadata cache list items and excludes nested checklist entries so progress reflects top-level task steps In Bases views, map tasks (file.tasks) to Checklist Progress Existing .base files need file.tasks added to the view order YAML manually Newly generated .base templates now include file.tasks in view order by default Thanks to @phortx for opening #1576 and for the earlier implementation PR, and @piyushaswani55 for feedback in the issue discussion Changed# Mdbase type generation no longer overwrites mdbase.yaml if the file already exists, preserving user customisations Webhooks now fire consistently regardless of whether updates come from the UI, HTTP API, or MCP Webhook runtime state now syncs automatically when plugin settings change Shared HTTP response/body parsing utilities are now consolidated in a dedicated httpUtils module Release notes now include a reminder on every release page that default generated .base template changes never overwrite existing user .base files, and that users can regenerate templates from Settings to pick up updates Fixed# (#1608) Fixed task title frontmatter being removed when storeTitleInFilename is enabled title is now retained in frontmatter while filename derivation from title remains unchanged Thanks to @victoraraujo105 for the PR (#1602) Fixed time tracking statistics showing incorrect or zero values for Today/Week/Month due to UTC-anchored date range boundaries in Stats View Updated range calculations to use local calendar-day boundaries consistently (#1602) Fixed inconsistent timeEntries timestamp formats across create/edit/drag/resize flows Time entry timestamps are now written in canonical UTC ISO format (toISOString() with Z) across all write paths (#1602) Fixed denormalized timeEntries.duration drift after edits Time tracking calculations now derive duration from startTime/endTime Time entry save paths now strip legacy duration values instead of persisting them Thanks to @dy66 for opening #1602"},{"title":"TaskNotes 4.5.0","url":"/obsidian/releases/4.5.0/","description":"TaskNotes documentation.","product":"obsidian","text":"Fixed# (#1652) Fixed API, MCP, and NLP task creation so it respects your configured filename format when title storage in filenames is disabled Thanks to @36mimu36 for reporting, and @rafavital and @warm-july for follow-up discussion and reports (#1601, #1709) Fixed reading-mode relationship widgets sometimes rendering multiple times during startup Applied the same protection to task cards so overlapping refreshes are coalesced there too Thanks to @wealthychef1 and @CarlJohnson99 for reporting, and @benmartinek for confirming the behavior (#1713) Fixed ICS export so date-only scheduled tasks are written as all-day events instead of midnight events Thanks to @bepolymathe for the request and interoperability details (#267, #948, #1682, #1717, #1725) Fixed expanded subtasks and dependency cards in Bases Task List and Kanban views so related items can inherit the current view's filters instead of always showing every linked task Added a per-view \"Expanded relationships\" option so you can switch between inherited filters and showing all related tasks Thanks to @mdbraber, @GardarikanetS, @Glint-Eye, @prepare4robots, and @robmcphers0n for the original reports and feature requests, and @marblebyte for follow-up discussion Improved custom view and search-pane activation when reopening deferred tabs (#1720) Fixed Bases Task List cards showing icon tokens such as clock instead of readable date-like values, and fixed property labels to use Bases display names instead of raw property IDs Thanks to @Sirnii for reporting (#1633) Fixed interactive task-card labels and ribbon labels so Bases-backed cards use translations and configured display names instead of hardcoded English or raw property IDs Thanks to @Sarryaz for reporting (#1651) Fixed date is query filtering so date-only searches also match timed scheduled and due values during prefiltering Thanks to @36mimu36 for reporting (#1644) Fixed generated default task views so recurring tasks without a complete_instances property still appear as incomplete where appropriate Thanks to @bkennedy-improving for reporting, and @SandroK for follow-up discussion on related default-view behavior (#1513, #1686) Fixed a calendar issue where creating or editing events and timeblocks could reset the visible date back to today In-place calendar recreation now preserves the visible date unless you explicitly navigate elsewhere Thanks to @owenoxen for opening #1513, and @Lorite for opening #1686 and contributing the fix Fixed documentation deployment CI failures caused by docs-builder/src/js/main.js being excluded by a broad .gitignore rule Reduced background calendar-sync overhead when persisting sync tokens Prevented duplicate auto-stop time-tracking listeners from accumulating after settings reloads Fixed a settings-lifecycle issue that could accumulate calendar update callbacks while the Integrations tab is repeatedly opened (#1630) Fixed TaskNote inline task cards ignoring centered \"Readable line length\" layout in the Minimal theme Thanks to @martin-forge for reporting Fixed a broken docs cross-reference from Property Types Reference to Task Properties settings Fixed docs site links so internal Markdown links resolve to app routes instead of broken .md paths Fixed docs release-note links by building Markdown pages even when they are not listed directly in the sidebar Added# (#1704) Added an option to widen the current day column in multi-day calendar time-grid views You can control the width multiplier and choose whether it applies to week view, custom multi-day view, or both Thanks to @dictionarymouse for the feature request Added TaskNotes Obsidian CLI commands for task creation, time tracking, and Pomodoro control Includes shared NLP-to-task conversion across the CLI, modal, and API capture flows, plus new user documentation for the built-in CLI commands (#1716) Added roomier subtask and dependency cards inside the task modal while keeping the task options menu available Thanks to @hokfujow for the feature request (#1619, #386, #621) Added drag-to-reorder for Kanban and Task List views Supports grouped Task List moves, manual ordering via the tasknotes_manual_order property, and improved drag/drop behavior for swimlanes, filtered views, and interactive task controls To use it, sort the view by the Manual Order field (tasknotes_manual_order by default), or regenerate the built-in .base templates from Settings → TaskNotes → General → Create Default Files Thanks to @ac8318740 for the original contribution in PR #1619, @iholston and @dsebastien for opening #386 and #621, and @mdbraber, @elvarb, @LucidToday, @craziedde, @kmaustral, @SKIERZZ, @sookochoff, and @kanzaki1201 for follow-up discussion and testing across the linked issues and PR Added a standalone TaskNotes Specification repo and docs section covering the data model, field mapping, recurrence behavior, validation rules, and conformance tests Added tasknotes-tui, a terminal UI for working with TaskNotes vaults Includes keyboard-driven views, date navigation, time tracking, recurring task support, and a command palette Changed# Refactored several internal modules to reduce coupling and make maintenance safer Updated generated _types/task.md output so dateCreated and dateModified include generated timestamp values, and recurrence_anchor defaults to scheduled Cleaned up API, webhook, NLP, privacy, settings, and view documentation for clarity and accuracy Expanded Task List and Kanban documentation for drag-to-reorder, including manual-order sorting, grouped and swimlane scope, and filtered-view limitations"},{"title":"TaskNotes 4.5.1","url":"/obsidian/releases/4.5.1/","description":"TaskNotes documentation.","product":"obsidian","text":"Fixed# (#1672) Fixed custom date ranges in the MCP time summary tool so from and to dates work as expected Thanks to @pib for the fix (#1742) Fixed calendar week and day views so the time scale stays aligned on the left instead of drifting inward Thanks to @ysafonov for the report and screenshot"},{"title":"TaskNotes 4.5.2","url":"/obsidian/releases/4.5.2/","description":"TaskNotes documentation.","product":"obsidian","text":"Added# (#1342, #1793) Added native tag autocomplete to time entry descriptions by using the embedded markdown editor in the time entry editor modal. Thanks to @fastrick for the request and @renatomen for the PR. (#1756, #1798) Added HTTP API support for configured custom user fields so task responses include them and create/update requests can round-trip their values. Thanks to @Treygec for the request and PR. (#1777) Added a Modal Fields setting to choose whether Tab/Shift+Tab move focus out of the task details editor or use the markdown editor's indentation behavior. Thanks to @P-Sc for the PR. Changed# Updated the Obsidian API dependency to 1.12.3 and switched the Bases integration to the official API type declarations. Bases task cards and property-event cards now render metadata values through Obsidian's native Bases value renderer so links, dates, lists, icons, and formula values display more faithfully. Fixed# (#1778) Fixed MCP initialize requests using newer protocol versions such as 2025-11-25 failing instead of negotiating down to TaskNotes' supported MCP version. Thanks to @SakulaPor for reporting. (#1781) Fixed duplicate metadata properties on Bases task cards when bare and note.-prefixed property IDs map to the same TaskNotes field. Thanks to @loukandr for reporting and tracing the issue. (#1787) Removed the \"(click to change)\" helper text from recurrence tooltips on task cards. Thanks to @kazerniel for reporting. (#1828) Fixed subtask creation from a task card dropping the parent task project when natural-language input also adds projects. Thanks to @prepare4robots for reporting. (#1786) Fixed TaskNotes task cards and relationships/subtasks widgets appearing inside embedded task-note heading or block sections. Skips note-level widget injection in detached or embedded Markdown editor contexts used by plugins such as Block Link Plus. Thanks to @3zra47 for reporting. (#1815) Fixed the Priority property settings so the NLP trigger character field is visible and editable even when priority NLP parsing is disabled. Thanks to @spiv for reporting. (#1035) Fixed the task modal title field causing the modal to jump to the bottom when focused on iPhone. Thanks to @3zra47 for reporting and following up. (#1045) Fixed inline linked recurring tasks keeping the previous day's completed state after the calendar day changes. Thanks to @3zra47 for reporting and following up. (#1788) Fixed Task List subgroup headers and cards rendering without clear indentation. Thanks to @renatomen for the PR. (#1810) Updated Japanese Kanban terminology to use the more natural katakana spelling. Thanks to @sigma7863 for the PR. (#1633) Fixed Bases task cards using fallback labels instead of Bases display names for mapped task fields and file properties. Thanks to @Sarryaz for reporting the Bases task card i18n and field-mapping issue. (#884) Fixed untranslated strings and English placeholder examples across non-English interface translations. Thanks to @berzernberg for reporting Russian translation gaps. (#1765, #1769) Fixed auto-archived tasks leaving stale Google Calendar events when cleanup runs before calendar sync is ready or after the task moves into the archive folder. Thanks to @martin-forge for reporting and the PR. (#1764) Fixed Google Calendar sync using stale task metadata after rapid task updates, and fixed late recurring completions/skips recording the completion day instead of the scheduled occurrence date. Thanks to @martin-forge for the PR and to @jpmoo for reporting the recurring completion issues. (#1782) Fixed CI test runs resolving the NLP parser package from a local sibling checkout instead of the published dependency. Thanks to @martin-forge for reporting. Published mdbase-tasknotes 0.1.3 with compatibility fixes for TaskNotes-generated mdbase schemas. Includes clearer create-path diagnostics, natural-language mtn list --due filters, timer log datetime filters, home-directory path expansion, project wikilink preservation, and correct mtn --version reporting. Thanks to @tparsons9, @anomatomato, @npondel, @plashal, and @waspeer for the reports and PR. (#1667) Fixed NLP scheduled-date parsing so standalone scheduled and start triggers can set scheduled dates alongside due dates. Thanks to @hokfujow for reporting and @UniqueClone for the NLP core PR. Fixed NLP parser title cleanup for explicit date triggers and Japanese/Chinese priority phrases. (#1658) Fixed Pomodoro stats date bucketing for sessions near local midnight. Pomodoro session stats now compare the recorded session calendar date against UTC-anchored target days without shifting through UTC or the reader's current timezone. Pomodoro daily-note storage now writes sessions to the daily note matching the recorded session date. Thanks to @ewgdg for reporting, @AntonIlinykh and @dkchacha for follow-up discussion, and @ITblacksheep for PR #1758. (#1813) Fixed Pomodoro timer UI stalls caused by refreshing session statistics on every timer tick. Pomodoro stats now refresh on initial render and session completion instead of once per second. Pomodoro daily-note stats now read the relevant date/range instead of routing through all history. Native Pomodoro notifications now respect the notification setting and granted permission before showing. Thanks to @Szu-Szu for reporting and @its-thex for confirming. (#1744) Fixed Bases Task List views so changing the per-view Expanded relationships option takes effect on re-render. Restores the expected show-all behavior for setups that hide subtasks at the top level with note.projects.isEmpty(). Thanks to @minol-dev for reporting, @Glint-Eye for follow-up discussion, and @stanley-910 for PR #1792 exploring the related standalone-subtask workflow. Fixed tag clicks in task cards opening the task edit modal in addition to the tag search panel, and kept rendered tag metadata on a single row inside task cards."},{"title":"TaskNotes 4.5.3","url":"/obsidian/releases/4.5.3/","description":"TaskNotes documentation.","product":"obsidian","text":"Fixed# (#1834, #1847) Fixed empty Bases formula and custom properties showing null or undefined on TaskNotes task cards. A big thanks to @Glint-Eye and @3zra47 for reporting. (#1836) Fixed TaskNotes Bases views not refreshing task cards after status, archive, and auto-archive updates. A big thanks to @kmaustral for reporting."},{"title":"TaskNotes 4.6.0","url":"/obsidian/releases/4.6.0/","description":"TaskNotes documentation.","product":"obsidian","text":"Changed# TaskNotes now requires Obsidian 1.12.2 or later, matching the Obsidian APIs used by the plugin. Improved internal code quality by resolving lint warnings, moving static inline styles into CSS utilities, and extending sentence-case lint coverage to English localization strings, with no intended behavior changes. Fixed# Fixed TaskNotes failing to load when Obsidian opened without an active Markdown file."},{"title":"TaskNotes 4.7.0","url":"/obsidian/releases/4.7.0/","description":"TaskNotes documentation.","product":"obsidian","text":"Changed# Enabled lint checks that mirror Obsidian community plugin review findings, including dynamic code execution, Promise handling, deprecated APIs, unsafe stringification, directive comments, Node built-in imports, and explicit any usage. Clarified privacy documentation for optional integrations that make periodic background network refreshes. Cleaned up internal Obsidian and Bases compatibility adapters used by search and grouped views. (#1839, #1881) Updated default Base urgency scoring so timed tasks earlier in the day sort above later tasks with the same priority and date Thanks to @loukandr for the contribution Fixed# Fixed project autocomplete searches so non-empty + queries only return files matching the query in the basename, title, aliases, or explicitly searchable metadata rows. (#1713) Fixed all-tasks ICS export when a task uses a space-separated scheduled datetime such as 2025-08-12 18:00 Thanks to @bepolymathe for requesting this and @m4to-3pe for following up Fixed Pomodoro stats reopening immediately after a plugin reload before the Pomodoro service has finished initializing. (#1872) Fixed unarchiving moved tasks so the destination task folder processes template variables such as {{project}} before moving the file Thanks to @OXI-717 for reporting (#1870) Fixed custom user field NLP triggers with file autosuggest so selecting a wikilink suggestion stores the link in the user field instead of leaving it in the task title Thanks to @Sineapple for reporting (#1878) Fixed completed tasks still appearing as active blockers for dependent tasks Thanks to @macbikegeek for reporting (#1880) Fixed the status bar time-tracking label for task titles that contain a dash Thanks to @ubidev for reporting (#1854) Fixed modal task completion so completed tasks receive a completed date consistently Thanks to @misolex for reporting (#1124, #1838, #1881) Fixed default Base views and formulas excluding tasks scheduled or due today at a non-midnight time from day-level comparisons Thanks to @kmaustral for reporting and @loukandr for the fix Removed# Removed JavaScript webhook transform support and examples. JSON webhook transform templates remain supported."},{"title":"TaskNotes 4.7.1","url":"/obsidian/releases/4.7.1/","description":"TaskNotes documentation.","product":"obsidian","text":"Changed# Release assets are now built with GitHub artifact attestations so users and reviewers can verify the provenance of main.js, manifest.json, and styles.css."},{"title":"TaskNotes 4.7.2","url":"/obsidian/releases/4.7.2/","description":"TaskNotes documentation.","product":"obsidian","text":"Changed# Improved local lint checks so package and CSS issues reported by Obsidian's online review can be caught before submission. Cleaned up stylesheet compatibility issues reported by Obsidian's online review without changing the intended TaskNotes appearance. Improved spacing and alignment in task, timeblock, and webhook modals after the stylesheet cleanup. Reworked optional calendar and ICS subscription refresh scheduling to avoid interval-based network polling while preserving the same refresh intervals. Cleaned up additional source patterns reported by Obsidian's online review, including unsafe default object stringification and redundant external type unions. Prevented a console error when plugin listeners are cleaned up after reloads. Added a local lint check to prevent interval-based polling in files that also perform network requests."},{"title":"TaskNotes 4.8.0","url":"/obsidian/releases/4.8.0/","description":"TaskNotes documentation.","product":"obsidian","text":"Added# (#353) Added a Has Subtasks filter for task queries, so views and API clients can show only project-style tasks or direct tasks. Thanks to @mdbraber for suggesting this. (#380) Added a test-reminder button in notification settings, so reminder setup can be checked without creating a real task reminder. Thanks to @mdbraber for suggesting this. (#711, #168) Added an optional task-creation setting to open the new task note after saving, either in the current tab or a new tab. Thanks to @phortx and @23426356587 for suggesting this, and to @edward-peters and @obsilover for the follow-up. (#1041, #1800) Added copy-drag support for timeblocks: hold Ctrl, Cmd, or Alt/Option while dragging an existing timeblock to duplicate it at the new date and time. Thanks to @0-BSCode and @cweekly for suggesting this. (#1052) Added a public JavaScript API for in-vault scripts at app.plugins.plugins.tasknotes.api.parseNaturalLanguage(text), so Templater, QuickAdd, and MetaBind workflows can use TaskNotes' natural-language parser without running the HTTP API. Thanks to @edakimling for suggesting this. (#1235) Added a task-card toggle for blocked tasks, so you can expand a blocked task to see the tasks it is waiting on. Thanks to @craziedde for suggesting this. (#1254) Added ../ and ./ normalization for folder templates after variables are expanded, so instant task conversion can target sibling folders such as {{currentNotePath}}/../Tasks. Thanks to @rdick for suggesting this. (#1267) Added Daily Notes-style date tokens such as YYYY, MM, DD, MMMM, and dddd to TaskNotes folder templates. Thanks to @paulsen-it for suggesting this. (#1380) Added tag actions to task context menus, including add/remove actions for individual tasks and batch-selected tasks. Thanks to @Chuhtra for suggesting this. (#1377) Added right-click Mini Calendar actions for opening daily notes from day cells and weekly notes from week numbers. Thanks to @hasanyilmaz for suggesting this. (#1151) Added a Mini Calendar max color note count option, so one-note days can use the strongest heatmap color when that better fits the view. Thanks to @arreme for suggesting this. (#1376) Added backslash escapes for NLP trigger tokens, so text like \\@context, \\*done, or \\tomorrow can stay in the task title. Thanks to @JerryLu086 for suggesting this. (#1366) Added CSS variables for compacting nested task-card indentation, with smaller defaults on mobile and documented snippets for tighter task-link lists. Thanks to @rk-kontur for suggesting this. (#1502, #603) Added calendar indicators for external events that have linked notes or tasks, and showed loaded event titles in task-card calendar metadata instead of only the linked event count. Thanks to @Robubble and @mdbraber for suggesting this, and to @ubidev for the follow-up. (#1522) Added a per-status option to skip rarely used statuses when cycling task-card status indicators. Thanks to @Glint-Eye for suggesting this. (#144) Added an \"Open note in new tab\" action to the task context menu. Thanks to @cathywu for suggesting this and @macbikegeek for the follow-up feedback. (#167) Added an optional next-status override for each status, so forward cycling can jump to a configured status instead of always following the status order. Thanks to @DanBrazelton for suggesting this, and to @michelebugio, @Moyf, @anareaty, and @vorrermid for the follow-up feedback. (#1520) Made tag and context fields show available suggestions as soon as the field is focused. Thanks to @Glint-Eye for suggesting this, and to @craziedde for the follow-up. (#1541) Added {{currentNotePath}} and {{currentNoteTitle}} support to the default tasks folder, so normal task creation can place new tasks beside the active note without creating an inline link. Thanks to @ChristianAnyanwu for suggesting this, and to @abbasou and @ttlaylor for the follow-up feedback. (#648, #1605) Added clickable links in task-card contexts for note links, markdown links, and web URLs while keeping plain contexts as tag-search buttons. Thanks to @trdischat and @Glint-Eye for suggesting this, and to @renatomen for the follow-up feedback. (#1482) Added clickable custom-field links on task cards for wikilinks, markdown links, autolinks, and bare web URLs. Thanks to @ptbosch-figueiredorj for suggesting this, and to @Soleone for the follow-up use case. (#1471) Added Kanban column and swimlane-cell add buttons that open the TaskNotes creation modal with the grouped values already filled in. Thanks to @byheaven for suggesting this and @Davincible for the project-board use case. (#933) Added non-Markdown vault files such as canvases to project suggestions, using extension-qualified link targets so those files can be selected as task projects. Thanks to @Alvin21Bon for suggesting this. (#1475, #725) Added quote/backtick escapes for NLP input, so literal course codes or date words can stay in task titles without being parsed as estimates or dates. Thanks to @RumiaKitinari and @gavingwebb for suggesting this. (#1462) Added natural-language date entry to the task date picker, so existing due and scheduled dates can be changed with phrases such as \"tomorrow at 3pm\" when NLP is enabled. Thanks to @Ruboks-Cube for suggesting this. (#1526) Added a native date field to the task date picker, so scheduled and due dates can be changed with the device date picker while keeping optional times visible. Thanks to @jmartinmcfly for suggesting this and @23426356587 for the follow-up feedback. (#1603) Added Calendar view toggles for hiding completed or skipped recurring task instances while keeping future outstanding instances visible. Thanks to @wandererovertheseaofpiss for suggesting this. (#287, #273, #274) Added linked hover highlighting for Calendar and Agenda events that come from the same task note, so scheduled, due, and recurring entries are easier to connect. Thanks to @girisumit for suggesting this. (#280) Added project-specific CSS hooks to task cards and Calendar events, so project-based visual styling can be handled with user snippets. Thanks to @girisumit for suggesting this. (#1625) Added Shift + Cmd/Ctrl + Enter in the Create Task modal to save the current task and reopen the modal for the next one. Thanks to @tcb678 for suggesting this. (#1353) Focused the Create Task modal's natural-language input when the modal opens, with a longer mobile delay so the keyboard can open after layout. Thanks to @GiovanH for suggesting this. (#1664) Added project-based custom filename template variables, including the first project, all projects, and a short projectId. Thanks to @bendavis987 for the contribution. (#923) Added {{projectFilePath}} and {{projectFilePaths}} folder template variables, so task folders can mirror project note locations in the vault. Thanks to @PacoTaco2 for suggesting this. (#1697) Added cached Google Calendar, Microsoft Calendar, and ICS events to Mini Calendar days, with compact colored dots and event details from the existing calendar connection. Thanks to @RPGArchivist for suggesting this. (#1754) Added optional icons for priority values, so task cards can show a configured priority icon instead of only a colored dot. Thanks to @BrucePlumb for suggesting this and @prepare4robots for the follow-up feedback. (#1761) Added TaskNotes edit and task-action submenu entries to Obsidian's native file context menu for recognized task notes. Thanks to @delzero for suggesting this. (#1771) Added mobile drag handles to manually sorted Task List Bases views, so dragging can start from the handle without disabling normal text interaction on the rest of the card. Thanks to @PatrickGolz for suggesting this. (#1776) Allowed calendar timeline end times after midnight, such as 26:00 for a 2 AM next-day end. Thanks to @chrabia for suggesting this. (#1784, #1833) Added a per-view pinnedColumns option for TaskNotes Kanban views, so selected empty columns can stay visible as drop targets while other empty columns remain hidden. Thanks to @loukandr for suggesting and prototyping this. (#1794) Added context updates to the task card context menu, so contexts can be added, toggled, or cleared without opening the task edit modal. Thanks to @m13ntrpn for suggesting this. (#315, #1356, #1748, #1809) Added a subtle task-card indicator and CSS hooks for tasks with note body details, including existing task bodies read through Obsidian's metadata cache. Thanks to @volodxyz, @Karut, @yeHHH1g, and @aliceinwaterdeep for suggesting this, and to @minchinweb for the follow-up. (#1808) Added advanced Kanban swimlane ordering through swimLaneOrder, so swimlane rows can stay in a stable configured order. Thanks to @rookledookle for suggesting this, and to @benmartinek and @chrabia for the follow-up feedback. (#1805) Added an ICS export option to omit completed tasks from generated calendar files. Thanks to @bepolymathe for suggesting this. (#659) Added Obsidian links to ICS export descriptions, so exported calendar events can open their source task notes. Thanks to @bepolymathe for suggesting this. (#589) Added an Appearance toggle to turn off strikethrough styling on completed task card titles. Thanks to @BrucePlumb for suggesting this. (#561) Added a \"Last day\" option to the custom recurrence month-day picker for month-end repeating tasks. Thanks to @TonyAtlas for suggesting this and @BrucePlumb for the follow-up. (#217) Added weekday selection to daily custom recurrence rules, so interval rules such as every three days can skip weekends from the recurrence modal. Thanks to @kmaustral for suggesting this. (#1818) Added an auto-height mode for TaskNotes Calendar Bases views so embedded agenda/list sections can size to their content instead of forcing an inner scroller. Thanks to @martin-forge for suggesting this. (#1201) Added a Calendar Bases toggle to hide the hourly breakdown in week, custom-days, and day views while keeping the all-day planning row visible. Thanks to @PacoTaco2 for suggesting this. (#1176) Added advanced Kanban WIP limits through wipLimits, so column headers can show (current/limit) counts and highlight exceeded limits. Thanks to @williamcheuk03 for suggesting this. (#914) Added a generated Due in countdown to the default Agenda Base and allowed Calendar Bases list agendas to span up to 365 days. Thanks to @williamcheuk03 for suggesting this. (#900) Added an instant-conversion setting to keep the original Markdown checkbox marker when converting a checkbox into a TaskNote link. Thanks to @dsebastien for suggesting this. (#898) Added a mobile-only calendar integration opt-out, so synced desktop calendar settings no longer have to trigger external calendar loading on Obsidian Mobile. Thanks to @cathywu for suggesting this. (#887) Added built-in scheduled and due date presets to the Quick actions palette for current tasks. Thanks to @willgraham345 for suggesting this and @anrie for the related preset feedback. (#819) Added a command to open Quick actions for the inline task link under the cursor. Thanks to @rlolingo for suggesting this. (#798, #1732, #1835) Added hotkeyable commands to edit the current task, add a project to the current task, and add an existing task as a subtask of the current note. Thanks to @xorander00 and @prepare4robots for requesting this, and to @musta-code and @ubidev for the follow-up suggestions. (#791) Added a UUID v4 task filename format and {{uuid}} custom filename template variable. Thanks to @bangbangbanggit for suggesting this. (#932) Added hotkeyable commands to cycle the current task's status and priority. Thanks to @rxunique for suggesting this and @luckb0x for the follow-up feedback. (#1655) Added live elapsed time to the optional active time tracking status bar item. Thanks to @connradolisboa for suggesting this. (#1622) Allowed multiple comma-separated default reminder offsets for timed Google Calendar task exports. Thanks to @solidabstract for suggesting this. (#706, #820, #1040) Added direct Pomodoro duration editing, hour-aware timer formatting, clearer one-minute controls, and an optional active Pomodoro status bar countdown. Thanks to @SublunarSage, @lj1446615403-cloud, @0-BSCode, and @thestrike72 for the suggestions and feedback. (#873) Added an optional built-in sound for task reminder notifications, with volume and preview controls in Settings. Thanks to @berzernberg for suggesting this. Added a generated Pomodoro statistics Base with daily and monthly summary views for Pomodoro history stored in daily notes. Changed# Expanded the bug report template to ask for Obsidian \"Show debug info\" output, affected task frontmatter, relevant Bases file contents, reproduction steps, and related logs or screenshots. Release notes now show the default .base file regeneration reminder only on the current version section, keeping older bundled sections focused on their own changes. Updated the release notes GitHub prompt to invite feedback while still asking satisfied users to star the project. (#239) Ordered Kanban status and priority columns by the configured status order and priority weights when no manual column order is saved. Thanks to @ScumbagScalawag for asking about this, and to @nightroman, @lavir, and @elvarb for the follow-up discussion. (#269) Marked Kanban status columns that come from values outside the configured TaskNotes statuses, so manually edited or external status values are visible as non-standard instead of blending into the board. Thanks to @cstelmach for suggesting this and @digitaldoctors for the follow-up. Refined Kanban empty columns, swimlane rows, and column drag handles, and added a per-view compact card layout option for denser boards. Kept Kanban swimlane rows from shrinking to share the viewport so the Max Swimlane Height setting is respected. Added guidance in Pomodoro statistics and Base file settings explaining that Pomodoro Base views require daily notes storage. (#323) Reordered task modal action buttons to match the right-click task menu order. Thanks to @23426356587 for suggesting this. (#1189) Made the Create/Edit Task modal priority picker follow the priority order configured in Settings. Thanks to @n1njaznutz for suggesting this. Made task-card priority dots and configured priority icons slightly larger for better visibility. (#1244) Clarified the Task Properties documentation for custom property keys and status values in Bases filters and sorting. Thanks to @Arachnidai for suggesting this. (#1234) Kept right-aligned subtask chevrons visible on task cards instead of only showing them on hover. Thanks to @n1njaznutz for suggesting this. (#1237) Made today's date more visible in the Mini Calendar view when another day is selected. Thanks to @riekusr for suggesting this. (#1348) Let long task titles wrap inside the Create/Edit Task modal title field while keeping saved titles single-line, and widened the contexts and tags fields in the modal details area. Thanks to @hasanyilmaz for suggesting this. (#1392) Made TaskNotes date fields accept compact YYYYMMDD typing and pasted dates. Thanks to @kazerniel for suggesting this. (#1431) Showed the year on task-card due and scheduled dates when the date is outside the current year. Thanks to @kazerniel for suggesting this. (#1429) Opened TaskNotes view commands in a new tab when they load configured Base files, so they do not replace the active note. Thanks to @Ruboks-Cube for suggesting this. (#1426) Added copy actions for TaskNotes Bases views, including current-view filenames, links, and titles from the result count menu, plus selected-task copy actions in the batch menu, while keeping the native Bases copy and CSV export actions available. Thanks to @kmaustral for suggesting this. Improved keyboard access, mobile layout, and theme color consistency across task cards, TaskNotes Kanban, Bases Kanban, calendar controls, stats, settings, and filter popovers. (#1526) Made the Create/Edit Task modal due and scheduled date buttons open a calendar-first "},{"title":"TaskNotes 4.8.1","url":"/obsidian/releases/4.8.1/","description":"TaskNotes documentation.","product":"obsidian","text":"Fixed# (#1903) Improved the Edit Task modal on iPhone-sized screens so opening a task no longer automatically focuses the title field, and the mobile layout gives the title, fields, and action buttons more usable space. Thanks to @3zra47 for reporting the issue and sharing the screen recording. (#1909) Fixed compact Kanban task cards showing oversized status and priority indicators on touch devices. Thanks to @pxxush for reporting the issue. (#1908) Restored newly generated Calendar Bases to show the full day by default and inherit the calendar start/end settings instead of hard-coding 06:00-22:00. Thanks to @AndreMonthy for the report. (#1907) Fixed calendar time labels drifting away from the left axis in narrow sidebar calendar views. Thanks to @kmaustral for reporting the issue. (#1906) Fixed NLP priority shortcuts leaving partial text in task titles when custom priority values include words like high or low. Thanks to @RumiaKitinari for reporting the issue. (#1904, #1905) Fixed long tags in task cards wrapping instead of forcing horizontal scrolling in TaskNotes Bases views and note cards. Long tag pills can now wrap across lines and break within very long tag names on narrow screens. Thanks to @3zra47 for reporting the issue and to @zhouzhou626 for the contribution. (#1901) Fixed the task context menu creating an undefined property when adding or removing tags. Hardened task property updates so invalid frontmatter property names are rejected instead of written. Thanks to @mgrecar for reporting the issue. (#1902) Fixed Markdown-style project links in task frontmatter not appearing as subtasks on project pages. Thanks to @minchinweb for reporting the issue. Changed# Improved the internal structure around service notifications, vault writes, and shared utilities to make future fixes easier to test and maintain."},{"title":"TaskNotes 4.9.0","url":"/obsidian/releases/4.9.0/","description":"TaskNotes documentation.","product":"obsidian","text":"Security# (#1923) Restricted the HTTP API server to loopback and limited browser CORS access to loopback origins. Thanks to @martin-forge for reporting. Added# (#1932) Added middle-click support for opening task cards in a new tab. Thanks to @imsuck for the request. Fixed# (#1934) Fixed custom priority colors being overridden by default task-card priority styles in views. Thanks to @KittehBit for reporting. (#1933) Added the note path to fallback frontmatter parse warnings so malformed task YAML is easier to find. Thanks to @rayvermey for reporting. (#1931) Made the Pomodoro task chooser open from cached task data and ignore repeated clicks while it is already opening. Thanks to @sumiyalairu03 for reporting. (#1930) Fixed starting the Pomodoro timer from its hotkey without starting time tracking for the selected Pomodoro task. Thanks to @sumiyalairu03 for reporting. (#1929) Fixed the bottom Relationships widget overlapping embedded content such as Bases/Kanban views in task notes. Thanks to @rchaklashiya for reporting and following up with the embed case. (#1922) Restored the native color picker alongside manual color text entry in Create/Edit Timeblock fields. Thanks to @AndreMonthy for reporting. (#1921) Fixed direct frontmatter edits to lifecycle-relevant task fields not triggering Google Calendar sync or auto-archive side effects. Thanks to @martin-forge for reporting and verifying the direct-edit reproduction. (#1919) Fixed the Pomodoro view rapidly resizing at certain sidebar sizes. Thanks to @RumiaKitinari for reporting. (#1898, #1907) Fixed Calendar time labels shifting into the middle of Day and sidebar calendar grids after switching views. Thanks to @ddevaal for reporting and confirming the regression, and to @kmaustral for confirming the sidebar case in 4.8.1. (#1936) Added a Calendar Base drag/drop resolution option so events can snap to smaller increments than the visible time slot grid. Thanks to @benmartinek for suggesting this. Improved mobile task cards, inline widgets, modals, and settings layouts so dense controls and long labels fit more comfortably on small screens. (#1916) Fixed Markdown task links using Obsidian's generated filename label instead of the TaskNote title in the task link overlay. Thanks to @minchinweb for reporting. (#1911) Fixed recurrence choices starting from today instead of the selected calendar date when creating a task from Calendar view. Thanks to @mikhailmarka for reporting. (#1912) Fixed \"Create subtask\" pre-filling the parent task's full folder path in the Projects field instead of using the normal Obsidian link text. Thanks to @pkuehne for reporting and @benmartinek for confirming."},{"title":"TaskNotes 4.9.1","url":"/obsidian/releases/4.9.1/","description":"TaskNotes documentation.","product":"obsidian","text":"Added# (#1885) Added Shift+arrow keyboard range selection while bulk task selection mode is active. Thanks to @chrabia for suggesting bulk selection improvements and @sumiyalairu03 for the keyboard selection idea. Fixed# (#781, #1085) Fixed Outlook-published ICS calendar events appearing at the wrong time when their feed used Windows timezone names without matching timezone definitions. Thanks to @chrlaney for reporting and @mjkrasny for confirming the Outlook timezone case. (#1696) Fixed Google Calendar export for scheduled recurring tasks when a single occurrence is moved to a different date. Keeps the recurring master event on its original rule, excludes the original occurrence date, and syncs the moved occurrence as a detached event. Thanks to @martin-forge for reporting and contributing the fix. (#1912) Fixed \"Create subtask\" inserting the full path of the parent task in the Projects field instead of using the normal Obsidian link text. Thanks to @pkuehne for reporting and @benmartinek for confirming. (#1921) Fixed Google Calendar and auto-archive updates not running after direct task file edits. TaskNotes now picks up status, completion, and date changes made directly in a task file without triggering a large one-time Google Calendar rewrite at startup. Recovery also removes stale Google Calendar links when task files were deleted or replaced outside TaskNotes. Thanks to @martin-forge for reporting and contributing the fix. (#1938) Fixed partial HTTP API task updates rewriting native tags with # prefixes or duplicate task tags. Thanks to @joseluisgonzalezdelgado-ctrl for reporting. (#1939) Fixed the task Details field rendering as a small nested textarea when the embedded editor falls back. Thanks to @g-arthurvanderbilt for reporting and @cookbr for confirming the desktop impact. Fixed tag and modal preview edge cases found during validation: double-hash tags no longer match the task tag, empty tag lists stay empty when read back, and natural-language previews remain visible when enabled. (#1941) Fixed mobile Kanban boards scrolling the whole board vertically instead of keeping each list independently scrollable. Thanks to @pxxush for reporting. (#1943) Fixed MCP task-query tool instructions so filter operators match the operators TaskNotes actually accepts. Thanks to @jordankbartos for reporting and proposing a fix in #1944. (#1945) Fixed Google Calendar export so overlapping sync services do not create duplicate events for the same task while the saved event ID is still catching up. Thanks to @martin-forge for reporting and contributing the fix. (#1946) Fixed the bottom task in virtualized Task List Bases being partially hidden behind Obsidian's mobile bottom bar. Thanks to @3zra47 for reporting. (#1947) Fixed mobile Task List cards with left-positioned subtask chevrons so the chevron remains visible and project/detail badges stay on the main row. Thanks to @Jomo94 for reporting. (#1948) Fixed Agenda Calendar Bases so completed recurring instances can appear on their recorded completion dates, even when recurring task projections are hidden or the completion date is outside the recurrence pattern. Thanks to @Jomo94 for reporting."},{"title":"TaskNotes 4.9.2","url":"/obsidian/releases/4.9.2/","description":"TaskNotes documentation.","product":"obsidian","text":"Added# (#1791) Added collapse and expand controls for grouped Bases Task List views, including a default collapsed state option. Thanks to @renatomen for the contribution. Fixed# Fixed Pomodoro storage migration so existing plugin-data history is written to daily notes before switching storage, and clarified that daily notes can come from either the core Daily Notes plugin or Periodic Notes. (#1964) Fixed Microsoft Calendar OAuth so connecting no longer forces a fresh consent prompt every time, and clarified the Microsoft desktop app setup steps. Thanks to @thechonta for reporting. (#1966) Fixed custom priority icons so they render as icons instead of filled squares on task cards. Thanks to @sruiz-savia for reporting. (#1963) Fixed Google Calendar sync so duplicate event ID fields are repaired when saving task calendar metadata. Thanks to @christenbc for reporting. (#1961) Fixed the default custom filename template so it uses the recommended double-brace syntax and no longer warns on first use. Thanks to @chmac for reporting. (#1962) Fixed task tag normalization so tags entered with spaces are saved with hyphens for Obsidian tag compatibility. Thanks to @christenbc for reporting. (#1959) Fixed the MCP tasknotes_list_tasks tool so circular internal task data and live Obsidian object references no longer break task-list responses. Thanks to @kmaustral for reporting. (#1957) Fixed the Pomodoro timer layout in vertically split panes so the timer header and progress circle remain reachable when the pane is short. Thanks to @sumiyalairu03 for reporting. (#1956) Fixed Google Calendar sync so completing a recurring task updates the linked event title with the completion checkmark. Thanks to @jacksoluke for reporting. (#1953) Fixed inline task conversion so source-line wikilinks no longer create nested wikilinks in the replacement link text. Thanks to @bgk0018 for reporting. (#1952) Fixed Pomodoro task picker search results so matching task titles are ranked and sorted ahead of due-date ordering. Thanks to @KFrancoD for reporting. (#1392, #1949) Fixed due and scheduled date picker fields so typed or pasted date edits stay open until you choose Select, including compact YYYYMMDD entry when a date is already set. Thanks to @kazerniel for reporting and following up. (#982, #1947) Restored larger mobile task-card typography and let secondary card icons wrap below the task details when they no longer fit comfortably on mobile. Thanks to @3zra47 for reporting the font-size regression, @chrsdk and @scottaltham-payroc for confirming the mobile font-size issue, and @Jomo94 for reporting the mobile card layout problem."},{"title":"TaskNotes - Unreleased","url":"/obsidian/releases/unreleased/","description":"TaskNotes documentation.","product":"obsidian","text":""},{"title":"Settings","url":"/obsidian/settings/","description":"TaskNotes settings are organized into tabs. Each tab controls a different part of plugin behavior.","product":"obsidian","text":"TaskNotes settings are organized into tabs. Each tab controls a different part of plugin behavior. General# The General tab controls task identification, storage locations, and task-card click behavior. Use this tab when your vault already has conventions such as custom tags, property-based identification, or specific folder structures. For more information, see the General Settings documentation. Task Properties# Task Properties defines the schema TaskNotes writes to frontmatter, including status, priority, dates, reminders, projects, and user fields. Each property card lets you remap key names and behavior so TaskNotes can match existing metadata rather than forcing a migration. For more detailed information, see the Task Properties Settings documentation. Modal Fields# Modal Fields controls the task create/edit experience by deciding which fields are visible and in what order. If your workflow depends on a handful of fields, you can surface only those and reduce form noise. For more information, see the Modal Fields Settings documentation. Appearance & UI# Appearance & UI handles task card density, calendar defaults, time formatting, and visual toggles for supporting widgets. Use this tab to tune how much information is visible at a glance. For more detailed information, see the Appearance & UI Settings documentation. Features# Features groups behavior toggles for inline tasks, natural language input, Pomodoro, reminders, and performance-related options. It is where you enable advanced workflow capabilities and then refine defaults. For more information, see the Features Settings documentation. Integrations# Integrations covers external connectivity: Bases view wiring, Google/Microsoft OAuth calendar sync, ICS subscriptions, automatic ICS export, HTTP API settings, and webhook endpoints. For more detailed information, see the Integrations Settings documentation."},{"title":"Appearance & UI Settings","url":"/obsidian/settings/appearance/","description":"These settings control the visual appearance of the plugin, including the calendar, task cards, and other UI elements.","product":"obsidian","text":"These settings control the visual appearance of the plugin, including the calendar, task cards, and other UI elements. Task Cards# Use Default visible properties to decide what metadata appears on task cards without opening each task. This is the primary control for card density. Checklist progress is available as a visible property in task cards. In Bases view order arrays, the corresponding source property is file.tasks (shown as tasks in Bases property pickers once present in the view order list). Nested task cards use CSS variables for their indentation. Add a CSS snippet if you want a denser hierarchy than the default: .tasknotes-plugin { --tn-nested-task-indent: 12px; --tn-nested-task-padding: 8px; } body.is-mobile .tasknotes-plugin { --tn-nested-task-indent: 8px; --tn-nested-task-padding: 6px; } If task links inside normal markdown lists feel visually doubled with both a list marker and the task status indicator, a CSS snippet can hide those markers for task-link lines: .markdown-reading-view li:has(.task-inline-preview--reading-mode)::marker { content: \"\"; } .markdown-source-view.mod-cm6 .cm-line:has(.tasknotes-inline-widget) .cm-formatting-list { display: none; } Display Formatting# Use Time format to switch between 12-hour and 24-hour display across all TaskNotes surfaces. Calendar View# Calendar view settings determine the default landing mode, day/week framing, and timeline affordances. You can choose the default view, custom day span, first day of week, weekend visibility, week numbers, and whether today/current-time markers are shown. Selection mirror controls whether drag selections show a visual preview before committing. Use Calendar locale for region-specific formatting and calendar systems (for example en, de, or fa). Leave it empty to use automatic detection. Default Event Visibility# This section controls which event layers are enabled when a calendar view opens. You can independently toggle scheduled tasks, due dates, due dates for already-scheduled tasks, time entries, recurring tasks, and ICS events. Time Settings# Time settings define the structure of timeline views: slot duration, earliest visible time, latest visible time, and initial scroll position. Use these together to match your workday shape. UI Elements# UI element toggles control auxiliary surfaces such as the tracked-task status bar entry, the project subtasks widget and its placement, expandable subtasks in cards, chevron position, and the alignment of the views/filters button. Related Settings# Some appearance-related settings are configured elsewhere: Task filename format: Configured in Task Properties → Title card Project autosuggest display: Configured in Task Properties → Projects card"},{"title":"Features Settings","url":"/obsidian/settings/features/","description":"These settings allow you to enable, disable, and configure the various features of the plugin, such as inline tasks, natural language processing, the Pomodoro timer, and notific...","product":"obsidian","text":"These settings allow you to enable, disable, and configure the various features of the plugin, such as inline tasks, natural language processing, the Pomodoro timer, and notifications. Inline Tasks# Inline task settings control how aggressively TaskNotes turns plain note content into structured task interactions. Task link overlay enables the Live Preview card behavior for task links, while Instant task convert surfaces conversion buttons next to list items and checkboxes. Keep checkbox when converting leaves the original Markdown checkbox marker in the source note when a checkbox becomes a TaskNote link. For conversion output, Inline task convert folder sets destination behavior and supports {{currentNotePath}}, and Use task defaults on instant convert applies your default task values at conversion time. The separate Convert current note to task command keeps the current note body as the task details. If the note has no scheduled frontmatter, the command uses the Scheduled Date default from Task Properties; it does not apply body templates. Body Template# Body template settings let you scaffold newly created tasks with consistent note content. When enabled, TaskNotes reads the configured template file and expands variables like {{title}}, {{date}}, {{time}}, {{priority}}, {{status}}, {{contexts}}, {{tags}}, and {{projects}}. Materialized occurrence notes can use a separate template. Set Occurrence note template file to provide a global fallback for occurrence notes; a recurring task's occurrence_template frontmatter field takes priority when it is set. If neither occurrence-specific template is configured, occurrence notes continue through the normal body template behavior. Natural Language Processing# NLP settings define how text input is interpreted during task capture. Enable natural language task input activates date and metadata parsing, Default to scheduled changes ambiguous date handling, NLP language selects parsing patterns, and Status suggestion trigger controls optional status autocomplete activation. Wrap text in double quotes, single quotes, or backticks to keep it as literal title text during NLP parsing. For example, BIO \"123H\" - HW1 keeps 123H in the title instead of treating it as a 123-hour estimate, while Review \"Today\" notes keeps Today as text instead of parsing it as a date. Pomodoro Timer# Pomodoro settings control interval lengths, long-break cadence, optional auto-start behavior, and end-of-session notifications/sound. Pomodoro data storage chooses whether history is kept in plugin data or daily notes. Notifications# Use this section to enable reminders globally, choose whether notices are shown in-app or through system notifications, and optionally play a built-in reminder sound with its own volume control. Performance & Behavior# Performance and behavior toggles let you refine overhead and interaction feel: exclude completed tasks from overdue calculations, disable indexing for very large vaults, and tune suggestion debounce timing. Time Tracking# Time tracking options handle completion behavior. You can automatically stop running timers when a task is completed and optionally show a confirmation notification. Recurring Tasks# Use Maintain due date offset in recurring tasks to keep due/scheduled spacing consistent when recurring tasks roll forward. Occurrence note behavior is configured per recurring task from the task context menu: open Recurrence → Occurrence notes to choose manual creation or automatic creation of the next materialized occurrence after completion. See Recurring Tasks for the workflow and storage model. Timeblocking# Timeblocking enables lightweight daily-note scheduling blocks and controls whether those blocks are visible by default in calendar views. Usage# In the calendar view, click and drag on a time slot to select a time range. A context menu will appear—select \"Create timeblock\" to create a timeblock (this option only appears if timeblocking is enabled in settings). Drag existing timeblocks to move them. Resize edges to adjust duration."},{"title":"General Settings","url":"/obsidian/settings/general/","description":"These settings control the foundational aspects of the plugin, such as task identification, file storage, and click behavior.","product":"obsidian","text":"These settings control the foundational aspects of the plugin, such as task identification, file storage, and click behavior. Task Storage# Task storage settings define where new and inline-created task files are created and how archived tasks are relocated. Default tasks folder sets the base location and supports folder template variables, including {{currentNotePath}} and {{currentNoteTitle}} for creating command-palette or ribbon tasks beside the active note. It also supports date variables such as {{year}} and Daily Notes-style date tokens such as YYYY/MM/DD. Folder for inline-created tasks controls the Create Inline Task command and instant conversion output. Leave it empty to use the default tasks folder, set a fixed folder path to centralize inline tasks, or use {{currentNotePath}} and {{currentNoteTitle}} placeholders for contextual routing. Relative path segments such as ../ are normalized after variables are expanded. If archive moves are enabled, completed archived tasks are moved automatically to your configured archive folder. Task Identification# TaskNotes can identify task notes using either a tag or a frontmatter property. Use Identify tasks by to select a strategy. Tag mode uses a configured task tag (for example task) and can optionally hide that identifying tag in card displays. Property mode matches a property/value pair (for example isTask: true or category: task) and is useful when you avoid tag-based identification. If you change the task tag after creating default Base views, existing .base filters will still point at the old tag until you update the default Base files or edit those filters. Hide Identification Tags# When using tag-based identification, you may want to keep your task identification tags in the frontmatter for organizational purposes, but hide them from the visual display in task cards to reduce clutter. The Hide identification tags in task cards setting allows you to do this. When enabled: Tags that exactly match your task identification tag (e.g., #task) will be hidden Hierarchical child tags (e.g., #task/project, #task/work/urgent) will also be hidden Other tags that don't match the identification pattern will still be displayed The setting only affects the visual display—tags remain in the frontmatter Example: If your task identification tag is task and a task has the tags #task, #task/project, #important, and #review: With the setting disabled (default): All tags are shown: #task, #task/project, #important, #review With the setting enabled: Only non-identifying tags are shown: #important, #review Folder Management# Use Excluded folders to omit paths from Notes tab indexing and keep large archive areas out of regular task browsing. Views & Base Files# TaskNotes uses Obsidian Bases files (.base) to power its task views. By default, missing view files are created automatically on startup. Use Create files to generate missing default files in TaskNotes/Views/ without overwriting existing files. Use Update files to overwrite the configured default files with templates generated from your current TaskNotes settings. Frontmatter# This section only appears when you have markdown links enabled globally in Obsidian settings. Use markdown links in frontmatter switches project/dependency serialization from wikilinks ([[path]]) to markdown links ([text](path)). This requires the obsidian-frontmatter-markdown-links plugin. Task Interaction# Task interaction settings define default click behavior on task cards. You can independently choose single-click and double-click actions (edit task, open note, or no action for double click). Release Notes# View release notes opens the release notes view for the current version. Notes also open automatically after updates and remain available from the command palette."},{"title":"Integrations Settings","url":"/obsidian/settings/integrations/","description":"These settings control the integration with other plugins and services, such as Bases and external calendars.","product":"obsidian","text":"These settings control the integration with other plugins and services, such as Bases and external calendars. Bases# TaskNotes v4 uses Obsidian's Bases core plugin for its main views. For setup instructions, see Core Concepts. View Commands Configuration# View command settings map TaskNotes commands and ribbon actions to specific .base files. This is useful when you maintain custom variants of the default views and want first-class command access to those files. Access these settings in Settings → TaskNotes → General → Views & base files. Default mappings: Open Mini Calendar View → TaskNotes/Views/mini-calendar-default.base Open Kanban View → TaskNotes/Views/kanban-default.base Open Tasks View → TaskNotes/Views/tasks-default.base Open Calendar View → TaskNotes/Views/calendar-default.base Open Agenda View → TaskNotes/Views/agenda-default.base Pomodoro Statistics Base → TaskNotes/Views/pomodoro-stats.base Relationships Widget → TaskNotes/Views/relationships.base Each command allows you to specify a custom .base file path and includes a reset button to restore the default path. Auto-create default files: When enabled, TaskNotes creates missing default .base files automatically on startup. Create files: Button to generate all default .base files in the TaskNotes/Views/ directory. Existing files are not overwritten. The generated Pomodoro statistics Base reads Pomodoro sessions from daily notes frontmatter. If your Pomodoro history is still stored in plugin data, migrate it from Settings → TaskNotes → Features before using that Base file. OAuth Calendar Integration# Connect Google Calendar or Microsoft Outlook to sync events bidirectionally with TaskNotes. Events automatically refresh every 15 minutes and sync when local changes are made (such as dragging events to reschedule). Enable Disable calendar integrations on mobile when you sync TaskNotes settings between desktop and mobile but do not want Obsidian Mobile to load external calendars on startup. The setting only affects mobile devices; desktop calendar integrations continue to run normally. Setup Requirements# OAuth integration requires creating your own OAuth application with Google and/or Microsoft. Initial setup takes approximately 15 minutes per provider. Setup Guide: See Calendar Integration Setup for detailed instructions on creating OAuth credentials with Google Cloud Console and Azure Portal. Google Calendar# Provide Client ID and Client Secret from Google Cloud Console, then use Connect Google Calendar to complete OAuth loopback authentication. Disconnect revokes account tokens while retaining the OAuth app credentials for reconnection. Use Forget saved credentials to remove the client ID and client secret. The Target calendar setting used for exporting tasks to Google Calendar is also used as the default selection when creating a manual external calendar event from the calendar view. If the target calendar is unavailable, TaskNotes falls back to the provider's primary calendar. For timed task exports, Default reminder accepts one or more minute offsets separated by commas, such as 60, 1440. All-day task exports use the target Google Calendar's default reminder settings. When connected, displays: Connected account email Connection time Last sync time Manual refresh button Microsoft Outlook Calendar# Provide Client ID and Client Secret from Azure App Registration, then use Connect Microsoft Calendar to authenticate. Disconnect revokes account tokens while retaining the OAuth app credentials for reconnection. Use Forget saved credentials to remove the client ID and client secret. When connected, displays: Connected account email Connection time Last sync time Security# OAuth client credentials and account tokens are stored in Obsidian Secret Storage, which is encrypted at rest when supported by the operating system OAuth credentials and account tokens are not written to TaskNotes' data.json Access tokens refresh automatically Calendar data syncs directly between Obsidian and the calendar provider (no intermediary servers) Disconnect at any time to revoke account access; use Forget saved credentials to remove the OAuth app credentials Calendar subscriptions (ICS)# ICS settings define how subscribed calendar events are represented in your vault. You can set a default template, destination folder, filename strategy, and custom filename template for generated notes. Use Add Calendar Subscription to register URLs or local files, and Refresh all subscriptions for manual synchronization. Recurring event related notes controls how notes linked from recurring external calendar events are matched. Series-wide keeps the current behavior: a note linked to one loaded recurrence can appear on the other loaded recurrences from the same Google, Microsoft, or ICS event series. Selected instance only limits related notes and counts to the exact recurrence instance that was linked. Automatic ICS export# Automatic export keeps an ICS feed of your tasks updated on a schedule. Configure whether it is enabled, where the file is written (vault-relative path), the refresh interval, and use Export now for immediate output. Export filters can omit archived tasks, completed tasks, tasks without due dates, or tasks without scheduled dates. When both due-date and scheduled-date requirements are enabled, exported tasks must have both dates. HTTP API# HTTP API settings control the local server lifecycle, listening port, and request authentication token. Changes to API enablement or port require an Obsidian restart to take effect. WarningThe HTTP API binds to loopback only and browser CORS is limited to loopback origins. If the authentication token is empty, local API requests are still unauthenticated. Set a token unless your local environment is fully trusted. Webhooks# Add Webhook: Register a new webhook endpoint."},{"title":"Modal Fields Settings","url":"/obsidian/settings/modal-fields/","description":"The Modal Fields tab lets you decide exactly which fields appear in the task creation and edit modals. Open Settings → TaskNotes → Modal Fields to manage the configuration.","product":"obsidian","text":"The Modal Fields tab lets you decide exactly which fields appear in the task creation and edit modals. Open Settings → TaskNotes → Modal Fields to manage the configuration. Field Groups# Fields are organized into draggable groups: Basic Information – Title and Details Metadata – Contexts, Tags, Time Estimate Organization – Projects and Subtasks Dependencies – Blocked By and Blocking Custom Fields – Any user-defined fields that you add through Task Properties Each group can be collapsed, and their order in the manager matches the order shown in the modal. Managing Fields# Every field entry includes: Visibility toggles for creation and edit modals Enable/disable checkbox Drag handle for ordering within its group Required toggle (where applicable, e.g., Title) Changes are saved automatically. Use this to hide fields you never touch, ensure required metadata appears up front, or reorder fields to match your workflow. Syncing User Fields# The Sync User Fields button pulls the latest user-defined fields from the Task Properties tab into the Custom Fields group. New user fields are appended, renamed fields update in place, and removed fields drop out of the configuration. Re-run the sync whenever you add or rename custom fields. Resetting to Defaults# Select Reset to Defaults to restore the stock configuration (all built-in fields enabled plus empty custom slots). The reset keeps your existing user field definitions; it only reverts modal layout and visibility."},{"title":"Property-based Task Identification","url":"/obsidian/settings/property-identification/","description":"When you choose to identify task files by a frontmatter property (instead of a tag), TaskNotes will match notes whose frontmatter property equals the configured value.","product":"obsidian","text":"When you choose to identify task files by a frontmatter property (instead of a tag), TaskNotes will match notes whose frontmatter property equals the configured value. Boolean values# Enter the setting value as true or false (without quotes) in the settings UI. Obsidian stores checkbox properties as real booleans, not strings. The plugin compares booleans correctly: \"true\" in settings matches frontmatter boolean true \"false\" in settings matches frontmatter boolean false Arrays are supported (e.g., property: [false, true]) Tip: You don’t need to quote boolean values in frontmatter. Use plain true/false to keep Obsidian’s property types consistent. Examples# Setting: Property Name = isTask, Property Value = true Matches: isTask: true Does not match: isTask: false Setting: Property Name = isTask, Property Value = false Matches: isTask: false Does not match: isTask: true For related configuration details, see Task Properties."},{"title":"Property Types Reference","url":"/obsidian/settings/property-types-reference/","description":"This reference documents the expected data types for each frontmatter property that TaskNotes uses.","product":"obsidian","text":"This reference documents the expected data types for each frontmatter property that TaskNotes uses. Quick Reference# Property Type Example title text \"My Task\" status text \"open\", \"in-progress\", \"done\" priority text \"low\", \"normal\", \"high\" due text (date) \"2025-01-15\" scheduled text (date) \"2025-01-10\" completedDate text (date) \"2025-01-20\" dateCreated text (datetime) \"2025-01-01T08:00:00Z\" dateModified text (datetime) \"2025-01-15T10:30:00Z\" tags list [\"work\", \"urgent\"] contexts list [\"office\", \"home\"] projects list [\"[[Project A]]\"] timeEstimate number 120 (minutes) recurrence text \"FREQ=WEEKLY;BYDAY=MO\" recurrence_anchor text \"scheduled\" or \"completion\" timeEntries list (objects) See Time Entries blockedBy list (objects) See Dependencies reminders list (objects) See Reminders complete_instances list [\"2025-01-08\", \"2025-01-15\"] skipped_instances list [\"2025-01-22\"] recurrence_parent text (link/path) \"[[Tasks/Weekly review]]\" occurrence_date text (date) \"2025-01-15\" occurrence_materialization text \"manual\" or \"on_completion\" occurrence_next_trigger text \"completion\" or \"completion_or_skip\" occurrence_template text (link/path) \"[[Templates/Occurrence]]\" occurrence_past_horizon text (duration) \"P7D\" occurrence_future_horizon text (duration) \"P14D\" icsEventId list [\"event-abc123\"] Use this table for fast validation when a field is not behaving as expected in views or API calls. Most parsing issues come from shape mismatches (for example scalar vs list) rather than missing values. Property Details# The sections below describe storage formats, but there is flexibility in authoring style. TaskNotes normalizes many equivalent YAML representations as long as the resulting data type is correct. Text Properties# title# Type: text (string) Description: The task's title or name Example: title: \"Complete project documentation\" status# Type: text (string) Description: The task's current status. Must match one of the status values configured in your settings. Default values: \"open\", \"in-progress\", \"done\" Example: status: \"in-progress\" Note: Also supports boolean values (true/false) for Obsidian checkbox compatibility. See Boolean Status Values. priority# Type: text (string) Description: The task's priority level. Must match one of the priority values configured in your settings. Default values: \"low\", \"normal\", \"high\" Example: priority: \"high\" Date Properties# All date properties are stored as text strings in your frontmatter. TaskNotes expects specific formats: When in doubt, prefer ISO-style values. They sort correctly as text, travel well through APIs, and are easiest to parse consistently. due# Type: text (date string) Format: YYYY-MM-DD or ISO 8601 timestamp Description: The task's due date Examples: due: \"2025-01-15\" due: \"2025-01-15T17:00:00\" scheduled# Type: text (date string) Format: YYYY-MM-DD or ISO 8601 timestamp Description: When the task is scheduled to be worked on Examples: scheduled: \"2025-01-10\" scheduled: \"2025-01-10T09:00:00\" completedDate# Type: text (date string) Format: YYYY-MM-DD Description: The date when the task was completed Example: completedDate: \"2025-01-20\" dateCreated# Type: text (datetime string) Format: ISO 8601 timestamp Description: When the task was created Example: dateCreated: \"2025-01-01T08:00:00Z\" dateModified# Type: text (datetime string) Format: ISO 8601 timestamp Description: When the task was last modified Example: dateModified: \"2025-01-15T10:30:00Z\" List Properties# List properties must be arrays, even when containing a single value. Single-item arrays may look verbose, but they prevent edge cases when filters and formulas assume list semantics. tags# Type: list (array of strings) Description: Tags associated with the task Examples: tags: [\"work\", \"documentation\"] tags: - work - documentation contexts# Type: list (array of strings) Description: Context labels for the task Examples: contexts: [\"office\", \"computer\"] contexts: - \"office\" - \"computer\" projects# Type: list (array of strings) Description: Project references (typically wiki-links) Examples: projects: [\"[[Website Redesign]]\", \"[[Q1 Planning]]\"] projects: - \"[[Website Redesign]]\" - \"[[Q1 Planning]]\" Numeric Properties# timeEstimate# Type: number Unit: minutes Description: Estimated time to complete the task Example: timeEstimate: 120 (2 hours) Recurrence Properties# recurrence# Type: text (string) Format: RFC 5545 RRULE format Description: Defines how the task repeats Examples: recurrence: \"FREQ=DAILY\" recurrence: \"FREQ=WEEKLY;BYDAY=MO,WE,FR\" recurrence: \"FREQ=MONTHLY;BYMONTHDAY=1\" recurrence_anchor# Type: text (string) Valid values: \"scheduled\" or \"completion\" Description: Determines whether the next occurrence is calculated from the scheduled date or when the task was completed Example: recurrence_anchor: \"scheduled\" complete_instances# Type: list (array of date strings) Format: YYYY-MM-DD Description: Dates when recurring task instances were completed Example: complete_instances: - \"2025-01-08\" - \"2025-01-15\" skipped_instances# Type: list (array of date strings) Format: YYYY-MM-DD Description: Dates when recurring task instances were skipped Example: skipped_instances: - \"2025-01-22\" Materialized Occurrence Properties# Materialized occurrence notes are ordinary task notes created for one date in a recurring series. The parent recurring task owns the recurrence rule; the occurrence note owns date-specific state such as status, completed date, body content, time entries, reminders, and comments. When an occurrence note is created, TaskNotes inherits parent planning metadata such as scheduled time, due offset, priority, tags, contexts, projects, reminders, dependencies, details, custom properties, and time estimate. It does not copy parent recurrence/history/runtime fields such as recurrence, complete_instances, skipped_instances, completedDate, provider event IDs, or timeEntries. recurrence_parent# Type: text (link or path string) Description: Parent recurring task for a materialized occurrence note Example: recurrence_parent: \"[[Tasks/Weekly review]]\" occurrence_date# Type: text (date string) Format: YYYY-MM-DD Description: Target recurrence date represented by a materialized occurrence note Example: occurrence_date: \"2025-01-15\" occurrence_materialization# Type: text (string) Valid values: \"manual\", \"on_completion\", \"rolling\" Description: Parent task policy for creating occurrence notes. The plugin currently supports manual creation and creating the next note after completion; rolling windows are defined by the spec but are not automated yet. Example: occurrence_materialization: \"on_completion\" occurrence_next_trigger# Type: text (string) Valid values: \"completion\" or \"completion_or_skip\" Description: Parent task policy for whether skip actions should also create the next occurrence note when occurrence materialization is set to on_completion Example: occurrence_next_trigger: \"completion_or_skip\" occurrence_template# Type: text (link or path string) Description: Optional template reference used when creating materialized occurrence notes. This parent-level template takes priority over the global occurrence note template fallback in Features settings. Example: occurrence_template: \"[[Templates/Weekly occurrence]]\" occurrence_past_horizon and occurrence_future_horizon# Type: text (ISO 8601 duration string) Description: Optional rolling-window bounds for occurrence materialization. These fields are part of the TaskNotes spec; automated rolling materialization is not currently enabled in the plugin. Examples: occurrence_past_horizon: \"P7D\" occurrence_future_horizon: \"P14D\" Complex Properties# These properties contain structured data with multiple fields. For these fields, copy known-good examples before editing manually. Minor schema deviations can break downstream features such as reminders, recurrence, or dependency checks. Time Entries# Type: list (array of objects) Description: Time tracking entries for the task Structure: timeEntries: - startTime: \"2025-01-15T10:30:00Z\" # Required: ISO 8601 timestamp endTime: \"2025-01-15T11:15:00Z\" # Optional: ISO 8601 timestamp description: \"Initial work\" # Optional: text Dependencies (blockedBy)# Type: list (array of objects) Description: Tasks that must be completed before this task can start Structure: blockedBy: - uid: \"path/to/blocking-task.md\" # Required: path to blocking task reltype: \"FINISHTOSTART\" # Required: relationship type gap: \"P1D\" # Optional: ISO 8601 duration offset Relationship types accepted in stored data: FINISHTOSTART, STARTTOSTART, FINISHTOFINISH, STARTTOFINISH Current behavior: Dependencies created from the UI use FINISHTOSTART. Blocking evaluation is based on dependency presence/completion state and does not currently apply distinct scheduling semantics for different reltype values or gap. Reminders# Type: list (array of objects) Description: Reminder notifications for the task Structure for relative reminders: reminders: - id: \"rem_1\" # Required: unique identifier type: \"relative\" # Required: \"relative\" or \"absolute\" relatedTo: \"due\" # Required for relative: \"due\" or \"scheduled\" offset: \"-PT1H\" # Required for relative: ISO 8601 duration description: \"1 hour before due\" # Optional: description Structure for absolute reminders: reminders: - id: \"rem_2\" type: \"absolute\" absoluteTime: \"2025-01-15T09:00:00Z\" # Required for absolute: ISO 8601 timestamp description: \"Morning reminder\" icsEventId# Type: list (array of strings) Description: ICS calendar event IDs linked to this task Example: icsEventId: - \"event-abc123\" - \"event-def456\" Complete Example# Here's a complete task with all property types: --- title: \"Complete quarterly report\" status: \"in-progress\" priority: \"high\" due: \"2025-01-31\" scheduled: \"2025-01-25\" tags: - work - reports contexts: - office projects: - \"[[Q1 Planning]]\" timeEstimate: 240 dateCreated: \"2025-01-01T08:00:00Z\" dateModified: \"2025-01-20T14:30:00Z\" timeEntries: - startTime: \"2025-01-20T10:00:00Z\" endTime: \"2025-01-20T11:30:00Z\" blockedBy: - uid: \"tasks/gather-data.md\" reltype: \"FINISHTOSTART\" reminders: - id: \"rem_1\" type: \"relative\" relatedTo: \"due\" offset: \"-P1D\" description: \"Due tomorrow\" --- Field Mapping# All property names can be customized via Settings → Task Properties → Field Mapping. If you change a field mapping, TaskNotes will read and write using your custom property name. Custom property names are frontmatter keys, so names with spaces or punctuation are valid in task files. When you write your own Bases filters or formulas for those keys, use bracket notation such as note[\"TN-status\"] or note[\"Task Type\"] instead of dot notation. Dot notation only works reliably for simple identifier-style names. For example, if you map due to dueDate, TaskNotes will expect: dueDate: \"2025-01-15\" See Task Properties settings for configuration details. Custom User Fields# You can define additional properties with these types: text - Single text value number - Numeric value date - Date string (YYYY-MM-DD) boolean - true/false list - Array of values See Custom User Fields for configuration details."},{"title":"Task Properties Settings","url":"/obsidian/settings/task-properties/","description":"This tab configures all task properties. Each property is displayed as a card containing its configuration options.","product":"obsidian","text":"This tab configures all task properties. Each property is displayed as a card containing its configuration options. Looking for property type documentation?See the Property Types Reference for detailed documentation on the expected data types (text, list, date, etc.) for each frontmatter property. Property Card Structure# Each property card contains: Property key: The frontmatter field name used to store this property Default: The default value applied to new tasks (where applicable) NLP trigger: Toggle and character configuration for natural language parsing (where applicable) Property-specific settings: Additional configuration options specific to that property This tab defines the task schema used by creation flows, NLP parsing, views, and API payloads. Property keys are YAML/frontmatter keys. TaskNotes can read and write keys that contain spaces or punctuation, but hand-written Bases filters and formulas must reference those keys with bracket syntax, for example note[\"TN-status\"], rather than dot syntax such as note.TN-status. Core Properties# Title# The task title property. Configuration options: Property key: Frontmatter field name (default: title) Store title in filename: When enabled, the task title is stored in the filename instead of frontmatter. The filename updates when the title changes. Filename format: When \"Store title in filename\" is disabled, choose how filenames are generated: Title-based Zettelkasten-style Timestamp-based UUID v4 Custom template Custom template: Define a custom filename pattern using variables (shown when \"custom\" format is selected) Status# Task completion state. Configuration options: Property key: Frontmatter field name (default: status) Default: Default status for new tasks NLP trigger: Character that triggers status parsing (default: *) Status Values: Expandable section containing individual status cards Each status value has: Value: Internal identifier stored in frontmatter (e.g., \"in-progress\") Label: Display name shown in the interface (e.g., \"In Progress\") Color: Visual indicator color Icon: Optional icon identifier Completed: Whether this status represents a finished task Skip when cycling: Exclude this status from the click-to-cycle order on task cards while keeping it available in menus, suggestions, and direct edits Next status: Optional override for the status used when cycling forward from this status; leave it set to the status order to use the normal sequence Auto-archive: Automatically archive tasks after a delay (1-1440 minutes) Status cards support drag-and-drop reordering. Use the Value field as the stable stored identifier and the Label field for display text with spaces or title casing. TaskNotes status menus and cycling use the configured order, and TaskNotes Kanban views can preserve dragged column order. Native Bases grouping/sorting may still order status values alphabetically by their stored Value, so use prefixes such as 1-open, 2-doing, 3-done if you need predictable native Bases order. Boolean Status Values# TaskNotes supports using boolean values (true and false) as status values, which integrates with Obsidian's native checkbox property format: When you set a task's status to \"true\" or \"false\" (case-insensitive), TaskNotes automatically converts it to a boolean in frontmatter When reading tasks with boolean status values from frontmatter, they are converted back to the strings \"true\" or \"false\" This allows you to use Obsidian's native checkbox property toggles in the Properties panel while maintaining compatibility with TaskNotes Example: --- status: true # Boolean checkbox in Obsidian --- Priority# Task priority level. Configuration options: Property key: Frontmatter field name (default: priority) Default: Default priority for new tasks (can be set to \"No default\") NLP trigger: Character that triggers priority parsing (default: !, disabled by default) Priority Values: Expandable section containing individual priority cards Each priority value has: Value: Internal identifier stored in frontmatter (e.g., \"high\") Label: Display name shown in the interface (e.g., \"High Priority\") Color: Visual indicator color Priority cards support drag-and-drop reordering. Status and priority values are stored in frontmatter; renaming them later may require migration of existing task files. Note for Bases plugin users: Obsidian's Bases plugin sorts priorities alphabetically by their Value. To control sort order, name values to sort alphabetically in the desired order: Example: 1-urgent, 2-high, 3-medium, 4-normal, 5-low Or: a-urgent, b-high, c-medium, d-normal, e-low Date Properties# Due Date# When the task must be completed. Configuration options: Property key: Frontmatter field name (default: due) Default: Default due date for new tasks (None, Today, Tomorrow, Next Week) Scheduled Date# When to work on the task. Configuration options: Property key: Frontmatter field name (default: scheduled) Default: Default scheduled date for new tasks (None, Today, Tomorrow, Next Week) When you use Convert current note to task, this default is also applied if the source note does not already have scheduled frontmatter. Choose None to keep converted notes unscheduled by default. due tracks commitment deadlines, while scheduled tracks intended execution time. Organization Properties# Contexts# Where or how the task can be done. Configuration options: Property key: Frontmatter field name (default: contexts) Default: Comma-separated list of default contexts (e.g., @home, @work) NLP trigger: Character that triggers context parsing (default: @) Projects# Projects the task belongs to. Configuration options: Property key: Frontmatter field name (default: projects) Default projects: Select project notes to automatically link to new tasks Use active note for new tasks: Automatically link the active note as a project when opening task creation from the command palette or ribbon Use parent note for inline/instant conversion: Automatically link the source note as a project when using inline task creation or instant task conversion NLP trigger: Character that triggers project parsing (default: +) Autosuggest Filters: Expandable section to filter which notes appear in project suggestions Customize Display: Expandable section to configure how project suggestions appear Autosuggest Filters# Control which notes appear when selecting projects: Required tags: Comma-separated list of tags (shows notes with ANY of these tags) Include folders: Comma-separated list of folder paths (shows notes in ANY of these folders) Required property key: Frontmatter property that must exist Required property value: Expected value for the property (optional) These filters reduce suggestion noise in large vaults. A \"Filters On\" badge appears when any filters are configured. Customize Display# Configure project suggestion appearance: Enable fuzzy matching: Allow typos and partial matches in project search Row 1, 2, 3: Configure up to 3 lines of information for each project suggestion Tags# Obsidian tags for categorization. Configuration options: Default: Comma-separated list of default tags (without #) NLP trigger: Character that triggers tag parsing (default: #) Note: Tags use native Obsidian tags and do not have a separate property key setting. Task Details# Time Estimate# Estimated time to complete the task. Configuration options: Property key: Frontmatter field name (default: timeEstimate) Default: Default time estimate in minutes (0 = no default) Recurrence# Pattern for repeating tasks. Configuration options: Property key: Frontmatter field name (default: recurrence) Default: Default recurrence pattern (None, Daily, Weekly, Monthly, Yearly) Recurring tasks also use the Recurrence anchor metadata property to decide whether the series advances from the scheduled date or the completion date. Materialized occurrence note controls live on each recurring task's context menu under Recurrence → Occurrence notes rather than as a global default. Reminders# Notifications before task deadlines. Configuration options: Property key: Frontmatter field name (default: reminders) Default Reminders: Expandable section containing default reminder cards Each default reminder can be: Relative reminders (triggered relative to due or scheduled date): Anchor date (due date or scheduled date) Offset amount and unit (minutes, hours, days) Direction (before or after) Description Absolute reminders (triggered at specific times): Date Time Description Metadata Properties# These properties are system-managed and typically only require property key configuration: Date Created: When the task was created Date Modified: When the task was last modified Completed Date: When the task was completed Archive Tag: Tag used to mark archived tasks Time Entries: Time tracking entries for the task Complete Instances: Completion history for recurring tasks Skipped Instances: Skip history for recurring tasks Recurrence Anchor: Whether recurring progression is based on scheduled date or completion date Blocked By: Tasks that must be completed first Materialized occurrence notes also use system-managed frontmatter fields such as recurrence_parent, occurrence_date, occurrence_materialization, occurrence_next_trigger, and optional occurrence template/horizon fields. Occurrence notes inherit parent planning metadata when they are created, but keep their own status, completion date, and time entries. These fields are documented in the Property Types Reference and are normally changed through recurrence and occurrence-note controls instead of by hand. Feature Properties# These properties are used by specific TaskNotes features and are not stored in task frontmatter: Pomodoros: Property key for Pomodoro session counts. When Pomodoro data storage is set to \"Daily notes\", this property is written to daily notes rather than task files. ICS Event ID: Property key for calendar event identifiers. Added to notes created from ICS calendar events to link them back to the source event. ICS Event Tag: Property key for calendar event tags. Added to notes created from ICS calendar events for identification. Custom User Fields# Define custom frontmatter properties to appear as filter options across views. Configuration options for each field: Display Name: How the field appears in the UI Property Key: The frontmatter property name Type: Data type (text, number, boolean, date, or list) Default Value: Pre-fill value for new tasks (format varies by type) NLP trigger: Toggle and character for natural language parsing Autosuggest Filters: Filter which files appear when using [[ wikilink autocomplete Custom fields are most maintainable when they map to repeated workflow decisions (for example effort, owner, or client). Link Values# Use a Text custom field for a single link and a List custom field for multiple links. Task cards render [[wikilinks]], [label](https://example.com), , and bare https://example.com values as clickable links. Autosuggest filters work with text and list fields when entering [[ wikilinks, so a field such as Related Note can suggest only files from a chosen folder or tag. Default Values# Each field type has a different input format for default values: Text: Enter the default text value Number: Enter the default number Boolean: Toggle switch to set default checked/unchecked state Date: Select from presets (None, Today, Tomorrow, Next Week) List: Enter comma-separated default values Default values are applied when creating tasks via: Task creation modal Instant task conversion \"Create or open task\" command HTTP API (when using task creation defaults) Autosuggestion Filters# Each custom field can configure filters to control which files appear in wikilink suggestions: Required tags: Comma-separated list of tags (shows files with ANY of these tags) Include folders: Comma-separated list of folder paths (shows files in ANY of these folders) Required property key: Frontmatter property that must exist Required property value: Expected value for the property (optional) A \"Filters On\" badge appears when filters are configured. See User Fields Feature Documentation for detailed examples."},{"title":"Troubleshooting","url":"/obsidian/troubleshooting/","description":"Common issues and solutions for TaskNotes.","product":"obsidian","text":"Common issues and solutions for TaskNotes. When debugging, start with one affected task and one affected view. Record the TaskNotes version from the plugin list, the Obsidian version from About, the operating system, and whether the problem also occurs in a fresh default Base. First checks# Confirm Obsidian meets the current version requirement and Bases is enabled. Open the affected task as Markdown and validate the --- frontmatter delimiters and indentation. Confirm the task matches Settings → TaskNotes → General → Task identification and is not in an excluded folder. Run TaskNotes: Refresh cache from the command palette. Close and reopen the affected .base file. Restart Obsidian only after the targeted checks above. If the issue remains, enable Settings → TaskNotes → Features → Debug logging, reproduce it once, and inspect the developer console with Ctrl/Cmd + Shift + I. Disable debug logging after collecting the relevant entries. Bases and Views (v4)# Views Not Loading# Symptoms: TaskNotes views show errors or don't display tasks First confirm Bases is enabled (Settings -> Core Plugins -> Bases), then restart Obsidian once. If views are still missing, verify .base files exist in TaskNotes/Views/. If needed, regenerate defaults from Settings -> TaskNotes -> General -> Views & base files (Create files). Commands Open Wrong Files# Symptoms: Ribbon icons or commands open unexpected files Check command mappings in Settings -> TaskNotes -> General (View Commands). Reset mappings that were changed unintentionally, then verify each referenced .base file exists at the configured path. Common Issues# Tasks Not Appearing in Views# Symptoms: Tasks you've created don't show up in TaskNotes views Follow this decision tree: Does Quick actions for current task work on the note? No: compare its tag or identification property with General → Task identification. Yes: task recognition works; continue to the Base filter. Is the note inside an excluded folder? Yes: move it or update Excluded folders. No: continue. Does a newly generated default task Base show it? Yes: the custom Base has a stale property name or filter. No: run TaskNotes: Refresh cache and validate the frontmatter. Did identification or field mapping change recently? Yes: update the default Base files or edit their filters and columns. Generated files do not update automatically when settings change. Task Link Widgets Not Working# Symptoms: Links to task files appear as normal wikilinks instead of interactive widgets Check that Task link overlay is enabled, then verify linked files are actually recognized as tasks (matching tag/property configuration). Links to normal notes will render as normal links by design. Instant Conversion Buttons Missing# Symptoms: Convert buttons don't appear next to checkbox tasks Instant convert buttons only appear when the feature is enabled, in edit mode, and with cursor proximity to list items. Enable the feature, switch from reading mode to edit mode, and place the cursor near the target checkbox. Calendar View Performance Issues# Symptoms: Calendar views are slow or unresponsive Reduce visible event layers first (scheduled/due/recurring/time entries), then increase ICS refresh intervals and shorten displayed date ranges. If slowness persists, apply the general performance guidance below. Natural Language Parsing Not Working# Symptoms: Natural language input doesn't extract expected task properties Enable NLP in Settings -> TaskNotes -> Features, then verify your trigger characters (@, #, ! by default) and any custom status/priority mappings. If parsing still seems inconsistent, compare input against the syntax in NLP API. Time Tracking Issues# Symptoms: Time tracking doesn't start/stop properly or data is lost Most tracking issues come from overlapping sessions, interrupted shutdowns, or save failures. Stop active sessions before starting new ones, confirm files are writable, and restart interrupted sessions. If needed, repair malformed time entries directly in frontmatter. Data Issues# Corrupted Task Files# Symptoms: Tasks appear broken or cause errors in views Open the task file directly and validate frontmatter syntax. Quote values that include special characters, validate YAML if necessary, and restore from backup for severe corruption. Missing Task Properties# Symptoms: Tasks missing expected properties or using default values unexpectedly Check field mappings first, then confirm Task Defaults. If properties are absent on older notes, add them manually or re-save through TaskNotes so current mapping rules are applied. Date Format Issues# Symptoms: Dates not displaying correctly or causing parse errors Use supported formats (YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS), quote where needed, and re-enter problematic dates via TaskNotes date pickers to normalize formatting and timezone handling. Performance Troubleshooting# Slow View Loading# To improve loading times, reduce external calendar subscriptions, increase ICS refresh intervals, exclude large folders, and disable event types you do not use. External Calendar Issues# OAuth Calendar Not Connecting# Symptoms: Google Calendar or Microsoft Outlook won't connect Verify credentials and loopback redirect configuration (127.0.0.1 with dynamic local port), ensure app publication/test-user access is correct, and retry after disconnecting. Also check popup blockers. For provider-specific setup details, use Calendar Setup. OAuth Calendar Not Syncing# Symptoms: Connected calendar shows old events or doesn't update Run manual refresh, check last-sync timestamps, reconnect if needed, and verify events exist in the source provider before debugging TaskNotes behavior. ICS Subscriptions Not Loading# Symptoms: ICS calendar events don't appear in calendar views Confirm the ICS URL/file is reachable, run manual refresh, validate the feed format, and inspect subscription status errors for provider-side failures. Calendar Sync Problems# Symptoms: External calendar changes not reflected in TaskNotes Check refresh intervals and force a manual refresh first. If source data is current but TaskNotes remains stale, remove and re-add the subscription to clear cached state. Getting Help# Reporting Issues# Report bugs on GitHub Issues. Include: Exact TaskNotes and Obsidian versions Operating system The smallest affected task frontmatter with private values removed The .base path and whether a regenerated default has the same problem Steps to reproduce from a fresh Obsidian start Relevant console errors and TaskNotes debug entries Screenshots if relevant Configuration Reset# Use a reversible reset only after the checks above: Close Obsidian Navigate to .obsidian/plugins/tasknotes/ Copy data.json to a backup outside the plugin directory Rename the original to data.json.backup-YYYY-MM-DD Restart Obsidian WarningA reset affects settings, status and priority configurations, integration state, saved views, and plugin-stored Pomodoro history. Keep the backup until the problem is resolved. Restore it only while Obsidian is closed. For full restore and uninstall guidance, see Backup, restore, and removal."},{"title":"Views","url":"/obsidian/views/","description":"TaskNotes provides multiple views for managing tasks and tracking productivity. All task-focused views operate as .base files located in the TaskNotes/Views/ directory and requi...","product":"obsidian","text":"TaskNotes provides multiple views for managing tasks and tracking productivity. All task-focused views operate as .base files located in the TaskNotes/Views/ directory and require Obsidian's Bases core plugin to be enabled. For details on Bases integration and how to enable it, see Core Concepts. For view templates and configuration examples, see Default Base Templates. Task-Focused Views# Task-focused views are different entry points into the same underlying task notes. The Task List View is a common starting view for day-to-day planning because it exposes filters, sorting, and grouping in list format. When you want workflow by status, Kanban View organizes cards into columns and can optionally add swimlanes for an extra organizational layer. Calendar Views are useful when schedule and timing matter more than backlog shape, with month/week/day/year/list modes plus drag-and-drop scheduling and time-block support. Agenda View is a preconfigured list-oriented calendar layout designed for short-horizon planning, while MiniCalendar View gives a compact month heatmap and fast keyboard navigation. Productivity-Focused Views# These views support time management and work tracking. Pomodoro View supports focused intervals directly inside Obsidian, and Pomodoro Stats View summarizes completed sessions so you can see pace and consistency over time. Screenshots in this section are captured via the Playwright docs suite (npm run e2e:docs)."},{"title":"Agenda View","url":"/obsidian/views/agenda-view/","description":"The Agenda view is a dedicated .base file that opens the calendar in list mode. It provides a scrollable agenda of upcoming tasks, notes, and external calendar events without ne...","product":"obsidian","text":"The Agenda view is a dedicated .base file that opens the calendar in list mode. It provides a scrollable agenda of upcoming tasks, notes, and external calendar events without needing to switch the primary calendar into list view manually. File Location# Default file: TaskNotes/Views/agenda-default.base Command: Open Agenda View (ribbon icon and command palette) Configure the file path in Settings → TaskNotes → General → View Commands TaskNotes creates missing default .base files automatically on startup when Auto-create default files is enabled. You can replace the command path with your own .base file if you maintain multiple agendas. Default Configuration# The stock agenda file renders the calendar in listWeek mode: views: - type: tasknotesCalendar name: \"Agenda\" calendarView: \"listWeek\" listDayCount: 7 startDateProperty: file.ctime titleProperty: file.basename order: - note.status - note.priority - note.due - formula.dueIn - note.scheduled This configuration displays seven days at a time, derives entries from file.ctime/file.basename, shows the generated Due in countdown next to due dates, and inherits the same display options (show scheduled/due/recurring/timeblocks/time entries/ICS events) as the primary calendar view. Customization# Edit the .base file to tailor the agenda: Change calendarView to listDay or listMonth for different spans Adjust listDayCount for shorter or longer agendas; the Bases option supports up to 365 days Add filters to focus on specific projects, tags, or statuses Modify order to control which task properties appear in the row layout Because the view runs inside Bases, any YAML changes are applied immediately after saving the file. Usage Tips# Use the calendar toolbar arrows (Previous/Next) to move the agenda window forward or backward, or simply scroll the list to review upcoming entries Saved views within Bases let you maintain multiple agenda variants (e.g., \"Work Week\" vs. \"Personal\") Calendar display options (show due, show scheduled, etc.) persist when you save the .base file, so you can maintain one agenda that includes external events and another that focuses strictly on TaskNotes tasks"},{"title":"Calendar Views","url":"/obsidian/views/calendar-views/","description":"TaskNotes provides two calendar-based views: the Mini Calendar and the Calendar View. Both operate as Bases views (.base files) and require the Bases core plugin to be enabled i...","product":"obsidian","text":"TaskNotes provides two calendar-based views: the Mini Calendar and the Calendar View. Both operate as Bases views (.base files) and require the Bases core plugin to be enabled in Obsidian. Mini Calendar is date-density and navigation focused, while Calendar View is scheduling focused. Bases View Architecture# Calendar views in TaskNotes v4 are implemented as Bases views, which means: Calendar views are created as .base files in your vault Configuration is controlled through YAML frontmatter in the base file The Bases plugin is an official Obsidian core plugin and must be enabled Views can be opened in tabs, pinned, and managed like other Obsidian views This architecture makes calendar behavior auditable. Filters, formulas, and display options are stored with the view file, so they are versionable and easy to share across vault setups. Mini Calendar View# The Mini Calendar displays a month-based view that shows which days contain tasks or other dated notes. It provides navigation and an overview of your task distribution across time. Features# Date Navigation: Click any date to open a fuzzy selector modal showing all notes associated with that date Keyboard Navigation: Navigate the calendar using arrow keys and select dates with Enter Heatmap Styling: Visual indicators show the density of tasks or notes on each day Configurable Date Property: Set which date property to track (not limited to tasks - can display any dated notes based on configured property) Month Navigation: Browse forward and backward through months to view historical and future task distribution Mini Calendar is commonly used as an entry view: select a date, then open Task List, Agenda, or Calendar for execution. Calendar View# The Calendar View provides multiple view modes (month, week, day, year, list, and custom days) with drag-and-drop scheduling and time-blocking capabilities. Tasks can be created by clicking on dates or time slots, and rescheduled by dragging them to new dates or times. View Modes# The Calendar View supports the following view modes: Month: Month grid showing all-day and timed events Week: Week view with hourly time slots for detailed scheduling Day: Single day view with hourly breakdown Year: Annual overview showing event distribution across months List: Chronological list of events. TaskNotes also includes a dedicated Agenda command that opens this mode via its own .base file for quick reviews. Custom Days: Configurable multi-day view (2-10 days) View modes can be switched within a single .base file based on planning horizon (day, week, month, year, or custom range). Week View Day View Year View Performance Improvements# The Calendar View uses virtual scrolling to maintain performance when displaying large numbers of events. This allows the calendar to handle extensive task lists and long time ranges without degradation in responsiveness. Custom Days View# The Custom Days view provides a configurable multi-day calendar that displays between 2-10 days at once. This view addresses screen space utilization by offering a middle ground between the single-day view and the full week view. Key Features# Configurable Duration: Set the number of days to display (2-10 days) via Settings > Calendar > Custom view day count TimeGrid Format: Uses the same hourly time slots and time-based event layout as Week and Day views Real-time Updates: The view updates immediately when the day count setting is changed Default Configuration: Ships with 3 days displayed by default for optimal space utilization Use Cases# The Custom Days view is particularly useful for: Users who find the single-day view too wide and wasteful of screen space Planning workflows that require seeing a few days at a glance without the full week Detailed scheduling tasks that benefit from the time-grid format Customizing the viewing window to match personal preference and screen size Configuration# Select the View: Choose \"Custom Days\" from the calendar toolbar alongside Month, Week, Day, and Year views Adjust Day Count: Navigate to Settings > Calendar > Custom view day count and use the slider to select 2-10 days Set as Default: Optionally set \"Custom Days\" as your default view in Settings > Calendar > Default view Recurring Task Support# The Calendar View provides recurring task management with visual hierarchy and drag-and-drop behavior. Visual Hierarchy# Recurring tasks are displayed with distinct visual styling: Next Scheduled Occurrence: Solid border with full opacity, representing the specific date/time when you plan to work on the next instance Pattern Instances: Dashed border with reduced opacity (70%), showing preview of when future recurring instances will appear based on the DTSTART and recurrence rule Drag and Drop Behavior# The calendar provides different behaviors depending on which type of recurring event you drag: Dragging Next Scheduled Occurrence (Solid Border): Updates only the scheduled field in the task Reschedules just that specific occurrence to the new date/time Leaves the recurrence pattern unchanged Notice: \"Rescheduled next occurrence. This does not change the recurrence pattern.\" Dragging Pattern Instances (Dashed Border): Updates the DTSTART time in the recurrence rule Changes when all future pattern instances appear Does not affect the independently scheduled next occurrence Notice: \"Updated recurring pattern time. All future instances now appear at this time.\" Flexible Scheduling# The next scheduled occurrence can appear on any date, even: Before the DTSTART date On days that don't match the recurring pattern (e.g., Tuesday for a weekly Monday pattern) At different times than the pattern instances This flexibility allows for complete control over both the recurring pattern and individual occurrence scheduling. View Options# The Calendar View provides several display options that control what types of events appear on the calendar: Show scheduled: Display tasks with scheduled dates Show due: Display tasks with due dates Show timeblocks: Display time-blocking entries Show recurring: Display recurring task events Show ICS events: Display events from imported ICS calendars Show time entries: Display time tracking entries All-day slot: Show or hide the all-day event area at the top of time grid views (Week, Day, and Custom views) Create daily notes from date links: Let date header links create a missing daily note before opening it. Turn this off if date links should only open existing daily notes. Drag/drop resolution: Set snapDuration when you want events to drag or resize in smaller increments than the visible slotDuration, such as 5-minute dragging on a 30-minute grid. Span tasks between scheduled and due dates: Display tasks as multi-day bars spanning from their scheduled date to their due date (see below) Multiple saved calendar views can store different option sets (for example planning vs focus), avoiding repeated manual toggles. The All-day slot option is particularly useful when you have many all-day tasks on a single date, as hiding it can resolve scrolling issues and make the hourly time slots more accessible. When disabled, all-day events will not be displayed in time grid views, but they will still appear in month view. Multi-Day Task Spans# The Span tasks between scheduled and due dates option provides a visual representation of task duration on the calendar. When enabled: Tasks with both a scheduled date and a due date display as a single bar spanning across all days from the scheduled date to the due date This replaces the separate scheduled and due markers for qualifying tasks Tasks with only a scheduled date or only a due date continue to display as single-day events Span events are shown as all-day bars with the task's priority color Span events are read-only on the calendar (edit the underlying scheduled/due dates to modify) This option is useful for project planning and visualizing how long tasks are expected to take, similar to Gantt chart-style views. These display options are preserved when you save a view, allowing you to create specialized calendar views that show only specific types of events and maintain those preferences across sessions. OAuth Calendar Integration# The Calendar View supports bidirectional synchronization with external calendar services through OAuth authentication: Google Calendar: Connect to Google Calendar accounts to display and sync events Microsoft Outlook: Connect to Microsoft Outlook accounts for calendar integration Synchronization Behavior# External calendar events appear alongside TaskNotes tasks in all calendar views Drag and drop events to reschedule them - changes sync back to the external calendar service Events from external calendars respect the same view options and display settings as native TaskNotes tasks Configuration# OAuth calendar connections are configured through the TaskNotes settings panel. Authentication uses standard OAuth flows to securely connect to external services. Time Entry Editor Modal# The Calendar View includes a Time Entry Editor Modal for creating time tracking entries directly from the calendar interface. Creating Time Entries# Drag on the calendar to select a time range When the selection menu appears, choose Create time entry The modal opens with the start and end times pre-populated based on the selection, and the entry can be linked to a task or left standalone Editing Time Entries# Time entries displayed on the calendar can be selected to open the Time Entry Editor Modal for modification. The modal provides fields for adjusting start time, end time, associated task, and other time entry metadata. Filtering and View Configuration# Calendar filtering is configured through the Bases YAML frontmatter in the .base file. This allows you to define which tasks and events appear in each calendar view. Filtering options include task properties, date ranges, tags, and other criteria supported by the Bases plugin. Saved calendar views retain their filter configuration, display options, and view mode, allowing you to create specialized calendar views for different purposes."},{"title":"Kanban View","url":"/obsidian/views/kanban-view/","description":"The Kanban View displays tasks as cards organized in columns, where each column represents a distinct value of a grouped property. Kanban emphasizes state transitions and drag o...","product":"obsidian","text":"The Kanban View displays tasks as cards organized in columns, where each column represents a distinct value of a grouped property. Kanban emphasizes state transitions and drag operations over dense list scanning. Configuration# Kanban views are stored as .base files in TaskNotes/Views/. The groupBy property determines the column structure—each unique value becomes a column in the board. Open a .base file and access the view settings panel to configure options. Core Settings (Bases)# Data source: Select which files or folders to include in the view Filter: Define criteria to include or exclude specific tasks Sort: Specify the order of tasks within each column Group by: Required. Defines the property that creates columns (e.g., status, priority) Choosing a stable groupBy field is the most important design decision. Frequent changes to this field create column churn and make historical comparisons harder. Kanban-Specific Options# Access these options through the Bases view settings panel: Swim Lane: Optional property for horizontal grouping. Creates a two-dimensional layout where tasks are organized by both column (groupBy) and row (swimLane) Column Width: Controls the width of columns in pixels. Range: 200-500px. Default: 280px Max Swimlane Height: Caps each swimlane row before the task area scrolls. Range: 300-1200px. Default: 600px Hide Empty Columns: When enabled, columns containing no tasks are hidden from the view Pinned Columns: Optional comma-separated list of column values that should stay visible even when empty. This is useful with Hide Empty Columns when each board needs a small stable subset of shared statuses or categories WIP Limits: Advanced JSON configuration for showing per-column work-in-progress limits in column headers Hide Empty Swimlanes: When enabled, ordered swimlanes with no tasks are hidden from the view Card Layout: Chooses the task card density for this board. Default uses the standard TaskNotes card layout. Compact uses a tighter card layout for denser boards Show items in multiple columns: When enabled (default), tasks with multiple values in list properties (contexts, tags, projects) appear in each individual column. For example, a task with contexts: [work, call] appears in both the \"work\" and \"call\" columns. When disabled, tasks appear in a single combined column (e.g., \"work, call\") Hide top-level subtasks: When enabled, tasks whose Projects field links to another task in the current filtered board are hidden as standalone cards and remain available through the parent task's expanded subtasks Column Order: Managed automatically when dragging column headers. Stores custom column ordering Swim Lane Order: Advanced JSON configuration for pinning swimlane rows in a stable order A common setup is to keep one board grouped by status and another grouped by project or context, each in a separate .base file. Interface Layout# Standard Layout# In standard mode, the Kanban board displays a horizontal row of columns. Each column corresponds to a unique value of the groupBy property. Each column includes: A header showing the property value and task count A scrollable area containing task cards An add button that opens the TaskNotes creation modal with the column value filled in Drag-and-drop functionality for reordering columns or moving tasks between columns Swimlane Layout# When a swimLane property is configured, the board displays a grid layout. The horizontal axis represents columns (groupBy values), and the vertical axis represents swimlanes. Each swimlane row includes: A label cell showing the swimlane property value and total task count Multiple cells, each representing a column within that swimlane Scrollable cells containing task cards Add buttons inside cells that fill in both the column value and swimlane value To pin swimlanes in a stable order, set the advanced swimLaneOrder option to a JSON object keyed by the swimlane property: config: swimLane: note.contexts swimLaneOrder: '{\"note.contexts\":[\"transitcal\",\"bill\",\"cycles-research\",\"astrolabe\"]}' Listed swimlane values render first in the configured order. Values not listed in swimLaneOrder render below them using the default order for status and priority swimlanes, or alphabetically for other properties. If hideEmptySwimLanes is disabled, listed values can remain visible even when no matching tasks are currently present. To show WIP limits in column headers, set the advanced wipLimits option to a JSON object keyed by column value: config: wipLimits: '{\"in-progress\":5,\"review\":2}' Columns with limits display counts as (current/limit). When the current count is above the configured limit, the count uses the error color. In swimlane boards, the column header count is the total for that column across all swimlanes. Task Cards# Each task card displays information based on the visible properties configured in the Bases view. Standard task information includes title, priority, due date, and scheduled date. Use the Card Layout setting when a board needs a different density from other task views. Existing boards use Default unless cardLayout: compact is set in the view options. To show checklist progress on cards, include file.tasks in the view order array. For existing .base files, add this in YAML manually first; after it is in order, it appears in the Bases picker as tasks. Click a card to open the task file for editing. Right-click to access the context menu for task actions. Drag cards between columns or swimlane cells to update the task's properties. Column Operations# Reordering Columns# Drag column headers to reorder columns. The new order persists across sessions and is stored in the columnOrder configuration. Drag-and-Drop Tasks# Drag task cards between columns to update the groupBy property value. In swimlane mode, dragging a task to a different cell updates both the groupBy and swimLane properties. When grouping by a list property (contexts, tags, projects) with \"Show items in multiple columns\" enabled, dragging a task between columns modifies the list rather than replacing it. The source column's value is removed and the target column's value is added. For example, dragging a task from the \"work\" column to the \"home\" column changes contexts: [work, call] to contexts: [call, home]. Drag operations write directly to task metadata, so consistent grouping values reduce ambiguity. The add button at the bottom of a column or swimlane cell keeps deterministic view filter defaults and fills in the grouped values for that location. Manual Reordering Within Columns# Kanban also supports drag-to-reorder within a column or swimlane cell when the view is sorted by the manual-order property. With the default field mapping, that property is tasknotes_manual_order. To enable persistent manual ordering within Kanban columns: sort: - column: tasknotes_manual_order direction: DESC Once the first sort criterion is the manual-order property, dragging a card within the same column updates stored frontmatter values so the new order persists across refreshes and sessions. In swimlane mode, the reorder scope is a single cell, not the entire board. A reorder inside the \"In Progress\" column for the \"High\" swimlane only adjusts the tasks in that cell. Important constraints: Manual drag-to-reorder only works when the view sort includes the manual-order property. Moving a card to a different column or swimlane still updates the grouped property values as usual. In filtered or partially visible columns, TaskNotes may also update hidden or filtered notes in the same reorder scope to preserve a stable persistent order. Large reorder operations may show a confirmation dialog before writing changes. The default generated TaskNotes templates use manual-order sorting in places where drag-to-reorder should work immediately, such as relationship views and manual-order task lists. Performance Optimization# The Kanban view implements virtual scrolling for columns or swimlane cells containing 30 or more tasks. This optimization reduces memory usage by approximately 85% and maintains 60fps scrolling performance for columns with 200+ tasks. Virtual scrolling activates automatically based on task count. No configuration is required. Example Configuration# A typical Kanban view .base file includes: --- type: query source: TaskNotes view: TaskNotes Kanban views: - name: TaskNotes Kanban type: tasknotesKanban groupBy: property: task.status config: swimLane: task.priority swimLaneOrder: '{\"task.priority\":[\"high\",\"normal\",\"low\"]}' columnWidth: 300 hideEmptyColumns: true pinnedColumns: to-do, in-progress, done wipLimits: '{\"in-progress\":5}' --- This configuration creates a Kanban board with: Columns based on task status Swimlanes based on task priority Priority swimlanes pinned in high, normal, low order 300px column width Empty unpinned columns hidden, while the to-do, in-progress, and done columns stay visible as drop targets A WIP limit of 5 tasks on the in-progress column Filtering and Sorting# Filtering and sorting are configured through the Bases view settings, not through a separate FilterBar component. Use the Bases filter editor to define conditions based on task properties. Use the Bases sort editor to specify the order of tasks within each column."},{"title":"Pomodoro View","url":"/obsidian/views/pomodoro-view/","description":"The Pomodoro View provides a timer for working in focused intervals, based on the Pomodoro Technique.","product":"obsidian","text":"The Pomodoro View provides a timer for working in focused intervals, based on the Pomodoro Technique. Timer Interface# The Pomodoro View includes a timer with controls to start, stop, and reset the timer. While a timer is running, the view shows both the remaining duration and the projected local finish time. You can also associate a task with the timer, and the time will be automatically recorded in the task's time tracking data when the session is complete. Pomodoro Stats View# The Pomodoro Stats View provides analytics and historical data about your Pomodoro sessions. This includes a history of completed sessions, as well as metrics like completion rates and total time spent on tasks."},{"title":"Task List View","url":"/obsidian/views/task-list/","description":"The Task List View displays tasks in a scrollable list format with filtering, sorting, and grouping capabilities. In TaskNotes v4, this view operates as a Bases view configured...","product":"obsidian","text":"The Task List View displays tasks in a scrollable list format with filtering, sorting, and grouping capabilities. In TaskNotes v4, this view operates as a Bases view configured through YAML. This view is optimized for high task volume and explicit filter definitions. Bases Architecture# Task List is implemented as a .base file located in TaskNotes/Views/tasks-default.base by default. It requires the Bases core plugin to be enabled. What is Bases?# Bases is an official Obsidian core plugin built directly into Obsidian (not a community plugin). It provides a framework for creating database views of notes and tasks. To enable Bases: Open Settings -> Core Plugins Enable \"Bases\" TaskNotes view commands will now open .base files from TaskNotes/Views/ If commands open empty or unexpected views, first confirm Bases is enabled and the command path points to the intended .base file. View File Location# When you use the \"Open Tasks View\" command or ribbon icon, TaskNotes opens the .base file configured under Settings -> TaskNotes -> General -> Views & base files (initially TaskNotes/Views/tasks-default.base). TaskNotes creates missing default .base files automatically on startup when Auto-create default files is enabled, and you can point the command to any other .base file if you maintain multiple task-list layouts. Configuration# Task List views are configured through YAML frontmatter in the .base file. The YAML defines which tasks to show, how to sort them, and how to group them. Basic Structure# # All Tasks views: - type: tasknotesTaskList name: \"All Tasks\" order: - note.status - note.priority - note.due - note.scheduled - note.projects - note.contexts - file.tags sort: - column: due direction: ASC Configuration Options# type: Must be tasknotesTaskList for Task List views name: Display name shown in the view header order: Array of property names that control which task properties are visible in the task cards. Properties are referenced using their Bases property paths (e.g., note.status, note.priority, note.due, file.tasks). For existing .base files, add file.tasks in YAML manually; once present in order, it appears in the Bases picker as tasks. sort: Array of sort criteria. Tasks are sorted by the first criterion, with ties broken by subsequent criteria. column: Property to sort by (e.g., due, scheduled, priority, title) direction: ASC (ascending) or DESC (descending) groupBy: Optional grouping configuration property: Property to group by (e.g., note.status, note.priority) direction: Sort direction for group headers hideTopLevelSubtasks: Optional boolean. When true, tasks whose Projects field links to another task in the current filtered result set are hidden as top-level rows and remain available through the parent task's expanded subtasks. filters: Optional filter conditions using Bases query syntax filters: and: - note.status == \"Open\" - note.priority == \"High\" Start with one or two simple filters, verify results, then layer complexity. Incremental edits are much easier to debug than large one-shot query rewrites. Property Mapping# TaskNotes properties are accessed in Bases YAML using these paths: TaskNotes Property Bases Property Path Description Status note.status Task status value Priority note.priority Priority level Due date note.due Due date/time Scheduled date note.scheduled Scheduled date/time Projects note.projects Associated projects Contexts note.contexts Task contexts Tags file.tags File tags Checklist progress file.tasks First-level markdown checkbox progress shown as the TaskNotes checklist progress bar Time estimate note.timeEstimate Estimated duration Recurrence note.recurrence Recurrence pattern Blocked by note.blockedBy Blocking dependencies Title file.name Task title (file name) Created file.ctime File creation date Modified file.mtime File modification date The exact property names depend on your TaskNotes field mapping settings (Settings -> TaskNotes -> Task Properties). The table above shows default mappings. Filtering and Sorting# Adding Filters# Edit the .base file to add filter conditions using Bases query syntax: views: - type: tasknotesTaskList name: \"High Priority Tasks\" filters: and: - note.priority == \"High\" - note.status != \"Completed\" order: - note.status - note.priority - note.due Filter Operators# Bases supports standard comparison operators: == (equals), != (not equals) >, <, >=, <= (comparison) contains() (substring/array membership) Boolean logic: and, or For detailed filter syntax, see the Bases documentation. Sorting Examples# Single sort criterion: sort: - column: due direction: ASC Multiple sort criteria: sort: - column: priority direction: DESC - column: due direction: ASC - column: title direction: ASC Drag-to-Reorder# Task List supports drag-to-reorder when the view is sorted by the manual-order property. With the default field mapping, that property is tasknotes_manual_order. To enable persistent manual ordering in a Task List view: sort: - column: tasknotes_manual_order direction: DESC Once the first sort criterion is the manual-order property, you can drag task cards to reorder them. TaskNotes writes updated LexoRank-style values into task frontmatter so the order persists across refreshes and sessions. If your field mapping changes the sort-order property name, use that mapped property name instead of tasknotes_manual_order. Drag-to-Reorder with Grouping# Grouped Task List views can also be reordered, but the reorder scope is the current group. For example, when grouping by status, dragging within the \"In Progress\" group updates the manual order for tasks in that group. Important constraints: Drag-to-reorder only works when the view sort includes the manual-order property. Reordering in formula-based groups is blocked because formula values are computed and cannot be edited directly. In filtered or partially visible lists, TaskNotes may also update hidden or filtered notes in the same reorder scope to preserve a stable persistent order. Large reorder operations may show a confirmation dialog before writing changes. The default generated TaskNotes task-list templates include a Manual Order view that is already configured for this behavior. Grouping# Groups organize tasks under collapsible headers based on a property value. Enable Grouping# Add groupBy configuration to your view: views: - type: tasknotesTaskList name: \"Tasks by Status\" groupBy: property: note.status direction: ASC order: - note.status - note.priority - note.due Available Grouping Properties# Common grouping properties: note.status - Group by task status note.priority - Group by priority level note.contexts - Group by first context note.projects - Group by project (tasks can appear in multiple groups) Interactive Group Headers# Group headers support interaction: Click to expand/collapse the group Click on project links in headers to navigate to project notes Hover over project links with Ctrl to preview project notes Collapsed State Persistence# Collapsed/expanded state for each group is preserved across sessions. Creating Multiple Views# You can create multiple .base files for different task perspectives: Duplicate an existing .base file in TaskNotes/Views/ Rename it (e.g., High Priority.base) Edit the YAML configuration for that view Open the file to see the customized view Example: Context-Specific View# # Work Tasks views: - type: tasknotesTaskList name: \"Work Context\" filters: and: - note.contexts.contains(\"work\") groupBy: property: note.priority direction: DESC order: - note.status - note.priority - note.due Migrating from v3 Saved Views# TaskNotes v3 stored filter configurations in plugin settings. These saved views are not automatically migrated to v4. To recreate a v3 saved view: Create a new .base file in TaskNotes/Views/ Translate your v3 filter conditions to Bases YAML syntax Configure sorting and grouping through YAML Save the file The v3 FilterBar UI component no longer exists - all configuration is done through YAML editing. Task Actions# The Task List View provides interaction with tasks through clicking and context menus: Click on a task: Opens the task for editing or navigates to the task note (behavior configured in Settings -> TaskNotes -> General in click-action controls) Right-click on a task: Opens a context menu with actions: Mark as complete Change priority Change status Edit dates Delete task And more Context menu availability depends on your TaskNotes settings and task properties. Virtual Scrolling# The Task List View automatically enables virtual scrolling when displaying 100 or more items (tasks + group headers). Virtual scrolling provides: Approximately 90% memory reduction for large lists Elimination of UI lag when scrolling through hundreds of tasks Smooth performance with unlimited task counts Virtual scrolling activates automatically and requires no configuration. When active, only visible tasks are rendered to the DOM, with off-screen tasks rendered on-demand as you scroll. Further Reading# Default Base Templates - Complete templates for all TaskNotes views Bases Plugin Documentation - Official Obsidian documentation for Bases syntax and features Kanban View - Alternative board-based task visualization Calendar Views - Time-based task visualization Views Overview - All available TaskNotes views"},{"title":"TaskNotes Webhooks","url":"/obsidian/webhooks/","description":"TaskNotes webhooks send HTTP POST requests when selected events occur.","product":"obsidian","text":"TaskNotes webhooks send HTTP POST requests when selected events occur. Prerequisites# Enable HTTP API in Settings -> TaskNotes -> Integrations -> HTTP API. Create at least one webhook (settings UI or API). Subscribe it to one or more events. Event Types# Task events: task.created task.updated task.deleted task.completed task.archived task.unarchived Time events: time.started time.stopped Pomodoro events: pomodoro.started pomodoro.completed pomodoro.interrupted Recurring events: recurring.instance.completed recurring.instance.skipped Completing a materialized occurrence note emits recurring.instance.completed with the reconciled parent task plus the completed occurrence and date in the event data. Skipping virtual recurring instances emits recurring.instance.skipped; materialized occurrence skip currently reconciles the parent and occurrence note without emitting a separate skip webhook. Reminder events: reminder.triggered Payload Shape# All webhook payloads use the same top-level envelope: { \"event\": \"task.created\", \"timestamp\": \"2026-02-21T10:30:00.000Z\", \"vault\": { \"name\": \"My Vault\", \"path\": \"/path/to/vault\" }, \"data\": {} } data is event-specific. Register and Manage Webhooks via API# Create# POST /api/webhooks Required fields: url (string) events (non-empty array) Optional fields: id secret (auto-generated if omitted) active (default true) transformFile corsHeaders (default true) Example: curl -X POST http://localhost:8080/api/webhooks \\ -H \"Content-Type: application/json\" \\ -d '{ \"url\": \"https://example.com/tasknotes\", \"events\": [\"task.completed\", \"task.created\"], \"transformFile\": \"TaskNotes/webhooks/slack.json\" }' List# GET /api/webhooks Returns registered hooks. Secrets are not returned. Delete# DELETE /api/webhooks/:id Delivery History# GET /api/webhooks/deliveries Returns last 100 in-memory deliveries. Delivery Behavior# Current implementation behavior: Webhook processing is asynchronous (fire-and-forget from task operation). Each delivery starts with one attempt. Failed deliveries retry with exponential backoff: 1s, 2s, 4s. Maximum retries: 3 retries after initial attempt (up to 4 attempts total). If cumulative failureCount for a webhook exceeds 10, webhook is auto-disabled. No explicit request timeout is set in delivery fetch. Because retries and duplicates are possible, handlers should be idempotent. Signature Verification# When corsHeaders is enabled (default), delivery includes: X-TaskNotes-Event X-TaskNotes-Signature X-TaskNotes-Delivery-ID Signature is HMAC-SHA256 over JSON.stringify(payload) using webhook secret. Node.js example: const crypto = require(\"crypto\"); function verifyWebhook(payload, signature, secret) { const expected = crypto .createHmac(\"sha256\", secret) .update(JSON.stringify(payload)) .digest(\"hex\"); return signature === expected; } Payload Transformations# A webhook can specify transformFile pointing to a file in your vault. Supported file types: .json: event template map with variable interpolation If transform execution fails, TaskNotes falls back to original payload. JavaScript transform files are no longer supported. JSON Transform Files# Structure: { \"task.completed\": { \"text\": \"Task completed: ${data.task.title}\", \"vault\": \"${vault.name}\" }, \"default\": { \"text\": \"TaskNotes event: ${event}\" } } Rules: Matching order: exact event key, then default. Variables use ${path.to.value}. Missing variables are left unchanged. CORS and Headers# Webhook delivery requests are outbound server-side requests from TaskNotes. corsHeaders behavior: true (default): sends TaskNotes custom headers including signature. false: only sends Content-Type: application/json. Disable custom headers for endpoints that reject non-standard headers. Testing# Local Test Server# Use repository script: node test-webhook.js Optional custom port: node test-webhook.js 8080 Default server values: URL: http://localhost:3000/webhook Test secret: test-secret-key-for-tasknotes-webhooks External Inspection# For quick inspection, use a request-bin tool such as webhook.site. Troubleshooting# No deliveries# Confirm HTTP API is enabled. Confirm webhook is active. Confirm event is subscribed. Signature mismatch# Confirm secret matches webhook config. Verify your verifier hashes the exact JSON body. Verify hex digest comparison. Webhook disabled automatically# If failures continue and failureCount exceeds 10, webhook is disabled. Fix endpoint availability or response handling. Re-enable webhook in TaskNotes settings, or recreate it via POST /api/webhooks. Transform errors# Confirm transformFile exists in vault. Confirm the file is a .json transform template. Check Obsidian console logs for transform exceptions."},{"title":"Workflows","url":"/obsidian/workflows/","description":"This page describes practical ways to combine TaskNotes features into repeatable workflows. The goal is to show how recurring tasks, projects, filtering, and scheduling fit toge...","product":"obsidian","text":"This page describes practical ways to combine TaskNotes features into repeatable workflows. The goal is to show how recurring tasks, projects, filtering, and scheduling fit together in everyday use. Habit Tracking with Recurring Tasks# Habit tracking in TaskNotes is built on recurring task notes. You can create a recurring task from natural language (for example, \"Exercise daily\" or \"Gym every Monday and Wednesday\") or configure recurrence explicitly in the task modal. The modal recurrence controls support frequency, interval, weekday selection, and end conditions. Once a task has a recurrence rule, its edit modal shows a recurrence calendar. That calendar is where you mark completion per occurrence. Completion history is stored in complete_instances, so a recurring task can remain open while still recording daily/weekly completion behavior. title: Morning Exercise recurrence: \"FREQ=DAILY\" scheduled: \"07:00\" complete_instances: - \"2025-01-01\" - \"2025-01-02\" - \"2025-01-04\" Use Calendar and Agenda views to review upcoming occurrences, and use recurring-task filters when you want a habit-only planning view. For richer recurring work, such as a weekly review or maintenance visit, right-click the recurrence in a task card, calendar view, or the edit modal's completion calendar and choose Open or create occurrence note. The occurrence note inherits planning metadata such as scheduled time, due offset, projects, tags, reminders, details, and time estimate, then keeps its own checklist, completion state, and time entries while the parent recurring task keeps the long-term rule. On the calendar, the note-backed occurrence replaces the matching virtual parent occurrence; dragging it reschedules that note without rewriting the recurrence pattern. Project-Centered Planning# Projects in TaskNotes can be plain text values or wikilinks to project notes. Wikilinks are usually the better long-term option because they connect task execution to project context, backlinks, and graph navigation. title: \"Research competitors\" projects: [\"[[Market Research]]\", \"[[Q1 Strategy]]\"] During task creation, use the project picker to search and assign one or more projects. In day-to-day planning, open Task List or Kanban, then filter on note.projects contains [[Project Name]] to isolate one initiative. Save that filter as a Bases saved view if you revisit it regularly. When work spans initiatives, assign multiple projects and combine with contexts or tags for secondary organization. title: \"Prepare presentation slides\" projects: [\"[[Q4 Planning]]\"] contexts: [\"computer\", \"office\"] tags: [\"review\"] Execution Workflow (Daily)# A typical daily flow is to start in Task List for prioritization, move to Calendar for schedule placement, and finish in Agenda for near-term sequencing. This keeps backlog management, time allocation, and short-horizon execution in one system. If you use timeboxing, drag-select on calendar timeline views and create timeblocks directly from the context menu. If you use Pomodoro, run sessions against active tasks so completion and timing data stay attached to task notes. Maintenance Workflow (Weekly)# A weekly review usually includes three steps: clean up completed/archived tasks, verify recurring-task completion patterns, and rebalance project filters/views. If calendar integrations are enabled, this is also a good point to refresh subscriptions and confirm sync health. For teams or complex personal systems, keep project notes as source-of-truth documents and use TaskNotes views as execution dashboards derived from those notes."},{"title":"TaskNotes privacy overview","url":"/privacy/","description":"How the TaskNotes app and Obsidian plugin store data and when optional services are involved.","product":"shared","text":"Last updated: August 6, 2026 TaskNotes products are built around portable Markdown records. The storage and network boundaries depend on the client and collection you choose. TaskNotes app# The TaskNotes app opens every collection through mdbase and requires a connection to read or change it. A hosted collection stores the authoritative Markdown with the hosted provider. A computer collection keeps the authoritative Markdown on that computer. TaskNotes reaches it through an end-to-end encrypted relay that cannot read record contents; the computer must remain reachable and run mdbase Connect. TaskNotes keeps only a temporary in-memory session cache. It does not retain a separate offline collection after the app or page closes. Reminder notifications for mdbase collections require explicit permission and use content-free event payloads. Task content is refreshed through the authorized collection connection. Obsidian plugin# The plugin keeps task and note content in the local Obsidian vault. Plugin settings live in Obsidian's plugin configuration. Network access occurs only for enabled features that require it, including release checks, calendar providers, ICS subscriptions, webhooks, and remotely loaded API documentation assets. Analytics# TaskNotes does not include a product telemetry or analytics pipeline. Services you choose to connect may keep their own operational, account, security, or billing records under their respective policies. Removal# Removing a client does not necessarily remove its authoritative collection. Use the hosted provider's controls for a hosted collection, or manage the Markdown folder on the computer that owns a computer collection. Back up records before removing an authoritative copy. Questions and source code# Use the relevant TaskNotes GitHub repository to report a privacy problem or inspect the implementation: TaskNotes app TaskNotes Obsidian plugin"}] diff --git a/public/sitemap.xml b/public/sitemap.xml index 756b546..ce7c87d 100644 --- a/public/sitemap.xml +++ b/public/sitemap.xml @@ -3,6 +3,7 @@ https://tasknotes.dev/ https://tasknotes.dev/app/ https://tasknotes.dev/app/collections/ + https://tasknotes.dev/app/connect-mdbase/ https://tasknotes.dev/app/connection/ https://tasknotes.dev/app/demo/ https://tasknotes.dev/app/getting-started/ @@ -176,6 +177,9 @@ https://tasknotes.dev/obsidian/releases/4.12.1/ https://tasknotes.dev/obsidian/releases/4.12.2/ https://tasknotes.dev/obsidian/releases/4.12.3/ + https://tasknotes.dev/obsidian/releases/4.12.4/ + https://tasknotes.dev/obsidian/releases/4.12.5/ + https://tasknotes.dev/obsidian/releases/4.13.0/ https://tasknotes.dev/obsidian/releases/4.2.0/ https://tasknotes.dev/obsidian/releases/4.2.1/ https://tasknotes.dev/obsidian/releases/4.3.0/ diff --git a/scripts/generate-content.mjs b/scripts/generate-content.mjs index 20ea482..8874929 100644 --- a/scripts/generate-content.mjs +++ b/scripts/generate-content.mjs @@ -441,6 +441,8 @@ function rewriteLinks(page) { ) return full; const { pathPart, suffix } = splitHref(href); + // Public downloads are files, not documentation routes with trailing slashes. + if (pathPart.startsWith("/assets/")) return full; if (pathPart.startsWith("/")) return `${before}${canonicalRouteForAbsolute(pathPart)}${suffix}${after}`; if (/\.md$/i.test(pathPart)) { diff --git a/tests/connect-walkthrough.test.mjs b/tests/connect-walkthrough.test.mjs new file mode 100644 index 0000000..654f467 --- /dev/null +++ b/tests/connect-walkthrough.test.mjs @@ -0,0 +1,66 @@ +import assert from "node:assert/strict"; +import { createHash } from "node:crypto"; +import { readFile } from "node:fs/promises"; +import test from "node:test"; + +const root = new URL("../", import.meta.url); +const media = "assets/app/connect-mdbase/"; +const generated = JSON.parse( + await readFile(new URL(".generated/content.json", root), "utf8"), +); +const page = generated.pages.find((page) => page.route === "/app/connect-mdbase/"); + +// Approved revision 6, 3:53, with visible cursors and four contextual sections. +// Source: https://3f1cda16.tasknotes-mdbase-video.pages.dev/ +const approvedVideoHash = "da55a40d0ef4f9b684adda89b1d733baeee5a0869115d09eaeff17a0db356a21"; +const videoDuration = 232.599347; + +test("publishes the approved walkthrough and its assets without changing them", async () => { + const video = await readFile(new URL(`public/${media}walkthrough.mp4`, root)); + assert.equal(createHash("sha256").update(video).digest("hex"), approvedVideoHash); + for (const name of ["walkthrough.mp4", "poster.png", "captions.en.vtt"]) { + const source = await readFile(new URL(`public/${media}${name}`, root)); + const published = await readFile(new URL(`dist/client/${media}${name}`, root)); + assert.deepEqual(published, source, `${name} is included in the static site`); + } +}); + +test("the authored transcript includes every timed instruction", async () => { + assert.equal(page?.source, "tasknotes.dev:content/app/connect-mdbase.md"); + assert.equal(page?.product, "app"); + const vtt = await readFile(new URL(`public/${media}captions.en.vtt`, root), "utf8"); + assert.ok(vtt.startsWith("WEBVTT\n")); + const cues = vtt.trim().split(/\n\n+/).slice(1); + const transcript = page.raw.split("## Transcript")[1]; + assert.ok(transcript); + const seconds = (value) => { + const [hours, minutes, seconds] = value.split(":").map(Number); + return hours * 3600 + minutes * 60 + seconds; + }; + let previousEnd = 0; + for (const cue of cues) { + const [timing, ...lines] = cue.split("\n"); + const match = timing.match(/^(\d{2}:\d{2}:\d{2}\.\d{3}) --> (\d{2}:\d{2}:\d{2}\.\d{3})$/); + assert.ok(match, timing); + const start = seconds(match[1]); + const end = seconds(match[2]); + assert.ok(start >= previousEnd && end > start && end <= videoDuration + 0.01); + assert.ok(transcript.includes(lines.join(" ")), lines.join(" ")); + const timestamp = match[1].slice(3, 8); + assert.ok(transcript.includes(`**${timestamp}**`), timestamp); + previousEnd = end; + } + assert.equal(cues.length, 26); + assert.match(page.raw, /Hosted collections can also be mirrored/); + assert.match(page.raw, /OS-specific installer dialogs are omitted/); +}); + +test("the app entry points and navigation link to the walkthrough", () => { + for (const route of ["/app/", "/app/getting-started/", "/app/collections/", "/app/mdbase/"]) { + const entry = generated.pages.find((page) => page.route === route); + assert.ok(entry?.html.includes('href="/app/connect-mdbase/"'), route); + } + assert.ok(generated.navigation.some((section) => + section.label === "TaskNotes app" && section.items.some((item) => item.route === page.route), + )); +}); diff --git a/tests/link-integrity.test.mjs b/tests/link-integrity.test.mjs index 854aadc..138907b 100644 --- a/tests/link-integrity.test.mjs +++ b/tests/link-integrity.test.mjs @@ -20,6 +20,8 @@ test("all internal documentation links resolve", () => { for (const page of generated.pages) { for (const url of internalUrls(page.html, "href")) { const pathname = url.split(/[?#]/)[0]; + // Asset downloads are checked against public/ alongside media below. + if (pathname.startsWith("/assets/")) continue; if (!routes.has(pathname) && !generated.redirects[pathname]) failures.push(`${page.route} -> ${url}`); } @@ -27,10 +29,15 @@ test("all internal documentation links resolve", () => { assert.deepEqual(failures, []); }); -test("all referenced public media exists", async () => { +test("all referenced public media, posters, and asset downloads exist", async () => { const failures = []; for (const page of generated.pages) { - for (const url of internalUrls(page.html, "src")) { + const urls = [ + ...internalUrls(page.html, "src"), + ...internalUrls(page.html, "poster"), + ...internalUrls(page.html, "href").filter((url) => url.startsWith("/assets/")), + ]; + for (const url of urls) { const pathname = url.split(/[?#]/)[0]; const publicPath = new URL(`public${pathname}`, root); try { diff --git a/tests/rendered-html.test.mjs b/tests/rendered-html.test.mjs index 1c70a48..53b912d 100644 --- a/tests/rendered-html.test.mjs +++ b/tests/rendered-html.test.mjs @@ -58,6 +58,29 @@ test("renders the interactive app demo immediately with minimal chrome", async ( assert.doesNotMatch(html, /aria-label="Documentation"/); }); +test("renders the connection walkthrough with an opt-in local video and transcript", async () => { + const response = await render("/app/connect-mdbase/"); + const html = await response.text(); + const video = html.match(/]*>/)?.[0]; + assert.ok(video, "the walkthrough has a native video player"); + assert.match(video, /\bcontrols\b/); + assert.match(video, /\bplaysinline\b/); + assert.match(video, /preload="none"/); + assert.match(video, /poster="\/assets\/app\/connect-mdbase\/poster\.png"/); + assert.match(video, /aria-describedby="walkthrough-description"/); + assert.doesNotMatch(video, /\b(?:autoplay|loop)\b/); + assert.match(html, /]*kind="captions"[^>]*srclang="en"/); + assert.match(html, /href="\/assets\/app\/connect-mdbase\/walkthrough\.mp4" download/); + assert.doesNotMatch(html, /walkthrough\.mp4\//); + assert.match(html, /
    /); + assert.match(html, /00:00<\/strong>/); + assert.match(html, /

    { const plugin = await render("/features/"); assert.equal(plugin.status, 200);